]> gitweb.ps.run Git - toc/blobdiff - src/typeInfo.h
pre change
[toc] / src / typeInfo.h
diff --git a/src/typeInfo.h b/src/typeInfo.h
new file mode 100644 (file)
index 0000000..3914847
--- /dev/null
@@ -0,0 +1,115 @@
+#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