diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/find.h | 111 | ||||
| -rw-r--r-- | src/repr.h | 10 | ||||
| -rw-r--r-- | src/repr_get.h | 39 | ||||
| -rw-r--r-- | src/toc.h | 215 | ||||
| -rw-r--r-- | src/typeInfo.h | 7 | ||||
| -rw-r--r-- | src/visit.h | 193 |
6 files changed, 519 insertions, 56 deletions
@@ -18,6 +18,15 @@ opt<T> find(const std::vector<T> & ts, std::function<bool(T)> f) return nullopt;
}
+template<typename T>
+opt<T *> findPtr(const std::vector<T> & ts, std::function<bool(T)> f)
+{
+ for (int i = 0; i < ts.size(); i++)
+ if (f(ts[i]))
+ return &((T *)ts.data())[i];
+ return nullopt;
+}
+
opt<Function> findFunction(
const Program & p,
const std::string & name,
@@ -55,6 +64,43 @@ opt<Function> findFunction( return find<Function>(p.functions, [&](Function f) { return f.name == name; });
}
+opt<Function *> findFunctionPtr(
+ const Program & p,
+ const std::string & name,
+ const std::vector<std::string> & namespacePrefixes)
+{
+ if (namespacePrefixes.empty())
+ {
+ return findPtr<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;
+
+ std::vector<Namespace> namespaces = { n.value() };
+
+ 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;
+
+ namespaces.push_back(n.value());
+ }
+
+ for (int i = namespaces.size()-1; i >= 0; i--)
+ {
+ auto f = findPtr<Function>(namespaces[i].functions, [&](Function f) { return f.name == name; });
+ if (f.has_value())
+ return f.value();
+ }
+
+ return findPtr<Function>(p.functions, [&](Function f) { return f.name == name; });
+}
+
opt<Struct> findStruct(
const Program & p,
const std::string & name,
@@ -69,6 +115,8 @@ opt<Struct> findStruct( if (!n.has_value())
return nullopt;
+
+ std::vector<Namespace> namespaces = { n.value() };
for (int i = 1; i < namespacePrefixes.size(); i++)
{
@@ -76,10 +124,57 @@ opt<Struct> findStruct( if (!n.has_value())
return nullopt;
+
+ namespaces.push_back(n.value());
+ }
+
+ for (int i = namespaces.size()-1; i >= 0; i--)
+ {
+ auto f = find<Struct>(namespaces[i].structs, [&](Struct f) { return f.name == name; });
+ if (f.has_value())
+ return f.value();
}
+
return find<Struct>(n.value().structs, [&](Struct s) { return s.name == name; });
}
+opt<Struct *> findStructPtr(
+ const Program & p,
+ const std::string & name,
+ const std::vector<std::string> & namespacePrefixes)
+{
+ if (namespacePrefixes.empty())
+ {
+ return findPtr<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;
+
+ std::vector<Namespace> namespaces = { n.value() };
+
+ 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;
+
+ namespaces.push_back(n.value());
+ }
+
+ for (int i = namespaces.size()-1; i >= 0; i--)
+ {
+ auto f = findPtr<Struct>(namespaces[i].structs, [&](Struct f) { return f.name == name; });
+ if (f.has_value())
+ return f.value();
+ }
+
+ return findPtr<Struct>(n.value().structs, [&](Struct s) { return s.name == name; });
+}
+
opt<Variable> findVariable(
const Program & p,
const std::string & name,
@@ -96,7 +191,7 @@ opt<Variable> findVariable( return nullopt;
}
-opt<Function> findStructMethod(
+opt<StructMember<Function>> findStructMethod(
const Program & p,
const std::string & name,
TypeInfo ti)
@@ -108,8 +203,20 @@ opt<Function> findStructMethod( return nullopt;
return find<StructMember<Function>>(s.value().methods, [&](Function f) { return f.name == name; });
}
+opt<StructMember<Function> *> findStructMethodPtr(
+ 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 findPtr<StructMember<Function>>(s.value().methods, [&](Function f) { return f.name == name; });
+}
-opt<Variable> findStructMember(
+opt<StructMember<Variable>> findStructMember(
const Program & p,
TypeInfo ti,
const std::string & name)
@@ -61,6 +61,7 @@ struct Type std::vector<std::string> namespacePrefixes;
std::string name;
std::vector<TypeModifier> modifiers;
+ std::vector<Type> genericInstantiation;
};
struct Variable
@@ -77,8 +78,10 @@ struct Body struct Function
{
- Type returnType;
std::string name;
+ std::vector<std::string> genericTypeNames;
+ std::vector<std::vector<Type>> genericInstantiations;
+ Type returnType;
std::vector<Variable> parameters;
bool defined;
Body body;
@@ -95,6 +98,8 @@ struct StructMember struct Struct
{
std::string name;
+ std::vector<std::string> genericTypeNames;
+ std::vector<std::vector<Type>> genericInstantiations;
std::vector<StructMember<Variable>> members;
std::vector<StructMember<Function>> methods;
};
@@ -126,6 +131,7 @@ struct FuncExpr std::vector<std::string> namespacePrefixes;
std::string functionName;
std::vector<Expr> arguments;
+ std::vector<Type> genericInstantiation;
};
struct MethodExpr
@@ -133,6 +139,7 @@ struct MethodExpr std::shared_ptr<Expr> expr;
std::string methodName;
std::vector<Expr> arguments;
+ std::vector<Type> genericInstantiation;
};
enum class LitType
@@ -157,6 +164,7 @@ struct ParenExpr struct DotExpr
{
+ bool isPointer;
std::shared_ptr<Expr> expr;
std::string identifier;
};
diff --git a/src/repr_get.h b/src/repr_get.h index 827c02b..2d321b0 100644 --- a/src/repr_get.h +++ b/src/repr_get.h @@ -43,6 +43,13 @@ Type getType(TocParser::TypeContext * ctx) isStaticArray ? atoi(m->INT_LIT()->toString().c_str()) : -1
);
}
+ if (ctx->genericInstantiation() != nullptr)
+ {
+ for (auto g : ctx->genericInstantiation()->type())
+ {
+ result.genericInstantiation.push_back(getType(g));
+ }
+ }
return result;
}
Variable getVariable(TocParser::VarContext * ctx)
@@ -77,11 +84,20 @@ Function getFunction(TocParser::FuncContext * ctx, std::shared_ptr<Context> pare Function result;
result.name = ctx->funcName()->NAME()->toString();
result.returnType = getType(ctx->type());
+ if (ctx->genericDecl() != nullptr)
+ {
+ for (auto t : ctx->genericDecl()->typeName())
+ {
+ result.genericTypeNames.push_back(t->getText());
+ }
+ }
+
if (!ctx->parameter()->var().empty())
{
for (auto p : ctx->parameter()->var())
result.parameters.push_back(getVariable(p));
}
+
if (ctx->body() != nullptr)
{
result.body = getBody(ctx->body(), parent);
@@ -97,6 +113,14 @@ Struct getStruct(TocParser::StructDeclContext * ctx, std::shared_ptr<Context> pa {
Struct result;
result.name = ctx->structName()->NAME()->toString();
+ if (ctx->genericDecl() != nullptr)
+ {
+ for (auto t : ctx->genericDecl()->typeName())
+ {
+ result.genericTypeNames.push_back(t->getText());
+ }
+ }
+
for (auto m : ctx->structMember())
{
if (m->structVar() != nullptr)
@@ -199,6 +223,13 @@ Expr getExpr(TocParser::FuncExprContext * ctx) for (auto n : ctx->namespaceSpecifier())
result._func.namespacePrefixes.push_back(n->typeName()->getText());
result._func.functionName = ctx->funcName()->NAME()->toString();
+ if (ctx->genericInstantiation() != nullptr)
+ {
+ for (auto g : ctx->genericInstantiation()->type())
+ {
+ result._func.genericInstantiation.push_back(getType(g));
+ }
+ }
for (auto e : ctx->expr())
result._func.arguments.push_back(getExpr(e));
return result;
@@ -209,6 +240,13 @@ Expr getExpr(TocParser::MethodExprContext * ctx) result.type = ExprType::Method;
result._method.expr = std::make_unique<Expr>(getExpr(ctx->expr(0)));
result._method.methodName = ctx->funcName()->NAME()->toString();
+ if (ctx->genericInstantiation() != nullptr)
+ {
+ for (auto g : ctx->genericInstantiation()->type())
+ {
+ result._method.genericInstantiation.push_back(getType(g));
+ }
+ }
for (int i = 1; i < ctx->expr().size(); i++)
result._method.arguments.push_back(getExpr(ctx->expr(i)));
return result;
@@ -252,6 +290,7 @@ Expr getExpr(TocParser::DotExprContext * ctx) result.type = ExprType::Dot;
result._dot.expr = std::make_unique<Expr>(getExpr(ctx->expr()));
result._dot.identifier = ctx->varName()->getText();
+ result._dot.isPointer = ctx->arrow() != nullptr;
return result;
}
Expr getExpr(TocParser::PrefixOpExprContext * ctx)
@@ -4,6 +4,7 @@ #include <sstream>
#include "repr.h"
+#include "generic.h"
#include "typeInfo.h"
template<typename T>
@@ -53,15 +54,27 @@ static std::string namespacePrefix() { return sstr.str();
}
+static std::map<std::string, Type> currentInstantiation;
+
static Program globalPrg;
static std::shared_ptr<Context> globalCtx;
std::ostream & operator<< (std::ostream & out, const Type & t)
{
+ for (auto kv : currentInstantiation)
+ {
+ if (t.name == kv.first)
+ {
+ out << kv.second;
+ return out;
+ }
+ }
TypeInfo ti = typeType(globalPrg, t);
if (ti.isStruct)
out << "struct ";
out << vectorStr(t.namespacePrefixes, "_", true) << t.name;
+ if (!t.genericInstantiation.empty())
+ out << genericAppendix(t.genericInstantiation);
return out;
}
@@ -135,16 +148,21 @@ std::ostream & operator<< (std::ostream & out, const Expr & e) TypeInfo ti = typeExpr(globalPrg, namespaces, globalCtx, e);
}
- out << vectorStr(e._func.namespacePrefixes, "_", true) << e._func.functionName << "(" << vectorStr(e._func.arguments, ", ") << ")"; break;
+ out << vectorStr(e._func.namespacePrefixes, "_", true) << e._func.functionName;
+ if (!e._func.genericInstantiation.empty())
+ out << genericAppendix(e._func.genericInstantiation);
+ out <<"(" << vectorStr(e._func.arguments, ", ") << ")"; break;
}
case ExprType::Method:
{
TypeInfo ti = typeExpr(globalPrg, namespaces, globalCtx, *e._method.expr);
out <<
vectorStr(ti.type.namespacePrefixes, "_", true) <<
- ti.type.name << "_" << e._method.methodName <<
- "(&" << *e._method.expr << (e._method.arguments.empty() ? "" : ", ") <<
- vectorStr(e._method.arguments, ", ") << ")"; break;
+ ti.type.name << genericAppendix(ti.type.genericInstantiation) << "_" << e._method.methodName;
+ if (!e._method.genericInstantiation.empty())
+ out << genericAppendix(e._method.genericInstantiation);
+ out << "(&" << *e._method.expr << (e._method.arguments.empty() ? "" : ", ") <<
+ vectorStr(e._method.arguments, ", ") << ")"; break;
}
case ExprType::Lit:
/**/ if (e._lit.type == LitType::Int) out << e._lit._int;
@@ -155,7 +173,7 @@ std::ostream & operator<< (std::ostream & out, const Expr & e) case ExprType::Paren:
out << "(" << e._paren.expr << ")"; break;
case ExprType::Dot:
- out << *e._dot.expr << "." << e._dot.identifier; break;
+ out << *e._dot.expr << (e._dot.isPointer ? "->" : ".") << e._dot.identifier; break;
case ExprType::PrefixOp:
out << PrefixOperatorTypeStrings[(int)e._prefixOp.type] << *e._prefixOp.expr; break;
case ExprType::PostfixOp:
@@ -216,75 +234,172 @@ void tocFunction (std::ostream & out, const Function & f, bool stub) {
if (!stub && !f.defined) return;
- out << f.returnType << " " << namespacePrefix() << f.name << " (" << vectorStr(f.parameters, ", ") << ")";
-
- if (stub)
+ if (f.genericTypeNames.empty())
{
- out << ";\n";
+ out << f.returnType << " " << namespacePrefix() << f.name << " (" << vectorStr(f.parameters, ", ") << ")";
+
+ if (stub)
+ {
+ out << ";\n";
+ }
+ else
+ {
+ out << "\n" << f.body;
+ }
}
else
{
- out << "\n" << f.body;
+ for (auto instantiation : f.genericInstantiations)
+ {
+ for (int i = 0; i < f.genericTypeNames.size(); i++)
+ {
+ currentInstantiation[f.genericTypeNames[i]] = instantiation[i];
+ }
+
+ out << f.returnType << " " << namespacePrefix() << f.name << genericAppendix(instantiation) << " (" << vectorStr(f.parameters, ", ") << ")";
+
+ if (stub)
+ {
+ out << ";\n";
+ }
+ else
+ {
+ out << "\n" << f.body;
+ }
+
+ currentInstantiation.clear();
+ }
}
}
void tocStruct (std::ostream & out, const Struct & s, bool stub)
{
- out << "struct " << namespacePrefix() << s.name;
- if (stub)
+ if (s.genericTypeNames.empty())
{
- out << ";\n";
+ out << "struct " << namespacePrefix() << s.name;
+ if (stub)
+ {
+ out << ";\n";
+ for (auto m : s.methods)
+ {
+ Function f = m;
+
+ f.parameters.insert(f.parameters.begin(),
+ {"this",
+ {
+ namespaces,
+ s.name,
+ {
+ {TypeModifierType::Pointer, false, -1}
+ }
+ }
+ });
+ out << f.returnType << " " <<
+ namespacePrefix() << s.name << "_" << f.name <<
+ " (" << vectorStr(f.parameters, ", ") << ");\n";
+ }
+ return;
+ }
+ out << "\n{\n";
+ indentation += 2;
+
+ for (auto m : s.members)
+ {
+ indent(out);
+ out << m << ";\n";
+ }
+
+ indent(out, -2);
+ out << "};\n";
+
for (auto m : s.methods)
{
Function f = m;
-
f.parameters.insert(f.parameters.begin(),
- {"this",
- {
- namespaces,
- s.name,
+ {"this",
{
- {TypeModifierType::Pointer, false, -1}
+ namespaces,
+ s.name,
+ {
+ {TypeModifierType::Pointer, false, -1}
+ }
}
- }
- });
+ });
out << f.returnType << " " <<
- namespacePrefix() << s.name << "_" << f.name <<
- " (" << vectorStr(f.parameters, ", ") << ");\n";
+ namespacePrefix() << s.name << "_" << f.name <<
+ " (" << vectorStr(f.parameters, ", ") << ")\n" << f.body;
}
- return;
- }
- out << "\n{\n";
- indentation += 2;
-
- for (auto m : s.members)
- {
- indent(out);
- out << m << ";\n";
}
-
- indent(out, -2);
- out << "};\n";
-
- for (auto m : s.methods)
+ else
{
- Function f = m;
- f.parameters.insert(f.parameters.begin(),
- {"this",
+ for (auto instantiation : s.genericInstantiations)
+ {
+ for (int i = 0; i < s.genericTypeNames.size(); i++)
+ {
+ currentInstantiation[s.genericTypeNames[i]] = instantiation[i];
+ }
+
+ out << "struct " << namespacePrefix() << s.name << genericAppendix(instantiation);
+ if (stub)
+ {
+ out << ";\n";
+ for (auto m : s.methods)
{
- namespaces,
- s.name,
- {
- {TypeModifierType::Pointer, false, -1}
- }
+ Function f = m;
+
+ f.parameters.insert(f.parameters.begin(),
+ {"this",
+ {
+ namespaces,
+ s.name + genericAppendix(instantiation),
+ {
+ {TypeModifierType::Pointer, false, -1}
+ }
+ }
+ });
+ out << f.returnType << " " <<
+ namespacePrefix() << s.name << genericAppendix(instantiation) << "_" << f.name <<
+ " (" << vectorStr(f.parameters, ", ") << ");\n";
}
- });
- out << f.returnType << " " <<
- namespacePrefix() << s.name << "_" << f.name <<
- " (" << vectorStr(f.parameters, ", ") << ")\n" << f.body;
+ return;
+ }
+ out << "\n{\n";
+ indentation += 2;
+
+ for (auto m : s.members)
+ {
+ indent(out);
+ out << m << ";\n";
+ }
+
+ indent(out, -2);
+ out << "};\n";
+
+ for (auto m : s.methods)
+ {
+ Function f = m;
+ f.parameters.insert(f.parameters.begin(),
+ {"this",
+ {
+ namespaces,
+ s.name + genericAppendix(instantiation),
+ {
+ {TypeModifierType::Pointer, false, -1}
+ }
+ }
+ });
+ out << f.returnType << " " <<
+ namespacePrefix() << s.name << genericAppendix(instantiation) << "_" << f.name <<
+ " (" << vectorStr(f.parameters, ", ") << ")\n" << f.body;
+ }
+
+ currentInstantiation.clear();
+ }
}
}
-void tocProgram (std::ostream & out, const Program & p)
+void tocProgram (std::ostream & out, const Program & _p)
{
+ Program p = instantiateGenerics(_p);
+
globalCtx = p.ctx;
globalPrg = p;
diff --git a/src/typeInfo.h b/src/typeInfo.h index 0fd4114..cbe421c 100644 --- a/src/typeInfo.h +++ b/src/typeInfo.h @@ -15,7 +15,8 @@ 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")
+ t.name == "char" || t.name == "long" || t.name == "short" || t.name == "bool" ||
+ t.name == "void")
{
result.isStruct = false;
}
@@ -47,7 +48,7 @@ TypeInfo typeExpr(const Program & p, const std::vector<std::string> & globalName auto m = findStructMethod(p, e._method.methodName, tiCaller);
if (!m.has_value())
throw "Unknown method";
- result = typeType(p, m.value().returnType);
+ result = typeType(p, m.value().t.returnType);
break;
}
case ExprType::Lit:
@@ -69,7 +70,7 @@ TypeInfo typeExpr(const Program & p, const std::vector<std::string> & globalName typeExpr(p, globalNamespace, globalCtx, *e._dot.expr), e._dot.identifier);
if (!sm.has_value())
throw "Unknown struct member";
- result = typeType(p, sm.value().type);
+ result = typeType(p, sm.value().t.type);
break;
}
case ExprType::PrefixOp:
diff --git a/src/visit.h b/src/visit.h new file mode 100644 index 0000000..0cfb9e6 --- /dev/null +++ b/src/visit.h @@ -0,0 +1,193 @@ +#pragma once
+
+#include "repr.h"
+
+#include <functional>
+
+struct Visitor {
+ std::function<void(const Type &, const std::vector<std::string> & namespaces)> onType = [](auto, auto){};
+ std::function<void(const Expr &, const std::vector<std::string> & namespaces)> onExpr = [](auto, auto){};
+ std::function<void(const Stmt &, const std::vector<std::string> & namespaces)> onStmt = [](auto, auto){};
+ std::function<void(const Body &, const std::vector<std::string> & namespaces)> onBody = [](auto, auto){};
+ std::function<void(const Function &, const std::vector<std::string> & namespaces)> onFunction = [](auto, auto){};
+ std::function<void(const Variable &, const std::vector<std::string> & namespaces)> onVariable = [](auto, auto){};
+ std::function<void(const StructMember<Function> &, const std::vector<std::string> & namespaces)> onStructMethod = [](auto, auto){};
+ std::function<void(const StructMember<Variable> &, const std::vector<std::string> & namespaces)> onStructMember = [](auto, auto){};
+ std::function<void(const Struct &, const std::vector<std::string> & namespaces)> onStruct = [](auto, auto){};
+ std::function<void(const Namespace &, const std::vector<std::string> & namespaces)> onNamespace = [](auto, auto){};
+ std::function<void(const Program &, const std::vector<std::string> & namespaces)> onProgram = [](auto, auto){};
+};
+
+#define VISIT(XS) for (auto x : XS) visit(x);
+
+struct Visit {
+private:
+ Visitor v;
+ std::vector<std::string> namespaces;
+public:
+ Visit(Visitor v)
+ {
+ this->v = v;
+ }
+ void visit(const Type & x)
+ {
+ v.onType(x, namespaces);
+ }
+ void visit(const Expr & x)
+ {
+ v.onExpr(x, namespaces);
+
+ switch (x.type)
+ {
+ case ExprType::Func:
+ VISIT(x._func.arguments)
+ break;
+ case ExprType::Method:
+ visit(*x._method.expr);
+ VISIT(x._method.arguments);
+ break;
+ case ExprType::Lit:
+ break;
+ case ExprType::Paren:
+ visit(*x._paren.expr);
+ break;
+ case ExprType::Dot:
+ visit(*x._dot.expr);
+ break;
+ case ExprType::PrefixOp:
+ visit(*x._prefixOp.expr);
+ break;
+ case ExprType::PostfixOp:
+ visit(*x._postfixOp.expr);
+ break;
+ case ExprType::BinaryOp:
+ visit(*x._binaryOp.lexpr);
+ visit(*x._binaryOp.rexpr);
+ break;
+ case ExprType::TernaryOp:
+ visit(*x._ternaryOp.lexpr);
+ visit(*x._ternaryOp.rexprTrue);
+ visit(*x._ternaryOp.rexprFalse);
+ break;
+ case ExprType::Bracket:
+ visit(*x._brackets.lexpr);
+ visit(*x._brackets.rexpr);
+ break;
+ case ExprType::Identifier:
+ break;
+ }
+ }
+ void visit(const Stmt & x)
+ {
+ v.onStmt(x, namespaces);
+
+ switch (x.type)
+ {
+ case StmtType::Assign:
+ visit(x._assign.lexpr);
+ visit(x._assign.rexpr);
+ break;
+ case StmtType::Expr:
+ visit(x._expr);
+ break;
+ case StmtType::For:
+ visit(x._for.init->lexpr);
+ visit(x._for.init->rexpr);
+ visit(*x._for.condition);
+ visit(*x._for.action);
+ visit(x._for.body);
+ break;
+ case StmtType::If:
+ visit(x._if.condition);
+ visit(x._if.body);
+ for (auto e : x._if.elses)
+ {
+ if (e._if)
+ visit(*e.expr);
+ visit(e.body);
+ }
+ break;
+ case StmtType::Return:
+ visit(x._return.expr);
+ break;
+ case StmtType::Switch:
+ visit(*x._switch.ident);
+ for (auto c : x._switch.cases)
+ {
+ visit(*c.expr);
+ visit(c.body);
+ }
+ break;
+ case StmtType::While:
+ visit(x._while.condition);
+ visit(x._while.body);
+ break;
+ }
+ }
+ void visit(const Body & x)
+ {
+ v.onBody(x, namespaces);
+
+ VISIT(x.ctx->variables)
+ VISIT(x.statements)
+ }
+ void visit(const Namespace & x)
+ {
+ v.onNamespace(x, namespaces);
+
+ namespaces.push_back(x.name);
+
+ VISIT(x.namespaces)
+ VISIT(x.ctx->variables)
+ VISIT(x.structs)
+ VISIT(x.functions)
+
+ namespaces.pop_back();
+ }
+ void visit(const Variable & x)
+ {
+ v.onVariable(x, namespaces);
+ visit(x.type);
+ }
+ void visit(const Function & x)
+ {
+ v.onFunction(x, namespaces);
+
+ if (x.defined) {
+ visit(x.body);
+ for (auto v : x.parameters)
+ visit(v.type);
+ }
+ }
+ void visit(const StructMember<Function> & x)
+ {
+ v.onStructMethod(x, namespaces);
+
+ visit(x.t);
+ }
+ void visit(const StructMember<Variable> & x)
+ {
+ v.onStructMember(x, namespaces);
+
+ visit(x.t);
+ }
+ void visit(const Struct & x)
+ {
+ v.onStruct(x, namespaces);
+
+ VISIT(x.members)
+ VISIT(x.methods)
+ }
+ void visit(const Program & x)
+ {
+ v.onProgram(x, namespaces);
+
+ VISIT(x.namespaces)
+ VISIT(x.ctx->variables)
+ VISIT(x.structs)
+ VISIT(x.functions)
+ }
+};
+
+#undef VISIT
+
|
