]> gitweb.ps.run Git - toc/blob - src/typeInfo.h
generic functions and structs
[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(p, e._func.functionName, namespacePrefixes);\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     auto m = findStructMethod(p, e._method.methodName, tiCaller);\r
49     if (!m.has_value())\r
50       throw "Unknown method";\r
51     result = typeType(p, m.value().t.returnType);\r
52     break;\r
53   }\r
54   case ExprType::Lit:\r
55     result.isStruct = false;\r
56     switch (e._lit.type)\r
57     {\r
58     case LitType::Bool:    result.type.name = "bool"; break;\r
59     case LitType::Int:     result.type.name = "int"; break;\r
60     case LitType::Decimal: result.type.name = "double"; break;\r
61     case LitType::String:  result.type.name = "char"; result.type.modifiers.push_back({ TypeModifierType::Pointer, false, -1 }); break;\r
62     }\r
63     break;\r
64   case ExprType::Paren:\r
65     result = typeExpr(p, globalNamespace, globalCtx, *e._paren.expr);\r
66     break;\r
67   case ExprType::Dot:\r
68   {\r
69     auto sm = findStructMember(p,\r
70         typeExpr(p, globalNamespace, globalCtx, *e._dot.expr), e._dot.identifier);\r
71     if (!sm.has_value())\r
72       throw "Unknown struct member";\r
73     result = typeType(p, sm.value().t.type);\r
74     break;\r
75   }\r
76   case ExprType::PrefixOp:\r
77     result = typeExpr(p, globalNamespace, globalCtx, *e._prefixOp.expr);\r
78     break;\r
79   case ExprType::PostfixOp:\r
80     result = typeExpr(p, globalNamespace, globalCtx, *e._postfixOp.expr);\r
81     break;\r
82   case ExprType::BinaryOp:\r
83     result = typeExpr(p, globalNamespace, globalCtx, *e._binaryOp.lexpr);\r
84     break;\r
85   case ExprType::TernaryOp:\r
86     result = typeExpr(p, globalNamespace, globalCtx, *e._ternaryOp.rexprTrue);\r
87     break;\r
88   case ExprType::Bracket:\r
89   {\r
90     TypeInfo ti = typeExpr(p, globalNamespace, globalCtx, *e._brackets.lexpr);\r
91     if (!ti.type.modifiers.empty())\r
92     {\r
93       result = ti;\r
94       result.type.modifiers.pop_back();\r
95     }\r
96     else\r
97     {\r
98       throw "Indexing non-array";\r
99     }\r
100   }\r
101   case ExprType::Identifier:\r
102   {\r
103     auto namespacePrefixes = globalNamespace;\r
104     namespacePrefixes.insert(namespacePrefixes.end(),\r
105       e._identifier.namespacePrefixes.begin(),\r
106       e._identifier.namespacePrefixes.end());\r
107     auto v = findVariable(p, e._identifier.identifier, globalCtx);\r
108     if (!v.has_value())\r
109       throw "Unknown variable";\r
110     result = typeType(p, v.value().type);\r
111     break;\r
112   }\r
113   }\r
114 \r
115   return result;\r
116 }