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