Function* Backend::compile(const Stmt& stmt, vector<ir::Var> output){ Environment env; std::set<Var> externSet; for (const Var& var : output) { if (!util::contains(externSet, var)) { // Remove duplicates externSet.insert(var); env.addExtern(var); } } return compile(stmt, env, Storage()); }
backend::Function* Backend::compile(const Stmt& stmt, const Environment& env, const Storage& storage) { Environment environment = env; // copy // Add output and undefined variable in the stmt to the environment as externs std::set<Var> globalsSet; util::ScopedMap<Var,void*> definedVariables; // Add all environment variables to defined variables for (auto& var : environment.getConstants()) { globalsSet.insert(var.first); definedVariables.insert(var.first, nullptr); } for (auto& ext : environment.getExterns()) { const Var& var = ext.getVar(); globalsSet.insert(var); definedVariables.insert(var, nullptr); } for (auto& tmp : environment.getTemporaries()) { globalsSet.insert(tmp); definedVariables.insert(tmp, nullptr); } // Find all undefined variables and add them to the context as globals. function<void(Var var)> addToGlobalsIfNotDefined = [&](Var var) { if (!definedVariables.contains(var) && !util::contains(globalsSet, var)) { environment.addExtern(var); globalsSet.insert(var); definedVariables.insert(var, nullptr); } }; match(stmt, function<void(const VarExpr*)>([&](const VarExpr* op) { addToGlobalsIfNotDefined(op->var); }) , function<void(const AssignStmt*)>([&](const AssignStmt* op) { definedVariables.insert(op->var, nullptr); }) , function<void(const VarDecl*)>([&](const VarDecl* op) { definedVariables.insert(op->var, nullptr); }) , function<void(const ForRange*,Matcher*)>([&](const ForRange* op, Matcher* ctx) { ctx->match(op->start); ctx->match(op->end); definedVariables.insert(op->var, nullptr); ctx->match(op->body); }) , function<void(const For*,Matcher*)>([&](const For* op, Matcher* ctx) { definedVariables.insert(op->var, nullptr); ctx->match(op->body); }) , function<void(const Scope*,Matcher*)>([&](const Scope* op, Matcher* ctx) { definedVariables.scope(); ctx->match(op->scopedStmt); definedVariables.unscope(); }) ); Func func("main", {}, {}, stmt, environment); return pimpl->compile(func, storage); }