]> gitweb.ps.run Git - toc/commitdiff
pre change
authorPatrick Schönberger <patrick.schoenberger@posteo.de>
Wed, 4 Aug 2021 12:51:36 +0000 (14:51 +0200)
committerPatrick Schönberger <patrick.schoenberger@posteo.de>
Wed, 4 Aug 2021 12:51:36 +0000 (14:51 +0200)
src/find.h [new file with mode: 0644]
src/typeInfo.h [new file with mode: 0644]

diff --git a/src/find.h b/src/find.h
new file mode 100644 (file)
index 0000000..31400ab
--- /dev/null
@@ -0,0 +1,121 @@
+#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
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