From 74e6dba9140991a04954d2b57d33630a20ac75c0 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Mon, 13 Apr 2020 14:20:35 -0700 Subject: [PATCH] Add parsed type data structure, type application and arity. --- code/compiler/11/CMakeLists.txt | 4 ++- code/compiler/11/parsed_type.cpp | 35 +++++++++++++++++++++++ code/compiler/11/parsed_type.hpp | 43 ++++++++++++++++++++++++++++ code/compiler/11/type.cpp | 48 ++++++++++++++++++++++++++++---- code/compiler/11/type.hpp | 15 ++++++++-- 5 files changed, 136 insertions(+), 9 deletions(-) create mode 100644 code/compiler/11/parsed_type.cpp create mode 100644 code/compiler/11/parsed_type.hpp diff --git a/code/compiler/11/CMakeLists.txt b/code/compiler/11/CMakeLists.txt index a16b8f9..c3fb2ef 100644 --- a/code/compiler/11/CMakeLists.txt +++ b/code/compiler/11/CMakeLists.txt @@ -21,7 +21,9 @@ llvm_map_components_to_libnames(LLVM_LIBS core x86asmparser x86codegen) # Create compiler executable add_executable(compiler - ast.cpp ast.hpp definition.cpp + definition.cpp definition.hpp + parsed_type.cpp parsed_type.hpp + ast.cpp ast.hpp llvm_context.cpp llvm_context.hpp type_env.cpp type_env.hpp env.cpp env.hpp diff --git a/code/compiler/11/parsed_type.cpp b/code/compiler/11/parsed_type.cpp new file mode 100644 index 0000000..ba6fddd --- /dev/null +++ b/code/compiler/11/parsed_type.cpp @@ -0,0 +1,35 @@ +#include "parsed_type.hpp" +#include "type.hpp" +#include "type_env.hpp" + +type_ptr parsed_type_app::to_type( + const std::set& vars, + const type_env& e) const { + auto parent_type = e.lookup_type(name); + if(parent_type == nullptr) throw 0; + type_base* base_type; + if(!(base_type = dynamic_cast(parent_type.get()))) throw 0; + + type_app* new_app = new type_app(std::move(parent_type)); + type_ptr to_return(new_app); + for(auto& arg : arguments) { + new_app->arguments.push_back(arg->to_type(vars, e)); + } + return to_return; +} + +type_ptr parsed_type_var::to_type( + const std::set& vars, + const type_env& e) const { + if(vars.find(var) != vars.end()) throw 0; + return type_ptr(new type_var(var)); +} + + +type_ptr parsed_type_arr::to_type( + const std::set& vars, + const type_env& env) const { + auto new_left = left->to_type(vars, env); + auto new_right = right->to_type(vars, env); + return type_ptr(new type_arr(std::move(new_left), std::move(new_right))); +} diff --git a/code/compiler/11/parsed_type.hpp b/code/compiler/11/parsed_type.hpp new file mode 100644 index 0000000..96c0fcc --- /dev/null +++ b/code/compiler/11/parsed_type.hpp @@ -0,0 +1,43 @@ +#pragma once +#include +#include +#include +#include "type_env.hpp" + +struct parsed_type { + virtual type_ptr to_type( + const std::set& vars, + const type_env& env) const = 0; +}; + +using parsed_type_ptr = std::unique_ptr; + +struct parsed_type_app : parsed_type { + std::string name; + std::vector arguments; + + parsed_type_app( + std::string n, + std::vector as) + : name(std::move(n)), arguments(std::move(as)) {} + + type_ptr to_type(const std::set& vars, const type_env& env) const; +}; + +struct parsed_type_var : parsed_type { + std::string var; + + parsed_type_var(std::string v) : var(std::move(v)) {} + + type_ptr to_type(const std::set& vars, const type_env& env) const; +}; + +struct parsed_type_arr : parsed_type { + parsed_type_ptr left; + parsed_type_ptr right; + + parsed_type_arr(parsed_type_ptr l, parsed_type_ptr r) + : left(std::move(l)), right(std::move(r)) {} + + type_ptr to_type(const std::set& vars, const type_env& env) const; +}; diff --git a/code/compiler/11/type.cpp b/code/compiler/11/type.cpp index d355e87..6c381b8 100644 --- a/code/compiler/11/type.cpp +++ b/code/compiler/11/type.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "error.hpp" void type_scheme::print(const type_mgr& mgr, std::ostream& to) const { @@ -27,6 +28,20 @@ type_ptr substitute(const type_mgr& mgr, const std::map& auto right_result = substitute(mgr, subst, arr->right); if(left_result == arr->left && right_result == arr->right) return t; return type_ptr(new type_arr(left_result, right_result)); + } else if(type_app* app = dynamic_cast(t.get())) { + auto constructor_result = substitute(mgr, subst, app->constructor); + bool arg_changed = false; + std::vector new_args; + for(auto& arg : app->arguments) { + auto arg_result = substitute(mgr, subst, arg); + arg_changed |= arg_result != arg; + new_args.push_back(std::move(arg_result)); + } + + if(constructor_result == app->constructor && !arg_changed) return t; + type_app* new_app = new type_app(std::move(constructor_result)); + std::swap(new_app->arguments, new_args); + return type_ptr(new_app); } return t; } @@ -60,6 +75,15 @@ void type_arr::print(const type_mgr& mgr, std::ostream& to) const { to << ")"; } +void type_app::print(const type_mgr& mgr, std::ostream& to) const { + constructor->print(mgr, to); + to << "* "; + for(auto& arg : arguments) { + to << " "; + arg->print(mgr, to); + } +} + std::string type_mgr::new_type_name() { int temp = last_id++; std::string str = ""; @@ -99,12 +123,10 @@ type_ptr type_mgr::resolve(type_ptr t, type_var*& var) const { } void type_mgr::unify(type_ptr l, type_ptr r) { - type_var* lvar; - type_var* rvar; - type_arr* larr; - type_arr* rarr; - type_base* lid; - type_base* rid; + type_var *lvar, *rvar; + type_arr *larr, *rarr; + type_base *lid, *rid; + type_app *lapp, *rapp; l = resolve(l, lvar); r = resolve(r, rvar); @@ -123,6 +145,17 @@ void type_mgr::unify(type_ptr l, type_ptr r) { } else if((lid = dynamic_cast(l.get())) && (rid = dynamic_cast(r.get()))) { if(lid->name == rid->name) return; + } else if((lapp = dynamic_cast(l.get())) && + (rapp = dynamic_cast(r.get()))) { + unify(lapp->constructor, rapp->constructor); + auto left_it = lapp->arguments.begin(); + auto right_it = rapp->arguments.begin(); + while(left_it != lapp->arguments.end() && + right_it != rapp->arguments.end()) { + unify(*left_it, *right_it); + left_it++, right_it++; + } + return; } throw unification_error(l, r); @@ -144,5 +177,8 @@ void type_mgr::find_free(const type_ptr& t, std::set& into) const { } else if(type_arr* arr = dynamic_cast(resolved.get())) { find_free(arr->left, into); find_free(arr->right, into); + } else if(type_app* app = dynamic_cast(resolved.get())) { + find_free(app->constructor, into); + for(auto& arg : app->arguments) find_free(arg, into); } } diff --git a/code/compiler/11/type.hpp b/code/compiler/11/type.hpp index 94c4f85..cd3bd45 100644 --- a/code/compiler/11/type.hpp +++ b/code/compiler/11/type.hpp @@ -38,9 +38,10 @@ struct type_var : public type { struct type_base : public type { std::string name; + int32_t arity; - type_base(std::string n) - : name(std::move(n)) {} + type_base(std::string n, int32_t a = 0) + : name(std::move(n)), arity(a) {} void print(const type_mgr& mgr, std::ostream& to) const; }; @@ -66,6 +67,16 @@ struct type_arr : public type { void print(const type_mgr& mgr, std::ostream& to) const; }; +struct type_app : public type { + type_ptr constructor; + std::vector arguments; + + type_app(type_ptr c) + : constructor(std::move(c)) {} + + void print(const type_mgr& mgr, std::ostream& to) const; +}; + struct type_mgr { int last_id = 0; std::map types;