Finalize draft of polymorphism post
This commit is contained in:
parent
de435d6c80
commit
08246f1474
|
@ -29,6 +29,7 @@ add_executable(compiler
|
||||||
error.cpp error.hpp
|
error.cpp error.hpp
|
||||||
binop.cpp binop.hpp
|
binop.cpp binop.hpp
|
||||||
instruction.cpp instruction.hpp
|
instruction.cpp instruction.hpp
|
||||||
|
graph.cpp graph.hpp
|
||||||
${BISON_parser_OUTPUTS}
|
${BISON_parser_OUTPUTS}
|
||||||
${FLEX_scanner_OUTPUTS}
|
${FLEX_scanner_OUTPUTS}
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#include "ast.hpp"
|
#include "ast.hpp"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <iostream>
|
||||||
#include "binop.hpp"
|
#include "binop.hpp"
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
|
#include "type.hpp"
|
||||||
#include "type_env.hpp"
|
#include "type_env.hpp"
|
||||||
|
|
||||||
static void print_indent(int n, std::ostream& to) {
|
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);
|
input_type = mgr.resolve(case_type, var);
|
||||||
if(!dynamic_cast<type_data*>(input_type.get())) {
|
if(!dynamic_cast<type_data*>(input_type.get())) {
|
||||||
|
std::cout << dynamic_cast<type_data*>(input_type.get()) << std::endl;
|
||||||
|
std::cout << dynamic_cast<type_base*>(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");
|
throw type_error("attempting case analysis of non-data type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "ast.hpp"
|
#include "ast.hpp"
|
||||||
#include "instruction.hpp"
|
#include "instruction.hpp"
|
||||||
#include "llvm_context.hpp"
|
#include "llvm_context.hpp"
|
||||||
|
#include "type.hpp"
|
||||||
#include "type_env.hpp"
|
#include "type_env.hpp"
|
||||||
#include <llvm/IR/DerivedTypes.h>
|
#include <llvm/IR/DerivedTypes.h>
|
||||||
#include <llvm/IR/Function.h>
|
#include <llvm/IR/Function.h>
|
||||||
|
@ -57,11 +58,12 @@ void definition_defn::generate_llvm(llvm_context& ctx) {
|
||||||
|
|
||||||
void definition_data::insert_types(type_mgr& mgr, type_env_ptr& env) {
|
void definition_data::insert_types(type_mgr& mgr, type_env_ptr& env) {
|
||||||
this->env = env;
|
this->env = env;
|
||||||
|
env->bind_type(name, type_ptr(new type_data(name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void definition_data::insert_constructors() const {
|
void definition_data::insert_constructors() const {
|
||||||
type_data* this_type = new type_data(name);
|
type_ptr return_type = env->lookup_type(name);
|
||||||
type_ptr return_type = type_ptr(this_type);
|
type_data* this_type = static_cast<type_data*>(return_type.get());
|
||||||
int next_tag = 0;
|
int next_tag = 0;
|
||||||
|
|
||||||
for(auto& constructor : constructors) {
|
for(auto& constructor : constructors) {
|
||||||
|
@ -70,7 +72,8 @@ void definition_data::insert_constructors() const {
|
||||||
|
|
||||||
type_ptr full_type = return_type;
|
type_ptr full_type = return_type;
|
||||||
for(auto it = constructor->types.rbegin(); it != constructor->types.rend(); it++) {
|
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));
|
full_type = type_ptr(new type_arr(type, full_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
10/examples/if.txt
Normal file
8
10/examples/if.txt
Normal file
|
@ -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 }
|
113
10/graph.hpp
113
10/graph.hpp
|
@ -50,116 +50,3 @@ class function_graph {
|
||||||
void add_edge(const function& from, const function& to);
|
void add_edge(const function& from, const function& to);
|
||||||
std::vector<group_ptr> compute_order();
|
std::vector<group_ptr> compute_order();
|
||||||
};
|
};
|
||||||
|
|
||||||
std::set<function_graph::edge> function_graph::compute_transitive_edges() {
|
|
||||||
std::set<edge> 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<edge>& transitive_edges,
|
|
||||||
std::map<function, group_id>& group_ids,
|
|
||||||
std::map<group_id, data_ptr>& 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<function, group_id>& group_ids,
|
|
||||||
std::map<group_id, data_ptr>& group_data_map) {
|
|
||||||
std::set<std::pair<group_id, group_id>> 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<group_ptr> function_graph::generate_order(
|
|
||||||
std::map<function, group_id>& group_ids,
|
|
||||||
std::map<group_id, data_ptr>& group_data_map) {
|
|
||||||
std::queue<group_id> id_queue;
|
|
||||||
std::vector<group_ptr> 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>& 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<group_ptr> function_graph::compute_order() {
|
|
||||||
std::set<edge> transitive_edges = compute_transitive_edges();
|
|
||||||
std::map<function, group_id> group_ids;
|
|
||||||
std::map<group_id, data_ptr> 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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,10 +29,11 @@ void typecheck_program(
|
||||||
const std::map<std::string, definition_defn_ptr>& defs_defn,
|
const std::map<std::string, definition_defn_ptr>& defs_defn,
|
||||||
type_mgr& mgr, type_env_ptr& env) {
|
type_mgr& mgr, type_env_ptr& env) {
|
||||||
type_ptr int_type = type_ptr(new type_base("Int"));
|
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(
|
type_ptr binop_type = type_ptr(new type_arr(
|
||||||
int_type,
|
int_type,
|
||||||
type_ptr(new type_arr(int_type, int_type))));
|
type_ptr(new type_arr(int_type, int_type))));
|
||||||
|
|
||||||
env->bind("+", binop_type);
|
env->bind("+", binop_type);
|
||||||
env->bind("-", binop_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) {
|
for(auto& def_defnn_name : group->members) {
|
||||||
auto& def_defn = defs_defn.find(def_defnn_name)->second;
|
auto& def_defn = defs_defn.find(def_defnn_name)->second;
|
||||||
def_defn->typecheck(mgr);
|
def_defn->typecheck(mgr);
|
||||||
|
}
|
||||||
|
for(auto& def_defnn_name : group->members) {
|
||||||
env->generalize(def_defnn_name, mgr);
|
env->generalize(def_defnn_name, mgr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,13 @@ type_scheme_ptr type_env::lookup(const std::string& name) const {
|
||||||
return nullptr;
|
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) {
|
void type_env::bind(const std::string& name, type_ptr t) {
|
||||||
names[name] = type_scheme_ptr(new type_scheme(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;
|
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) {
|
void type_env::generalize(const std::string& name, type_mgr& mgr) {
|
||||||
auto names_it = names.find(name);
|
auto names_it = names.find(name);
|
||||||
if(names_it == names.end()) throw 0;
|
if(names_it == names.end()) throw 0;
|
||||||
|
|
|
@ -8,13 +8,16 @@ using type_env_ptr = std::shared_ptr<type_env>;
|
||||||
struct type_env {
|
struct type_env {
|
||||||
type_env_ptr parent;
|
type_env_ptr parent;
|
||||||
std::map<std::string, type_scheme_ptr> names;
|
std::map<std::string, type_scheme_ptr> names;
|
||||||
|
std::map<std::string, type_ptr> type_names;
|
||||||
|
|
||||||
type_env(type_env_ptr p) : parent(std::move(p)) {}
|
type_env(type_env_ptr p) : parent(std::move(p)) {}
|
||||||
type_env() : type_env(nullptr) {}
|
type_env() : type_env(nullptr) {}
|
||||||
|
|
||||||
type_scheme_ptr lookup(const std::string& name) const;
|
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_ptr t);
|
||||||
void bind(const std::string& name, type_scheme_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);
|
void generalize(const std::string& name, type_mgr& mgr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user