From 17860defa84c6d8bc0e8bc088a7e09361f17db07 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Patrick=20Sch=C3=B6nberger?= Date: Wed, 11 Aug 2021 18:02:56 +0200 Subject: [PATCH] structs and functions in ctx --- src/find.h | 213 ++++++++++++++++--------------------------------- src/repr.h | 7 +- src/repr_get.h | 8 +- src/toc.h | 12 +-- src/typeInfo.h | 20 +++-- src/visit.h | 68 +++++++++------- test/test2.toc | 2 + 7 files changed, 137 insertions(+), 193 deletions(-) diff --git a/src/find.h b/src/find.h index fec540f..ea3ae22 100644 --- a/src/find.h +++ b/src/find.h @@ -27,202 +27,127 @@ opt findPtr(const std::vector & ts, std::function f) return nullopt; } -opt findFunction( - const Program & p, - const std::string & name, - const std::vector & namespacePrefixes) +bool checkNamespace(std::shared_ptr ctx, const std::vector & namespacePrefix) { - 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; - - std::vector namespaces = { n.value() }; + bool prefixMatches = true; + + auto nIt = ctx; + for (int i = namespacePrefix.size() - 1; i >= 0; i--) + { + const std::string & prefix = namespacePrefix[i]; + if (nIt == nullptr || ! nIt->name.has_value() || nIt->name.value() != prefix) + { + prefixMatches = false; + break; + } + nIt = nIt->parent; + } + + return prefixMatches; +} - 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; - namespaces.push_back(n.value()); - } - for (int i = namespaces.size()-1; i >= 0; i--) +opt findFunction( + const std::string & name, + const std::vector & namespacePrefix, + std::shared_ptr ctx) +{ + for (auto it = ctx; it != nullptr; it = it->parent) { - auto f = find(namespaces[i].functions, [&](Function f) { return f.name == name; }); - if (f.has_value()) - return f.value(); + auto f = find(it->functions, [&](Function f) { return f.name == name; }); + if (f.has_value() && checkNamespace(it, namespacePrefix)) + return f; } - - return find(p.functions, [&](Function f) { return f.name == name; }); + return nullopt; } opt findFunctionPtr( - const Program & p, const std::string & name, - const std::vector & namespacePrefixes) + const std::vector & namespacePrefix, + std::shared_ptr ctx) { - if (namespacePrefixes.empty()) + for (auto it = ctx; it != nullptr; it = it->parent) { - return findPtr(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; - - std::vector namespaces = { n.value() }; - - 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; - - namespaces.push_back(n.value()); + auto f = findPtr(it->functions, [&](Function f) { return f.name == name; }); + if (f.has_value() && checkNamespace(it, namespacePrefix)) + return f; } + return nullopt; +} - for (int i = namespaces.size()-1; i >= 0; i--) - { - auto f = findPtr(namespaces[i].functions, [&](Function f) { return f.name == name; }); - if (f.has_value()) - return f.value(); - } - return findPtr(p.functions, [&](Function f) { return f.name == name; }); -} opt findStruct( - const Program & p, const std::string & name, - const std::vector & namespacePrefixes) + const std::vector & namespacePrefix, + std::shared_ptr ctx) { - if (namespacePrefixes.empty()) + for (auto it = ctx; it != nullptr; it = it->parent) { - return find(p.structs, [&](Struct s) { return s.name == name; }); + auto s = find(it->structs, [&](Struct s) { return s.name == name; }); + if (s.has_value() && checkNamespace(it, namespacePrefix)) + return s; } - - auto n = find(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; }); - - if (!n.has_value()) - return nullopt; - - std::vector namespaces = { n.value() }; - - 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; - - namespaces.push_back(n.value()); - } - - for (int i = namespaces.size()-1; i >= 0; i--) - { - auto f = find(namespaces[i].structs, [&](Struct f) { return f.name == name; }); - if (f.has_value()) - return f.value(); - } - - return find(n.value().structs, [&](Struct s) { return s.name == name; }); + return nullopt; } opt findStructPtr( - const Program & p, const std::string & name, - const std::vector & namespacePrefixes) + const std::vector & namespacePrefix, + std::shared_ptr ctx) { - if (namespacePrefixes.empty()) - { - return findPtr(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; - - std::vector namespaces = { n.value() }; - - for (int i = 1; i < namespacePrefixes.size(); i++) + for (auto it = ctx; it != nullptr; it = it->parent) { - n = find(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; }); - - if (!n.has_value()) - return nullopt; - - namespaces.push_back(n.value()); + auto s = findPtr(it->structs, [&](Struct s) { return s.name == name; }); + if (s.has_value() && checkNamespace(it, namespacePrefix)) + return s; } + return nullopt; +} - for (int i = namespaces.size()-1; i >= 0; i--) - { - auto f = findPtr(namespaces[i].structs, [&](Struct f) { return f.name == name; }); - if (f.has_value()) - return f.value(); - } - return findPtr(n.value().structs, [&](Struct s) { return s.name == name; }); -} opt findVariable( - const Program & p, const std::string & name, + const std::vector & namespacePrefix, std::shared_ptr ctx) { - auto it = ctx; - while (it != nullptr) + for (auto it = ctx; it != nullptr; it = it->parent) { auto v = find(it->variables, [&](Variable v) { return v.name == name; }); - if (v.has_value()) + if (v.has_value() && checkNamespace(it, namespacePrefix)) return v; - it = it->parent; } return nullopt; } + + opt> findStructMethod( - const Program & p, const std::string & name, - TypeInfo ti) + const Struct & s) { - 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; }); + return find>(s.methods, [&](Function f) { return f.name == name; }); } opt *> findStructMethodPtr( - const Program & p, const std::string & name, - TypeInfo ti) + const Struct & s) { - if (!ti.isStruct) - return nullopt; - auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes); - if (!s.has_value()) - return nullopt; - return findPtr>(s.value().methods, [&](Function f) { return f.name == name; }); + return findPtr>(s.methods, [&](Function f) { return f.name == name; }); } opt> findStructMember( - const Program & p, - TypeInfo ti, - const std::string & name) + const std::string & name, + const Struct & s) +{ + return find>(s.members, [&](Variable v) { return v.name == name; }); +} + +opt *> findStructMemberPtr( + const std::string & name, + const Struct & s) { - 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; }); + return findPtr>(s.members, [&](Variable v) { return v.name == name; }); } \ No newline at end of file diff --git a/src/repr.h b/src/repr.h index ff54f97..709528d 100644 --- a/src/repr.h +++ b/src/repr.h @@ -39,8 +39,11 @@ struct Stmt; struct Context { + std::optional name; std::shared_ptr parent; std::vector variables; + std::vector functions; + std::vector structs; }; enum class TypeModifierType @@ -110,16 +113,12 @@ struct Namespace { std::string name; std::shared_ptr ctx; - std::vector structs; - std::vector functions; std::vector namespaces; }; struct Program { std::shared_ptr ctx; - std::vector structs; - std::vector functions; std::vector namespaces; }; diff --git a/src/repr_get.h b/src/repr_get.h index 2d321b0..7436dde 100644 --- a/src/repr_get.h +++ b/src/repr_get.h @@ -153,11 +153,11 @@ Namespace getNamespace(TocParser::NamespaceDeclContext * ctx, std::shared_ptrfuncDecl() != nullptr) { - result.functions.push_back(getFunction(d->funcDecl()->func(), result.ctx)); + result.ctx->functions.push_back(getFunction(d->funcDecl()->func(), result.ctx)); } if (d->structDecl() != nullptr) { - result.structs.push_back(getStruct(d->structDecl(), result.ctx)); + result.ctx->structs.push_back(getStruct(d->structDecl(), result.ctx)); } if (d->namespaceDecl() != nullptr) { @@ -178,11 +178,11 @@ Program getProgram(TocParser::ProgContext * ctx, std::shared_ptr parent } if (d->funcDecl() != nullptr) { - result.functions.push_back(getFunction(d->funcDecl()->func(), result.ctx)); + result.ctx->functions.push_back(getFunction(d->funcDecl()->func(), result.ctx)); } if (d->structDecl() != nullptr) { - result.structs.push_back(getStruct(d->structDecl(), result.ctx)); + result.ctx->structs.push_back(getStruct(d->structDecl(), result.ctx)); } if (d->namespaceDecl() != nullptr) { diff --git a/src/toc.h b/src/toc.h index 659c9f3..8bf0e68 100644 --- a/src/toc.h +++ b/src/toc.h @@ -408,12 +408,12 @@ void tocProgram (std::ostream & out, const Program & _p) tocNamespace(out, n, true); } out << "\n\n"; - for (auto s : p.structs) + for (auto s : p.ctx->structs) { tocStruct(out, s, true); } out << "\n\n"; - for (auto f : p.functions) + for (auto f : p.ctx->functions) { tocFunction(out, f, true); } @@ -429,12 +429,12 @@ void tocProgram (std::ostream & out, const Program & _p) tocNamespace(out, n, false); } out << "\n\n"; - for (auto s : p.structs) + for (auto s : p.ctx->structs) { tocStruct(out, s, false); } out << "\n\n"; - for (auto f : p.functions) + for (auto f : p.ctx->functions) { tocFunction(out, f, false); } @@ -461,12 +461,12 @@ void tocNamespace (std::ostream & out, const Namespace & n, bool stub) tocNamespace(out, n, stub); out << "\n\n"; } - for (auto s : n.structs) + for (auto s : n.ctx->structs) { tocStruct(out, s, stub); out << "\n\n"; } - for (auto f : n.functions) + for (auto f : n.ctx->functions) { tocFunction(out, f, stub); out << "\n\n"; diff --git a/src/typeInfo.h b/src/typeInfo.h index cbe421c..89fff2a 100644 --- a/src/typeInfo.h +++ b/src/typeInfo.h @@ -36,7 +36,7 @@ TypeInfo typeExpr(const Program & p, const std::vector & globalName namespacePrefixes.insert(namespacePrefixes.end(), e._func.namespacePrefixes.begin(), e._func.namespacePrefixes.end()); - auto f = findFunction(p, e._func.functionName, namespacePrefixes); + auto f = findFunction(e._func.functionName, e._func.namespacePrefixes, globalCtx); if (!f.has_value()) throw "Unknown function"; result = typeType(p, f.value().returnType); @@ -45,7 +45,12 @@ TypeInfo typeExpr(const Program & p, const std::vector & globalName case ExprType::Method: { TypeInfo tiCaller = typeExpr(p, globalNamespace, globalCtx, *e._method.expr); - auto m = findStructMethod(p, e._method.methodName, tiCaller); + if (!tiCaller.isStruct) + throw "Calling method on non-struct"; + auto s = findStruct(tiCaller.type.name, tiCaller.type.namespacePrefixes, globalCtx); + if (!s.has_value()) + throw "Calling method on unknown struct"; + auto m = findStructMethod(e._method.methodName, s.value()); if (!m.has_value()) throw "Unknown method"; result = typeType(p, m.value().t.returnType); @@ -66,8 +71,13 @@ TypeInfo typeExpr(const Program & p, const std::vector & globalName break; case ExprType::Dot: { - auto sm = findStructMember(p, - typeExpr(p, globalNamespace, globalCtx, *e._dot.expr), e._dot.identifier); + auto tiCaller = typeExpr(p, globalNamespace, globalCtx, *e._dot.expr); + if (!tiCaller.isStruct) + throw "Accessing member of non-struct"; + auto s = findStruct(tiCaller.type.name, tiCaller.type.namespacePrefixes, globalCtx); + if (!s.has_value()) + throw "Calling method on unknown struct"; + auto sm = findStructMember(e._dot.identifier, s.value()); if (!sm.has_value()) throw "Unknown struct member"; result = typeType(p, sm.value().t.type); @@ -104,7 +114,7 @@ TypeInfo typeExpr(const Program & p, const std::vector & globalName namespacePrefixes.insert(namespacePrefixes.end(), e._identifier.namespacePrefixes.begin(), e._identifier.namespacePrefixes.end()); - auto v = findVariable(p, e._identifier.identifier, globalCtx); + auto v = findVariable(e._identifier.identifier, namespacePrefixes, globalCtx); if (!v.has_value()) throw "Unknown variable"; result = typeType(p, v.value().type); diff --git a/src/visit.h b/src/visit.h index 0cfb9e6..3fe2cb2 100644 --- a/src/visit.h +++ b/src/visit.h @@ -5,17 +5,17 @@ #include struct Visitor { - std::function & namespaces)> onType = [](auto, auto){}; - std::function & namespaces)> onExpr = [](auto, auto){}; - std::function & namespaces)> onStmt = [](auto, auto){}; - std::function & namespaces)> onBody = [](auto, auto){}; - std::function & namespaces)> onFunction = [](auto, auto){}; - std::function & namespaces)> onVariable = [](auto, auto){}; - std::function &, const std::vector & namespaces)> onStructMethod = [](auto, auto){}; - std::function &, const std::vector & namespaces)> onStructMember = [](auto, auto){}; - std::function & namespaces)> onStruct = [](auto, auto){}; - std::function & namespaces)> onNamespace = [](auto, auto){}; - std::function & namespaces)> onProgram = [](auto, auto){}; + std::function ctx)> onType = [](auto, auto){}; + std::function ctx)> onExpr = [](auto, auto){}; + std::function ctx)> onStmt = [](auto, auto){}; + std::function ctx)> onBody = [](auto, auto){}; + std::function ctx)> onFunction = [](auto, auto){}; + std::function ctx)> onVariable = [](auto, auto){}; + std::function &, const std::shared_ptr ctx)> onStructMethod = [](auto, auto){}; + std::function &, const std::shared_ptr ctx)> onStructMember = [](auto, auto){}; + std::function ctx)> onStruct = [](auto, auto){}; + std::function ctx)> onNamespace = [](auto, auto){}; + std::function ctx)> onProgram = [](auto, auto){}; }; #define VISIT(XS) for (auto x : XS) visit(x); @@ -23,7 +23,7 @@ struct Visitor { struct Visit { private: Visitor v; - std::vector namespaces; + std::shared_ptr ctx; public: Visit(Visitor v) { @@ -31,11 +31,11 @@ public: } void visit(const Type & x) { - v.onType(x, namespaces); + v.onType(x, ctx); } void visit(const Expr & x) { - v.onExpr(x, namespaces); + v.onExpr(x, ctx); switch (x.type) { @@ -79,7 +79,7 @@ public: } void visit(const Stmt & x) { - v.onStmt(x, namespaces); + v.onStmt(x, ctx); switch (x.type) { @@ -126,32 +126,36 @@ public: } void visit(const Body & x) { - v.onBody(x, namespaces); + v.onBody(x, ctx); + + ctx = x.ctx; VISIT(x.ctx->variables) VISIT(x.statements) + + ctx = ctx->parent; } void visit(const Namespace & x) { - v.onNamespace(x, namespaces); - - namespaces.push_back(x.name); + v.onNamespace(x, ctx); + + ctx = x.ctx; VISIT(x.namespaces) VISIT(x.ctx->variables) - VISIT(x.structs) - VISIT(x.functions) + VISIT(x.ctx->structs) + VISIT(x.ctx->functions) - namespaces.pop_back(); + ctx = ctx->parent; } void visit(const Variable & x) { - v.onVariable(x, namespaces); + v.onVariable(x, ctx); visit(x.type); } void visit(const Function & x) { - v.onFunction(x, namespaces); + v.onFunction(x, ctx); if (x.defined) { visit(x.body); @@ -161,31 +165,35 @@ public: } void visit(const StructMember & x) { - v.onStructMethod(x, namespaces); + v.onStructMethod(x, ctx); visit(x.t); } void visit(const StructMember & x) { - v.onStructMember(x, namespaces); + v.onStructMember(x, ctx); visit(x.t); } void visit(const Struct & x) { - v.onStruct(x, namespaces); + v.onStruct(x, ctx); VISIT(x.members) VISIT(x.methods) } void visit(const Program & x) { - v.onProgram(x, namespaces); + v.onProgram(x, ctx); + + ctx = x.ctx; VISIT(x.namespaces) VISIT(x.ctx->variables) - VISIT(x.structs) - VISIT(x.functions) + VISIT(x.ctx->structs) + VISIT(x.ctx->functions) + + ctx = nullptr; } }; diff --git a/test/test2.toc b/test/test2.toc index 1447c8f..abd6bc7 100644 --- a/test/test2.toc +++ b/test/test2.toc @@ -13,6 +13,7 @@ namespace N1 { m1(i: int) : int { this->i3 = this->i1 * this->i2; + f1(); N1::f1(); return this->i1 + this->i2; @@ -21,6 +22,7 @@ namespace N1 { func f1() : void { var s1 : N1::N2::S1; + s1.m1(123); } } -- 2.50.1