]> gitweb.ps.run Git - toc/blob - src/typeInfo.h
fixed NAME grammar rule
[toc] / src / typeInfo.h
1 #pragma once\r
2 \r
3 #include "repr.h"\r
4 \r
5 struct TypeInfo\r
6 {\r
7   Type type;\r
8   bool isStruct;\r
9 };\r
10 \r
11 #include "find.h"\r
12 \r
13 TypeInfo typeType(std::shared_ptr<Context> globalCtx, Type t)\r
14 {\r
15   TypeInfo result;\r
16   result.isStruct = true;\r
17   if (t.name == "int" || t.name == "float" || t.name == "double" ||\r
18       t.name == "char" || t.name == "long" || t.name == "short" || t.name == "bool" ||\r
19       t.name == "void")\r
20   {\r
21     result.isStruct = false;\r
22   }\r
23   result.type = t;\r
24 \r
25   return result;\r
26 }\r
27 \r
28 TypeInfo typeExpr(std::shared_ptr<Context> globalCtx, Expr e)\r
29 {\r
30   TypeInfo result;\r
31 \r
32   switch (e.type)\r
33   {\r
34   case ExprType::Func:\r
35   {\r
36     auto f = findFunction(e._func.functionName, e._func.namespacePrefixes, globalCtx);\r
37     if (!f.has_value())\r
38       throw "Unknown function";\r
39     result = typeType(globalCtx, std::get<0>(*f).returnType);\r
40     break;\r
41   }\r
42   case ExprType::Method:\r
43   {\r
44     TypeInfo tiCaller = typeExpr(globalCtx, *e._method.expr);\r
45     if (!tiCaller.isStruct)\r
46       throw "Calling method on non-struct";\r
47     auto s = findStruct(tiCaller.type.name, tiCaller.type.namespacePrefixes, globalCtx);\r
48     if (!s.has_value())\r
49       throw "Calling method on unknown struct";\r
50     auto m = findStructMethod(e._method.methodName, std::get<0>(*s));\r
51     if (!m.has_value())\r
52       throw "Unknown method";\r
53     result = typeType(globalCtx, m->t.returnType);\r
54     break;\r
55   }\r
56   case ExprType::Lit:\r
57     result.isStruct = false;\r
58     switch (e._lit.type)\r
59     {\r
60     case LitType::Bool:    result.type.name = "bool"; break;\r
61     case LitType::Int:     result.type.name = "int"; break;\r
62     case LitType::Decimal: result.type.name = "double"; break;\r
63     case LitType::String:  result.type.name = "char"; result.type.modifiers.push_back({ TypeModifierType::Pointer, false, -1 }); break;\r
64     }\r
65     break;\r
66   case ExprType::Paren:\r
67     result = typeExpr(globalCtx, *e._paren.expr);\r
68     break;\r
69   case ExprType::Dot:\r
70   {\r
71     auto tiCaller = typeExpr(globalCtx, *e._dot.expr);\r
72     if (!tiCaller.isStruct)\r
73       throw "Accessing member of non-struct";\r
74     auto s = findStruct(tiCaller.type.name, tiCaller.type.namespacePrefixes, globalCtx);\r
75     if (!s.has_value())\r
76       throw "Calling method on unknown struct";\r
77     auto sm = findStructMember(e._dot.identifier, std::get<0>(*s));\r
78     if (!sm.has_value())\r
79       throw "Unknown struct member";\r
80     result = typeType(globalCtx, sm->t.type);\r
81     break;\r
82   }\r
83   case ExprType::PrefixOp:\r
84     result = typeExpr(globalCtx, *e._prefixOp.expr);\r
85     break;\r
86   case ExprType::PostfixOp:\r
87     result = typeExpr(globalCtx, *e._postfixOp.expr);\r
88     break;\r
89   case ExprType::BinaryOp:\r
90     result = typeExpr(globalCtx, *e._binaryOp.lexpr);\r
91     break;\r
92   case ExprType::TernaryOp:\r
93     result = typeExpr(globalCtx, *e._ternaryOp.rexprTrue);\r
94     break;\r
95   case ExprType::Bracket:\r
96   {\r
97     TypeInfo ti = typeExpr(globalCtx, *e._brackets.lexpr);\r
98     if (!ti.type.modifiers.empty())\r
99     {\r
100       result = ti;\r
101       result.type.modifiers.pop_back();\r
102     }\r
103     else\r
104     {\r
105       throw "Indexing non-array";\r
106     }\r
107   }\r
108   case ExprType::Identifier:\r
109   {\r
110     auto v = findVariable(e._identifier.identifier, e._identifier.namespacePrefixes, globalCtx);\r
111     if (!v.has_value())\r
112       throw "Unknown variable";\r
113     result = typeType(globalCtx, std::get<0>(*v).type);\r
114     break;\r
115   }\r
116   }\r
117 \r
118   return result;\r
119 }