#pragma once #include "BasicBlock.hpp" #include "Constant.hpp" #include "Function.hpp" #include "IRBuilder.hpp" #include "Module.hpp" #include "Type.hpp" #include "ast.hpp" #include #include class Scope { public: // enter a new scope void enter() { inner.emplace_back(); } // exit a scope void exit() { inner.pop_back(); } bool in_global() { return inner.size() == 1; } // push a name to scope // return true if successful // return false if this name already exits bool push(const std::string& name, Value *val) { auto result = inner[inner.size() - 1].insert({name, val}); return result.second; } Value *find(const std::string& name) { for (auto s = inner.rbegin(); s != inner.rend(); s++) { auto iter = s->find(name); if (iter != s->end()) { return iter->second; } } // Name not found: handled here? assert(false && "Name not found in scope"); return nullptr; } private: std::vector> inner; }; class CminusfBuilder : public ASTVisitor { public: CminusfBuilder() { module = std::make_unique(); builder = std::make_unique(nullptr, module.get()); auto *TyVoid = module->get_void_type(); auto *TyInt32 = module->get_int32_type(); auto *TyFloat = module->get_float_type(); auto *input_type = FunctionType::get(TyInt32, {}); auto *input_fun = Function::create(input_type, "input", module.get()); std::vector output_params; output_params.push_back(TyInt32); auto *output_type = FunctionType::get(TyVoid, output_params); auto *output_fun = Function::create(output_type, "output", module.get()); std::vector output_float_params; output_float_params.push_back(TyFloat); auto *output_float_type = FunctionType::get(TyVoid, output_float_params); auto *output_float_fun = Function::create(output_float_type, "outputFloat", module.get()); auto *neg_idx_except_type = FunctionType::get(TyVoid, {}); auto *neg_idx_except_fun = Function::create( neg_idx_except_type, "neg_idx_except", module.get()); scope.enter(); scope.push("input", input_fun); scope.push("output", output_fun); scope.push("outputFloat", output_float_fun); scope.push("neg_idx_except", neg_idx_except_fun); } std::unique_ptr getModule() { return std::move(module); } private: virtual Value *visit(ASTProgram &) override final; virtual Value *visit(ASTNum &) override final; virtual Value *visit(ASTVarDeclaration &) override final; virtual Value *visit(ASTFunDeclaration &) override final; virtual Value *visit(ASTParam &) override final; virtual Value *visit(ASTCompoundStmt &) override final; virtual Value *visit(ASTExpressionStmt &) override final; virtual Value *visit(ASTSelectionStmt &) override final; virtual Value *visit(ASTIterationStmt &) override final; virtual Value *visit(ASTReturnStmt &) override final; virtual Value *visit(ASTAssignExpression &) override final; virtual Value *visit(ASTSimpleExpression &) override final; virtual Value *visit(ASTAdditiveExpression &) override final; virtual Value *visit(ASTVar &) override final; virtual Value *visit(ASTTerm &) override final; virtual Value *visit(ASTCall &) override final; std::unique_ptr builder; Scope scope; std::unique_ptr module; struct { // function that is being built Function *func = nullptr; // TODO: you should add more fields to store state } context; };