]> gitweb.ps.run Git - toc/blob - src/typeInfo.h
structs and functions in ctx
[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(const Program & p, 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   return result;\r
25 }\r
26 \r
27 TypeInfo typeExpr(const Program & p, const std::vector<std::string> & globalNamespace, std::shared_ptr<Context> globalCtx, Expr e)\r
28 {\r
29   TypeInfo result;\r
30 \r
31   switch (e.type)\r
32   {\r
33   case ExprType::Func:\r
34   {\r
35     auto namespacePrefixes = globalNamespace;\r
36     namespacePrefixes.insert(namespacePrefixes.end(),\r
37       e._func.namespacePrefixes.begin(),\r
38       e._func.namespacePrefixes.end());\r
39     auto f = findFunction(e._func.functionName, e._func.namespacePrefixes, globalCtx);\r
40     if (!f.has_value())\r
41       throw "Unknown function";\r
42     result = typeType(p, f.value().returnType);\r
43     break;\r
44   }\r
45   case ExprType::Method:\r
46   {\r
47     TypeInfo tiCaller = typeExpr(p, globalNamespace, 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, s.value());\r
54     if (!m.has_value())\r
55       throw "Unknown method";\r
56     result = typeType(p, m.value().t.returnType);\r
57     break;\r
58   }\r
59   case ExprType::Lit:\r
60     result.isStruct = false;\r
61     switch (e._lit.type)\r
62     {\r
63     case LitType::Bool:    result.type.name = "bool"; break;\r
64     case LitType::Int:     result.type.name = "int"; break;\r
65     case LitType::Decimal: result.type.name = "double"; break;\r
66     case LitType::String:  result.type.name = "char"; result.type.modifiers.push_back({ TypeModifierType::Pointer, false, -1 }); break;\r
67     }\r
68     break;\r
69   case ExprType::Paren:\r
70     result = typeExpr(p, globalNamespace, globalCtx, *e._paren.expr);\r
71     break;\r
72   case ExprType::Dot:\r
73   {\r
74     auto tiCaller = typeExpr(p, globalNamespace, globalCtx, *e._dot.expr);\r
75     if (!tiCaller.isStruct)\r
76       throw "Accessing member of non-struct";\r
77     auto s = findStruct(tiCaller.type.name, tiCaller.type.namespacePrefixes, globalCtx);\r
78     if (!s.has_value())\r
79       throw "Calling method on unknown struct";\r
80     auto sm = findStructMember(e._dot.identifier, s.value());\r
81     if (!sm.has_value())\r
82       throw "Unknown struct member";\r
83     result = typeType(p, sm.value().t.type);\r
84     break;\r
85   }\r
86   case ExprType::PrefixOp:\r
87     result = typeExpr(p, globalNamespace, globalCtx, *e._prefixOp.expr);\r
88     break;\r
89   case ExprType::PostfixOp:\r
90     result = typeExpr(p, globalNamespace, globalCtx, *e._postfixOp.expr);\r
91     break;\r
92   case ExprType::BinaryOp:\r
93     result = typeExpr(p, globalNamespace, globalCtx, *e._binaryOp.lexpr);\r
94     break;\r
95   case ExprType::TernaryOp:\r
96     result = typeExpr(p, globalNamespace, globalCtx, *e._ternaryOp.rexprTrue);\r
97     break;\r
98   case ExprType::Bracket:\r
99   {\r
100     TypeInfo ti = typeExpr(p, globalNamespace, globalCtx, *e._brackets.lexpr);\r
101     if (!ti.type.modifiers.empty())\r
102     {\r
103       result = ti;\r
104       result.type.modifiers.pop_back();\r
105     }\r
106     else\r
107     {\r
108       throw "Indexing non-array";\r
109     }\r
110   }\r
111   case ExprType::Identifier:\r
112   {\r
113     auto namespacePrefixes = globalNamespace;\r
114     namespacePrefixes.insert(namespacePrefixes.end(),\r
115       e._identifier.namespacePrefixes.begin(),\r
116       e._identifier.namespacePrefixes.end());\r
117     auto v = findVariable(e._identifier.identifier, namespacePrefixes, globalCtx);\r
118     if (!v.has_value())\r
119       throw "Unknown variable";\r
120     result = typeType(p, v.value().type);\r
121     break;\r
122   }\r
123   }\r
124 \r
125   return result;\r
126 }