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
+bool checkNamespace(std::shared_ptr<Context> ctx, const std::vector<std::string> & namespacePrefix)\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
- std::vector<Namespace> namespaces = { n.value() };\r
+ bool prefixMatches = true;\r
+\r
+ auto nIt = ctx;\r
+ for (int i = namespacePrefix.size() - 1; i >= 0; i--)\r
+ {\r
+ const std::string & prefix = namespacePrefix[i];\r
+ if (nIt == nullptr || ! nIt->name.has_value() || nIt->name.value() != prefix)\r
+ {\r
+ prefixMatches = false;\r
+ break;\r
+ }\r
+ nIt = nIt->parent;\r
+ }\r
+\r
+ return prefixMatches;\r
+}\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
- namespaces.push_back(n.value());\r
- }\r
\r
- for (int i = namespaces.size()-1; i >= 0; i--)\r
+opt<Function> findFunction(\r
+ const std::string & name,\r
+ const std::vector<std::string> & namespacePrefix,\r
+ std::shared_ptr<Context> ctx)\r
+{\r
+ for (auto it = ctx; it != nullptr; it = it->parent)\r
{\r
- auto f = find<Function>(namespaces[i].functions, [&](Function f) { return f.name == name; });\r
- if (f.has_value())\r
- return f.value();\r
+ auto f = find<Function>(it->functions, [&](Function f) { return f.name == name; });\r
+ if (f.has_value() && checkNamespace(it, namespacePrefix))\r
+ return f;\r
}\r
-\r
- return find<Function>(p.functions, [&](Function f) { return f.name == name; });\r
+ return nullopt;\r
}\r
\r
opt<Function *> findFunctionPtr(\r
- const Program & p,\r
const std::string & name,\r
- const std::vector<std::string> & namespacePrefixes)\r
+ const std::vector<std::string> & namespacePrefix,\r
+ std::shared_ptr<Context> ctx)\r
{\r
- if (namespacePrefixes.empty())\r
+ for (auto it = ctx; it != nullptr; it = it->parent)\r
{\r
- return findPtr<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
- std::vector<Namespace> namespaces = { n.value() };\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
- namespaces.push_back(n.value());\r
+ auto f = findPtr<Function>(it->functions, [&](Function f) { return f.name == name; });\r
+ if (f.has_value() && checkNamespace(it, namespacePrefix))\r
+ return f;\r
}\r
+ return nullopt;\r
+}\r
\r
- for (int i = namespaces.size()-1; i >= 0; i--)\r
- {\r
- auto f = findPtr<Function>(namespaces[i].functions, [&](Function f) { return f.name == name; });\r
- if (f.has_value())\r
- return f.value();\r
- }\r
\r
- return findPtr<Function>(p.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
+ const std::vector<std::string> & namespacePrefix,\r
+ std::shared_ptr<Context> ctx)\r
{\r
- if (namespacePrefixes.empty())\r
+ for (auto it = ctx; it != nullptr; it = it->parent)\r
{\r
- return find<Struct>(p.structs, [&](Struct s) { return s.name == name; });\r
+ auto s = find<Struct>(it->structs, [&](Struct s) { return s.name == name; });\r
+ if (s.has_value() && checkNamespace(it, namespacePrefix))\r
+ return s;\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
- std::vector<Namespace> namespaces = { n.value() };\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
- namespaces.push_back(n.value());\r
- }\r
-\r
- for (int i = namespaces.size()-1; i >= 0; i--)\r
- {\r
- auto f = find<Struct>(namespaces[i].structs, [&](Struct f) { return f.name == name; });\r
- if (f.has_value())\r
- return f.value();\r
- }\r
-\r
- return find<Struct>(n.value().structs, [&](Struct s) { return s.name == name; });\r
+ return nullopt;\r
}\r
\r
opt<Struct *> findStructPtr(\r
- const Program & p,\r
const std::string & name,\r
- const std::vector<std::string> & namespacePrefixes)\r
+ const std::vector<std::string> & namespacePrefix,\r
+ std::shared_ptr<Context> ctx)\r
{\r
- if (namespacePrefixes.empty())\r
- {\r
- return findPtr<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
- std::vector<Namespace> namespaces = { n.value() };\r
- \r
- for (int i = 1; i < namespacePrefixes.size(); i++)\r
+ for (auto it = ctx; it != nullptr; it = it->parent)\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
- namespaces.push_back(n.value());\r
+ auto s = findPtr<Struct>(it->structs, [&](Struct s) { return s.name == name; });\r
+ if (s.has_value() && checkNamespace(it, namespacePrefix))\r
+ return s;\r
}\r
+ return nullopt;\r
+}\r
\r
- for (int i = namespaces.size()-1; i >= 0; i--)\r
- {\r
- auto f = findPtr<Struct>(namespaces[i].structs, [&](Struct f) { return f.name == name; });\r
- if (f.has_value())\r
- return f.value();\r
- }\r
\r
- return findPtr<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> & namespacePrefix,\r
std::shared_ptr<Context> ctx)\r
{\r
- auto it = ctx;\r
- while (it != nullptr)\r
+ for (auto it = ctx; it != nullptr; it = it->parent)\r
{\r
auto v = find<Variable>(it->variables, [&](Variable v) { return v.name == name; });\r
- if (v.has_value())\r
+ if (v.has_value() && checkNamespace(it, namespacePrefix))\r
return v;\r
- it = it->parent;\r
}\r
return nullopt;\r
}\r
\r
+\r
+\r
opt<StructMember<Function>> findStructMethod(\r
- const Program & p,\r
const std::string & name,\r
- TypeInfo ti)\r
+ const Struct & s)\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
+ return find<StructMember<Function>>(s.methods, [&](Function f) { return f.name == name; });\r
}\r
opt<StructMember<Function> *> findStructMethodPtr(\r
- const Program & p,\r
const std::string & name,\r
- TypeInfo ti)\r
+ const Struct & s)\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 findPtr<StructMember<Function>>(s.value().methods, [&](Function f) { return f.name == name; });\r
+ return findPtr<StructMember<Function>>(s.methods, [&](Function f) { return f.name == name; });\r
}\r
\r
opt<StructMember<Variable>> findStructMember(\r
- const Program & p,\r
- TypeInfo ti,\r
- const std::string & name)\r
+ const std::string & name,\r
+ const Struct & s)\r
+{\r
+ return find<StructMember<Variable>>(s.members, [&](Variable v) { return v.name == name; });\r
+}\r
+\r
+opt<StructMember<Variable> *> findStructMemberPtr(\r
+ const std::string & name,\r
+ const Struct & s)\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
+ return findPtr<StructMember<Variable>>(s.members, [&](Variable v) { return v.name == name; });\r
}
\ No newline at end of file
\r
struct Context\r
{\r
+ std::optional<std::string> name;\r
std::shared_ptr<Context> parent;\r
std::vector<Variable> variables;\r
+ std::vector<Function> functions;\r
+ std::vector<Struct> structs;\r
};\r
\r
enum class TypeModifierType\r
{\r
std::string name;\r
std::shared_ptr<Context> ctx;\r
- std::vector<Struct> structs;\r
- std::vector<Function> functions;\r
std::vector<Namespace> namespaces;\r
};\r
\r
struct Program\r
{\r
std::shared_ptr<Context> ctx;\r
- std::vector<Struct> structs;\r
- std::vector<Function> functions;\r
std::vector<Namespace> namespaces;\r
};\r
\r
}\r
if (d->funcDecl() != nullptr)\r
{\r
- result.functions.push_back(getFunction(d->funcDecl()->func(), result.ctx));\r
+ result.ctx->functions.push_back(getFunction(d->funcDecl()->func(), result.ctx));\r
}\r
if (d->structDecl() != nullptr)\r
{\r
- result.structs.push_back(getStruct(d->structDecl(), result.ctx));\r
+ result.ctx->structs.push_back(getStruct(d->structDecl(), result.ctx));\r
}\r
if (d->namespaceDecl() != nullptr)\r
{\r
}\r
if (d->funcDecl() != nullptr)\r
{\r
- result.functions.push_back(getFunction(d->funcDecl()->func(), result.ctx));\r
+ result.ctx->functions.push_back(getFunction(d->funcDecl()->func(), result.ctx));\r
}\r
if (d->structDecl() != nullptr)\r
{\r
- result.structs.push_back(getStruct(d->structDecl(), result.ctx));\r
+ result.ctx->structs.push_back(getStruct(d->structDecl(), result.ctx));\r
}\r
if (d->namespaceDecl() != nullptr)\r
{\r
tocNamespace(out, n, true);\r
}\r
out << "\n\n";\r
- for (auto s : p.structs)\r
+ for (auto s : p.ctx->structs)\r
{\r
tocStruct(out, s, true);\r
}\r
out << "\n\n";\r
- for (auto f : p.functions)\r
+ for (auto f : p.ctx->functions)\r
{\r
tocFunction(out, f, true);\r
}\r
tocNamespace(out, n, false);\r
}\r
out << "\n\n";\r
- for (auto s : p.structs)\r
+ for (auto s : p.ctx->structs)\r
{\r
tocStruct(out, s, false);\r
}\r
out << "\n\n";\r
- for (auto f : p.functions)\r
+ for (auto f : p.ctx->functions)\r
{\r
tocFunction(out, f, false);\r
}\r
tocNamespace(out, n, stub);\r
out << "\n\n";\r
}\r
- for (auto s : n.structs)\r
+ for (auto s : n.ctx->structs)\r
{\r
tocStruct(out, s, stub);\r
out << "\n\n";\r
}\r
- for (auto f : n.functions)\r
+ for (auto f : n.ctx->functions)\r
{\r
tocFunction(out, f, stub);\r
out << "\n\n";\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
+ auto f = findFunction(e._func.functionName, e._func.namespacePrefixes, globalCtx);\r
if (!f.has_value())\r
throw "Unknown function";\r
result = typeType(p, f.value().returnType);\r
case ExprType::Method:\r
{\r
TypeInfo tiCaller = typeExpr(p, globalNamespace, globalCtx, *e._method.expr);\r
- auto m = findStructMethod(p, e._method.methodName, tiCaller);\r
+ if (!tiCaller.isStruct)\r
+ throw "Calling method on non-struct";\r
+ auto s = findStruct(tiCaller.type.name, tiCaller.type.namespacePrefixes, globalCtx);\r
+ if (!s.has_value())\r
+ throw "Calling method on unknown struct";\r
+ auto m = findStructMethod(e._method.methodName, s.value());\r
if (!m.has_value())\r
throw "Unknown method";\r
result = typeType(p, m.value().t.returnType);\r
break;\r
case ExprType::Dot:\r
{\r
- auto sm = findStructMember(p,\r
- typeExpr(p, globalNamespace, globalCtx, *e._dot.expr), e._dot.identifier);\r
+ auto tiCaller = typeExpr(p, globalNamespace, globalCtx, *e._dot.expr);\r
+ if (!tiCaller.isStruct)\r
+ throw "Accessing member of non-struct";\r
+ auto s = findStruct(tiCaller.type.name, tiCaller.type.namespacePrefixes, globalCtx);\r
+ if (!s.has_value())\r
+ throw "Calling method on unknown struct";\r
+ auto sm = findStructMember(e._dot.identifier, s.value());\r
if (!sm.has_value())\r
throw "Unknown struct member";\r
result = typeType(p, sm.value().t.type);\r
namespacePrefixes.insert(namespacePrefixes.end(),\r
e._identifier.namespacePrefixes.begin(),\r
e._identifier.namespacePrefixes.end());\r
- auto v = findVariable(p, e._identifier.identifier, globalCtx);\r
+ auto v = findVariable(e._identifier.identifier, namespacePrefixes, globalCtx);\r
if (!v.has_value())\r
throw "Unknown variable";\r
result = typeType(p, v.value().type);\r
#include <functional>\r
\r
struct Visitor {\r
- std::function<void(const Type &, const std::vector<std::string> & namespaces)> onType = [](auto, auto){};\r
- std::function<void(const Expr &, const std::vector<std::string> & namespaces)> onExpr = [](auto, auto){};\r
- std::function<void(const Stmt &, const std::vector<std::string> & namespaces)> onStmt = [](auto, auto){};\r
- std::function<void(const Body &, const std::vector<std::string> & namespaces)> onBody = [](auto, auto){};\r
- std::function<void(const Function &, const std::vector<std::string> & namespaces)> onFunction = [](auto, auto){};\r
- std::function<void(const Variable &, const std::vector<std::string> & namespaces)> onVariable = [](auto, auto){};\r
- std::function<void(const StructMember<Function> &, const std::vector<std::string> & namespaces)> onStructMethod = [](auto, auto){};\r
- std::function<void(const StructMember<Variable> &, const std::vector<std::string> & namespaces)> onStructMember = [](auto, auto){};\r
- std::function<void(const Struct &, const std::vector<std::string> & namespaces)> onStruct = [](auto, auto){};\r
- std::function<void(const Namespace &, const std::vector<std::string> & namespaces)> onNamespace = [](auto, auto){};\r
- std::function<void(const Program &, const std::vector<std::string> & namespaces)> onProgram = [](auto, auto){};\r
+ std::function<void(const Type &, const std::shared_ptr<Context> ctx)> onType = [](auto, auto){};\r
+ std::function<void(const Expr &, const std::shared_ptr<Context> ctx)> onExpr = [](auto, auto){};\r
+ std::function<void(const Stmt &, const std::shared_ptr<Context> ctx)> onStmt = [](auto, auto){};\r
+ std::function<void(const Body &, const std::shared_ptr<Context> ctx)> onBody = [](auto, auto){};\r
+ std::function<void(const Function &, const std::shared_ptr<Context> ctx)> onFunction = [](auto, auto){};\r
+ std::function<void(const Variable &, const std::shared_ptr<Context> ctx)> onVariable = [](auto, auto){};\r
+ std::function<void(const StructMember<Function> &, const std::shared_ptr<Context> ctx)> onStructMethod = [](auto, auto){};\r
+ std::function<void(const StructMember<Variable> &, const std::shared_ptr<Context> ctx)> onStructMember = [](auto, auto){};\r
+ std::function<void(const Struct &, const std::shared_ptr<Context> ctx)> onStruct = [](auto, auto){};\r
+ std::function<void(const Namespace &, const std::shared_ptr<Context> ctx)> onNamespace = [](auto, auto){};\r
+ std::function<void(const Program &, const std::shared_ptr<Context> ctx)> onProgram = [](auto, auto){};\r
};\r
\r
#define VISIT(XS) for (auto x : XS) visit(x);\r
struct Visit {\r
private:\r
Visitor v;\r
- std::vector<std::string> namespaces;\r
+ std::shared_ptr<Context> ctx;\r
public:\r
Visit(Visitor v)\r
{\r
}\r
void visit(const Type & x)\r
{\r
- v.onType(x, namespaces);\r
+ v.onType(x, ctx);\r
}\r
void visit(const Expr & x)\r
{\r
- v.onExpr(x, namespaces);\r
+ v.onExpr(x, ctx);\r
\r
switch (x.type)\r
{\r
}\r
void visit(const Stmt & x)\r
{\r
- v.onStmt(x, namespaces);\r
+ v.onStmt(x, ctx);\r
\r
switch (x.type)\r
{\r
}\r
void visit(const Body & x)\r
{\r
- v.onBody(x, namespaces);\r
+ v.onBody(x, ctx);\r
+\r
+ ctx = x.ctx;\r
\r
VISIT(x.ctx->variables)\r
VISIT(x.statements)\r
+\r
+ ctx = ctx->parent;\r
}\r
void visit(const Namespace & x)\r
{\r
- v.onNamespace(x, namespaces);\r
-\r
- namespaces.push_back(x.name);\r
+ v.onNamespace(x, ctx);\r
+ \r
+ ctx = x.ctx;\r
\r
VISIT(x.namespaces)\r
VISIT(x.ctx->variables)\r
- VISIT(x.structs)\r
- VISIT(x.functions)\r
+ VISIT(x.ctx->structs)\r
+ VISIT(x.ctx->functions)\r
\r
- namespaces.pop_back();\r
+ ctx = ctx->parent;\r
}\r
void visit(const Variable & x)\r
{\r
- v.onVariable(x, namespaces);\r
+ v.onVariable(x, ctx);\r
visit(x.type);\r
}\r
void visit(const Function & x)\r
{\r
- v.onFunction(x, namespaces);\r
+ v.onFunction(x, ctx);\r
\r
if (x.defined) {\r
visit(x.body);\r
}\r
void visit(const StructMember<Function> & x)\r
{\r
- v.onStructMethod(x, namespaces);\r
+ v.onStructMethod(x, ctx);\r
\r
visit(x.t);\r
}\r
void visit(const StructMember<Variable> & x)\r
{\r
- v.onStructMember(x, namespaces);\r
+ v.onStructMember(x, ctx);\r
\r
visit(x.t);\r
}\r
void visit(const Struct & x)\r
{\r
- v.onStruct(x, namespaces);\r
+ v.onStruct(x, ctx);\r
\r
VISIT(x.members)\r
VISIT(x.methods)\r
}\r
void visit(const Program & x)\r
{\r
- v.onProgram(x, namespaces);\r
+ v.onProgram(x, ctx);\r
+\r
+ ctx = x.ctx;\r
\r
VISIT(x.namespaces)\r
VISIT(x.ctx->variables)\r
- VISIT(x.structs)\r
- VISIT(x.functions)\r
+ VISIT(x.ctx->structs)\r
+ VISIT(x.ctx->functions)\r
+\r
+ ctx = nullptr;\r
}\r
};\r
\r
m1(i: int) : int {\r
this->i3 = this->i1 * this->i2;\r
\r
+ f1();\r
N1::f1();\r
\r
return this->i1 + this->i2;\r
\r
func f1() : void {\r
var s1 : N1::N2::S1;\r
+\r
s1.m1(123);\r
}\r
}\r