From 08246f1474f3c71420df86c08850cfd79d7afdc6 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 25 Mar 2020 03:22:21 -0700 Subject: [PATCH] Finalize draft of polymorphism post --- 10/CMakeLists.txt | 1 + 10/ast.cpp | 6 +++ 10/definition.cpp | 9 ++-- 10/examples/if.txt | 8 ++++ 10/graph.hpp | 113 --------------------------------------------- 10/main.cpp | 5 +- 10/type_env.cpp | 12 +++++ 10/type_env.hpp | 3 ++ 8 files changed, 40 insertions(+), 117 deletions(-) create mode 100644 10/examples/if.txt diff --git a/10/CMakeLists.txt b/10/CMakeLists.txt index 1347f11..a16b8f9 100644 --- a/10/CMakeLists.txt +++ b/10/CMakeLists.txt @@ -29,6 +29,7 @@ add_executable(compiler error.cpp error.hpp binop.cpp binop.hpp instruction.cpp instruction.hpp + graph.cpp graph.hpp ${BISON_parser_OUTPUTS} ${FLEX_scanner_OUTPUTS} main.cpp diff --git a/10/ast.cpp b/10/ast.cpp index b55c347..bbf72e7 100644 --- a/10/ast.cpp +++ b/10/ast.cpp @@ -1,7 +1,9 @@ #include "ast.hpp" #include +#include #include "binop.hpp" #include "error.hpp" +#include "type.hpp" #include "type_env.hpp" static void print_indent(int n, std::ostream& to) { @@ -162,6 +164,10 @@ type_ptr ast_case::typecheck(type_mgr& mgr) { input_type = mgr.resolve(case_type, var); if(!dynamic_cast(input_type.get())) { + std::cout << dynamic_cast(input_type.get()) << std::endl; + std::cout << dynamic_cast(input_type.get()) << std::endl; + std::cout << var << std::endl; + input_type->print(mgr, std::cout); std::cout << std::endl; throw type_error("attempting case analysis of non-data type"); } diff --git a/10/definition.cpp b/10/definition.cpp index c4bf4f7..91b0178 100644 --- a/10/definition.cpp +++ b/10/definition.cpp @@ -3,6 +3,7 @@ #include "ast.hpp" #include "instruction.hpp" #include "llvm_context.hpp" +#include "type.hpp" #include "type_env.hpp" #include #include @@ -57,11 +58,12 @@ void definition_defn::generate_llvm(llvm_context& ctx) { void definition_data::insert_types(type_mgr& mgr, type_env_ptr& env) { this->env = env; + env->bind_type(name, type_ptr(new type_data(name))); } void definition_data::insert_constructors() const { - type_data* this_type = new type_data(name); - type_ptr return_type = type_ptr(this_type); + type_ptr return_type = env->lookup_type(name); + type_data* this_type = static_cast(return_type.get()); int next_tag = 0; for(auto& constructor : constructors) { @@ -70,7 +72,8 @@ void definition_data::insert_constructors() const { type_ptr full_type = return_type; for(auto it = constructor->types.rbegin(); it != constructor->types.rend(); it++) { - type_ptr type = type_ptr(new type_base(*it)); + type_ptr type = env->lookup_type(*it); + if(!type) throw 0; full_type = type_ptr(new type_arr(type, full_type)); } diff --git a/10/examples/if.txt b/10/examples/if.txt new file mode 100644 index 0000000..c00df35 --- /dev/null +++ b/10/examples/if.txt @@ -0,0 +1,8 @@ +data Bool = { True, False } +defn if c t e = { + case c of { + True -> { t } + False -> { e } + } +} +defn main = { if (if True False True) 11 3 } diff --git a/10/graph.hpp b/10/graph.hpp index d1b0a86..2db8d7c 100644 --- a/10/graph.hpp +++ b/10/graph.hpp @@ -50,116 +50,3 @@ class function_graph { void add_edge(const function& from, const function& to); std::vector compute_order(); }; - -std::set function_graph::compute_transitive_edges() { - std::set transitive_edges; - transitive_edges.insert(edges.begin(), edges.end()); - for(auto& connector : adjacency_lists) { - for(auto& from : adjacency_lists) { - edge to_connector { from.first, connector.first }; - for(auto& to : adjacency_lists) { - edge full_jump { from.first, to.first }; - if(transitive_edges.find(full_jump) != transitive_edges.end()) continue; - - edge from_connector { connector.first, to.first }; - if(transitive_edges.find(to_connector) != transitive_edges.end() && - transitive_edges.find(from_connector) != transitive_edges.end()) - transitive_edges.insert(std::move(full_jump)); - } - } - } - return transitive_edges; -} - -void function_graph::create_groups( - const std::set& transitive_edges, - std::map& group_ids, - std::map& group_data_map) { - group_id id_counter = 0; - for(auto& vertex : adjacency_lists) { - if(group_ids.find(vertex.first) != group_ids.end()) - continue; - data_ptr new_group(new group_data); - new_group->functions.insert(vertex.first); - group_data_map[id_counter] = new_group; - group_ids[vertex.first] = id_counter; - for(auto& other_vertex : adjacency_lists) { - if(transitive_edges.find({vertex.first, other_vertex.first}) != transitive_edges.end() && - transitive_edges.find({other_vertex.first, vertex.first}) != transitive_edges.end()) { - group_ids[other_vertex.first] = id_counter; - new_group->functions.insert(other_vertex.first); - } - } - id_counter++; - } -} - -void function_graph::create_edges( - std::map& group_ids, - std::map& group_data_map) { - std::set> group_edges; - for(auto& vertex : adjacency_lists) { - auto vertex_id = group_ids[vertex.first]; - auto& vertex_data = group_data_map[vertex_id]; - for(auto& other_vertex : vertex.second) { - auto other_id = group_ids[other_vertex]; - if(vertex_id == other_id) continue; - if(group_edges.find({vertex_id, other_id}) != group_edges.end()) - continue; - group_edges.insert({vertex_id, other_id}); - vertex_data->adjacency_list.insert(other_id); - group_data_map[other_id]->indegree++; - } - } -} - -std::vector function_graph::generate_order( - std::map& group_ids, - std::map& group_data_map) { - std::queue id_queue; - std::vector output; - for(auto& group : group_data_map) { - if(group.second->indegree == 0) id_queue.push(group.first); - } - - while(!id_queue.empty()) { - auto new_id = id_queue.front(); - auto& group_data = group_data_map[new_id]; - group_ptr output_group(new group); - output_group->members = std::move(group_data->functions); - id_queue.pop(); - - for(auto& adjacent_group : group_data->adjacency_list) { - if(--group_data_map[adjacent_group]->indegree == 0) - id_queue.push(adjacent_group); - } - - output.push_back(std::move(output_group)); - } - - return output; -} - -std::set& function_graph::add_function(const function& f) { - auto adjacency_list_it = adjacency_lists.find(f); - if(adjacency_list_it != adjacency_lists.end()) { - return adjacency_list_it->second; - } else { - return adjacency_lists[f] = { }; - } -} - -void function_graph::add_edge(const function& from, const function& to) { - add_function(from).insert(to); - edges.insert({ from, to }); -} - -std::vector function_graph::compute_order() { - std::set transitive_edges = compute_transitive_edges(); - std::map group_ids; - std::map group_data_map; - - create_groups(transitive_edges, group_ids, group_data_map); - create_edges(group_ids, group_data_map); - return generate_order(group_ids, group_data_map); -} diff --git a/10/main.cpp b/10/main.cpp index dabc108..bc181d6 100644 --- a/10/main.cpp +++ b/10/main.cpp @@ -29,10 +29,11 @@ void typecheck_program( const std::map& defs_defn, type_mgr& mgr, type_env_ptr& env) { type_ptr int_type = type_ptr(new type_base("Int")); + env->bind_type("Int", int_type); + type_ptr binop_type = type_ptr(new type_arr( int_type, type_ptr(new type_arr(int_type, int_type)))); - env->bind("+", binop_type); env->bind("-", binop_type); env->bind("*", binop_type); @@ -68,6 +69,8 @@ void typecheck_program( for(auto& def_defnn_name : group->members) { auto& def_defn = defs_defn.find(def_defnn_name)->second; def_defn->typecheck(mgr); + } + for(auto& def_defnn_name : group->members) { env->generalize(def_defnn_name, mgr); } } diff --git a/10/type_env.cpp b/10/type_env.cpp index 0418af6..3e654be 100644 --- a/10/type_env.cpp +++ b/10/type_env.cpp @@ -8,6 +8,13 @@ type_scheme_ptr type_env::lookup(const std::string& name) const { return nullptr; } +type_ptr type_env::lookup_type(const std::string& name) const { + auto it = type_names.find(name); + if(it != type_names.end()) return it->second; + if(parent) return parent->lookup_type(name); + return nullptr; +} + void type_env::bind(const std::string& name, type_ptr t) { names[name] = type_scheme_ptr(new type_scheme(t)); } @@ -16,6 +23,11 @@ void type_env::bind(const std::string& name, type_scheme_ptr t) { names[name] = t; } +void type_env::bind_type(const std::string& type_name, type_ptr t) { + if(lookup_type(type_name) != nullptr) throw 0; + type_names[type_name] = t; +} + void type_env::generalize(const std::string& name, type_mgr& mgr) { auto names_it = names.find(name); if(names_it == names.end()) throw 0; diff --git a/10/type_env.hpp b/10/type_env.hpp index 69bc703..444e26b 100644 --- a/10/type_env.hpp +++ b/10/type_env.hpp @@ -8,13 +8,16 @@ using type_env_ptr = std::shared_ptr; struct type_env { type_env_ptr parent; std::map names; + std::map type_names; type_env(type_env_ptr p) : parent(std::move(p)) {} type_env() : type_env(nullptr) {} type_scheme_ptr lookup(const std::string& name) const; + type_ptr lookup_type(const std::string& name) const; void bind(const std::string& name, type_ptr t); void bind(const std::string& name, type_scheme_ptr t); + void bind_type(const std::string& type_name, type_ptr t); void generalize(const std::string& name, type_mgr& mgr); };