--- /dev/null
+#pragma once\r
+\r
+#include "repr.h"\r
+\r
+struct TypeInfo\r
+{\r
+ Type type;\r
+ bool isStruct;\r
+};\r
+\r
+#include "find.h"\r
+\r
+TypeInfo typeType(const Program & p, Type t)\r
+{\r
+ TypeInfo result;\r
+ result.isStruct = true;\r
+ if (t.name == "int" || t.name == "float" || t.name == "double" ||\r
+ t.name == "char" || t.name == "long" || t.name == "short" || t.name == "bool")\r
+ {\r
+ result.isStruct = false;\r
+ }\r
+ result.type = t;\r
+ return result;\r
+}\r
+\r
+TypeInfo typeExpr(const Program & p, const std::vector<string> & globalNamespace, Expr e)\r
+{\r
+ TypeInfo result;\r
+\r
+ switch (e.type)\r
+ {\r
+ case ExprType::Func:\r
+ {\r
+ auto namespacePrefixes = globalNamespace;\r
+ namespacePrefixes.insert(namespacePrefixes.end(),\r
+ e._func.namespacePrefixes.begin(),\r
+ e._func.namespacePrefixes.end());\r
+ auto f = findFunction(p, e._func.functionName, namespacePrefixes);\r
+ if (!f.has_value())\r
+ throw "Unknown function";\r
+ result = typeType(p, f.value().returnType);\r
+ break;\r
+ }\r
+ case ExprType::Method:\r
+ {\r
+ TypeInfo tiCaller = typeExpr(p, globalNamespace, *e._method.expr);\r
+ auto m = findStructMethod(p, e._method.methodName, tiCaller);\r
+ if (!m.has_value())\r
+ throw "Unknown method";\r
+ result = typeType(p, m.value().returnType);\r
+ break;\r
+ }\r
+ case ExprType::Lit:\r
+ result.isStruct = false;\r
+ switch (e._lit.type)\r
+ {\r
+ case LitType::Bool: result.type.name = "bool"; break;\r
+ case LitType::Int: result.type.name = "int"; break;\r
+ case LitType::Decimal: result.type.name = "double"; break;\r
+ case LitType::String: result.type.name = "char"; result.type.modifiers.push_back({ TypeModifierType::Pointer, false, -1 }); break;\r
+ }\r
+ break;\r
+ case ExprType::Paren:\r
+ result = typeExpr(p, globalNamespace, *e._paren.expr);\r
+ break;\r
+ case ExprType::Dot:\r
+ {\r
+ auto sm = findStructMember(p,\r
+ typeExpr(p, globalNamespace, *e._dot.expr), e._dot.identifier);\r
+ if (!sm.has_value())\r
+ throw "Unknown struct member";\r
+ result = typeType(p, sm.value().type);\r
+ break;\r
+ }\r
+ case ExprType::PrefixOp:\r
+ result = typeExpr(p, globalNamespace, *e._prefixOp.expr);\r
+ break;\r
+ case ExprType::PostfixOp:\r
+ result = typeExpr(p, globalNamespace, *e._postfixOp.expr);\r
+ break;\r
+ case ExprType::BinaryOp:\r
+ result = typeExpr(p, globalNamespace, *e._binaryOp.lexpr);\r
+ break;\r
+ case ExprType::TernaryOp:\r
+ result = typeExpr(p, globalNamespace, *e._ternaryOp.rexprTrue);\r
+ break;\r
+ case ExprType::Bracket:\r
+ {\r
+ TypeInfo ti = typeExpr(p, globalNamespace, *e._brackets.lexpr);\r
+ if (!ti.type.modifiers.empty())\r
+ {\r
+ result = ti;\r
+ result.type.modifiers.pop_back();\r
+ }\r
+ else\r
+ {\r
+ throw "Indexing non-array";\r
+ }\r
+ }\r
+ case ExprType::Identifier:\r
+ {\r
+ auto namespacePrefixes = globalNamespace;\r
+ namespacePrefixes.insert(namespacePrefixes.end(),\r
+ e._identifier.namespacePrefixes.begin(),\r
+ e._identifier.namespacePrefixes.end());\r
+ auto v = findVariable(p, e._identifier.identifier, namespacePrefixes);\r
+ if (!v.has_value())\r
+ throw "Unknown variable";\r
+ result = typeType(p, v.value().type);\r
+ break;\r
+ }\r
+ }\r
+\r
+ return result;\r
+}
\ No newline at end of file