Add parsed type data structure, type application and arity.

This commit is contained in:
Danila Fedorin 2020-04-13 14:20:35 -07:00
parent d7846e0b32
commit 74e6dba914
5 changed files with 136 additions and 9 deletions

View File

@ -21,7 +21,9 @@ llvm_map_components_to_libnames(LLVM_LIBS core x86asmparser x86codegen)
# Create compiler executable # Create compiler executable
add_executable(compiler 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 llvm_context.cpp llvm_context.hpp
type_env.cpp type_env.hpp type_env.cpp type_env.hpp
env.cpp env.hpp env.cpp env.hpp

View File

@ -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<std::string>& 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<type_base*>(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<std::string>& 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<std::string>& 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)));
}

View File

@ -0,0 +1,43 @@
#pragma once
#include <memory>
#include <set>
#include <string>
#include "type_env.hpp"
struct parsed_type {
virtual type_ptr to_type(
const std::set<std::string>& vars,
const type_env& env) const = 0;
};
using parsed_type_ptr = std::unique_ptr<parsed_type>;
struct parsed_type_app : parsed_type {
std::string name;
std::vector<parsed_type_ptr> arguments;
parsed_type_app(
std::string n,
std::vector<parsed_type_ptr> as)
: name(std::move(n)), arguments(std::move(as)) {}
type_ptr to_type(const std::set<std::string>& 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<std::string>& 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<std::string>& vars, const type_env& env) const;
};

View File

@ -2,6 +2,7 @@
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include <vector>
#include "error.hpp" #include "error.hpp"
void type_scheme::print(const type_mgr& mgr, std::ostream& to) const { 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<std::string, type_ptr>&
auto right_result = substitute(mgr, subst, arr->right); auto right_result = substitute(mgr, subst, arr->right);
if(left_result == arr->left && right_result == arr->right) return t; if(left_result == arr->left && right_result == arr->right) return t;
return type_ptr(new type_arr(left_result, right_result)); return type_ptr(new type_arr(left_result, right_result));
} else if(type_app* app = dynamic_cast<type_app*>(t.get())) {
auto constructor_result = substitute(mgr, subst, app->constructor);
bool arg_changed = false;
std::vector<type_ptr> 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; return t;
} }
@ -60,6 +75,15 @@ void type_arr::print(const type_mgr& mgr, std::ostream& to) const {
to << ")"; 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() { std::string type_mgr::new_type_name() {
int temp = last_id++; int temp = last_id++;
std::string str = ""; 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) { void type_mgr::unify(type_ptr l, type_ptr r) {
type_var* lvar; type_var *lvar, *rvar;
type_var* rvar; type_arr *larr, *rarr;
type_arr* larr; type_base *lid, *rid;
type_arr* rarr; type_app *lapp, *rapp;
type_base* lid;
type_base* rid;
l = resolve(l, lvar); l = resolve(l, lvar);
r = resolve(r, rvar); r = resolve(r, rvar);
@ -123,6 +145,17 @@ void type_mgr::unify(type_ptr l, type_ptr r) {
} else if((lid = dynamic_cast<type_base*>(l.get())) && } else if((lid = dynamic_cast<type_base*>(l.get())) &&
(rid = dynamic_cast<type_base*>(r.get()))) { (rid = dynamic_cast<type_base*>(r.get()))) {
if(lid->name == rid->name) return; if(lid->name == rid->name) return;
} else if((lapp = dynamic_cast<type_app*>(l.get())) &&
(rapp = dynamic_cast<type_app*>(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); throw unification_error(l, r);
@ -144,5 +177,8 @@ void type_mgr::find_free(const type_ptr& t, std::set<std::string>& into) const {
} else if(type_arr* arr = dynamic_cast<type_arr*>(resolved.get())) { } else if(type_arr* arr = dynamic_cast<type_arr*>(resolved.get())) {
find_free(arr->left, into); find_free(arr->left, into);
find_free(arr->right, into); find_free(arr->right, into);
} else if(type_app* app = dynamic_cast<type_app*>(resolved.get())) {
find_free(app->constructor, into);
for(auto& arg : app->arguments) find_free(arg, into);
} }
} }

View File

@ -38,9 +38,10 @@ struct type_var : public type {
struct type_base : public type { struct type_base : public type {
std::string name; std::string name;
int32_t arity;
type_base(std::string n) type_base(std::string n, int32_t a = 0)
: name(std::move(n)) {} : name(std::move(n)), arity(a) {}
void print(const type_mgr& mgr, std::ostream& to) const; 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; void print(const type_mgr& mgr, std::ostream& to) const;
}; };
struct type_app : public type {
type_ptr constructor;
std::vector<type_ptr> arguments;
type_app(type_ptr c)
: constructor(std::move(c)) {}
void print(const type_mgr& mgr, std::ostream& to) const;
};
struct type_mgr { struct type_mgr {
int last_id = 0; int last_id = 0;
std::map<std::string, type_ptr> types; std::map<std::string, type_ptr> types;