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 import stdx.allocator.gc_allocator : GCAllocator;
28 
29 enum ResolutionFlags : ubyte
30 {
31 	inheritance = 0b0000_0001,
32 	type = 0b0000_0010,
33 	mixinTemplates = 0b0000_0100,
34 }
35 
36 alias TypeLookupsAllocator = GCAllocator; // NOTE using `Mallocator` here fails when analysing Phobos as: `munmap_chunk(): invalid pointer`
37 alias TypeLookups = UnrolledList!(TypeLookup*, TypeLookupsAllocator);
38 
39 /**
40  * Intermediate form between DSymbol and the AST classes. Stores enough
41  * information to resolve things like base classes and alias this.
42  */
43 struct SemanticSymbol
44 {
45 public:
46 
47 	/// Disable default construction.
48 	@disable this();
49 	/// Disable copy construction
50 	@disable this(this);
51 
52 	/**
53 	 * Params:
54 	 *    name = the name
55 	 */
56 	this(DSymbol* acSymbol)
57 	{
58 		this.acSymbol = acSymbol;
59 	}
60 
61 	~this()
62 	{
63 		import stdx.allocator : dispose;
64 
65 		foreach (child; children[])
66 			typeid(SemanticSymbol).destroy(child);
67 		foreach (lookup; typeLookups[])
68 			TypeLookupsAllocator.instance.dispose(lookup);
69 	}
70 
71 	/**
72 	 * Adds a child to the children field and updates the acSymbol's parts field
73 	 */
74 	void addChild(SemanticSymbol* child, bool owns)
75 	{
76 		children.insert(child);
77 		acSymbol.addChild(child.acSymbol, owns);
78 	}
79 
80 	/// Information used to do type resolution, inheritance, mixins, and alias this
81 	TypeLookups typeLookups;
82 
83 	/// Child symbols
84 	UnrolledList!(SemanticSymbol*, GCAllocator) children; // NOTE using `Mallocator` here fails when analysing Phobos
85 
86 	/// Autocompletion symbol
87 	DSymbol* acSymbol;
88 
89 	/// Parent symbol
90 	SemanticSymbol* parent;
91 
92 	/// Protection level for this symobol
93 	deprecated("Use acSymbol.protection instead") ref inout(IdType) protection() @property inout
94 	{
95 		return acSymbol.protection;
96 	}
97 }
98 
99 /**
100  * Type of the _argptr variable
101  */
102 Type argptrType;
103 
104 /**
105  * Type of _arguments
106  */
107 Type argumentsType;
108 
109 alias GlobalsAllocator = Mallocator;
110 
111 static this()
112 {
113 	import dsymbol.string_interning : internString;
114 	import stdx.allocator : make;
115 
116 	// TODO: Replace these with DSymbols
117 
118 	// _argptr has type void*
119 	argptrType = GlobalsAllocator.instance.make!Type();
120 	argptrType.type2 = GlobalsAllocator.instance.make!Type2();
121 	argptrType.type2.builtinType = tok!"void";
122 	TypeSuffix argptrTypeSuffix = GlobalsAllocator.instance.make!TypeSuffix();
123 	argptrTypeSuffix.star = Token(tok!"*");
124 	argptrType.typeSuffixes = cast(TypeSuffix[]) GlobalsAllocator.instance.allocate(TypeSuffix.sizeof);
125 	argptrType.typeSuffixes[0] = argptrTypeSuffix;
126 
127 	// _arguments has type TypeInfo[]
128 	argumentsType = GlobalsAllocator.instance.make!Type();
129 	argumentsType.type2 = GlobalsAllocator.instance.make!Type2();
130 	argumentsType.type2.typeIdentifierPart = GlobalsAllocator.instance.make!TypeIdentifierPart();
131 	IdentifierOrTemplateInstance i = GlobalsAllocator.instance.make!IdentifierOrTemplateInstance();
132 	i.identifier.text = internString("TypeInfo");
133 	i.identifier.type = tok!"identifier";
134 	argumentsType.type2.typeIdentifierPart.identifierOrTemplateInstance = i;
135 	TypeSuffix argumentsTypeSuffix = GlobalsAllocator.instance.make!TypeSuffix();
136 	argumentsTypeSuffix.array = true;
137 	argumentsType.typeSuffixes = cast(TypeSuffix[]) GlobalsAllocator.instance.allocate(TypeSuffix.sizeof);
138 	argumentsType.typeSuffixes[0] = argumentsTypeSuffix;
139 }
140 
141 static ~this()
142 {
143 	import stdx.allocator : dispose;
144 	GlobalsAllocator.instance.dispose(argumentsType.typeSuffixes[0]);
145 	GlobalsAllocator.instance.dispose(argumentsType.type2.typeIdentifierPart.identifierOrTemplateInstance);
146 	GlobalsAllocator.instance.dispose(argumentsType.type2.typeIdentifierPart);
147 	GlobalsAllocator.instance.dispose(argumentsType.type2);
148 	GlobalsAllocator.instance.dispose(argptrType.typeSuffixes[0]);
149 	GlobalsAllocator.instance.dispose(argptrType.type2);
150 
151 	GlobalsAllocator.instance.deallocate(argumentsType.typeSuffixes);
152 	GlobalsAllocator.instance.deallocate(argptrType.typeSuffixes);
153 
154 	GlobalsAllocator.instance.dispose(argumentsType);
155 	GlobalsAllocator.instance.dispose(argptrType);
156 }