From be56e29997e17685eebf8bd7cb745183c60de7db Mon Sep 17 00:00:00 2001 From: =?utf8?q?Patrick=20Sch=C3=B6nberger?= Date: Wed, 4 Aug 2021 14:51:36 +0200 Subject: [PATCH] pre change --- src/find.h | 121 +++++++++++++++++++++++++++++++++++++++++++++++++ src/typeInfo.h | 115 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 src/find.h create mode 100644 src/typeInfo.h 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 +#include + +template +using opt = std::optional; + +template +opt find(const std::vector & ts, std::function f) +{ + for (auto t : ts) + if (f(t)) + return t; + return nullopt; +} + +opt findFunction( + const Program & p, + const std::string & name, + const std::vector & namespacePrefixes) +{ + if (namespacePrefixes.empty()) + { + return find(p.functions, [&](Function f) { return f.name == name; }); + } + + auto n = find(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(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; }); + + if (!n.has_value()) + return nullopt; + } + + return find(n.value().functions, [&](Function f) { return f.name == name; }); +} + +opt findStruct( + const Program & p, + const std::string & name, + const std::vector & namespacePrefixes) +{ + if (namespacePrefixes.empty()) + { + return find(p.structs, [&](Struct s) { return s.name == name; }); + } + + auto n = find(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(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; }); + + if (!n.has_value()) + return nullopt; + } + return find(n.value().structs, [&](Struct s) { return s.name == name; }); +} + +opt findVariable( + const Program & p, + const std::string & name, + const std::vector & namespacePrefixes) +{ + for (auto n : namespacePrefixes) + std::cout << n << std::endl; + if (namespacePrefixes.empty()) + { + return find(p.variables, [&](Variable v) { return v.name == name; }); + } + + auto n = find(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(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; }); + + if (!n.has_value()) + return nullopt; + } + return find(n.value().variables, [&](Variable v) { return v.name == name; }); +} + +opt 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>(s.value().methods, [&](Function f) { return f.name == name; }); +} + +opt 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>(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 & 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 -- 2.50.1