1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity low)
4 module dil.ast.Meta;
5 
6 import dil.String;
7 import common;
8 
9 /// Generates code declaring variables with the correct type and value,
10 /// which are then passed on to ctor().
11 ///
12 /// E.g.: makeNewClass("Expression", "Token*")
13 /// ---
14 /// assert(argtypes.length == args.length);
15 /// assert(argtypes.length == 2);
16 /// assert(argtypes[0] == typeid(Expression));
17 /// auto _0 = *cast(Expression*)args[0];
18 /// assert(argtypes[1] == typeid(Token*));
19 /// auto _1 = *cast(Token**)args[1];
20 /// auto node = ctor(_0,_1,);
21 /// ---
22 char[] makeNewClass(cstring[] argtypes)
23 {
24   char[] args = "assert(argtypes.length == args.length);\n" ~
25     "assert(argtypes.length == " ~ itoa(argtypes.length) ~ ");\n";
26   char[] ctorArgs;
27   foreach (i, t; argtypes)
28   {
29     auto istr = itoa(i);
30     args ~=
31       "assert(argtypes[" ~ istr ~ "] == typeid(" ~ t ~ "));\n" ~
32       "auto _" ~ istr ~ " = *cast(" ~ t ~ "*)args[" ~ istr ~ "];\n";
33     ctorArgs ~= "_" ~ istr ~ ",";
34   }
35   return args ~ "auto node = ctor(" ~ ctorArgs ~ ");";
36 }
37 
38 //pragma(msg, makeNewClass(["A","B","C"]));
39 
40 /// Provides functions for constructing a class from run-time arguments.
41 mixin template createMethod()
42 {
43   alias Class = typeof(this);
44 
45   static Class ctor(Class.CTTI_Types args)
46   {
47     return new Class(args);
48   }
49 
50   static Class create(TypeInfo[] argtypes, void*[] args)
51   {
52     mixin(makeNewClass(Class.CTTI_TypeStrs));
53     return node;
54   }
55 }
56 
57 /// Provides a collection of methods.
58 mixin template methods()
59 {
60   mixin copyMethod;
61   mixin createMethod;
62 }
63 
64 /// Generates information on Node members, which is used to generate code
65 /// for copying or visiting methods.
66 ///
67 /// E.g.:
68 /// ---
69 /// static enum CTTI_Members = ["una","args",];
70 /// static enum CTTI_MayBeNull = [false,true,];
71 /// static alias CTTI_Types = Tuple!(typeof(una),typeof(args),);
72 /// static enum CTTI_TypeStrs = [typeof(una).stringof,typeof(args).stringof,];
73 /// ---
74 char[] memberInfo(string[] members...)
75 {
76   char[] names, mayBeNull, types, typeStrs;
77   foreach (m; members)
78   {
79     auto isOpt = m[$-1] == '?';
80     m = isOpt ? m[0..$-1] : m; // Strip '?'.
81     names ~= '"' ~ m ~ `",`;
82     mayBeNull ~= (isOpt ? "true" : "false") ~ ",";
83     types ~= "typeof(" ~ m ~ "),";
84     typeStrs ~= "typeof(" ~ m ~ ").stringof,";
85   }
86   return "static enum CTTI_Members = [" ~ names ~ "];\n" ~
87          "static enum CTTI_MayBeNull = [" ~ mayBeNull ~ "];\n" ~
88          "static alias CTTI_Types = Tuple!(" ~ types ~ ");\n" ~
89          "static enum CTTI_TypeStrs = [" ~ typeStrs ~ "];\n";
90 }
91 
92 //pragma(msg, memberInfo("una", "args?"));