--- /dev/null
+#pragma once\r
+\r
+#include "repr.h"\r
+#include "typeInfo.h"\r
+\r
+#include <functional>\r
+#include <optional>\r
+\r
+template<typename T>\r
+using opt = std::optional<T>;\r
+\r
+template<typename T>\r
+opt<T> find(const std::vector<T> & ts, std::function<bool(T)> f)\r
+{\r
+ for (auto t : ts)\r
+ if (f(t))\r
+ return t;\r
+ return nullopt;\r
+}\r
+\r
+opt<Function> findFunction(\r
+ const Program & p,\r
+ const std::string & name,\r
+ const std::vector<std::string> & namespacePrefixes)\r
+{\r
+ if (namespacePrefixes.empty())\r
+ {\r
+ return find<Function>(p.functions, [&](Function f) { return f.name == name; });\r
+ }\r
+ \r
+ auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });\r
+\r
+ if (!n.has_value())\r
+ return nullopt;\r
+\r
+ for (int i = 1; i < namespacePrefixes.size(); i++)\r
+ {\r
+ n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });\r
+ \r
+ if (!n.has_value())\r
+ return nullopt;\r
+ }\r
+\r
+ return find<Function>(n.value().functions, [&](Function f) { return f.name == name; });\r
+}\r
+\r
+opt<Struct> findStruct(\r
+ const Program & p,\r
+ const std::string & name,\r
+ const std::vector<std::string> & namespacePrefixes)\r
+{\r
+ if (namespacePrefixes.empty())\r
+ {\r
+ return find<Struct>(p.structs, [&](Struct s) { return s.name == name; });\r
+ }\r
+ \r
+ auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });\r
+ \r
+ if (!n.has_value())\r
+ return nullopt;\r
+ \r
+ for (int i = 1; i < namespacePrefixes.size(); i++)\r
+ {\r
+ n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });\r
+\r
+ if (!n.has_value())\r
+ return nullopt;\r
+ }\r
+ return find<Struct>(n.value().structs, [&](Struct s) { return s.name == name; });\r
+}\r
+\r
+opt<Variable> findVariable(\r
+ const Program & p,\r
+ const std::string & name,\r
+ const std::vector<std::string> & namespacePrefixes)\r
+{\r
+ for (auto n : namespacePrefixes)\r
+ std::cout << n << std::endl;\r
+ if (namespacePrefixes.empty())\r
+ {\r
+ return find<Variable>(p.variables, [&](Variable v) { return v.name == name; });\r
+ }\r
+ \r
+ auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });\r
+ \r
+ if (!n.has_value())\r
+ return nullopt;\r
+ \r
+ for (int i = 1; i < namespacePrefixes.size(); i++)\r
+ {\r
+ n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });\r
+ \r
+ if (!n.has_value())\r
+ return nullopt;\r
+ }\r
+ return find<Variable>(n.value().variables, [&](Variable v) { return v.name == name; });\r
+}\r
+\r
+opt<Function> findStructMethod(\r
+ const Program & p,\r
+ const std::string & name,\r
+ TypeInfo ti)\r
+{\r
+ if (!ti.isStruct)\r
+ return nullopt;\r
+ auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);\r
+ if (!s.has_value())\r
+ return nullopt;\r
+ return find<StructMember<Function>>(s.value().methods, [&](Function f) { return f.name == name; });\r
+}\r
+\r
+opt<Variable> findStructMember(\r
+ const Program & p,\r
+ TypeInfo ti,\r
+ const std::string & name)\r
+{\r
+ auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);\r
+ if (!s.has_value())\r
+ return nullopt;\r
+ return find<StructMember<Variable>>(s.value().members, [&](Variable v) { return v.name == name; });\r
+}
\ No newline at end of file
--- /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