1 /**
2  * This file is part of DCD, a development tool for the D programming language.
3  * Copyright (C) 2014 Brian Schott
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 module dsymbol.semantic;
20 
21 import dsymbol.symbol;
22 import dparse.ast;
23 import dparse.lexer;
24 import containers.unrolledlist;
25 import dsymbol.type_lookup;
26 import stdx.allocator.mallocator : Mallocator;
27 
28 enum ResolutionFlags : ubyte
29 {
30 	inheritance = 0b0000_0001,
31 	type = 0b0000_0010,
32 	mixinTemplates = 0b0000_0100,
33 }
34 
35 /**
36  * Intermediate form between DSymbol and the AST classes. Stores enough
37  * information to resolve things like base classes and alias this.
38  */
39 struct SemanticSymbol
40 {
41 public:
42 
43 	/// Disable default construction.
44 	@disable this();
45 	/// Disable copy construction
46 	@disable this(this);
47 
48 	/**
49 	 * Params:
50 	 *    name = the name
51 	 */
52 	this(DSymbol* acSymbol)
53 	{
54 		this.acSymbol = acSymbol;
55 	}
56 
57 	~this()
58 	{
59 		import stdx.allocator.mallocator : Mallocator;
60 		import stdx.allocator : dispose;
61 
62 		foreach (child; children[])
63 			typeid(SemanticSymbol).destroy(child);
64 		foreach (lookup; typeLookups[])
65 			Mallocator.instance.dispose(lookup);
66 	}
67 
68 	/**
69 	 * Adds a child to the children field and updates the acSymbol's parts field
70 	 */
71 	void addChild(SemanticSymbol* child, bool owns)
72 	{
73 		children.insert(child);
74 		acSymbol.addChild(child.acSymbol, owns);
75 	}
76 
77 	/// Information used to do type resolution, inheritance, mixins, and alias this
78 	UnrolledList!(TypeLookup*, Mallocator, false) typeLookups;
79 
80 	/// Child symbols
81 	UnrolledList!(SemanticSymbol*, Mallocator, false) children;
82 
83 	/// Autocompletion symbol
84 	DSymbol* acSymbol;
85 
86 	/// Parent symbol
87 	SemanticSymbol* parent;
88 
89 	/// Protection level for this symobol
90 	deprecated("Use acSymbol.protection instead") ref inout(IdType) protection() @property inout
91 	{
92 		return acSymbol.protection;
93 	}
94 }
95 
96 /**
97  * Type of the _argptr variable
98  */
99 Type argptrType;
100 
101 /**
102  * Type of _arguments
103  */
104 Type argumentsType;
105 
106 static this()
107 {
108 	import dsymbol.string_interning : internString;
109 	import stdx.allocator : make;
110 	import stdx.allocator.mallocator : Mallocator;
111 
112 	// TODO: Replace these with DSymbols
113 
114 	// _argptr has type void*
115 	argptrType = make!Type(Mallocator.instance);
116 	argptrType.type2 = make!Type2(Mallocator.instance);
117 	argptrType.type2.builtinType = tok!"void";
118 	TypeSuffix argptrTypeSuffix = make!TypeSuffix(Mallocator.instance);
119 	argptrTypeSuffix.star = Token(tok!"*");
120 	argptrType.typeSuffixes = cast(TypeSuffix[]) Mallocator.instance.allocate(TypeSuffix.sizeof);
121 	argptrType.typeSuffixes[0] = argptrTypeSuffix;
122 
123 	// _arguments has type TypeInfo[]
124 	argumentsType = make!Type(Mallocator.instance);
125 	argumentsType.type2 = make!Type2(Mallocator.instance);
126 	argumentsType.type2.typeIdentifierPart = make!TypeIdentifierPart(Mallocator.instance);
127 	IdentifierOrTemplateInstance i = make!IdentifierOrTemplateInstance(Mallocator.instance);
128 	i.identifier.text = internString("TypeInfo");
129 	i.identifier.type = tok!"identifier";
130 	argumentsType.type2.typeIdentifierPart.identifierOrTemplateInstance = i;
131 	TypeSuffix argumentsTypeSuffix = make!TypeSuffix(Mallocator.instance);
132 	argumentsTypeSuffix.array = true;
133 	argumentsType.typeSuffixes = cast(TypeSuffix[]) Mallocator.instance.allocate(TypeSuffix.sizeof);
134 	argumentsType.typeSuffixes[0] = argumentsTypeSuffix;
135 }
136 
137 static ~this()
138 {
139 	import stdx.allocator : dispose;
140 	import stdx.allocator.mallocator : Mallocator;
141 
142 	dispose(Mallocator.instance, argumentsType.typeSuffixes[0]);
143 	dispose(Mallocator.instance, argumentsType.type2.typeIdentifierPart.identifierOrTemplateInstance);
144 	dispose(Mallocator.instance, argumentsType.type2.typeIdentifierPart);
145 	dispose(Mallocator.instance, argumentsType.type2);
146 	dispose(Mallocator.instance, argptrType.typeSuffixes[0]);
147 	dispose(Mallocator.instance, argptrType.type2);
148 
149 	Mallocator.instance.deallocate(argumentsType.typeSuffixes);
150 	Mallocator.instance.deallocate(argptrType.typeSuffixes);
151 
152 	dispose(Mallocator.instance, argumentsType);
153 	dispose(Mallocator.instance, argptrType);
154 }