#pragma once #include #include #include #include "type.hpp" #include "type_env.hpp" #include "binop.hpp" #include "instruction.hpp" #include "env.hpp" #include "definition.hpp" #include "location.hh" #include "global_scope.hpp" struct ast { type_env_ptr env; yy::location loc; ast(yy::location l) : env(nullptr), loc(std::move(l)) {} virtual ~ast() = default; virtual void print(int indent, std::ostream& to) const = 0; virtual void find_free(std::set& into) = 0; virtual type_ptr typecheck(type_mgr& mgr, type_env_ptr& env) = 0; virtual void translate(global_scope& scope) = 0; virtual void compile(const env_ptr& env, std::vector& into) const = 0; }; using ast_ptr = std::unique_ptr; struct pattern { yy::location loc; pattern(yy::location l) : loc(std::move(l)) {} virtual ~pattern() = default; virtual void print(std::ostream& to) const = 0; virtual void find_variables(std::set& into) const = 0; virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const = 0; }; using pattern_ptr = std::unique_ptr; struct branch { pattern_ptr pat; ast_ptr expr; branch(pattern_ptr p, ast_ptr a) : pat(std::move(p)), expr(std::move(a)) {} }; using branch_ptr = std::unique_ptr; struct ast_int : public ast { int value; explicit ast_int(int v, yy::location l = yy::location()) : ast(std::move(l)), value(v) {} void print(int indent, std::ostream& to) const; void find_free(std::set& into); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; struct ast_lid : public ast { std::string id; explicit ast_lid(std::string i, yy::location l = yy::location()) : ast(std::move(l)), id(std::move(i)) {} void print(int indent, std::ostream& to) const; void find_free(std::set& into); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; struct ast_uid : public ast { std::string id; explicit ast_uid(std::string i, yy::location l = yy::location()) : ast(std::move(l)), id(std::move(i)) {} void print(int indent, std::ostream& to) const; void find_free(std::set& into); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; struct ast_binop : public ast { binop op; ast_ptr left; ast_ptr right; ast_binop(binop o, ast_ptr l, ast_ptr r, yy::location lc = yy::location()) : ast(std::move(lc)), op(o), left(std::move(l)), right(std::move(r)) {} void print(int indent, std::ostream& to) const; void find_free(std::set& into); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; struct ast_app : public ast { ast_ptr left; ast_ptr right; ast_app(ast_ptr l, ast_ptr r, yy::location lc = yy::location()) : ast(std::move(lc)), left(std::move(l)), right(std::move(r)) {} void print(int indent, std::ostream& to) const; void find_free(std::set& into); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; struct ast_case : public ast { ast_ptr of; type_ptr input_type; std::vector branches; ast_case(ast_ptr o, std::vector b, yy::location l = yy::location()) : ast(std::move(l)), of(std::move(o)), branches(std::move(b)) {} void print(int indent, std::ostream& to) const; void find_free(std::set& into); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; struct ast_let : public ast { using basic_definition = std::pair; definition_group definitions; ast_ptr in; std::vector translated_definitions; ast_let(definition_group g, ast_ptr i, yy::location l = yy::location()) : ast(std::move(l)), definitions(std::move(g)), in(std::move(i)) {} void print(int indent, std::ostream& to) const; void find_free(std::set& into); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; struct ast_lambda : public ast { std::vector params; ast_ptr body; type_env_ptr var_env; std::set free_variables; ast_ptr translated; ast_lambda(std::vector ps, ast_ptr b, yy::location l = yy::location()) : ast(std::move(l)), params(std::move(ps)), body(std::move(b)) {} void print(int indent, std::ostream& to) const; void find_free(std::set& into); type_ptr typecheck(type_mgr& mgr, type_env_ptr& env); void translate(global_scope& scope); void compile(const env_ptr& env, std::vector& into) const; }; struct pattern_var : public pattern { std::string var; pattern_var(std::string v, yy::location l = yy::location()) : pattern(std::move(l)), var(std::move(v)) {} void print(std::ostream &to) const; void find_variables(std::set& into) const; void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const; }; struct pattern_constr : public pattern { std::string constr; std::vector params; pattern_constr(std::string c, std::vector p, yy::location l = yy::location()) : pattern(std::move(l)), constr(std::move(c)), params(std::move(p)) {} void print(std::ostream &to) const; void find_variables(std::set& into) const; virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const; };