abouttreesummaryrefslogcommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/find.h121
-rw-r--r--src/typeInfo.h115
2 files changed, 236 insertions, 0 deletions
diff --git a/src/find.h b/src/find.h
new file mode 100644
index 0000000..31400ab
--- /dev/null
+++ b/src/find.h
@@ -0,0 +1,121 @@
+#pragma once
+
+#include "repr.h"
+#include "typeInfo.h"
+
+#include <functional>
+#include <optional>
+
+template<typename T>
+using opt = std::optional<T>;
+
+template<typename T>
+opt<T> find(const std::vector<T> & ts, std::function<bool(T)> f)
+{
+ for (auto t : ts)
+ if (f(t))
+ return t;
+ return nullopt;
+}
+
+opt<Function> findFunction(
+ const Program & p,
+ const std::string & name,
+ const std::vector<std::string> & namespacePrefixes)
+{
+ if (namespacePrefixes.empty())
+ {
+ return find<Function>(p.functions, [&](Function f) { return f.name == name; });
+ }
+
+ auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });
+
+ if (!n.has_value())
+ return nullopt;
+
+ for (int i = 1; i < namespacePrefixes.size(); i++)
+ {
+ n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });
+
+ if (!n.has_value())
+ return nullopt;
+ }
+
+ return find<Function>(n.value().functions, [&](Function f) { return f.name == name; });
+}
+
+opt<Struct> findStruct(
+ const Program & p,
+ const std::string & name,
+ const std::vector<std::string> & namespacePrefixes)
+{
+ if (namespacePrefixes.empty())
+ {
+ return find<Struct>(p.structs, [&](Struct s) { return s.name == name; });
+ }
+
+ auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });
+
+ if (!n.has_value())
+ return nullopt;
+
+ for (int i = 1; i < namespacePrefixes.size(); i++)
+ {
+ n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });
+
+ if (!n.has_value())
+ return nullopt;
+ }
+ return find<Struct>(n.value().structs, [&](Struct s) { return s.name == name; });
+}
+
+opt<Variable> findVariable(
+ const Program & p,
+ const std::string & name,
+ const std::vector<std::string> & namespacePrefixes)
+{
+ for (auto n : namespacePrefixes)
+ std::cout << n << std::endl;
+ if (namespacePrefixes.empty())
+ {
+ return find<Variable>(p.variables, [&](Variable v) { return v.name == name; });
+ }
+
+ auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });
+
+ if (!n.has_value())
+ return nullopt;
+
+ for (int i = 1; i < namespacePrefixes.size(); i++)
+ {
+ n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });
+
+ if (!n.has_value())
+ return nullopt;
+ }
+ return find<Variable>(n.value().variables, [&](Variable v) { return v.name == name; });
+}
+
+opt<Function> findStructMethod(
+ const Program & p,
+ const std::string & name,
+ TypeInfo ti)
+{
+ if (!ti.isStruct)
+ return nullopt;
+ auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);
+ if (!s.has_value())
+ return nullopt;
+ return find<StructMember<Function>>(s.value().methods, [&](Function f) { return f.name == name; });
+}
+
+opt<Variable> findStructMember(
+ const Program & p,
+ TypeInfo ti,
+ const std::string & name)
+{
+ auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);
+ if (!s.has_value())
+ return nullopt;
+ return find<StructMember<Variable>>(s.value().members, [&](Variable v) { return v.name == name; });
+} \ No newline at end of file
diff --git a/src/typeInfo.h b/src/typeInfo.h
new file mode 100644
index 0000000..3914847
--- /dev/null
+++ b/src/typeInfo.h
@@ -0,0 +1,115 @@
+#pragma once
+
+#include "repr.h"
+
+struct TypeInfo
+{
+ Type type;
+ bool isStruct;
+};
+
+#include "find.h"
+
+TypeInfo typeType(const Program & p, Type t)
+{
+ TypeInfo result;
+ result.isStruct = true;
+ if (t.name == "int" || t.name == "float" || t.name == "double" ||
+ t.name == "char" || t.name == "long" || t.name == "short" || t.name == "bool")
+ {
+ result.isStruct = false;
+ }
+ result.type = t;
+ return result;
+}
+
+TypeInfo typeExpr(const Program & p, const std::vector<string> & globalNamespace, Expr e)
+{
+ TypeInfo result;
+
+ switch (e.type)
+ {
+ case ExprType::Func:
+ {
+ auto namespacePrefixes = globalNamespace;
+ namespacePrefixes.insert(namespacePrefixes.end(),
+ e._func.namespacePrefixes.begin(),
+ e._func.namespacePrefixes.end());
+ auto f = findFunction(p, e._func.functionName, namespacePrefixes);
+ if (!f.has_value())
+ throw "Unknown function";
+ result = typeType(p, f.value().returnType);
+ break;
+ }
+ case ExprType::Method:
+ {
+ TypeInfo tiCaller = typeExpr(p, globalNamespace, *e._method.expr);
+ auto m = findStructMethod(p, e._method.methodName, tiCaller);
+ if (!m.has_value())
+ throw "Unknown method";
+ result = typeType(p, m.value().returnType);
+ break;
+ }
+ case ExprType::Lit:
+ result.isStruct = false;
+ switch (e._lit.type)
+ {
+ case LitType::Bool: result.type.name = "bool"; break;
+ case LitType::Int: result.type.name = "int"; break;
+ case LitType::Decimal: result.type.name = "double"; break;
+ case LitType::String: result.type.name = "char"; result.type.modifiers.push_back({ TypeModifierType::Pointer, false, -1 }); break;
+ }
+ break;
+ case ExprType::Paren:
+ result = typeExpr(p, globalNamespace, *e._paren.expr);
+ break;
+ case ExprType::Dot:
+ {
+ auto sm = findStructMember(p,
+ typeExpr(p, globalNamespace, *e._dot.expr), e._dot.identifier);
+ if (!sm.has_value())
+ throw "Unknown struct member";
+ result = typeType(p, sm.value().type);
+ break;
+ }
+ case ExprType::PrefixOp:
+ result = typeExpr(p, globalNamespace, *e._prefixOp.expr);
+ break;
+ case ExprType::PostfixOp:
+ result = typeExpr(p, globalNamespace, *e._postfixOp.expr);
+ break;
+ case ExprType::BinaryOp:
+ result = typeExpr(p, globalNamespace, *e._binaryOp.lexpr);
+ break;
+ case ExprType::TernaryOp:
+ result = typeExpr(p, globalNamespace, *e._ternaryOp.rexprTrue);
+ break;
+ case ExprType::Bracket:
+ {
+ TypeInfo ti = typeExpr(p, globalNamespace, *e._brackets.lexpr);
+ if (!ti.type.modifiers.empty())
+ {
+ result = ti;
+ result.type.modifiers.pop_back();
+ }
+ else
+ {
+ throw "Indexing non-array";
+ }
+ }
+ case ExprType::Identifier:
+ {
+ auto namespacePrefixes = globalNamespace;
+ namespacePrefixes.insert(namespacePrefixes.end(),
+ e._identifier.namespacePrefixes.begin(),
+ e._identifier.namespacePrefixes.end());
+ auto v = findVariable(p, e._identifier.identifier, namespacePrefixes);
+ if (!v.has_value())
+ throw "Unknown variable";
+ result = typeType(p, v.value().type);
+ break;
+ }
+ }
+
+ return result;
+} \ No newline at end of file