1 /** 
2  * Copyright: Enalye
3  * License: Zlib
4  * Authors: Enalye
5  */
6 module grimoire.compiler.pretty;
7 
8 import std.conv : to;
9 import grimoire.compiler.type, grimoire.compiler.mangle;
10 
11 /// Convert a type into a pretty format for display.
12 string grGetPrettyType(GrType variableType) {
13     final switch (variableType.baseType) with (GrBaseType) {
14     case void_:
15         return "void";
16     case null_:
17         return "null";
18     case int_:
19         return "int";
20     case float_:
21         return "float";
22     case bool_:
23         return "bool";
24     case string_:
25         return "string";
26     case array_:
27         string result = "array(";
28         int i;
29         auto parameters = grUnmangleSignature(variableType.mangledType);
30         foreach (parameter; parameters) {
31             result ~= grGetPrettyType(parameter);
32             if ((i + 2) <= parameters.length)
33                 result ~= ", ";
34             i++;
35         }
36         result ~= ")";
37         return result;
38     case function_:
39         string result = "func(";
40         int i;
41         auto inSignature = grUnmangleSignature(variableType.mangledType);
42         foreach (type; inSignature) {
43             result ~= grGetPrettyType(type);
44             if ((i + 2) <= inSignature.length)
45                 result ~= ", ";
46             i++;
47         }
48         result ~= ")";
49         auto outSignature = grUnmangleSignature(variableType.mangledReturnType);
50         if (outSignature.length)
51             result ~= " ";
52         foreach (type; outSignature) {
53             result ~= grGetPrettyType(type);
54             if ((i + 2) <= outSignature.length)
55                 result ~= ", ";
56             i++;
57         }
58         return result;
59     case chan:
60         string result = "chan(";
61         int i;
62         auto parameters = grUnmangleSignature(variableType.mangledType);
63         foreach (parameter; parameters) {
64             result ~= grGetPrettyType(parameter);
65             if ((i + 2) <= parameters.length)
66                 result ~= ", ";
67             i++;
68         }
69         result ~= ")";
70         return result;
71     case reference:
72         string result = "ref(";
73         int i;
74         auto parameters = grUnmangleSignature(variableType.mangledType);
75         foreach (parameter; parameters) {
76             result ~= grGetPrettyType(parameter);
77             if ((i + 2) <= parameters.length)
78                 result ~= ", ";
79             i++;
80         }
81         result ~= ")";
82         return result;
83     case task:
84         string result = "task(";
85         int i;
86         auto parameters = grUnmangleSignature(variableType.mangledType);
87         foreach (parameter; parameters) {
88             result ~= grGetPrettyType(parameter);
89             if ((i + 2) <= parameters.length)
90                 result ~= ", ";
91             i++;
92         }
93         result ~= ")";
94         return result;
95     case enum_:
96         return to!string(variableType.mangledType);
97     case foreign:
98     case class_:
99         import std.algorithm.searching : findSplitBefore;
100 
101         const mangledTuple = findSplitBefore(variableType.mangledType, "$");
102         string result = mangledTuple[0];
103         GrType[] templateTypes = grUnmangleSignature(mangledTuple[1]);
104         if (templateTypes.length) {
105             result ~= "<";
106             int i;
107             foreach (templateType; templateTypes) {
108                 result ~= grGetPrettyType(templateType);
109                 if ((i + 2) <= templateTypes.length)
110                     result ~= ", ";
111                 i++;
112             }
113             result ~= ">";
114         }
115         return result;
116     case internalTuple:
117         string result = "(";
118         int i;
119         auto parameters = grUnmangleSignature(variableType.mangledType);
120         foreach (parameter; parameters) {
121             result ~= grGetPrettyType(parameter);
122             if ((i + 2) <= parameters.length)
123                 result ~= ", ";
124             i++;
125         }
126         result ~= ")";
127         return result;
128     }
129 }
130 
131 /// Displayable format for a mangled string of format: function$signature \
132 /// Return signature is not used.
133 string grGetPrettyFunctionCall(string mangledName) {
134     import std..string : indexOf;
135 
136     int index = cast(int) indexOf(mangledName, '$');
137     assert(index != 0 && mangledName.length,
138             "Invalid mangling format, named function have no name.");
139 
140     if (index < 0)
141         return to!string(mangledName) ~ "()";
142 
143     string name = mangledName[0 .. index];
144     mangledName = mangledName[index .. $];
145 
146     string result = to!string(name) ~ "(";
147     int i;
148     auto inSignature = grUnmangleSignature(mangledName);
149     foreach (type; inSignature) {
150         result ~= grGetPrettyType(type);
151         if ((i + 2) <= inSignature.length)
152             result ~= ", ";
153         i++;
154     }
155     result ~= ")";
156     return result;
157 }
158 
159 /// Displayable format for a mangled string of format: function$signature \
160 /// Return signature is not used.
161 string grGetPrettyFunctionCall(string name, GrType[] signature) {
162     string result = to!string(name) ~ "(";
163     int i;
164     foreach (type; signature) {
165         result ~= grGetPrettyType(type);
166         if ((i + 2) <= signature.length)
167             result ~= ", ";
168         i++;
169     }
170     result ~= ")";
171     return result;
172 }
173 
174 /// Prettify a function.
175 string grGetPrettyFunction(string name, GrType[] inSignature, GrType[] outSignature) {
176     string result = to!string(name) ~ "(";
177     int i;
178     foreach (type; inSignature) {
179         result ~= grGetPrettyType(type);
180         if ((i + 2) <= inSignature.length)
181             result ~= ", ";
182         i++;
183     }
184     result ~= ")";
185     if (outSignature.length)
186         result ~= "(";
187     foreach (type; outSignature) {
188         result ~= grGetPrettyType(type);
189         if ((i + 2) <= outSignature.length)
190             result ~= ", ";
191         i++;
192     }
193     if (outSignature.length)
194         result ~= ")";
195     return result;
196 }
197 
198 /// Ditto
199 string grGetPrettyFunction(GrFunction func) {
200     return grGetPrettyFunction(func.name, func.inSignature, func.outSignature);
201 }