1 /** 
2  * Copyright: Enalye
3  * License: Zlib
4  * Authors: Enalye
5  */
6 module grimoire.compiler.type;
7 
8 import std.conv : to;
9 
10 import grimoire.runtime;
11 import grimoire.assembly;
12 import grimoire.compiler.mangle;
13 import grimoire.compiler.data;
14 
15 /**
16 Type category.
17 
18 Complex types use mangledType and mangledReturnType
19 to represent them.
20 */
21 enum GrBaseType {
22     void_,
23     null_,
24     int_,
25     float_,
26     bool_,
27     string_,
28     array_,
29     function_,
30     task,
31     class_,
32     foreign,
33     chan,
34     enum_,
35     internalTuple,
36     reference
37 }
38 
39 /**
40 Compiler type definition for Grimoire's type system.
41 It doesn't mean anything for the VM.
42 */
43 struct GrType {
44     /// General type, basic types only use that while compound types also use mangledType
45     /// and mangledReturnType.
46     GrBaseType baseType;
47     /// Used for compound types like arrays, functions, etc.
48     string mangledType, mangledReturnType;
49     /// Is this from an object field ?
50     bool isField;
51     /// Can this type match with others ?
52     bool isAny;
53     /// Is the type abstract ?
54     /// An abstract type cannot be used in signatures.
55     bool isAbstract;
56     /// Predicate to validate any type
57     bool function(GrType, GrAnyData) predicate;
58 
59     /// Init as a basic type.
60     this(GrBaseType baseType_) {
61         baseType = baseType_;
62     }
63 
64     /// Compound type.
65     this(GrBaseType baseType_, string mangledType_) {
66         baseType = baseType_;
67         mangledType = mangledType_;
68     }
69 
70     /// Only assign a simple type (baseType).
71     GrType opOpAssign(string op)(GrBaseType t) {
72         mixin("baseType = baseType" ~ op ~ "t;");
73         return this;
74     }
75 
76     /// Check general type equality.
77     bool opEquals(const GrBaseType v) const {
78         return (baseType == v);
79     }
80 
81     /// Check full type equality.
82     bool opEquals(const GrType v) const {
83         if (baseType != v.baseType)
84             return false;
85         if (baseType == GrBaseType.function_ || baseType == GrBaseType.task)
86             return mangledType == v.mangledType && mangledReturnType == v.mangledReturnType;
87         if (baseType == GrBaseType.foreign || baseType == GrBaseType.class_
88                 || baseType == GrBaseType.enum_ || baseType == GrBaseType.array_)
89             return mangledType == v.mangledType;
90         return true;
91     }
92 
93     /// Only to disable warnings because of opEquals.
94     size_t toHash() const @safe pure nothrow {
95         return 0;
96     }
97 }
98 
99 /// No type
100 const GrType grVoid = GrType(GrBaseType.void_);
101 /// Integer
102 const GrType grInt = GrType(GrBaseType.int_);
103 /// Float
104 const GrType grFloat = GrType(GrBaseType.float_);
105 /// Bool
106 const GrType grBool = GrType(GrBaseType.bool_);
107 /// String
108 const GrType grString = GrType(GrBaseType.string_);
109 /// Int array
110 const GrType grIntArray = GrType(GrBaseType.array_, grMangleSignature([grInt]));
111 /// Float array
112 const GrType grFloatArray = GrType(GrBaseType.array_, grMangleSignature([
113             grFloat
114         ]));
115 /// Bool array
116 const GrType grBoolArray = GrType(GrBaseType.array_, grMangleSignature([grBool]));
117 /// String array
118 const GrType grStringArray = GrType(GrBaseType.array_, grMangleSignature([
119             grString
120         ]));
121 /// Int channel
122 const GrType grIntChannel = GrType(GrBaseType.chan, grMangleSignature([grInt]));
123 /// Float channel
124 const GrType grFloatChannel = GrType(GrBaseType.chan, grMangleSignature([
125             grFloat
126         ]));
127 /// Bool channel
128 const GrType grBoolChannel = GrType(GrBaseType.chan, grMangleSignature([grBool]));
129 /// String channel
130 const GrType grStringChannel = GrType(GrBaseType.chan, grMangleSignature([
131             grString
132         ]));
133 
134 /// Returns an array GrType of `subType` subtype.
135 GrType grArray(GrType subType) {
136     return GrType(GrBaseType.array_, grMangleSignature([subType]));
137 }
138 
139 /// Returns a channel GrType of `subType` subtype.
140 GrType grChannel(GrType subType) {
141     return GrType(GrBaseType.chan, grMangleSignature([subType]));
142 }
143 
144 /// Special type the matches another type with a predicate.
145 GrType grAny(string name, bool function(GrType, GrAnyData) predicate = (a, b) => true) {
146     GrType type;
147     type.baseType = GrBaseType.void_;
148     type.mangledType = name;
149     type.isAny = true;
150     type.predicate = predicate;
151     return type;
152 }
153 
154 /// The type is handled by a int based register
155 bool grIsKindOfInt(GrBaseType type) {
156     return type == GrBaseType.int_ || type == GrBaseType.bool_
157         || type == GrBaseType.function_ || type == GrBaseType.task || type == GrBaseType.enum_;
158 }
159 
160 /// The type is handled by a float based register
161 bool grIsKindOfFloat(GrBaseType type) {
162     return type == GrBaseType.float_;
163 }
164 
165 /// The type is handled by a string based register
166 bool grIsKindOfString(GrBaseType type) {
167     return type == GrBaseType.string_;
168 }
169 
170 /// The type is handled by a ptr based register
171 bool grIsKindOfObject(GrBaseType type) {
172     return type == GrBaseType.class_ || type == GrBaseType.array_ || type == GrBaseType.foreign
173         || type == GrBaseType.chan || type == GrBaseType.reference || type == GrBaseType.null_;
174 }
175 
176 /// Context for any validation
177 final class GrAnyData {
178     private {
179         GrType[string] _types;
180     }
181 
182     /// Clear any stored type definition
183     void clear() {
184         _types.clear;
185     }
186 
187     /// Define a new type
188     void set(string key, GrType type) {
189         _types[key] = type;
190     }
191 
192     /// Fetch an already defined type
193     GrType get(string key) {
194         return _types.get(key, grVoid);
195     }
196 }
197 
198 /// Pack multiple types as a single one.
199 package GrType grPackTuple(GrType[] types) {
200     const string mangledName = grMangleSignature(types);
201     GrType type = GrBaseType.internalTuple;
202     type.mangledType = mangledName;
203     return type;
204 }
205 
206 /// Unpack multiple types from a single one.
207 package GrType[] grUnpackTuple(GrType type) {
208     if (type.baseType != GrBaseType.internalTuple)
209         throw new Exception("Cannot unpack a not tuple type.");
210     return grUnmangleSignature(type.mangledType);
211 }
212 
213 /**
214 A local or global variable.
215 */
216 package class GrVariable {
217     /// Its type.
218     GrType type;
219     /// Register position, separate for each type (int, float, string and objects);
220     uint register = uint.max;
221     /// Declared from the global scope ?
222     bool isGlobal;
223     /// Declared from an object definition ?
224     bool isField;
225     /// Does it have a value yet ?
226     bool isInitialized;
227     /// Is the type to be infered automatically ? (e.g. the `let` keyword).
228     bool isAuto;
229     /// Can we modify its value ?
230     bool isConstant;
231     /// Its unique name inside its scope (function based scope).
232     string name;
233     /// Is the variable visible from other files ? (Global only)
234     bool isPublic;
235     /// The file where the variable is declared.
236     uint fileId;
237     /// Position information in case of errors.
238     uint lexPosition;
239 }
240 
241 /// Define an arbitrary D pointer.
242 final class GrForeignDefinition {
243     /// Identifier.
244     string name;
245     /// Mother class it inherit from.
246     string parent;
247 }
248 
249 /// Ditto
250 final class GrAbstractForeignDefinition {
251     /// Identifier.
252     string name;
253     /// Mother class it inherits from.
254     string parent;
255     /// Template values
256     string[] templateVariables;
257     /// Template signature
258     GrType[] parentTemplateSignature;
259 }
260 
261 /// Create a foreign GrType for the type system.
262 GrType grGetForeignType(string name, GrType[] signature = []) {
263     GrType type = GrBaseType.foreign;
264     type.mangledType = grMangleComposite(name, signature);
265     return type;
266 }
267 
268 /**
269 Define the content of a type alias. \
270 Not to be confused with GrType used by the type system.
271 ---
272 type MyNewType = AnotherType;
273 ---
274 */
275 final class GrTypeAliasDefinition {
276     /// Identifier.
277     string name;
278     /// The type aliased.
279     GrType type;
280     /// Is the type visible from other files ?
281     bool isPublic;
282     /// The file where the type is declared.
283     uint fileId;
284 }
285 
286 /**
287 Define the content of an enum. \
288 Not to be confused with GrType used by the type system.
289 ---
290 enum MyEnum {
291     field1;
292     field2;
293 }
294 ---
295 */
296 final class GrEnumDefinition {
297     /// Identifier.
298     string name;
299     /// List of field names.
300     string[] fields;
301     /// Unique ID of the enum definition.
302     size_t index;
303     /// Is the type visible from other files ?
304     bool isPublic;
305     /// The file where the type is declared.
306     uint fileId;
307 
308     /// Does the field name exists ?
309     bool hasField(string name) const {
310         foreach (field; fields) {
311             if (field == name)
312                 return true;
313         }
314         return false;
315     }
316 
317     /// Returns the value of the field
318     int getField(string name) const {
319         import std.conv : to;
320 
321         int fieldIndex = 0;
322         foreach (field; fields) {
323             if (field == name)
324                 return fieldIndex;
325             fieldIndex++;
326         }
327         assert(false, "Undefined enum \'" ~ name ~ "\'");
328     }
329 }
330 
331 /// Create a GrType of enum for the type system.
332 GrType grGetEnumType(string name) {
333     GrType stType = GrBaseType.enum_;
334     stType.mangledType = name;
335     return stType;
336 }
337 
338 /**
339 Define the content of a class. \
340 Not to be confused with GrType used by the type system.
341 ---
342 class MyClass {
343     // Fields
344 }
345 ---
346 */
347 final class GrClassDefinition {
348     /// Identifier.
349     string name;
350     /// Mother class it inherit from.
351     string parent;
352     /// List of field types.
353     GrType[] signature;
354     /// List of field names.
355     string[] fields;
356     /// List of template variables.
357     string[] templateVariables;
358     /// List of template types.
359     GrType[] templateTypes, parentTemplateSignature;
360 
361     package {
362         struct FieldInfo {
363             bool isPublic;
364             uint fileId;
365             uint position;
366         }
367 
368         FieldInfo[] fieldsInfo;
369 
370         /// The lexeme that declared it.
371         uint position;
372     }
373     /// Unique ID of the object definition.
374     size_t index;
375     /// Is the type visible from other files ?
376     bool isPublic;
377     /// The file where the type is declared.
378     uint fileId;
379     /// Is the declaration of the class already parsed ?
380     bool isParsed;
381 }
382 
383 /// Create a GrType of class for the type system.
384 GrType grGetClassType(string name, GrType[] signature = []) {
385     GrType stType = GrBaseType.class_;
386     stType.mangledType = grMangleComposite(name, signature);
387     return stType;
388 }
389 
390 /// Define a variable defined from a library
391 final class GrVariableDefinition {
392     /// Identifier.
393     string name;
394     /// Its type
395     GrType type;
396     /// Does the variable use a custom initialization value ?
397     bool isInitialized;
398     /// Integral init value
399     GrInt ivalue;
400     /// Floating init value
401     GrFloat fvalue;
402     /// String init value
403     GrString svalue;
404     /// Can the variable be mutated in script ?
405     bool isConstant;
406     /// Register.
407     uint register;
408 }
409 
410 /// A single instruction used by the VM.
411 struct GrInstruction {
412     /// What needs to be done.
413     GrOpcode opcode;
414     /// Payload, may not be used.
415     uint value;
416 }
417 
418 /**
419 Function/Task/Event definition.
420 */
421 package class GrFunction {
422     /// Local scoping
423     struct Scope {
424         /// Every variable declared within its scope.
425         GrVariable[string] localVariables;
426     }
427     /// Ditto
428     Scope[] scopes;
429 
430     uint[] iregisterAvailables, fregisterAvailables, sregisterAvailables, oregisterAvailables;
431 
432     /// All the function instructions.
433     GrInstruction[] instructions;
434     uint stackSize, index, offset;
435 
436     /// Unmangled function name.
437     string name;
438     /// Mangled function name.
439     string mangledName;
440     /// Function input parameters' name.
441     string[] inputVariables, templateVariables;
442     /// Function parameters' type.
443     GrType[] inSignature, outSignature, templateSignature;
444     bool isTask, isAnonymous, isEvent, isMain;
445 
446     /// Function calls made from within its scope.
447     GrFunctionCall[] functionCalls;
448     GrFunction anonParent;
449     uint position, anonReference;
450 
451     uint nbIntegerParameters, nbFloatParameters, nbStringParameters, nbObjectParameters;
452     uint ilocalsCount, flocalsCount, slocalsCount, olocalsCount;
453 
454     GrDeferrableSection[] deferrableSections;
455     GrDeferBlock[] registeredDeferBlocks;
456     bool[] isDeferrableSectionLocked = [false];
457 
458     /// Is the function visible from other files ?
459     bool isPublic;
460     /// The file where the function is declared.
461     uint fileId;
462 
463     uint lexPosition;
464 
465     struct DebugPositionSymbol {
466         uint line, column;
467     }
468 
469     DebugPositionSymbol[] debugSymbol;
470 
471     this() {
472         scopes.length = 1;
473     }
474 
475     GrVariable getLocal(string name) {
476         foreach_reverse (ref Scope scope_; scopes) {
477             //Check if declared locally.
478             GrVariable* variable = (name in scope_.localVariables);
479             if (variable !is null)
480                 return *variable;
481         }
482         return null;
483     }
484 
485     void setLocal(GrVariable variable_) {
486         GrVariable* oldVariable = (variable_.name in scopes[$ - 1].localVariables);
487         if (oldVariable !is null) {
488             freeRegister(*oldVariable);
489         }
490         scopes[$ - 1].localVariables[variable_.name] = variable_;
491     }
492 
493     void openScope() {
494         scopes.length++;
495     }
496 
497     void closeScope() {
498         foreach (GrVariable variable; scopes[$ - 1].localVariables) {
499             freeRegister(variable);
500         }
501         scopes.length--;
502     }
503 
504     private void freeRegister(GrVariable variable) {
505         final switch (variable.type.baseType) with (GrBaseType) {
506         case int_:
507         case bool_:
508         case function_:
509         case task:
510         case enum_:
511             iregisterAvailables ~= variable.register;
512             break;
513         case float_:
514             fregisterAvailables ~= variable.register;
515             break;
516         case string_:
517             sregisterAvailables ~= variable.register;
518             break;
519         case array_:
520         case class_:
521         case foreign:
522         case chan:
523             oregisterAvailables ~= variable.register;
524             break;
525         case internalTuple:
526         case reference:
527         case null_:
528         case void_:
529             break;
530         }
531     }
532 }
533 
534 /// Get the type of the function.
535 GrType grGetFunctionAsType(GrFunction func) {
536     GrType type = func.isTask ? GrBaseType.task : GrBaseType.function_;
537     type.mangledType = grMangleSignature(func.inSignature);
538     type.mangledReturnType = grMangleSignature(func.outSignature);
539     return type;
540 }
541 
542 package class GrTemplateFunction {
543     /// Unmangled function name.
544     string name;
545     /// Function input parameters' name.
546     string[] inputVariables;
547     /// Function parameters' type.
548     GrType[] inSignature, outSignature;
549     bool isTask;
550     bool isConversion;
551     /// Is the function visible from other files ?
552     bool isPublic;
553     /// The file where the template is declared.
554     uint fileId;
555 
556     string[] templateVariables;
557 
558     uint lexPosition;
559 }
560 
561 package class GrFunctionCall {
562     string name;
563     GrType[] signature;
564     uint position;
565     GrFunction caller, functionToCall;
566     GrType expectedType;
567     bool isAddress;
568     uint fileId;
569 }
570 
571 package class GrDeferrableSection {
572     GrDeferBlock[] deferredBlocks;
573     uint deferInitPositions;
574     uint[] deferredCalls;
575 }
576 
577 package class GrDeferBlock {
578     uint position;
579     uint parsePosition;
580     uint scopeLevel;
581 }