diff --git a/.gitmodules b/.gitmodules index 260df05..bb7a83b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "code/blog-static-flake"] path = code/blog-static-flake url = https://dev.danilafe.com/Nix-Configs/blog-static-flake.git +[submodule "code/compiler"] + path = code/compiler + url = https://dev.danilafe.com/DanilaFe/bloglang.git diff --git a/code/compiler b/code/compiler new file mode 160000 index 0000000..137455b --- /dev/null +++ b/code/compiler @@ -0,0 +1 @@ +Subproject commit 137455b0f4365ba3fd11c45ce49781cdbe829ec3 diff --git a/code/compiler/01/scanner.l b/code/compiler/01/scanner.l deleted file mode 100644 index b0bb329..0000000 --- a/code/compiler/01/scanner.l +++ /dev/null @@ -1,33 +0,0 @@ -%option noyywrap - -%{ -#include -%} - -%% - -[ \n]+ {} -\+ { std::cout << "PLUS" << std::endl; } -\* { std::cout << "TIMES" << std::endl; } -- { std::cout << "MINUS" << std::endl; } -\/ { std::cout << "DIVIDE" << std::endl; } -[0-9]+ { std::cout << "NUMBER: " << yytext << std::endl; } -defn { std::cout << "KEYWORD: defn" << std::endl; } -data { std::cout << "KEYWORD: data" << std::endl; } -case { std::cout << "KEYWORD: case" << std::endl; } -of { std::cout << "KEYWORD: of" << std::endl; } -\{ { std::cout << "OPEN CURLY" << std::endl; } -\} { std::cout << "CLOSED CURLY" << std::endl; } -\( { std::cout << "OPEN PARENTH" << std::endl; } -\) { std::cout << "CLOSE PARENTH" << std::endl; } -, { std::cout << "COMMA" << std::endl; } --> { std::cout << "PATTERN ARROW" << std::endl; } -= { std::cout << "EQUAL" << std::endl; } -[a-z][a-zA-Z]* { std::cout << "LOWERCASE IDENTIFIER: " << yytext << std::endl; } -[A-Z][a-zA-Z]* { std::cout << "UPPERCASE IDENTIFIER: " << yytext << std::endl; } - -%% - -int main() { - yylex(); -} diff --git a/code/compiler/02/ast.hpp b/code/compiler/02/ast.hpp deleted file mode 100644 index 70c2af9..0000000 --- a/code/compiler/02/ast.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once -#include -#include - -struct ast { - virtual ~ast() = default; -}; - -using ast_ptr = std::unique_ptr; - -struct pattern { - virtual ~pattern() = default; -}; - -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 constructor { - std::string name; - std::vector types; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition { - virtual ~definition() = default; -}; - -using definition_ptr = std::unique_ptr; - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -struct ast_int : public ast { - int value; - - explicit ast_int(int v) - : value(v) {} -}; - -struct ast_lid : public ast { - std::string id; - - explicit ast_lid(std::string i) - : id(std::move(i)) {} -}; - -struct ast_uid : public ast { - std::string id; - - explicit ast_uid(std::string i) - : id(std::move(i)) {} -}; - -struct ast_binop : public ast { - binop op; - ast_ptr left; - ast_ptr right; - - ast_binop(binop o, ast_ptr l, ast_ptr r) - : op(o), left(std::move(l)), right(std::move(r)) {} -}; - -struct ast_app : public ast { - ast_ptr left; - ast_ptr right; - - ast_app(ast_ptr l, ast_ptr r) - : left(std::move(l)), right(std::move(r)) {} -}; - -struct ast_case : public ast { - ast_ptr of; - std::vector branches; - - ast_case(ast_ptr o, std::vector b) - : of(std::move(o)), branches(std::move(b)) {} -}; - -struct pattern_var : public pattern { - std::string var; - - pattern_var(std::string v) - : var(std::move(v)) {} -}; - -struct pattern_constr : public pattern { - std::string constr; - std::vector params; - - pattern_constr(std::string c, std::vector p) - : constr(std::move(c)), params(std::move(p)) {} -}; - -struct definition_defn : public definition { - std::string name; - std::vector params; - ast_ptr body; - - definition_defn(std::string n, std::vector p, ast_ptr b) - : name(std::move(n)), params(std::move(p)), body(std::move(b)) { - - } -}; - -struct definition_data : public definition { - std::string name; - std::vector constructors; - - definition_data(std::string n, std::vector cs) - : name(std::move(n)), constructors(std::move(cs)) {} -}; diff --git a/code/compiler/02/clean.sh b/code/compiler/02/clean.sh deleted file mode 100755 index 4fea7ec..0000000 --- a/code/compiler/02/clean.sh +++ /dev/null @@ -1 +0,0 @@ -rm -f parser.o parser.cpp parser.hpp stack.hh scanner.cpp scanner.o a.out diff --git a/code/compiler/02/compile.sh b/code/compiler/02/compile.sh deleted file mode 100755 index 2b2d0fe..0000000 --- a/code/compiler/02/compile.sh +++ /dev/null @@ -1,5 +0,0 @@ -bison -o parser.cpp -d parser.y -flex -o scanner.cpp scanner.l -g++ -c -o scanner.o scanner.cpp -g++ -c -o parser.o parser.cpp -g++ main.cpp parser.o scanner.o diff --git a/code/compiler/02/main.cpp b/code/compiler/02/main.cpp deleted file mode 100644 index dc9312a..0000000 --- a/code/compiler/02/main.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "ast.hpp" -#include "parser.hpp" - -void yy::parser::error(const std::string& msg) { - std::cout << "An error occured: " << msg << std::endl; -} - -extern std::vector program; - -int main() { - yy::parser parser; - parser.parse(); - std::cout << program.size() << std::endl; -} diff --git a/code/compiler/02/parser.y b/code/compiler/02/parser.y deleted file mode 100644 index fdb72c9..0000000 --- a/code/compiler/02/parser.y +++ /dev/null @@ -1,140 +0,0 @@ -%{ -#include -#include -#include "ast.hpp" -#include "parser.hpp" - -std::vector program; -extern yy::parser::symbol_type yylex(); - -%} - -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%type > lowercaseParams uppercaseParams -%type > program definitions -%type > branches -%type > constructors -%type aAdd aMul case app appBase -%type definition defn data -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { program = std::move($1); } - ; - -definitions - : definitions definition { $$ = std::move($1); $$.push_back(std::move($2)); } - | definition { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -definition - : defn { $$ = std::move($1); } - | data { $$ = std::move($1); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6))); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -uppercaseParams - : %empty { $$ = std::vector(); } - | uppercaseParams UID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } - ; - -branches - : branches branch { $$ = std::move($1); $1.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } - ; - -data - : DATA UID EQUAL OCURLY constructors CCURLY - { $$ = definition_ptr(new definition_data(std::move($2), std::move($5))); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID uppercaseParams - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - diff --git a/code/compiler/02/scanner.l b/code/compiler/02/scanner.l deleted file mode 100644 index 683deeb..0000000 --- a/code/compiler/02/scanner.l +++ /dev/null @@ -1,34 +0,0 @@ -%option noyywrap - -%{ -#include -#include "ast.hpp" -#include "parser.hpp" - -#define YY_DECL yy::parser::symbol_type yylex() - -%} - -%% - -[ \n]+ {} -\+ { return yy::parser::make_PLUS(); } -\* { return yy::parser::make_TIMES(); } -- { return yy::parser::make_MINUS(); } -\/ { return yy::parser::make_DIVIDE(); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } -defn { return yy::parser::make_DEFN(); } -data { return yy::parser::make_DATA(); } -case { return yy::parser::make_CASE(); } -of { return yy::parser::make_OF(); } -\{ { return yy::parser::make_OCURLY(); } -\} { return yy::parser::make_CCURLY(); } -\( { return yy::parser::make_OPAREN(); } -\) { return yy::parser::make_CPAREN(); } -, { return yy::parser::make_COMMA(); } --> { return yy::parser::make_ARROW(); } -= { return yy::parser::make_EQUAL(); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } - -%% diff --git a/code/compiler/03/ast.cpp b/code/compiler/03/ast.cpp deleted file mode 100644 index bdee157..0000000 --- a/code/compiler/03/ast.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "ast.hpp" - -std::string op_name(binop op) { - switch(op) { - case PLUS: return "+"; - case MINUS: return "-"; - case TIMES: return "*"; - case DIVIDE: return "/"; - } - throw 0; -} - -type_ptr ast_int::typecheck(type_mgr& mgr, const type_env& env) const { - return type_ptr(new type_base("Int")); -} - -type_ptr ast_lid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -type_ptr ast_uid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -type_ptr ast_binop::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck(mgr, env); - type_ptr rtype = right->typecheck(mgr, env); - type_ptr ftype = env.lookup(op_name(op)); - if(!ftype) throw 0; - - type_ptr return_type = mgr.new_type(); - type_ptr arrow_one = type_ptr(new type_arr(rtype, return_type)); - type_ptr arrow_two = type_ptr(new type_arr(ltype, arrow_one)); - - mgr.unify(arrow_two, ftype); - return return_type; -} - -type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck(mgr, env); - type_ptr rtype = right->typecheck(mgr, env); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); - mgr.unify(arrow, ltype); - return return_type; -} - -type_ptr ast_case::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr case_type = of->typecheck(mgr, env); - type_ptr branch_type = mgr.new_type(); - - for(auto& branch : branches) { - type_env new_env = env.scope(); - branch->pat->match(case_type, mgr, new_env); - type_ptr curr_branch_type = branch->expr->typecheck(mgr, new_env); - mgr.unify(branch_type, curr_branch_type); - } - - return branch_type; -} - -void pattern_var::match(type_ptr t, type_mgr& mgr, type_env& env) const { - env.bind(var, t); -} - -void pattern_constr::match(type_ptr t, type_mgr& mgr, type_env& env) const { - type_ptr constructor_type = env.lookup(constr); - if(!constructor_type) throw 0; - - for(int i = 0; i < params.size(); i++) { - type_arr* arr = dynamic_cast(constructor_type.get()); - if(!arr) throw 0; - - env.bind(params[i], arr->left); - constructor_type = arr->right; - } - - mgr.unify(t, constructor_type); - type_base* result_type = dynamic_cast(constructor_type.get()); - if(!result_type) throw 0; -} diff --git a/code/compiler/03/ast.hpp b/code/compiler/03/ast.hpp deleted file mode 100644 index c658be7..0000000 --- a/code/compiler/03/ast.hpp +++ /dev/null @@ -1,162 +0,0 @@ -#pragma once -#include -#include -#include "type.hpp" -#include "env.hpp" - -struct ast { - virtual ~ast() = default; - - virtual type_ptr typecheck(type_mgr& mgr, const type_env& env) const = 0; -}; - -using ast_ptr = std::unique_ptr; - -struct pattern { - virtual ~pattern() = default; - - virtual void match(type_ptr t, type_mgr& mgr, type_env& 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 constructor { - std::string name; - std::vector types; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition { - virtual ~definition() = default; - - virtual void typecheck_first(type_mgr& mgr, type_env& env) = 0; - virtual void typecheck_second(type_mgr& mgr, const type_env& env) const = 0; -}; - -using definition_ptr = std::unique_ptr; - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -struct ast_int : public ast { - int value; - - explicit ast_int(int v) - : value(v) {} - - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct ast_lid : public ast { - std::string id; - - explicit ast_lid(std::string i) - : id(std::move(i)) {} - - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct ast_uid : public ast { - std::string id; - - explicit ast_uid(std::string i) - : id(std::move(i)) {} - - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct ast_binop : public ast { - binop op; - ast_ptr left; - ast_ptr right; - - ast_binop(binop o, ast_ptr l, ast_ptr r) - : op(o), left(std::move(l)), right(std::move(r)) {} - - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct ast_app : public ast { - ast_ptr left; - ast_ptr right; - - ast_app(ast_ptr l, ast_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct ast_case : public ast { - ast_ptr of; - std::vector branches; - - ast_case(ast_ptr o, std::vector b) - : of(std::move(o)), branches(std::move(b)) {} - - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct pattern_var : public pattern { - std::string var; - - pattern_var(std::string v) - : var(std::move(v)) {} - - void match(type_ptr t, type_mgr& mgr, type_env& env) const; -}; - -struct pattern_constr : public pattern { - std::string constr; - std::vector params; - - pattern_constr(std::string c, std::vector p) - : constr(std::move(c)), params(std::move(p)) {} - - void match(type_ptr t, type_mgr&, type_env& env) const; -}; - -struct definition_defn : public definition { - std::string name; - std::vector params; - ast_ptr body; - - type_ptr return_type; - std::vector param_types; - - definition_defn(std::string n, std::vector p, ast_ptr b) - : name(std::move(n)), params(std::move(p)), body(std::move(b)) { - - } - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; -}; - -struct definition_data : public definition { - std::string name; - std::vector constructors; - - definition_data(std::string n, std::vector cs) - : name(std::move(n)), constructors(std::move(cs)) {} - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; -}; diff --git a/code/compiler/03/bad1.txt b/code/compiler/03/bad1.txt deleted file mode 100644 index 86d4bc4..0000000 --- a/code/compiler/03/bad1.txt +++ /dev/null @@ -1,2 +0,0 @@ -data Bool = { True, False } -defn main = { 3 + True } diff --git a/code/compiler/03/bad2.txt b/code/compiler/03/bad2.txt deleted file mode 100644 index def8785..0000000 --- a/code/compiler/03/bad2.txt +++ /dev/null @@ -1 +0,0 @@ -defn main = { 1 2 3 4 5 } diff --git a/code/compiler/03/clean.sh b/code/compiler/03/clean.sh deleted file mode 100755 index 7580487..0000000 --- a/code/compiler/03/clean.sh +++ /dev/null @@ -1 +0,0 @@ -rm -f parser.o parser.cpp parser.hpp stack.hh scanner.cpp scanner.o type.o env.o ast.o definition.o a.out diff --git a/code/compiler/03/compile.sh b/code/compiler/03/compile.sh deleted file mode 100755 index e67846b..0000000 --- a/code/compiler/03/compile.sh +++ /dev/null @@ -1,9 +0,0 @@ -bison -o parser.cpp -d parser.y -flex -o scanner.cpp scanner.l -g++ -g -c -o scanner.o scanner.cpp -g++ -g -c -o parser.o parser.cpp -g++ -g -c -o type.o type.cpp -g++ -g -c -o env.o env.cpp -g++ -g -c -o ast.o ast.cpp -g++ -g -c -o definition.o definition.cpp -g++ -g main.cpp parser.o scanner.o type.o env.o ast.o definition.o diff --git a/code/compiler/03/definition.cpp b/code/compiler/03/definition.cpp deleted file mode 100644 index 69b3196..0000000 --- a/code/compiler/03/definition.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "ast.hpp" - -void definition_defn::typecheck_first(type_mgr& mgr, type_env& env) { - return_type = mgr.new_type(); - type_ptr full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - full_type = type_ptr(new type_arr(param_type, full_type)); - param_types.push_back(param_type); - } - - env.bind(name, full_type); -} - -void definition_defn::typecheck_second(type_mgr& mgr, const type_env& env) const { - type_env new_env = env.scope(); - auto param_it = params.begin(); - auto type_it = param_types.rbegin(); - - while(param_it != params.end() && type_it != param_types.rend()) { - new_env.bind(*param_it, *type_it); - param_it++; - type_it++; - } - - type_ptr body_type = body->typecheck(mgr, new_env); - mgr.unify(return_type, body_type); -} - -void definition_data::typecheck_first(type_mgr& mgr, type_env& env) { - type_ptr return_type = type_ptr(new type_base(name)); - - for(auto& constructor : constructors) { - type_ptr full_type = return_type; - - for(auto& type_name : constructor->types) { - type_ptr type = type_ptr(new type_base(type_name)); - full_type = type_ptr(new type_arr(type, full_type)); - } - - env.bind(constructor->name, full_type); - } -} - -void definition_data::typecheck_second(type_mgr& mgr, const type_env& env) const { - // Nothing -} diff --git a/code/compiler/03/env.cpp b/code/compiler/03/env.cpp deleted file mode 100644 index 74059a8..0000000 --- a/code/compiler/03/env.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "env.hpp" - -type_ptr type_env::lookup(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second; - if(parent) return parent->lookup(name); - return nullptr; -} - -void type_env::bind(const std::string& name, type_ptr t) { - names[name] = t; -} - -type_env type_env::scope() const { - return type_env(this); -} diff --git a/code/compiler/03/env.hpp b/code/compiler/03/env.hpp deleted file mode 100644 index 6470bdd..0000000 --- a/code/compiler/03/env.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_env { - std::map names; - type_env const* parent = nullptr; - - type_env(type_env const* p) - : parent(p) {} - type_env() : type_env(nullptr) {} - - type_ptr lookup(const std::string& name) const; - void bind(const std::string& name, type_ptr t); - type_env scope() const; -}; diff --git a/code/compiler/03/main.cpp b/code/compiler/03/main.cpp deleted file mode 100644 index 43c1b4f..0000000 --- a/code/compiler/03/main.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "ast.hpp" -#include "parser.hpp" -#include "type.hpp" - -void yy::parser::error(const std::string& msg) { - std::cout << "An error occured: " << msg << std::endl; -} - -extern std::vector program; - -void typecheck_program(const std::vector& prog) { - type_mgr mgr; - type_env env; - - type_ptr int_type = type_ptr(new type_base("Int")); - 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); - env.bind("/", binop_type); - - for(auto& def : prog) { - def->typecheck_first(mgr, env); - } - - for(auto& def : prog) { - def->typecheck_second(mgr, env); - } -} - -int main() { - yy::parser parser; - parser.parse(); - typecheck_program(program); - std::cout << program.size() << std::endl; -} diff --git a/code/compiler/03/parser.y b/code/compiler/03/parser.y deleted file mode 100644 index fdb72c9..0000000 --- a/code/compiler/03/parser.y +++ /dev/null @@ -1,140 +0,0 @@ -%{ -#include -#include -#include "ast.hpp" -#include "parser.hpp" - -std::vector program; -extern yy::parser::symbol_type yylex(); - -%} - -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%type > lowercaseParams uppercaseParams -%type > program definitions -%type > branches -%type > constructors -%type aAdd aMul case app appBase -%type definition defn data -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { program = std::move($1); } - ; - -definitions - : definitions definition { $$ = std::move($1); $$.push_back(std::move($2)); } - | definition { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -definition - : defn { $$ = std::move($1); } - | data { $$ = std::move($1); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6))); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -uppercaseParams - : %empty { $$ = std::vector(); } - | uppercaseParams UID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } - ; - -branches - : branches branch { $$ = std::move($1); $1.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } - ; - -data - : DATA UID EQUAL OCURLY constructors CCURLY - { $$ = definition_ptr(new definition_data(std::move($2), std::move($5))); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID uppercaseParams - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - diff --git a/code/compiler/03/scanner.l b/code/compiler/03/scanner.l deleted file mode 100644 index 683deeb..0000000 --- a/code/compiler/03/scanner.l +++ /dev/null @@ -1,34 +0,0 @@ -%option noyywrap - -%{ -#include -#include "ast.hpp" -#include "parser.hpp" - -#define YY_DECL yy::parser::symbol_type yylex() - -%} - -%% - -[ \n]+ {} -\+ { return yy::parser::make_PLUS(); } -\* { return yy::parser::make_TIMES(); } -- { return yy::parser::make_MINUS(); } -\/ { return yy::parser::make_DIVIDE(); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } -defn { return yy::parser::make_DEFN(); } -data { return yy::parser::make_DATA(); } -case { return yy::parser::make_CASE(); } -of { return yy::parser::make_OF(); } -\{ { return yy::parser::make_OCURLY(); } -\} { return yy::parser::make_CCURLY(); } -\( { return yy::parser::make_OPAREN(); } -\) { return yy::parser::make_CPAREN(); } -, { return yy::parser::make_COMMA(); } --> { return yy::parser::make_ARROW(); } -= { return yy::parser::make_EQUAL(); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } - -%% diff --git a/code/compiler/03/type.cpp b/code/compiler/03/type.cpp deleted file mode 100644 index f370a91..0000000 --- a/code/compiler/03/type.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "type.hpp" -#include -#include - -std::string type_mgr::new_type_name() { - int temp = last_id++; - std::string str = ""; - - while(temp != -1) { - str += (char) ('a' + (temp % 26)); - temp = temp / 26 - 1; - } - - std::reverse(str.begin(), str.end()); - return str; -} - -type_ptr type_mgr::new_type() { - return type_ptr(new type_var(new_type_name())); -} - -type_ptr type_mgr::new_arrow_type() { - return type_ptr(new type_arr(new_type(), new_type())); -} - -type_ptr type_mgr::resolve(type_ptr t, type_var*& var) { - type_var* cast; - - var = nullptr; - while((cast = dynamic_cast(t.get()))) { - auto it = types.find(cast->name); - - if(it == types.end()) { - var = cast; - break; - } - t = it->second; - } - - return t; -} - -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; - - l = resolve(l, lvar); - r = resolve(r, rvar); - - if(lvar) { - bind(lvar->name, r); - return; - } else if(rvar) { - bind(rvar->name, l); - return; - } else if((larr = dynamic_cast(l.get())) && - (rarr = dynamic_cast(r.get()))) { - unify(larr->left, rarr->left); - unify(larr->right, rarr->right); - return; - } else if((lid = dynamic_cast(l.get())) && - (rid = dynamic_cast(r.get()))) { - if(lid->name == rid->name) return; - } - - throw 0; -} - -void type_mgr::bind(const std::string& s, type_ptr t) { - type_var* other = dynamic_cast(t.get()); - - if(other && other->name == s) return; - types[s] = t; -} diff --git a/code/compiler/03/type.hpp b/code/compiler/03/type.hpp deleted file mode 100644 index e63040e..0000000 --- a/code/compiler/03/type.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once -#include -#include - -struct type { - virtual ~type() = default; -}; - -using type_ptr = std::shared_ptr; - -struct type_var : public type { - std::string name; - - type_var(std::string n) - : name(std::move(n)) {} -}; - -struct type_base : public type { - std::string name; - - type_base(std::string n) - : name(std::move(n)) {} -}; - -struct type_arr : public type { - type_ptr left; - type_ptr right; - - type_arr(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)) {} -}; - -struct type_mgr { - int last_id = 0; - std::map types; - - std::string new_type_name(); - type_ptr new_type(); - type_ptr new_arrow_type(); - - void unify(type_ptr l, type_ptr r); - type_ptr resolve(type_ptr t, type_var*& var); - void bind(const std::string& s, type_ptr t); -}; diff --git a/code/compiler/03/works1.txt b/code/compiler/03/works1.txt deleted file mode 100644 index bedb5d8..0000000 --- a/code/compiler/03/works1.txt +++ /dev/null @@ -1,2 +0,0 @@ -defn main = { plus 320 6 } -defn plus x y = { x + y } diff --git a/code/compiler/03/works2.txt b/code/compiler/03/works2.txt deleted file mode 100644 index 8332fde..0000000 --- a/code/compiler/03/works2.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn add x y = { x + y } -defn double x = { add x x } -defn main = { double 163 } diff --git a/code/compiler/03/works3.txt b/code/compiler/03/works3.txt deleted file mode 100644 index cfffd20..0000000 --- a/code/compiler/03/works3.txt +++ /dev/null @@ -1,7 +0,0 @@ -data List = { Nil, Cons Int List } -defn length l = { - case l of { - Nil -> { 0 } - Cons x xs -> { 1 + length xs } - } -} diff --git a/code/compiler/04/CMakeLists.txt b/code/compiler/04/CMakeLists.txt deleted file mode 100644 index 9d2d571..0000000 --- a/code/compiler/04/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(compiler) - -find_package(BISON) -find_package(FLEX) -bison_target(parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser.y - ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp - COMPILE_FLAGS "-d") -flex_target(scanner - ${CMAKE_CURRENT_SOURCE_DIR}/scanner.l - ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp) -add_flex_bison_dependency(scanner parser) - -add_executable(compiler - ast.cpp ast.hpp definition.cpp - env.cpp env.hpp - type.cpp type.hpp - error.cpp error.hpp - ${BISON_parser_OUTPUTS} - ${FLEX_scanner_OUTPUTS} - main.cpp -) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/code/compiler/04/ast.cpp b/code/compiler/04/ast.cpp deleted file mode 100644 index 8880df2..0000000 --- a/code/compiler/04/ast.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "ast.hpp" -#include -#include "error.hpp" - -std::string op_name(binop op) { - switch(op) { - case PLUS: return "+"; - case MINUS: return "-"; - case TIMES: return "*"; - case DIVIDE: return "/"; - } - return "??"; -} - -void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void ast_int::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "INT: " << value << std::endl; -} - -type_ptr ast_int::typecheck(type_mgr& mgr, const type_env& env) const { - return type_ptr(new type_base("Int")); -} - -void ast_lid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LID: " << id << std::endl; -} - -type_ptr ast_lid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -void ast_uid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "UID: " << id << std::endl; -} - -type_ptr ast_uid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -void ast_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BINOP: " << op_name(op) << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -type_ptr ast_binop::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck(mgr, env); - type_ptr rtype = right->typecheck(mgr, env); - type_ptr ftype = env.lookup(op_name(op)); - if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op)); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow_one = type_ptr(new type_arr(rtype, return_type)); - type_ptr arrow_two = type_ptr(new type_arr(ltype, arrow_one)); - - mgr.unify(arrow_two, ftype); - return return_type; -} - -void ast_app::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "APP:" << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck(mgr, env); - type_ptr rtype = right->typecheck(mgr, env); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); - mgr.unify(arrow, ltype); - return return_type; -} - -void ast_case::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "CASE: " << std::endl; - for(auto& branch : branches) { - print_indent(indent + 1, to); - branch->pat->print(to); - to << std::endl; - branch->expr->print(indent + 2, to); - } -} - -type_ptr ast_case::typecheck(type_mgr& mgr, const type_env& env) const { - type_var* var; - type_ptr case_type = mgr.resolve(of->typecheck(mgr, env), var); - type_ptr branch_type = mgr.new_type(); - - for(auto& branch : branches) { - type_env new_env = env.scope(); - branch->pat->match(case_type, mgr, new_env); - type_ptr curr_branch_type = branch->expr->typecheck(mgr, new_env); - mgr.unify(branch_type, curr_branch_type); - } - - case_type = mgr.resolve(case_type, var); - if(!dynamic_cast(case_type.get())) { - throw type_error("attempting case analysis of non-data type"); - } - - return branch_type; -} - -void pattern_var::print(std::ostream& to) const { - to << var; -} - -void pattern_var::match(type_ptr t, type_mgr& mgr, type_env& env) const { - env.bind(var, t); -} - -void pattern_constr::print(std::ostream& to) const { - to << constr; - for(auto& param : params) { - to << " " << param; - } -} - -void pattern_constr::match(type_ptr t, type_mgr& mgr, type_env& env) const { - type_ptr constructor_type = env.lookup(constr); - if(!constructor_type) { - throw type_error(std::string("pattern using unknown constructor ") + constr); - } - - for(int i = 0; i < params.size(); i++) { - type_arr* arr = dynamic_cast(constructor_type.get()); - if(!arr) throw type_error("too many parameters in constructor pattern"); - - env.bind(params[i], arr->left); - constructor_type = arr->right; - } - - mgr.unify(t, constructor_type); -} diff --git a/code/compiler/04/ast.hpp b/code/compiler/04/ast.hpp deleted file mode 100644 index fcfed19..0000000 --- a/code/compiler/04/ast.hpp +++ /dev/null @@ -1,172 +0,0 @@ -#pragma once -#include -#include -#include "type.hpp" -#include "env.hpp" - -struct ast { - virtual ~ast() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual type_ptr typecheck(type_mgr& mgr, const type_env& env) const = 0; -}; - -using ast_ptr = std::unique_ptr; - -struct pattern { - virtual ~pattern() = default; - - virtual void print(std::ostream& to) const = 0; - virtual void match(type_ptr t, type_mgr& mgr, type_env& 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 constructor { - std::string name; - std::vector types; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition { - virtual ~definition() = default; - - virtual void typecheck_first(type_mgr& mgr, type_env& env) = 0; - virtual void typecheck_second(type_mgr& mgr, const type_env& env) const = 0; -}; - -using definition_ptr = std::unique_ptr; - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -struct ast_int : public ast { - int value; - - explicit ast_int(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct ast_lid : public ast { - std::string id; - - explicit ast_lid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct ast_uid : public ast { - std::string id; - - explicit ast_uid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct ast_binop : public ast { - binop op; - ast_ptr left; - ast_ptr right; - - ast_binop(binop o, ast_ptr l, ast_ptr r) - : op(o), left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct ast_app : public ast { - ast_ptr left; - ast_ptr right; - - ast_app(ast_ptr l, ast_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct ast_case : public ast { - ast_ptr of; - std::vector branches; - - ast_case(ast_ptr o, std::vector b) - : of(std::move(o)), branches(std::move(b)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; -}; - -struct pattern_var : public pattern { - std::string var; - - pattern_var(std::string v) - : var(std::move(v)) {} - - void print(std::ostream &to) const; - void match(type_ptr t, type_mgr& mgr, type_env& env) const; -}; - -struct pattern_constr : public pattern { - std::string constr; - std::vector params; - - pattern_constr(std::string c, std::vector p) - : constr(std::move(c)), params(std::move(p)) {} - - void print(std::ostream &to) const; - void match(type_ptr t, type_mgr&, type_env& env) const; -}; - -struct definition_defn : public definition { - std::string name; - std::vector params; - ast_ptr body; - - type_ptr return_type; - std::vector param_types; - - definition_defn(std::string n, std::vector p, ast_ptr b) - : name(std::move(n)), params(std::move(p)), body(std::move(b)) { - - } - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; -}; - -struct definition_data : public definition { - std::string name; - std::vector constructors; - - definition_data(std::string n, std::vector cs) - : name(std::move(n)), constructors(std::move(cs)) {} - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; -}; diff --git a/code/compiler/04/definition.cpp b/code/compiler/04/definition.cpp deleted file mode 100644 index f0889b6..0000000 --- a/code/compiler/04/definition.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "ast.hpp" - -void definition_defn::typecheck_first(type_mgr& mgr, type_env& env) { - return_type = mgr.new_type(); - type_ptr full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - full_type = type_ptr(new type_arr(param_type, full_type)); - param_types.push_back(param_type); - } - - env.bind(name, full_type); -} - -void definition_defn::typecheck_second(type_mgr& mgr, const type_env& env) const { - type_env new_env = env.scope(); - auto param_it = params.begin(); - auto type_it = param_types.rbegin(); - - while(param_it != params.end() && type_it != param_types.rend()) { - new_env.bind(*param_it, *type_it); - param_it++; - type_it++; - } - - type_ptr body_type = body->typecheck(mgr, new_env); - mgr.unify(return_type, body_type); -} - -void definition_data::typecheck_first(type_mgr& mgr, type_env& env) { - type_ptr return_type = type_ptr(new type_base(name)); - - for(auto& constructor : constructors) { - 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)); - full_type = type_ptr(new type_arr(type, full_type)); - } - - env.bind(constructor->name, full_type); - } -} - -void definition_data::typecheck_second(type_mgr& mgr, const type_env& env) const { - // Nothing -} diff --git a/code/compiler/04/env.cpp b/code/compiler/04/env.cpp deleted file mode 100644 index 74059a8..0000000 --- a/code/compiler/04/env.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "env.hpp" - -type_ptr type_env::lookup(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second; - if(parent) return parent->lookup(name); - return nullptr; -} - -void type_env::bind(const std::string& name, type_ptr t) { - names[name] = t; -} - -type_env type_env::scope() const { - return type_env(this); -} diff --git a/code/compiler/04/env.hpp b/code/compiler/04/env.hpp deleted file mode 100644 index 6470bdd..0000000 --- a/code/compiler/04/env.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_env { - std::map names; - type_env const* parent = nullptr; - - type_env(type_env const* p) - : parent(p) {} - type_env() : type_env(nullptr) {} - - type_ptr lookup(const std::string& name) const; - void bind(const std::string& name, type_ptr t); - type_env scope() const; -}; diff --git a/code/compiler/04/error.cpp b/code/compiler/04/error.cpp deleted file mode 100644 index f5125e3..0000000 --- a/code/compiler/04/error.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "error.hpp" - -const char* type_error::what() const noexcept { - return "an error occured while checking the types of the program"; -} diff --git a/code/compiler/04/error.hpp b/code/compiler/04/error.hpp deleted file mode 100644 index 5bfbc7e..0000000 --- a/code/compiler/04/error.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_error : std::exception { - std::string description; - - type_error(std::string d) - : description(std::move(d)) {} - - const char* what() const noexcept override; -}; - -struct unification_error : public type_error { - type_ptr left; - type_ptr right; - - unification_error(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)), - type_error("failed to unify types") {} -}; diff --git a/code/compiler/04/examples/bad1.txt b/code/compiler/04/examples/bad1.txt deleted file mode 100644 index 86d4bc4..0000000 --- a/code/compiler/04/examples/bad1.txt +++ /dev/null @@ -1,2 +0,0 @@ -data Bool = { True, False } -defn main = { 3 + True } diff --git a/code/compiler/04/examples/bad2.txt b/code/compiler/04/examples/bad2.txt deleted file mode 100644 index def8785..0000000 --- a/code/compiler/04/examples/bad2.txt +++ /dev/null @@ -1 +0,0 @@ -defn main = { 1 2 3 4 5 } diff --git a/code/compiler/04/examples/works1.txt b/code/compiler/04/examples/works1.txt deleted file mode 100644 index bedb5d8..0000000 --- a/code/compiler/04/examples/works1.txt +++ /dev/null @@ -1,2 +0,0 @@ -defn main = { plus 320 6 } -defn plus x y = { x + y } diff --git a/code/compiler/04/examples/works2.txt b/code/compiler/04/examples/works2.txt deleted file mode 100644 index 8332fde..0000000 --- a/code/compiler/04/examples/works2.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn add x y = { x + y } -defn double x = { add x x } -defn main = { double 163 } diff --git a/code/compiler/04/examples/works3.txt b/code/compiler/04/examples/works3.txt deleted file mode 100644 index cfffd20..0000000 --- a/code/compiler/04/examples/works3.txt +++ /dev/null @@ -1,7 +0,0 @@ -data List = { Nil, Cons Int List } -defn length l = { - case l of { - Nil -> { 0 } - Cons x xs -> { 1 + length xs } - } -} diff --git a/code/compiler/04/main.cpp b/code/compiler/04/main.cpp deleted file mode 100644 index 60dd9c9..0000000 --- a/code/compiler/04/main.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "ast.hpp" -#include -#include "parser.hpp" -#include "error.hpp" -#include "type.hpp" - -void yy::parser::error(const std::string& msg) { - std::cout << "An error occured: " << msg << std::endl; -} - -extern std::vector program; - -void typecheck_program( - const std::vector& prog, - type_mgr& mgr, type_env& env) { - type_ptr int_type = type_ptr(new type_base("Int")); - 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); - env.bind("/", binop_type); - - for(auto& def : prog) { - def->typecheck_first(mgr, env); - } - - for(auto& def : prog) { - def->typecheck_second(mgr, env); - } - - for(auto& pair : env.names) { - std::cout << pair.first << ": "; - pair.second->print(mgr, std::cout); - std::cout << std::endl; - } -} - -int main() { - yy::parser parser; - type_mgr mgr; - type_env env; - - parser.parse(); - for(auto& definition : program) { - definition_defn* def = dynamic_cast(definition.get()); - if(!def) continue; - - std::cout << def->name; - for(auto& param : def->params) std::cout << " " << param; - std::cout << ":" << std::endl; - - def->body->print(1, std::cout); - } - try { - typecheck_program(program, mgr, env); - } catch(unification_error& err) { - std::cout << "failed to unify types: " << std::endl; - std::cout << " (1) \033[34m"; - err.left->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - std::cout << " (2) \033[32m"; - err.right->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - } catch(type_error& err) { - std::cout << "failed to type check program: " << err.description << std::endl; - } -} diff --git a/code/compiler/04/parser.y b/code/compiler/04/parser.y deleted file mode 100644 index 3874aca..0000000 --- a/code/compiler/04/parser.y +++ /dev/null @@ -1,140 +0,0 @@ -%{ -#include -#include -#include "ast.hpp" -#include "parser.hpp" - -std::vector program; -extern yy::parser::symbol_type yylex(); - -%} - -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%type > lowercaseParams uppercaseParams -%type > program definitions -%type > branches -%type > constructors -%type aAdd aMul case app appBase -%type definition defn data -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { program = std::move($1); } - ; - -definitions - : definitions definition { $$ = std::move($1); $$.push_back(std::move($2)); } - | definition { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -definition - : defn { $$ = std::move($1); } - | data { $$ = std::move($1); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6))); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -uppercaseParams - : %empty { $$ = std::vector(); } - | uppercaseParams UID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } - ; - -branches - : branches branch { $$ = std::move($1); $$.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } - ; - -data - : DATA UID EQUAL OCURLY constructors CCURLY - { $$ = definition_ptr(new definition_data(std::move($2), std::move($5))); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID uppercaseParams - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - diff --git a/code/compiler/04/scanner.l b/code/compiler/04/scanner.l deleted file mode 100644 index 683deeb..0000000 --- a/code/compiler/04/scanner.l +++ /dev/null @@ -1,34 +0,0 @@ -%option noyywrap - -%{ -#include -#include "ast.hpp" -#include "parser.hpp" - -#define YY_DECL yy::parser::symbol_type yylex() - -%} - -%% - -[ \n]+ {} -\+ { return yy::parser::make_PLUS(); } -\* { return yy::parser::make_TIMES(); } -- { return yy::parser::make_MINUS(); } -\/ { return yy::parser::make_DIVIDE(); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } -defn { return yy::parser::make_DEFN(); } -data { return yy::parser::make_DATA(); } -case { return yy::parser::make_CASE(); } -of { return yy::parser::make_OF(); } -\{ { return yy::parser::make_OCURLY(); } -\} { return yy::parser::make_CCURLY(); } -\( { return yy::parser::make_OPAREN(); } -\) { return yy::parser::make_CPAREN(); } -, { return yy::parser::make_COMMA(); } --> { return yy::parser::make_ARROW(); } -= { return yy::parser::make_EQUAL(); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } - -%% diff --git a/code/compiler/04/type.cpp b/code/compiler/04/type.cpp deleted file mode 100644 index 0fc7364..0000000 --- a/code/compiler/04/type.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "type.hpp" -#include -#include -#include "error.hpp" - -void type_var::print(const type_mgr& mgr, std::ostream& to) const { - auto it = mgr.types.find(name); - if(it != mgr.types.end()) { - it->second->print(mgr, to); - } else { - to << name; - } -} - -void type_base::print(const type_mgr& mgr, std::ostream& to) const { - to << name; -} - -void type_arr::print(const type_mgr& mgr, std::ostream& to) const { - left->print(mgr, to); - to << " -> ("; - right->print(mgr, to); - to << ")"; -} - -std::string type_mgr::new_type_name() { - int temp = last_id++; - std::string str = ""; - - while(temp != -1) { - str += (char) ('a' + (temp % 26)); - temp = temp / 26 - 1; - } - - std::reverse(str.begin(), str.end()); - return str; -} - -type_ptr type_mgr::new_type() { - return type_ptr(new type_var(new_type_name())); -} - -type_ptr type_mgr::new_arrow_type() { - return type_ptr(new type_arr(new_type(), new_type())); -} - -type_ptr type_mgr::resolve(type_ptr t, type_var*& var) { - type_var* cast; - - var = nullptr; - while((cast = dynamic_cast(t.get()))) { - auto it = types.find(cast->name); - - if(it == types.end()) { - var = cast; - break; - } - t = it->second; - } - - return t; -} - -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; - - l = resolve(l, lvar); - r = resolve(r, rvar); - - if(lvar) { - bind(lvar->name, r); - return; - } else if(rvar) { - bind(rvar->name, l); - return; - } else if((larr = dynamic_cast(l.get())) && - (rarr = dynamic_cast(r.get()))) { - unify(larr->left, rarr->left); - unify(larr->right, rarr->right); - return; - } else if((lid = dynamic_cast(l.get())) && - (rid = dynamic_cast(r.get()))) { - if(lid->name == rid->name) return; - } - - throw unification_error(l, r); -} - -void type_mgr::bind(const std::string& s, type_ptr t) { - type_var* other = dynamic_cast(t.get()); - - if(other && other->name == s) return; - types[s] = t; -} diff --git a/code/compiler/04/type.hpp b/code/compiler/04/type.hpp deleted file mode 100644 index 2774c29..0000000 --- a/code/compiler/04/type.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#include -#include - -struct type_mgr; - -struct type { - virtual ~type() = default; - - virtual void print(const type_mgr& mgr, std::ostream& to) const = 0; -}; - -using type_ptr = std::shared_ptr; - -struct type_var : public type { - std::string name; - - type_var(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_base : public type { - std::string name; - - type_base(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_arr : public type { - type_ptr left; - type_ptr right; - - type_arr(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_mgr { - int last_id = 0; - std::map types; - - std::string new_type_name(); - type_ptr new_type(); - type_ptr new_arrow_type(); - - void unify(type_ptr l, type_ptr r); - type_ptr resolve(type_ptr t, type_var*& var); - void bind(const std::string& s, type_ptr t); -}; diff --git a/code/compiler/06/CMakeLists.txt b/code/compiler/06/CMakeLists.txt deleted file mode 100644 index 5e5dab4..0000000 --- a/code/compiler/06/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(compiler) - -find_package(BISON) -find_package(FLEX) -bison_target(parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser.y - ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp - COMPILE_FLAGS "-d") -flex_target(scanner - ${CMAKE_CURRENT_SOURCE_DIR}/scanner.l - ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp) -add_flex_bison_dependency(scanner parser) - -add_executable(compiler - ast.cpp ast.hpp definition.cpp - type_env.cpp type_env.hpp - env.cpp env.hpp - type.cpp type.hpp - error.cpp error.hpp - binop.cpp binop.hpp - instruction.cpp instruction.hpp - ${BISON_parser_OUTPUTS} - ${FLEX_scanner_OUTPUTS} - main.cpp -) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/code/compiler/06/ast.cpp b/code/compiler/06/ast.cpp deleted file mode 100644 index 486607b..0000000 --- a/code/compiler/06/ast.cpp +++ /dev/null @@ -1,262 +0,0 @@ -#include "ast.hpp" -#include -#include "error.hpp" - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -type_ptr ast::typecheck_common(type_mgr& mgr, const type_env& env) { - node_type = typecheck(mgr, env); - return node_type; -} - -void ast::resolve_common(const type_mgr& mgr) { - type_var* var; - type_ptr resolved_type = mgr.resolve(node_type, var); - if(var) throw type_error("ambiguously typed program"); - - resolve(mgr); - node_type = std::move(resolved_type); -} - -void ast_int::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "INT: " << value << std::endl; -} - -type_ptr ast_int::typecheck(type_mgr& mgr, const type_env& env) const { - return type_ptr(new type_base("Int")); -} - -void ast_int::resolve(const type_mgr& mgr) const { - -} - -void ast_int::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushint(value))); -} - -void ast_lid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LID: " << id << std::endl; -} - -type_ptr ast_lid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -void ast_lid::resolve(const type_mgr& mgr) const { - -} - -void ast_lid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr( - env->has_variable(id) ? - (instruction*) new instruction_push(env->get_offset(id)) : - (instruction*) new instruction_pushglobal(id))); -} - -void ast_uid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "UID: " << id << std::endl; -} - -type_ptr ast_uid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -void ast_uid::resolve(const type_mgr& mgr) const { - -} - -void ast_uid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushglobal(id))); -} - -void ast_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BINOP: " << op_name(op) << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -type_ptr ast_binop::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck_common(mgr, env); - type_ptr rtype = right->typecheck_common(mgr, env); - type_ptr ftype = env.lookup(op_name(op)); - if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op)); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow_one = type_ptr(new type_arr(rtype, return_type)); - type_ptr arrow_two = type_ptr(new type_arr(ltype, arrow_one)); - - mgr.unify(arrow_two, ftype); - return return_type; -} - -void ast_binop::resolve(const type_mgr& mgr) const { - left->resolve_common(mgr); - right->resolve_common(mgr); -} - -void ast_binop::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - - into.push_back(instruction_ptr(new instruction_pushglobal(op_action(op)))); - into.push_back(instruction_ptr(new instruction_mkapp())); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_app::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "APP:" << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck_common(mgr, env); - type_ptr rtype = right->typecheck_common(mgr, env); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); - mgr.unify(arrow, ltype); - return return_type; -} - -void ast_app::resolve(const type_mgr& mgr) const { - left->resolve_common(mgr); - right->resolve_common(mgr); -} - -void ast_app::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_case::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "CASE: " << std::endl; - for(auto& branch : branches) { - print_indent(indent + 1, to); - branch->pat->print(to); - to << std::endl; - branch->expr->print(indent + 2, to); - } -} - -type_ptr ast_case::typecheck(type_mgr& mgr, const type_env& env) const { - type_var* var; - type_ptr case_type = mgr.resolve(of->typecheck_common(mgr, env), var); - type_ptr branch_type = mgr.new_type(); - - for(auto& branch : branches) { - type_env new_env = env.scope(); - branch->pat->match(case_type, mgr, new_env); - type_ptr curr_branch_type = branch->expr->typecheck_common(mgr, new_env); - mgr.unify(branch_type, curr_branch_type); - } - - case_type = mgr.resolve(case_type, var); - if(!dynamic_cast(case_type.get())) { - throw type_error("attempting case analysis of non-data type"); - } - - return branch_type; -} - -void ast_case::resolve(const type_mgr& mgr) const { - of->resolve_common(mgr); - for(auto& branch : branches) { - branch->expr->resolve_common(mgr); - } -} - -void ast_case::compile(const env_ptr& env, std::vector& into) const { - type_data* type = dynamic_cast(of->node_type.get()); - - of->compile(env, into); - into.push_back(instruction_ptr(new instruction_eval())); - - instruction_jump* jump_instruction = new instruction_jump(); - into.push_back(instruction_ptr(jump_instruction)); - for(auto& branch : branches) { - std::vector branch_instructions; - pattern_var* vpat; - pattern_constr* cpat; - - if((vpat = dynamic_cast(branch->pat.get()))) { - branch->expr->compile(env_ptr(new env_offset(1, env)), branch_instructions); - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) != - jump_instruction->tag_mappings.end()) - break; - - jump_instruction->tag_mappings[constr_pair.second.tag] = - jump_instruction->branches.size(); - } - jump_instruction->branches.push_back(std::move(branch_instructions)); - } else if((cpat = dynamic_cast(branch->pat.get()))) { - env_ptr new_env = env; - for(auto it = cpat->params.rbegin(); it != cpat->params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - - branch_instructions.push_back(instruction_ptr(new instruction_split())); - branch->expr->compile(new_env, branch_instructions); - branch_instructions.push_back(instruction_ptr(new instruction_slide( - cpat->params.size()))); - - int new_tag = type->constructors[cpat->constr].tag; - if(jump_instruction->tag_mappings.find(new_tag) != - jump_instruction->tag_mappings.end()) - throw type_error("technically not a type error: duplicate pattern"); - - jump_instruction->tag_mappings[new_tag] = - jump_instruction->branches.size(); - jump_instruction->branches.push_back(std::move(branch_instructions)); - } - } - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) == - jump_instruction->tag_mappings.end()) - throw type_error("non-total pattern"); - } -} - -void pattern_var::print(std::ostream& to) const { - to << var; -} - -void pattern_var::match(type_ptr t, type_mgr& mgr, type_env& env) const { - env.bind(var, t); -} - -void pattern_constr::print(std::ostream& to) const { - to << constr; - for(auto& param : params) { - to << " " << param; - } -} - -void pattern_constr::match(type_ptr t, type_mgr& mgr, type_env& env) const { - type_ptr constructor_type = env.lookup(constr); - if(!constructor_type) { - throw type_error(std::string("pattern using unknown constructor ") + constr); - } - - for(int i = 0; i < params.size(); i++) { - type_arr* arr = dynamic_cast(constructor_type.get()); - if(!arr) throw type_error("too many parameters in constructor pattern"); - - env.bind(params[i], arr->left); - constructor_type = arr->right; - } - - mgr.unify(t, constructor_type); -} diff --git a/code/compiler/06/ast.hpp b/code/compiler/06/ast.hpp deleted file mode 100644 index 2cc54bf..0000000 --- a/code/compiler/06/ast.hpp +++ /dev/null @@ -1,197 +0,0 @@ -#pragma once -#include -#include -#include "type.hpp" -#include "type_env.hpp" -#include "binop.hpp" -#include "instruction.hpp" -#include "env.hpp" - -struct ast { - type_ptr node_type; - - virtual ~ast() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual type_ptr typecheck(type_mgr& mgr, const type_env& env) const = 0; - virtual void resolve(const type_mgr& mgr) const = 0; - virtual void compile(const env_ptr& env, - std::vector& into) const = 0; - - type_ptr typecheck_common(type_mgr& mgr, const type_env& env); - void resolve_common(const type_mgr& mgr); -}; - -using ast_ptr = std::unique_ptr; - -struct pattern { - virtual ~pattern() = default; - - virtual void print(std::ostream& to) const = 0; - virtual void match(type_ptr t, type_mgr& mgr, type_env& 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 constructor { - std::string name; - std::vector types; - int8_t tag; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition { - virtual ~definition() = default; - - virtual void typecheck_first(type_mgr& mgr, type_env& env) = 0; - virtual void typecheck_second(type_mgr& mgr, const type_env& env) const = 0; - virtual void resolve(const type_mgr& mgr) = 0; - virtual void compile() = 0; -}; - -using definition_ptr = std::unique_ptr; - -struct ast_int : public ast { - int value; - - explicit ast_int(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_lid : public ast { - std::string id; - - explicit ast_lid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_uid : public ast { - std::string id; - - explicit ast_uid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - 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) - : op(o), left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - 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) - : left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_case : public ast { - ast_ptr of; - std::vector branches; - - ast_case(ast_ptr o, std::vector b) - : of(std::move(o)), branches(std::move(b)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct pattern_var : public pattern { - std::string var; - - pattern_var(std::string v) - : var(std::move(v)) {} - - void print(std::ostream &to) const; - void match(type_ptr t, type_mgr& mgr, type_env& env) const; -}; - -struct pattern_constr : public pattern { - std::string constr; - std::vector params; - - pattern_constr(std::string c, std::vector p) - : constr(std::move(c)), params(std::move(p)) {} - - void print(std::ostream &to) const; - void match(type_ptr t, type_mgr&, type_env& env) const; -}; - -struct definition_defn : public definition { - std::string name; - std::vector params; - ast_ptr body; - - type_ptr return_type; - std::vector param_types; - - std::vector instructions; - - definition_defn(std::string n, std::vector p, ast_ptr b) - : name(std::move(n)), params(std::move(p)), body(std::move(b)) { - - } - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr); - void compile(); -}; - -struct definition_data : public definition { - std::string name; - std::vector constructors; - - definition_data(std::string n, std::vector cs) - : name(std::move(n)), constructors(std::move(cs)) {} - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr); - void compile(); -}; diff --git a/code/compiler/06/binop.cpp b/code/compiler/06/binop.cpp deleted file mode 100644 index 3a5f0ca..0000000 --- a/code/compiler/06/binop.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "binop.hpp" - -std::string op_name(binop op) { - switch(op) { - case PLUS: return "+"; - case MINUS: return "-"; - case TIMES: return "*"; - case DIVIDE: return "/"; - } - return "??"; -} - -std::string op_action(binop op) { - switch(op) { - case PLUS: return "plus"; - case MINUS: return "minus"; - case TIMES: return "times"; - case DIVIDE: return "divide"; - } - return "??"; -} diff --git a/code/compiler/06/binop.hpp b/code/compiler/06/binop.hpp deleted file mode 100644 index 8d07858..0000000 --- a/code/compiler/06/binop.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -std::string op_name(binop op); -std::string op_action(binop op); diff --git a/code/compiler/06/definition.cpp b/code/compiler/06/definition.cpp deleted file mode 100644 index 29b16cc..0000000 --- a/code/compiler/06/definition.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "ast.hpp" -#include "error.hpp" - -void definition_defn::typecheck_first(type_mgr& mgr, type_env& env) { - return_type = mgr.new_type(); - type_ptr full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - full_type = type_ptr(new type_arr(param_type, full_type)); - param_types.push_back(param_type); - } - - env.bind(name, full_type); -} - -void definition_defn::typecheck_second(type_mgr& mgr, const type_env& env) const { - type_env new_env = env.scope(); - auto param_it = params.begin(); - auto type_it = param_types.rbegin(); - - while(param_it != params.end() && type_it != param_types.rend()) { - new_env.bind(*param_it, *type_it); - param_it++; - type_it++; - } - - type_ptr body_type = body->typecheck_common(mgr, new_env); - mgr.unify(return_type, body_type); -} - -void definition_defn::resolve(const type_mgr& mgr) { - type_var* var; - body->resolve_common(mgr); - - return_type = mgr.resolve(return_type, var); - if(var) throw type_error("ambiguously typed program"); - for(auto& param_type : param_types) { - param_type = mgr.resolve(param_type, var); - if(var) throw type_error("ambiguously typed program"); - } -} - -void definition_defn::compile() { - env_ptr new_env = env_ptr(new env_offset(0, nullptr)); - for(auto it = params.rbegin(); it != params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - body->compile(new_env, instructions); - instructions.push_back(instruction_ptr(new instruction_update(params.size()))); - instructions.push_back(instruction_ptr(new instruction_pop(params.size()))); -} - -void definition_data::typecheck_first(type_mgr& mgr, type_env& env) { - type_data* this_type = new type_data(name); - type_ptr return_type = type_ptr(this_type); - int next_tag = 0; - - for(auto& constructor : constructors) { - constructor->tag = next_tag; - this_type->constructors[constructor->name] = { next_tag++ }; - - 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)); - full_type = type_ptr(new type_arr(type, full_type)); - } - - env.bind(constructor->name, full_type); - } -} - -void definition_data::typecheck_second(type_mgr& mgr, const type_env& env) const { - // Nothing -} - -void definition_data::resolve(const type_mgr& mgr) { - // Nothing -} - -void definition_data::compile() { - -} diff --git a/code/compiler/06/env.cpp b/code/compiler/06/env.cpp deleted file mode 100644 index 818cf5d..0000000 --- a/code/compiler/06/env.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "env.hpp" - -int env_var::get_offset(const std::string& name) const { - if(name == this->name) return 0; - if(parent) return parent->get_offset(name) + 1; - throw 0; -} - -bool env_var::has_variable(const std::string& name) const { - if(name == this->name) return true; - if(parent) return parent->has_variable(name); - return false; -} - -int env_offset::get_offset(const std::string& name) const { - if(parent) return parent->get_offset(name) + offset; - throw 0; -} - -bool env_offset::has_variable(const std::string& name) const { - if(parent) return parent->has_variable(name); - return false; -} diff --git a/code/compiler/06/env.hpp b/code/compiler/06/env.hpp deleted file mode 100644 index a8fbbec..0000000 --- a/code/compiler/06/env.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include - -struct env { - virtual ~env() = default; - - virtual int get_offset(const std::string& name) const = 0; - virtual bool has_variable(const std::string& name) const = 0; -}; - -using env_ptr = std::shared_ptr; - -struct env_var : public env { - std::string name; - env_ptr parent; - - env_var(std::string& n, env_ptr p) - : name(std::move(n)), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; - -struct env_offset : public env { - int offset; - env_ptr parent; - - env_offset(int o, env_ptr p) - : offset(o), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; diff --git a/code/compiler/06/error.cpp b/code/compiler/06/error.cpp deleted file mode 100644 index f5125e3..0000000 --- a/code/compiler/06/error.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "error.hpp" - -const char* type_error::what() const noexcept { - return "an error occured while checking the types of the program"; -} diff --git a/code/compiler/06/error.hpp b/code/compiler/06/error.hpp deleted file mode 100644 index 5bfbc7e..0000000 --- a/code/compiler/06/error.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_error : std::exception { - std::string description; - - type_error(std::string d) - : description(std::move(d)) {} - - const char* what() const noexcept override; -}; - -struct unification_error : public type_error { - type_ptr left; - type_ptr right; - - unification_error(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)), - type_error("failed to unify types") {} -}; diff --git a/code/compiler/06/examples/bad1.txt b/code/compiler/06/examples/bad1.txt deleted file mode 100644 index 86d4bc4..0000000 --- a/code/compiler/06/examples/bad1.txt +++ /dev/null @@ -1,2 +0,0 @@ -data Bool = { True, False } -defn main = { 3 + True } diff --git a/code/compiler/06/examples/bad2.txt b/code/compiler/06/examples/bad2.txt deleted file mode 100644 index def8785..0000000 --- a/code/compiler/06/examples/bad2.txt +++ /dev/null @@ -1 +0,0 @@ -defn main = { 1 2 3 4 5 } diff --git a/code/compiler/06/examples/bad3.txt b/code/compiler/06/examples/bad3.txt deleted file mode 100644 index 6f82b3d..0000000 --- a/code/compiler/06/examples/bad3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } - -defn head l = { - case l of { - Nil -> { 0 } - Cons x y z -> { x } - } -} diff --git a/code/compiler/06/examples/works1.txt b/code/compiler/06/examples/works1.txt deleted file mode 100644 index bedb5d8..0000000 --- a/code/compiler/06/examples/works1.txt +++ /dev/null @@ -1,2 +0,0 @@ -defn main = { plus 320 6 } -defn plus x y = { x + y } diff --git a/code/compiler/06/examples/works2.txt b/code/compiler/06/examples/works2.txt deleted file mode 100644 index 8332fde..0000000 --- a/code/compiler/06/examples/works2.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn add x y = { x + y } -defn double x = { add x x } -defn main = { double 163 } diff --git a/code/compiler/06/examples/works3.txt b/code/compiler/06/examples/works3.txt deleted file mode 100644 index cfffd20..0000000 --- a/code/compiler/06/examples/works3.txt +++ /dev/null @@ -1,7 +0,0 @@ -data List = { Nil, Cons Int List } -defn length l = { - case l of { - Nil -> { 0 } - Cons x xs -> { 1 + length xs } - } -} diff --git a/code/compiler/06/instruction.cpp b/code/compiler/06/instruction.cpp deleted file mode 100644 index 3b421c0..0000000 --- a/code/compiler/06/instruction.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "instruction.hpp" - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void instruction_pushint::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushInt(" << value << ")" << std::endl; -} - -void instruction_pushglobal::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushGlobal(" << name << ")" << std::endl; -} - -void instruction_push::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Push(" << offset << ")" << std::endl; -} - -void instruction_pop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pop(" << count << ")" << std::endl; -} - -void instruction_mkapp::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "MkApp()" << std::endl; -} - -void instruction_update::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Update(" << offset << ")" << std::endl; -} - -void instruction_pack::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pack(" << tag << ", " << size << ")" << std::endl; -} - -void instruction_split::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Split()" << std::endl; -} - -void instruction_jump::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Jump(" << std::endl; - for(auto& instruction_set : branches) { - for(auto& instruction : instruction_set) { - instruction->print(indent + 2, to); - } - to << std::endl; - } - print_indent(indent, to); - to << ")" << std::endl; -} - -void instruction_slide::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Slide(" << offset << ")" << std::endl; -} - -void instruction_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BinOp(" << op_action(op) << ")" << std::endl; -} - -void instruction_eval::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Eval()" << std::endl; -} - -void instruction_alloc::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Alloc(" << amount << ")" << std::endl; -} - -void instruction_unwind::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Unwind()" << std::endl; -} diff --git a/code/compiler/06/instruction.hpp b/code/compiler/06/instruction.hpp deleted file mode 100644 index 5228209..0000000 --- a/code/compiler/06/instruction.hpp +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "binop.hpp" - -struct instruction { - virtual ~instruction() = default; - - virtual void print(int indent, std::ostream& to) const = 0; -}; - -using instruction_ptr = std::unique_ptr; - -struct instruction_pushint : public instruction { - int value; - - instruction_pushint(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_pushglobal : public instruction { - std::string name; - - instruction_pushglobal(std::string n) - : name(std::move(n)) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_push : public instruction { - int offset; - - instruction_push(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_pop : public instruction { - int count; - - instruction_pop(int c) - : count(c) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_mkapp : public instruction { - void print(int indent, std::ostream& to) const; -}; - -struct instruction_update : public instruction { - int offset; - - instruction_update(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_pack : public instruction { - int tag; - int size; - - instruction_pack(int t, int s) - : tag(t), size(s) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_split : public instruction { - void print(int indent, std::ostream& to) const; -}; - -struct instruction_jump : public instruction { - std::vector> branches; - std::map tag_mappings; - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_slide : public instruction { - int offset; - - instruction_slide(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_binop : public instruction { - binop op; - - instruction_binop(binop o) - : op(o) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_eval : public instruction { - void print(int indent, std::ostream& to) const; -}; - -struct instruction_alloc : public instruction { - int amount; - - instruction_alloc(int a) - : amount(a) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_unwind : public instruction { - void print(int indent, std::ostream& to) const; -}; diff --git a/code/compiler/06/main.cpp b/code/compiler/06/main.cpp deleted file mode 100644 index ffbd4e5..0000000 --- a/code/compiler/06/main.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "ast.hpp" -#include -#include "parser.hpp" -#include "error.hpp" -#include "type.hpp" - -void yy::parser::error(const std::string& msg) { - std::cout << "An error occured: " << msg << std::endl; -} - -extern std::vector program; - -void typecheck_program( - const std::vector& prog, - type_mgr& mgr, type_env& env) { - type_ptr int_type = type_ptr(new type_base("Int")); - 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); - env.bind("/", binop_type); - - for(auto& def : prog) { - def->typecheck_first(mgr, env); - } - - for(auto& def : prog) { - def->typecheck_second(mgr, env); - } - - for(auto& pair : env.names) { - std::cout << pair.first << ": "; - pair.second->print(mgr, std::cout); - std::cout << std::endl; - } - - for(auto& def : prog) { - def->resolve(mgr); - } -} - -void compile_program(const std::vector& prog) { - for(auto& def : prog) { - def->compile(); - - definition_defn* defn = dynamic_cast(def.get()); - if(!defn) continue; - for(auto& instruction : defn->instructions) { - instruction->print(0, std::cout); - } - std::cout << std::endl; - } -} - -int main() { - yy::parser parser; - type_mgr mgr; - type_env env; - - parser.parse(); - for(auto& definition : program) { - definition_defn* def = dynamic_cast(definition.get()); - if(!def) continue; - - std::cout << def->name; - for(auto& param : def->params) std::cout << " " << param; - std::cout << ":" << std::endl; - - def->body->print(1, std::cout); - } - try { - typecheck_program(program, mgr, env); - compile_program(program); - } catch(unification_error& err) { - std::cout << "failed to unify types: " << std::endl; - std::cout << " (1) \033[34m"; - err.left->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - std::cout << " (2) \033[32m"; - err.right->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - } catch(type_error& err) { - std::cout << "failed to type check program: " << err.description << std::endl; - } -} diff --git a/code/compiler/06/parser.y b/code/compiler/06/parser.y deleted file mode 100644 index 3874aca..0000000 --- a/code/compiler/06/parser.y +++ /dev/null @@ -1,140 +0,0 @@ -%{ -#include -#include -#include "ast.hpp" -#include "parser.hpp" - -std::vector program; -extern yy::parser::symbol_type yylex(); - -%} - -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%type > lowercaseParams uppercaseParams -%type > program definitions -%type > branches -%type > constructors -%type aAdd aMul case app appBase -%type definition defn data -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { program = std::move($1); } - ; - -definitions - : definitions definition { $$ = std::move($1); $$.push_back(std::move($2)); } - | definition { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -definition - : defn { $$ = std::move($1); } - | data { $$ = std::move($1); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6))); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -uppercaseParams - : %empty { $$ = std::vector(); } - | uppercaseParams UID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } - ; - -branches - : branches branch { $$ = std::move($1); $$.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } - ; - -data - : DATA UID EQUAL OCURLY constructors CCURLY - { $$ = definition_ptr(new definition_data(std::move($2), std::move($5))); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID uppercaseParams - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - diff --git a/code/compiler/06/scanner.l b/code/compiler/06/scanner.l deleted file mode 100644 index 683deeb..0000000 --- a/code/compiler/06/scanner.l +++ /dev/null @@ -1,34 +0,0 @@ -%option noyywrap - -%{ -#include -#include "ast.hpp" -#include "parser.hpp" - -#define YY_DECL yy::parser::symbol_type yylex() - -%} - -%% - -[ \n]+ {} -\+ { return yy::parser::make_PLUS(); } -\* { return yy::parser::make_TIMES(); } -- { return yy::parser::make_MINUS(); } -\/ { return yy::parser::make_DIVIDE(); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } -defn { return yy::parser::make_DEFN(); } -data { return yy::parser::make_DATA(); } -case { return yy::parser::make_CASE(); } -of { return yy::parser::make_OF(); } -\{ { return yy::parser::make_OCURLY(); } -\} { return yy::parser::make_CCURLY(); } -\( { return yy::parser::make_OPAREN(); } -\) { return yy::parser::make_CPAREN(); } -, { return yy::parser::make_COMMA(); } --> { return yy::parser::make_ARROW(); } -= { return yy::parser::make_EQUAL(); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } - -%% diff --git a/code/compiler/06/type.cpp b/code/compiler/06/type.cpp deleted file mode 100644 index f5868d5..0000000 --- a/code/compiler/06/type.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "type.hpp" -#include -#include -#include "error.hpp" - -void type_var::print(const type_mgr& mgr, std::ostream& to) const { - auto it = mgr.types.find(name); - if(it != mgr.types.end()) { - it->second->print(mgr, to); - } else { - to << name; - } -} - -void type_base::print(const type_mgr& mgr, std::ostream& to) const { - to << name; -} - -void type_arr::print(const type_mgr& mgr, std::ostream& to) const { - left->print(mgr, to); - to << " -> ("; - right->print(mgr, to); - to << ")"; -} - -std::string type_mgr::new_type_name() { - int temp = last_id++; - std::string str = ""; - - while(temp != -1) { - str += (char) ('a' + (temp % 26)); - temp = temp / 26 - 1; - } - - std::reverse(str.begin(), str.end()); - return str; -} - -type_ptr type_mgr::new_type() { - return type_ptr(new type_var(new_type_name())); -} - -type_ptr type_mgr::new_arrow_type() { - return type_ptr(new type_arr(new_type(), new_type())); -} - -type_ptr type_mgr::resolve(type_ptr t, type_var*& var) const { - type_var* cast; - - var = nullptr; - while((cast = dynamic_cast(t.get()))) { - auto it = types.find(cast->name); - - if(it == types.end()) { - var = cast; - break; - } - t = it->second; - } - - return t; -} - -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; - - l = resolve(l, lvar); - r = resolve(r, rvar); - - if(lvar) { - bind(lvar->name, r); - return; - } else if(rvar) { - bind(rvar->name, l); - return; - } else if((larr = dynamic_cast(l.get())) && - (rarr = dynamic_cast(r.get()))) { - unify(larr->left, rarr->left); - unify(larr->right, rarr->right); - return; - } else if((lid = dynamic_cast(l.get())) && - (rid = dynamic_cast(r.get()))) { - if(lid->name == rid->name) return; - } - - throw unification_error(l, r); -} - -void type_mgr::bind(const std::string& s, type_ptr t) { - type_var* other = dynamic_cast(t.get()); - - if(other && other->name == s) return; - types[s] = t; -} diff --git a/code/compiler/06/type.hpp b/code/compiler/06/type.hpp deleted file mode 100644 index 09e525f..0000000 --- a/code/compiler/06/type.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once -#include -#include - -struct type_mgr; - -struct type { - virtual ~type() = default; - - virtual void print(const type_mgr& mgr, std::ostream& to) const = 0; -}; - -using type_ptr = std::shared_ptr; - -struct type_var : public type { - std::string name; - - type_var(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_base : public type { - std::string name; - - type_base(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_data : public type_base { - struct constructor { - int tag; - }; - - std::map constructors; - - type_data(std::string n) - : type_base(std::move(n)) {} -}; - -struct type_arr : public type { - type_ptr left; - type_ptr right; - - type_arr(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_mgr { - int last_id = 0; - std::map types; - - std::string new_type_name(); - type_ptr new_type(); - type_ptr new_arrow_type(); - - void unify(type_ptr l, type_ptr r); - type_ptr resolve(type_ptr t, type_var*& var) const; - void bind(const std::string& s, type_ptr t); -}; diff --git a/code/compiler/06/type_env.cpp b/code/compiler/06/type_env.cpp deleted file mode 100644 index c11a759..0000000 --- a/code/compiler/06/type_env.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "type_env.hpp" - -type_ptr type_env::lookup(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second; - if(parent) return parent->lookup(name); - return nullptr; -} - -void type_env::bind(const std::string& name, type_ptr t) { - names[name] = t; -} - -type_env type_env::scope() const { - return type_env(this); -} diff --git a/code/compiler/06/type_env.hpp b/code/compiler/06/type_env.hpp deleted file mode 100644 index 6470bdd..0000000 --- a/code/compiler/06/type_env.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_env { - std::map names; - type_env const* parent = nullptr; - - type_env(type_env const* p) - : parent(p) {} - type_env() : type_env(nullptr) {} - - type_ptr lookup(const std::string& name) const; - void bind(const std::string& name, type_ptr t); - type_env scope() const; -}; diff --git a/code/compiler/07/CMakeLists.txt b/code/compiler/07/CMakeLists.txt deleted file mode 100644 index 5e5dab4..0000000 --- a/code/compiler/07/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(compiler) - -find_package(BISON) -find_package(FLEX) -bison_target(parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser.y - ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp - COMPILE_FLAGS "-d") -flex_target(scanner - ${CMAKE_CURRENT_SOURCE_DIR}/scanner.l - ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp) -add_flex_bison_dependency(scanner parser) - -add_executable(compiler - ast.cpp ast.hpp definition.cpp - type_env.cpp type_env.hpp - env.cpp env.hpp - type.cpp type.hpp - error.cpp error.hpp - binop.cpp binop.hpp - instruction.cpp instruction.hpp - ${BISON_parser_OUTPUTS} - ${FLEX_scanner_OUTPUTS} - main.cpp -) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/code/compiler/07/ast.cpp b/code/compiler/07/ast.cpp deleted file mode 100644 index 486607b..0000000 --- a/code/compiler/07/ast.cpp +++ /dev/null @@ -1,262 +0,0 @@ -#include "ast.hpp" -#include -#include "error.hpp" - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -type_ptr ast::typecheck_common(type_mgr& mgr, const type_env& env) { - node_type = typecheck(mgr, env); - return node_type; -} - -void ast::resolve_common(const type_mgr& mgr) { - type_var* var; - type_ptr resolved_type = mgr.resolve(node_type, var); - if(var) throw type_error("ambiguously typed program"); - - resolve(mgr); - node_type = std::move(resolved_type); -} - -void ast_int::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "INT: " << value << std::endl; -} - -type_ptr ast_int::typecheck(type_mgr& mgr, const type_env& env) const { - return type_ptr(new type_base("Int")); -} - -void ast_int::resolve(const type_mgr& mgr) const { - -} - -void ast_int::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushint(value))); -} - -void ast_lid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LID: " << id << std::endl; -} - -type_ptr ast_lid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -void ast_lid::resolve(const type_mgr& mgr) const { - -} - -void ast_lid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr( - env->has_variable(id) ? - (instruction*) new instruction_push(env->get_offset(id)) : - (instruction*) new instruction_pushglobal(id))); -} - -void ast_uid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "UID: " << id << std::endl; -} - -type_ptr ast_uid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -void ast_uid::resolve(const type_mgr& mgr) const { - -} - -void ast_uid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushglobal(id))); -} - -void ast_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BINOP: " << op_name(op) << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -type_ptr ast_binop::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck_common(mgr, env); - type_ptr rtype = right->typecheck_common(mgr, env); - type_ptr ftype = env.lookup(op_name(op)); - if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op)); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow_one = type_ptr(new type_arr(rtype, return_type)); - type_ptr arrow_two = type_ptr(new type_arr(ltype, arrow_one)); - - mgr.unify(arrow_two, ftype); - return return_type; -} - -void ast_binop::resolve(const type_mgr& mgr) const { - left->resolve_common(mgr); - right->resolve_common(mgr); -} - -void ast_binop::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - - into.push_back(instruction_ptr(new instruction_pushglobal(op_action(op)))); - into.push_back(instruction_ptr(new instruction_mkapp())); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_app::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "APP:" << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck_common(mgr, env); - type_ptr rtype = right->typecheck_common(mgr, env); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); - mgr.unify(arrow, ltype); - return return_type; -} - -void ast_app::resolve(const type_mgr& mgr) const { - left->resolve_common(mgr); - right->resolve_common(mgr); -} - -void ast_app::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_case::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "CASE: " << std::endl; - for(auto& branch : branches) { - print_indent(indent + 1, to); - branch->pat->print(to); - to << std::endl; - branch->expr->print(indent + 2, to); - } -} - -type_ptr ast_case::typecheck(type_mgr& mgr, const type_env& env) const { - type_var* var; - type_ptr case_type = mgr.resolve(of->typecheck_common(mgr, env), var); - type_ptr branch_type = mgr.new_type(); - - for(auto& branch : branches) { - type_env new_env = env.scope(); - branch->pat->match(case_type, mgr, new_env); - type_ptr curr_branch_type = branch->expr->typecheck_common(mgr, new_env); - mgr.unify(branch_type, curr_branch_type); - } - - case_type = mgr.resolve(case_type, var); - if(!dynamic_cast(case_type.get())) { - throw type_error("attempting case analysis of non-data type"); - } - - return branch_type; -} - -void ast_case::resolve(const type_mgr& mgr) const { - of->resolve_common(mgr); - for(auto& branch : branches) { - branch->expr->resolve_common(mgr); - } -} - -void ast_case::compile(const env_ptr& env, std::vector& into) const { - type_data* type = dynamic_cast(of->node_type.get()); - - of->compile(env, into); - into.push_back(instruction_ptr(new instruction_eval())); - - instruction_jump* jump_instruction = new instruction_jump(); - into.push_back(instruction_ptr(jump_instruction)); - for(auto& branch : branches) { - std::vector branch_instructions; - pattern_var* vpat; - pattern_constr* cpat; - - if((vpat = dynamic_cast(branch->pat.get()))) { - branch->expr->compile(env_ptr(new env_offset(1, env)), branch_instructions); - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) != - jump_instruction->tag_mappings.end()) - break; - - jump_instruction->tag_mappings[constr_pair.second.tag] = - jump_instruction->branches.size(); - } - jump_instruction->branches.push_back(std::move(branch_instructions)); - } else if((cpat = dynamic_cast(branch->pat.get()))) { - env_ptr new_env = env; - for(auto it = cpat->params.rbegin(); it != cpat->params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - - branch_instructions.push_back(instruction_ptr(new instruction_split())); - branch->expr->compile(new_env, branch_instructions); - branch_instructions.push_back(instruction_ptr(new instruction_slide( - cpat->params.size()))); - - int new_tag = type->constructors[cpat->constr].tag; - if(jump_instruction->tag_mappings.find(new_tag) != - jump_instruction->tag_mappings.end()) - throw type_error("technically not a type error: duplicate pattern"); - - jump_instruction->tag_mappings[new_tag] = - jump_instruction->branches.size(); - jump_instruction->branches.push_back(std::move(branch_instructions)); - } - } - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) == - jump_instruction->tag_mappings.end()) - throw type_error("non-total pattern"); - } -} - -void pattern_var::print(std::ostream& to) const { - to << var; -} - -void pattern_var::match(type_ptr t, type_mgr& mgr, type_env& env) const { - env.bind(var, t); -} - -void pattern_constr::print(std::ostream& to) const { - to << constr; - for(auto& param : params) { - to << " " << param; - } -} - -void pattern_constr::match(type_ptr t, type_mgr& mgr, type_env& env) const { - type_ptr constructor_type = env.lookup(constr); - if(!constructor_type) { - throw type_error(std::string("pattern using unknown constructor ") + constr); - } - - for(int i = 0; i < params.size(); i++) { - type_arr* arr = dynamic_cast(constructor_type.get()); - if(!arr) throw type_error("too many parameters in constructor pattern"); - - env.bind(params[i], arr->left); - constructor_type = arr->right; - } - - mgr.unify(t, constructor_type); -} diff --git a/code/compiler/07/ast.hpp b/code/compiler/07/ast.hpp deleted file mode 100644 index 2cc54bf..0000000 --- a/code/compiler/07/ast.hpp +++ /dev/null @@ -1,197 +0,0 @@ -#pragma once -#include -#include -#include "type.hpp" -#include "type_env.hpp" -#include "binop.hpp" -#include "instruction.hpp" -#include "env.hpp" - -struct ast { - type_ptr node_type; - - virtual ~ast() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual type_ptr typecheck(type_mgr& mgr, const type_env& env) const = 0; - virtual void resolve(const type_mgr& mgr) const = 0; - virtual void compile(const env_ptr& env, - std::vector& into) const = 0; - - type_ptr typecheck_common(type_mgr& mgr, const type_env& env); - void resolve_common(const type_mgr& mgr); -}; - -using ast_ptr = std::unique_ptr; - -struct pattern { - virtual ~pattern() = default; - - virtual void print(std::ostream& to) const = 0; - virtual void match(type_ptr t, type_mgr& mgr, type_env& 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 constructor { - std::string name; - std::vector types; - int8_t tag; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition { - virtual ~definition() = default; - - virtual void typecheck_first(type_mgr& mgr, type_env& env) = 0; - virtual void typecheck_second(type_mgr& mgr, const type_env& env) const = 0; - virtual void resolve(const type_mgr& mgr) = 0; - virtual void compile() = 0; -}; - -using definition_ptr = std::unique_ptr; - -struct ast_int : public ast { - int value; - - explicit ast_int(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_lid : public ast { - std::string id; - - explicit ast_lid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_uid : public ast { - std::string id; - - explicit ast_uid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - 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) - : op(o), left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - 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) - : left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_case : public ast { - ast_ptr of; - std::vector branches; - - ast_case(ast_ptr o, std::vector b) - : of(std::move(o)), branches(std::move(b)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct pattern_var : public pattern { - std::string var; - - pattern_var(std::string v) - : var(std::move(v)) {} - - void print(std::ostream &to) const; - void match(type_ptr t, type_mgr& mgr, type_env& env) const; -}; - -struct pattern_constr : public pattern { - std::string constr; - std::vector params; - - pattern_constr(std::string c, std::vector p) - : constr(std::move(c)), params(std::move(p)) {} - - void print(std::ostream &to) const; - void match(type_ptr t, type_mgr&, type_env& env) const; -}; - -struct definition_defn : public definition { - std::string name; - std::vector params; - ast_ptr body; - - type_ptr return_type; - std::vector param_types; - - std::vector instructions; - - definition_defn(std::string n, std::vector p, ast_ptr b) - : name(std::move(n)), params(std::move(p)), body(std::move(b)) { - - } - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr); - void compile(); -}; - -struct definition_data : public definition { - std::string name; - std::vector constructors; - - definition_data(std::string n, std::vector cs) - : name(std::move(n)), constructors(std::move(cs)) {} - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr); - void compile(); -}; diff --git a/code/compiler/07/binop.cpp b/code/compiler/07/binop.cpp deleted file mode 100644 index 3a5f0ca..0000000 --- a/code/compiler/07/binop.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "binop.hpp" - -std::string op_name(binop op) { - switch(op) { - case PLUS: return "+"; - case MINUS: return "-"; - case TIMES: return "*"; - case DIVIDE: return "/"; - } - return "??"; -} - -std::string op_action(binop op) { - switch(op) { - case PLUS: return "plus"; - case MINUS: return "minus"; - case TIMES: return "times"; - case DIVIDE: return "divide"; - } - return "??"; -} diff --git a/code/compiler/07/binop.hpp b/code/compiler/07/binop.hpp deleted file mode 100644 index 8d07858..0000000 --- a/code/compiler/07/binop.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -std::string op_name(binop op); -std::string op_action(binop op); diff --git a/code/compiler/07/definition.cpp b/code/compiler/07/definition.cpp deleted file mode 100644 index 29b16cc..0000000 --- a/code/compiler/07/definition.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "ast.hpp" -#include "error.hpp" - -void definition_defn::typecheck_first(type_mgr& mgr, type_env& env) { - return_type = mgr.new_type(); - type_ptr full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - full_type = type_ptr(new type_arr(param_type, full_type)); - param_types.push_back(param_type); - } - - env.bind(name, full_type); -} - -void definition_defn::typecheck_second(type_mgr& mgr, const type_env& env) const { - type_env new_env = env.scope(); - auto param_it = params.begin(); - auto type_it = param_types.rbegin(); - - while(param_it != params.end() && type_it != param_types.rend()) { - new_env.bind(*param_it, *type_it); - param_it++; - type_it++; - } - - type_ptr body_type = body->typecheck_common(mgr, new_env); - mgr.unify(return_type, body_type); -} - -void definition_defn::resolve(const type_mgr& mgr) { - type_var* var; - body->resolve_common(mgr); - - return_type = mgr.resolve(return_type, var); - if(var) throw type_error("ambiguously typed program"); - for(auto& param_type : param_types) { - param_type = mgr.resolve(param_type, var); - if(var) throw type_error("ambiguously typed program"); - } -} - -void definition_defn::compile() { - env_ptr new_env = env_ptr(new env_offset(0, nullptr)); - for(auto it = params.rbegin(); it != params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - body->compile(new_env, instructions); - instructions.push_back(instruction_ptr(new instruction_update(params.size()))); - instructions.push_back(instruction_ptr(new instruction_pop(params.size()))); -} - -void definition_data::typecheck_first(type_mgr& mgr, type_env& env) { - type_data* this_type = new type_data(name); - type_ptr return_type = type_ptr(this_type); - int next_tag = 0; - - for(auto& constructor : constructors) { - constructor->tag = next_tag; - this_type->constructors[constructor->name] = { next_tag++ }; - - 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)); - full_type = type_ptr(new type_arr(type, full_type)); - } - - env.bind(constructor->name, full_type); - } -} - -void definition_data::typecheck_second(type_mgr& mgr, const type_env& env) const { - // Nothing -} - -void definition_data::resolve(const type_mgr& mgr) { - // Nothing -} - -void definition_data::compile() { - -} diff --git a/code/compiler/07/env.cpp b/code/compiler/07/env.cpp deleted file mode 100644 index 818cf5d..0000000 --- a/code/compiler/07/env.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "env.hpp" - -int env_var::get_offset(const std::string& name) const { - if(name == this->name) return 0; - if(parent) return parent->get_offset(name) + 1; - throw 0; -} - -bool env_var::has_variable(const std::string& name) const { - if(name == this->name) return true; - if(parent) return parent->has_variable(name); - return false; -} - -int env_offset::get_offset(const std::string& name) const { - if(parent) return parent->get_offset(name) + offset; - throw 0; -} - -bool env_offset::has_variable(const std::string& name) const { - if(parent) return parent->has_variable(name); - return false; -} diff --git a/code/compiler/07/env.hpp b/code/compiler/07/env.hpp deleted file mode 100644 index a8fbbec..0000000 --- a/code/compiler/07/env.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include - -struct env { - virtual ~env() = default; - - virtual int get_offset(const std::string& name) const = 0; - virtual bool has_variable(const std::string& name) const = 0; -}; - -using env_ptr = std::shared_ptr; - -struct env_var : public env { - std::string name; - env_ptr parent; - - env_var(std::string& n, env_ptr p) - : name(std::move(n)), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; - -struct env_offset : public env { - int offset; - env_ptr parent; - - env_offset(int o, env_ptr p) - : offset(o), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; diff --git a/code/compiler/07/error.cpp b/code/compiler/07/error.cpp deleted file mode 100644 index f5125e3..0000000 --- a/code/compiler/07/error.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "error.hpp" - -const char* type_error::what() const noexcept { - return "an error occured while checking the types of the program"; -} diff --git a/code/compiler/07/error.hpp b/code/compiler/07/error.hpp deleted file mode 100644 index 5bfbc7e..0000000 --- a/code/compiler/07/error.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_error : std::exception { - std::string description; - - type_error(std::string d) - : description(std::move(d)) {} - - const char* what() const noexcept override; -}; - -struct unification_error : public type_error { - type_ptr left; - type_ptr right; - - unification_error(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)), - type_error("failed to unify types") {} -}; diff --git a/code/compiler/07/examples/bad1.txt b/code/compiler/07/examples/bad1.txt deleted file mode 100644 index 86d4bc4..0000000 --- a/code/compiler/07/examples/bad1.txt +++ /dev/null @@ -1,2 +0,0 @@ -data Bool = { True, False } -defn main = { 3 + True } diff --git a/code/compiler/07/examples/bad2.txt b/code/compiler/07/examples/bad2.txt deleted file mode 100644 index def8785..0000000 --- a/code/compiler/07/examples/bad2.txt +++ /dev/null @@ -1 +0,0 @@ -defn main = { 1 2 3 4 5 } diff --git a/code/compiler/07/examples/bad3.txt b/code/compiler/07/examples/bad3.txt deleted file mode 100644 index 6f82b3d..0000000 --- a/code/compiler/07/examples/bad3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } - -defn head l = { - case l of { - Nil -> { 0 } - Cons x y z -> { x } - } -} diff --git a/code/compiler/07/examples/runtime1.c b/code/compiler/07/examples/runtime1.c deleted file mode 100644 index 0157051..0000000 --- a/code/compiler/07/examples/runtime1.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "../runtime.h" - -void f_add(struct stack* s) { - struct node_num* left = (struct node_num*) eval(stack_peek(s, 0)); - struct node_num* right = (struct node_num*) eval(stack_peek(s, 1)); - stack_push(s, (struct node_base*) alloc_num(left->value + right->value)); -} - -void f_main(struct stack* s) { - // PushInt 320 - stack_push(s, (struct node_base*) alloc_num(320)); - - // PushInt 6 - stack_push(s, (struct node_base*) alloc_num(6)); - - // PushGlobal f_add (the function for +) - stack_push(s, (struct node_base*) alloc_global(f_add, 2)); - - struct node_base* left; - struct node_base* right; - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); -} diff --git a/code/compiler/07/examples/works1.txt b/code/compiler/07/examples/works1.txt deleted file mode 100644 index bedb5d8..0000000 --- a/code/compiler/07/examples/works1.txt +++ /dev/null @@ -1,2 +0,0 @@ -defn main = { plus 320 6 } -defn plus x y = { x + y } diff --git a/code/compiler/07/examples/works2.txt b/code/compiler/07/examples/works2.txt deleted file mode 100644 index 8332fde..0000000 --- a/code/compiler/07/examples/works2.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn add x y = { x + y } -defn double x = { add x x } -defn main = { double 163 } diff --git a/code/compiler/07/examples/works3.txt b/code/compiler/07/examples/works3.txt deleted file mode 100644 index cfffd20..0000000 --- a/code/compiler/07/examples/works3.txt +++ /dev/null @@ -1,7 +0,0 @@ -data List = { Nil, Cons Int List } -defn length l = { - case l of { - Nil -> { 0 } - Cons x xs -> { 1 + length xs } - } -} diff --git a/code/compiler/07/instruction.cpp b/code/compiler/07/instruction.cpp deleted file mode 100644 index 3b421c0..0000000 --- a/code/compiler/07/instruction.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "instruction.hpp" - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void instruction_pushint::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushInt(" << value << ")" << std::endl; -} - -void instruction_pushglobal::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushGlobal(" << name << ")" << std::endl; -} - -void instruction_push::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Push(" << offset << ")" << std::endl; -} - -void instruction_pop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pop(" << count << ")" << std::endl; -} - -void instruction_mkapp::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "MkApp()" << std::endl; -} - -void instruction_update::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Update(" << offset << ")" << std::endl; -} - -void instruction_pack::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pack(" << tag << ", " << size << ")" << std::endl; -} - -void instruction_split::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Split()" << std::endl; -} - -void instruction_jump::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Jump(" << std::endl; - for(auto& instruction_set : branches) { - for(auto& instruction : instruction_set) { - instruction->print(indent + 2, to); - } - to << std::endl; - } - print_indent(indent, to); - to << ")" << std::endl; -} - -void instruction_slide::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Slide(" << offset << ")" << std::endl; -} - -void instruction_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BinOp(" << op_action(op) << ")" << std::endl; -} - -void instruction_eval::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Eval()" << std::endl; -} - -void instruction_alloc::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Alloc(" << amount << ")" << std::endl; -} - -void instruction_unwind::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Unwind()" << std::endl; -} diff --git a/code/compiler/07/instruction.hpp b/code/compiler/07/instruction.hpp deleted file mode 100644 index 5228209..0000000 --- a/code/compiler/07/instruction.hpp +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "binop.hpp" - -struct instruction { - virtual ~instruction() = default; - - virtual void print(int indent, std::ostream& to) const = 0; -}; - -using instruction_ptr = std::unique_ptr; - -struct instruction_pushint : public instruction { - int value; - - instruction_pushint(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_pushglobal : public instruction { - std::string name; - - instruction_pushglobal(std::string n) - : name(std::move(n)) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_push : public instruction { - int offset; - - instruction_push(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_pop : public instruction { - int count; - - instruction_pop(int c) - : count(c) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_mkapp : public instruction { - void print(int indent, std::ostream& to) const; -}; - -struct instruction_update : public instruction { - int offset; - - instruction_update(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_pack : public instruction { - int tag; - int size; - - instruction_pack(int t, int s) - : tag(t), size(s) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_split : public instruction { - void print(int indent, std::ostream& to) const; -}; - -struct instruction_jump : public instruction { - std::vector> branches; - std::map tag_mappings; - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_slide : public instruction { - int offset; - - instruction_slide(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_binop : public instruction { - binop op; - - instruction_binop(binop o) - : op(o) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_eval : public instruction { - void print(int indent, std::ostream& to) const; -}; - -struct instruction_alloc : public instruction { - int amount; - - instruction_alloc(int a) - : amount(a) {} - - void print(int indent, std::ostream& to) const; -}; - -struct instruction_unwind : public instruction { - void print(int indent, std::ostream& to) const; -}; diff --git a/code/compiler/07/main.cpp b/code/compiler/07/main.cpp deleted file mode 100644 index ffbd4e5..0000000 --- a/code/compiler/07/main.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "ast.hpp" -#include -#include "parser.hpp" -#include "error.hpp" -#include "type.hpp" - -void yy::parser::error(const std::string& msg) { - std::cout << "An error occured: " << msg << std::endl; -} - -extern std::vector program; - -void typecheck_program( - const std::vector& prog, - type_mgr& mgr, type_env& env) { - type_ptr int_type = type_ptr(new type_base("Int")); - 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); - env.bind("/", binop_type); - - for(auto& def : prog) { - def->typecheck_first(mgr, env); - } - - for(auto& def : prog) { - def->typecheck_second(mgr, env); - } - - for(auto& pair : env.names) { - std::cout << pair.first << ": "; - pair.second->print(mgr, std::cout); - std::cout << std::endl; - } - - for(auto& def : prog) { - def->resolve(mgr); - } -} - -void compile_program(const std::vector& prog) { - for(auto& def : prog) { - def->compile(); - - definition_defn* defn = dynamic_cast(def.get()); - if(!defn) continue; - for(auto& instruction : defn->instructions) { - instruction->print(0, std::cout); - } - std::cout << std::endl; - } -} - -int main() { - yy::parser parser; - type_mgr mgr; - type_env env; - - parser.parse(); - for(auto& definition : program) { - definition_defn* def = dynamic_cast(definition.get()); - if(!def) continue; - - std::cout << def->name; - for(auto& param : def->params) std::cout << " " << param; - std::cout << ":" << std::endl; - - def->body->print(1, std::cout); - } - try { - typecheck_program(program, mgr, env); - compile_program(program); - } catch(unification_error& err) { - std::cout << "failed to unify types: " << std::endl; - std::cout << " (1) \033[34m"; - err.left->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - std::cout << " (2) \033[32m"; - err.right->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - } catch(type_error& err) { - std::cout << "failed to type check program: " << err.description << std::endl; - } -} diff --git a/code/compiler/07/parser.y b/code/compiler/07/parser.y deleted file mode 100644 index 3874aca..0000000 --- a/code/compiler/07/parser.y +++ /dev/null @@ -1,140 +0,0 @@ -%{ -#include -#include -#include "ast.hpp" -#include "parser.hpp" - -std::vector program; -extern yy::parser::symbol_type yylex(); - -%} - -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%type > lowercaseParams uppercaseParams -%type > program definitions -%type > branches -%type > constructors -%type aAdd aMul case app appBase -%type definition defn data -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { program = std::move($1); } - ; - -definitions - : definitions definition { $$ = std::move($1); $$.push_back(std::move($2)); } - | definition { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -definition - : defn { $$ = std::move($1); } - | data { $$ = std::move($1); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6))); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -uppercaseParams - : %empty { $$ = std::vector(); } - | uppercaseParams UID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } - ; - -branches - : branches branch { $$ = std::move($1); $$.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } - ; - -data - : DATA UID EQUAL OCURLY constructors CCURLY - { $$ = definition_ptr(new definition_data(std::move($2), std::move($5))); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID uppercaseParams - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - diff --git a/code/compiler/07/runtime.c b/code/compiler/07/runtime.c deleted file mode 100644 index c7bc5b0..0000000 --- a/code/compiler/07/runtime.c +++ /dev/null @@ -1,159 +0,0 @@ -#include -#include -#include -#include "runtime.h" - -struct node_base* alloc_node() { - struct node_base* new_node = malloc(sizeof(struct node_app)); - assert(new_node != NULL); - return new_node; -} - -struct node_app* alloc_app(struct node_base* l, struct node_base* r) { - struct node_app* node = (struct node_app*) alloc_node(); - node->base.tag = NODE_APP; - node->left = l; - node->right = r; - return node; -} - -struct node_num* alloc_num(int32_t n) { - struct node_num* node = (struct node_num*) alloc_node(); - node->base.tag = NODE_NUM; - node->value = n; - return node; -} - -struct node_global* alloc_global(void (*f)(struct stack*), int32_t a) { - struct node_global* node = (struct node_global*) alloc_node(); - node->base.tag = NODE_GLOBAL; - node->arity = a; - node->function = f; - return node; -} - -struct node_ind* alloc_ind(struct node_base* n) { - struct node_ind* node = (struct node_ind*) alloc_node(); - node->base.tag = NODE_IND; - node->next = n; - return node; -} - -void stack_init(struct stack* s) { - s->size = 4; - s->count = 0; - s->data = malloc(sizeof(*s->data) * s->size); - assert(s->data != NULL); -} - -void stack_free(struct stack* s) { - free(s->data); -} - -void stack_push(struct stack* s, struct node_base* n) { - while(s->count >= s->size) { - s->data = realloc(s->data, sizeof(*s->data) * (s->size *= 2)); - assert(s->data != NULL); - } - s->data[s->count++] = n; -} - -struct node_base* stack_pop(struct stack* s) { - assert(s->count > 0); - return s->data[--s->count]; -} - -struct node_base* stack_peek(struct stack* s, size_t o) { - assert(s->count > o); - return s->data[s->count - o - 1]; -} - -void stack_popn(struct stack* s, size_t n) { - assert(s->count >= n); - s->count -= n; -} - -void stack_slide(struct stack* s, size_t n) { - assert(s->count > n); - s->data[s->count - n - 1] = s->data[s->count - 1]; - s->count -= n; -} - -void stack_update(struct stack* s, size_t o) { - assert(s->count > o + 1); - struct node_ind* ind = (struct node_ind*) s->data[s->count - o - 2]; - ind->base.tag = NODE_IND; - ind->next = s->data[s->count -= 1]; -} - -void stack_alloc(struct stack* s, size_t o) { - while(o--) { - stack_push(s, (struct node_base*) alloc_ind(NULL)); - } -} - -void stack_pack(struct stack* s, size_t n, int8_t t) { - assert(s->count >= n); - - struct node_base** data = malloc(sizeof(*data) * n); - assert(data != NULL); - memcpy(data, &s->data[s->count - 1 - n], n * sizeof(*data)); - - struct node_data* new_node = (struct node_data*) alloc_node(); - new_node->array = data; - new_node->base.tag = NODE_DATA; - new_node->tag = t; - - stack_popn(s, n); - stack_push(s, (struct node_base*) new_node); -} - -void stack_split(struct stack* s, size_t n) { - struct node_data* node = (struct node_data*) stack_pop(s); - for(size_t i = 0; i < n; i++) { - stack_push(s, node->array[i]); - } -} - -void unwind(struct stack* s) { - while(1) { - struct node_base* peek = stack_peek(s, 0); - if(peek->tag == NODE_APP) { - struct node_app* n = (struct node_app*) peek; - stack_push(s, n->left); - } else if(peek->tag == NODE_GLOBAL) { - struct node_global* n = (struct node_global*) peek; - assert(s->count > n->arity); - - for(size_t i = 1; i <= n->arity; i++) { - s->data[s->count - i] - = ((struct node_app*) s->data[s->count - i - 1])->right; - } - - n->function(s); - } else if(peek->tag == NODE_IND) { - struct node_ind* n = (struct node_ind*) peek; - stack_pop(s); - stack_push(s, n->next); - } else { - break; - } - } -} - -struct node_base* eval(struct node_base* n) { - struct stack program_stack; - stack_init(&program_stack); - stack_push(&program_stack, n); - unwind(&program_stack); - struct node_base* result = stack_pop(&program_stack); - stack_free(&program_stack); - return result; -} - -extern void f_main(struct stack* s); - -int main(int argc, char** argv) { - struct node_global* first_node = alloc_global(f_main, 0); - struct node_base* result = eval((struct node_base*) first_node); -} diff --git a/code/compiler/07/runtime.h b/code/compiler/07/runtime.h deleted file mode 100644 index baaaaae..0000000 --- a/code/compiler/07/runtime.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once -#include - -struct stack; - -enum node_tag { - NODE_APP, - NODE_NUM, - NODE_GLOBAL, - NODE_IND, - NODE_DATA -}; - -struct node_base { - enum node_tag tag; -}; - -struct node_app { - struct node_base base; - struct node_base* left; - struct node_base* right; -}; - -struct node_num { - struct node_base base; - int32_t value; -}; - -struct node_global { - struct node_base base; - int32_t arity; - void (*function)(struct stack*); -}; - -struct node_ind { - struct node_base base; - struct node_base* next; -}; - -struct node_data { - struct node_base base; - int8_t tag; - struct node_base** array; -}; - -struct node_base* alloc_node(); -struct node_app* alloc_app(struct node_base* l, struct node_base* r); -struct node_num* alloc_num(int32_t n); -struct node_global* alloc_global(void (*f)(struct stack*), int32_t a); -struct node_ind* alloc_ind(struct node_base* n); - -struct stack { - size_t size; - size_t count; - struct node_base** data; -}; - -void stack_init(struct stack* s); -void stack_free(struct stack* s); -void stack_push(struct stack* s, struct node_base* n); -struct node_base* stack_pop(struct stack* s); -struct node_base* stack_peek(struct stack* s, size_t o); -void stack_popn(struct stack* s, size_t n); -void stack_slide(struct stack* s, size_t n); -void stack_update(struct stack* s, size_t o); -void stack_alloc(struct stack* s, size_t o); -void stack_pack(struct stack* s, size_t n, int8_t t); -void stack_split(struct stack* s, size_t n); - -struct node_base* eval(struct node_base* n); diff --git a/code/compiler/07/scanner.l b/code/compiler/07/scanner.l deleted file mode 100644 index 683deeb..0000000 --- a/code/compiler/07/scanner.l +++ /dev/null @@ -1,34 +0,0 @@ -%option noyywrap - -%{ -#include -#include "ast.hpp" -#include "parser.hpp" - -#define YY_DECL yy::parser::symbol_type yylex() - -%} - -%% - -[ \n]+ {} -\+ { return yy::parser::make_PLUS(); } -\* { return yy::parser::make_TIMES(); } -- { return yy::parser::make_MINUS(); } -\/ { return yy::parser::make_DIVIDE(); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } -defn { return yy::parser::make_DEFN(); } -data { return yy::parser::make_DATA(); } -case { return yy::parser::make_CASE(); } -of { return yy::parser::make_OF(); } -\{ { return yy::parser::make_OCURLY(); } -\} { return yy::parser::make_CCURLY(); } -\( { return yy::parser::make_OPAREN(); } -\) { return yy::parser::make_CPAREN(); } -, { return yy::parser::make_COMMA(); } --> { return yy::parser::make_ARROW(); } -= { return yy::parser::make_EQUAL(); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } - -%% diff --git a/code/compiler/07/type.cpp b/code/compiler/07/type.cpp deleted file mode 100644 index f5868d5..0000000 --- a/code/compiler/07/type.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "type.hpp" -#include -#include -#include "error.hpp" - -void type_var::print(const type_mgr& mgr, std::ostream& to) const { - auto it = mgr.types.find(name); - if(it != mgr.types.end()) { - it->second->print(mgr, to); - } else { - to << name; - } -} - -void type_base::print(const type_mgr& mgr, std::ostream& to) const { - to << name; -} - -void type_arr::print(const type_mgr& mgr, std::ostream& to) const { - left->print(mgr, to); - to << " -> ("; - right->print(mgr, to); - to << ")"; -} - -std::string type_mgr::new_type_name() { - int temp = last_id++; - std::string str = ""; - - while(temp != -1) { - str += (char) ('a' + (temp % 26)); - temp = temp / 26 - 1; - } - - std::reverse(str.begin(), str.end()); - return str; -} - -type_ptr type_mgr::new_type() { - return type_ptr(new type_var(new_type_name())); -} - -type_ptr type_mgr::new_arrow_type() { - return type_ptr(new type_arr(new_type(), new_type())); -} - -type_ptr type_mgr::resolve(type_ptr t, type_var*& var) const { - type_var* cast; - - var = nullptr; - while((cast = dynamic_cast(t.get()))) { - auto it = types.find(cast->name); - - if(it == types.end()) { - var = cast; - break; - } - t = it->second; - } - - return t; -} - -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; - - l = resolve(l, lvar); - r = resolve(r, rvar); - - if(lvar) { - bind(lvar->name, r); - return; - } else if(rvar) { - bind(rvar->name, l); - return; - } else if((larr = dynamic_cast(l.get())) && - (rarr = dynamic_cast(r.get()))) { - unify(larr->left, rarr->left); - unify(larr->right, rarr->right); - return; - } else if((lid = dynamic_cast(l.get())) && - (rid = dynamic_cast(r.get()))) { - if(lid->name == rid->name) return; - } - - throw unification_error(l, r); -} - -void type_mgr::bind(const std::string& s, type_ptr t) { - type_var* other = dynamic_cast(t.get()); - - if(other && other->name == s) return; - types[s] = t; -} diff --git a/code/compiler/07/type.hpp b/code/compiler/07/type.hpp deleted file mode 100644 index 09e525f..0000000 --- a/code/compiler/07/type.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once -#include -#include - -struct type_mgr; - -struct type { - virtual ~type() = default; - - virtual void print(const type_mgr& mgr, std::ostream& to) const = 0; -}; - -using type_ptr = std::shared_ptr; - -struct type_var : public type { - std::string name; - - type_var(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_base : public type { - std::string name; - - type_base(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_data : public type_base { - struct constructor { - int tag; - }; - - std::map constructors; - - type_data(std::string n) - : type_base(std::move(n)) {} -}; - -struct type_arr : public type { - type_ptr left; - type_ptr right; - - type_arr(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_mgr { - int last_id = 0; - std::map types; - - std::string new_type_name(); - type_ptr new_type(); - type_ptr new_arrow_type(); - - void unify(type_ptr l, type_ptr r); - type_ptr resolve(type_ptr t, type_var*& var) const; - void bind(const std::string& s, type_ptr t); -}; diff --git a/code/compiler/07/type_env.cpp b/code/compiler/07/type_env.cpp deleted file mode 100644 index c11a759..0000000 --- a/code/compiler/07/type_env.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "type_env.hpp" - -type_ptr type_env::lookup(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second; - if(parent) return parent->lookup(name); - return nullptr; -} - -void type_env::bind(const std::string& name, type_ptr t) { - names[name] = t; -} - -type_env type_env::scope() const { - return type_env(this); -} diff --git a/code/compiler/07/type_env.hpp b/code/compiler/07/type_env.hpp deleted file mode 100644 index 6470bdd..0000000 --- a/code/compiler/07/type_env.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_env { - std::map names; - type_env const* parent = nullptr; - - type_env(type_env const* p) - : parent(p) {} - type_env() : type_env(nullptr) {} - - type_ptr lookup(const std::string& name) const; - void bind(const std::string& name, type_ptr t); - type_env scope() const; -}; diff --git a/code/compiler/08/CMakeLists.txt b/code/compiler/08/CMakeLists.txt deleted file mode 100644 index 1347f11..0000000 --- a/code/compiler/08/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(compiler) - -# Find all the required packages -find_package(BISON) -find_package(FLEX) -find_package(LLVM REQUIRED CONFIG) - -# Set up the flex and bison targets -bison_target(parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser.y - ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp - COMPILE_FLAGS "-d") -flex_target(scanner - ${CMAKE_CURRENT_SOURCE_DIR}/scanner.l - ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp) -add_flex_bison_dependency(scanner parser) - -# Find all the relevant LLVM components -llvm_map_components_to_libnames(LLVM_LIBS core x86asmparser x86codegen) - -# Create compiler executable -add_executable(compiler - ast.cpp ast.hpp definition.cpp - llvm_context.cpp llvm_context.hpp - type_env.cpp type_env.hpp - env.cpp env.hpp - type.cpp type.hpp - error.cpp error.hpp - binop.cpp binop.hpp - instruction.cpp instruction.hpp - ${BISON_parser_OUTPUTS} - ${FLEX_scanner_OUTPUTS} - main.cpp -) - -# Configure compiler executable -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) -target_include_directories(compiler PUBLIC ${LLVM_INCLUDE_DIRS}) -target_compile_definitions(compiler PUBLIC ${LLVM_DEFINITIONS}) -target_link_libraries(compiler ${LLVM_LIBS}) diff --git a/code/compiler/08/ast.cpp b/code/compiler/08/ast.cpp deleted file mode 100644 index 453a12b..0000000 --- a/code/compiler/08/ast.cpp +++ /dev/null @@ -1,264 +0,0 @@ -#include "ast.hpp" -#include -#include "binop.hpp" -#include "error.hpp" - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -type_ptr ast::typecheck_common(type_mgr& mgr, const type_env& env) { - node_type = typecheck(mgr, env); - return node_type; -} - -void ast::resolve_common(const type_mgr& mgr) { - type_var* var; - type_ptr resolved_type = mgr.resolve(node_type, var); - if(var) throw type_error("ambiguously typed program"); - - resolve(mgr); - node_type = std::move(resolved_type); -} - -void ast_int::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "INT: " << value << std::endl; -} - -type_ptr ast_int::typecheck(type_mgr& mgr, const type_env& env) const { - return type_ptr(new type_base("Int")); -} - -void ast_int::resolve(const type_mgr& mgr) const { - -} - -void ast_int::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushint(value))); -} - -void ast_lid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LID: " << id << std::endl; -} - -type_ptr ast_lid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -void ast_lid::resolve(const type_mgr& mgr) const { - -} - -void ast_lid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr( - env->has_variable(id) ? - (instruction*) new instruction_push(env->get_offset(id)) : - (instruction*) new instruction_pushglobal(id))); -} - -void ast_uid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "UID: " << id << std::endl; -} - -type_ptr ast_uid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -void ast_uid::resolve(const type_mgr& mgr) const { - -} - -void ast_uid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushglobal(id))); -} - -void ast_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BINOP: " << op_name(op) << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -type_ptr ast_binop::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck_common(mgr, env); - type_ptr rtype = right->typecheck_common(mgr, env); - type_ptr ftype = env.lookup(op_name(op)); - if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op)); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow_one = type_ptr(new type_arr(rtype, return_type)); - type_ptr arrow_two = type_ptr(new type_arr(ltype, arrow_one)); - - mgr.unify(arrow_two, ftype); - return return_type; -} - -void ast_binop::resolve(const type_mgr& mgr) const { - left->resolve_common(mgr); - right->resolve_common(mgr); -} - -void ast_binop::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - - into.push_back(instruction_ptr(new instruction_pushglobal(op_action(op)))); - into.push_back(instruction_ptr(new instruction_mkapp())); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_app::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "APP:" << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck_common(mgr, env); - type_ptr rtype = right->typecheck_common(mgr, env); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); - mgr.unify(arrow, ltype); - return return_type; -} - -void ast_app::resolve(const type_mgr& mgr) const { - left->resolve_common(mgr); - right->resolve_common(mgr); -} - -void ast_app::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_case::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "CASE: " << std::endl; - for(auto& branch : branches) { - print_indent(indent + 1, to); - branch->pat->print(to); - to << std::endl; - branch->expr->print(indent + 2, to); - } -} - -type_ptr ast_case::typecheck(type_mgr& mgr, const type_env& env) const { - type_var* var; - type_ptr case_type = mgr.resolve(of->typecheck_common(mgr, env), var); - type_ptr branch_type = mgr.new_type(); - - for(auto& branch : branches) { - type_env new_env = env.scope(); - branch->pat->match(case_type, mgr, new_env); - type_ptr curr_branch_type = branch->expr->typecheck_common(mgr, new_env); - mgr.unify(branch_type, curr_branch_type); - } - - case_type = mgr.resolve(case_type, var); - if(!dynamic_cast(case_type.get())) { - throw type_error("attempting case analysis of non-data type"); - } - - return branch_type; -} - -void ast_case::resolve(const type_mgr& mgr) const { - of->resolve_common(mgr); - for(auto& branch : branches) { - branch->expr->resolve_common(mgr); - } -} - -void ast_case::compile(const env_ptr& env, std::vector& into) const { - type_data* type = dynamic_cast(of->node_type.get()); - - of->compile(env, into); - into.push_back(instruction_ptr(new instruction_eval())); - - instruction_jump* jump_instruction = new instruction_jump(); - into.push_back(instruction_ptr(jump_instruction)); - for(auto& branch : branches) { - std::vector branch_instructions; - pattern_var* vpat; - pattern_constr* cpat; - - if((vpat = dynamic_cast(branch->pat.get()))) { - branch->expr->compile(env_ptr(new env_offset(1, env)), branch_instructions); - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) != - jump_instruction->tag_mappings.end()) - break; - - jump_instruction->tag_mappings[constr_pair.second.tag] = - jump_instruction->branches.size(); - } - jump_instruction->branches.push_back(std::move(branch_instructions)); - } else if((cpat = dynamic_cast(branch->pat.get()))) { - env_ptr new_env = env; - for(auto it = cpat->params.rbegin(); it != cpat->params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - - branch_instructions.push_back(instruction_ptr(new instruction_split( - cpat->params.size()))); - branch->expr->compile(new_env, branch_instructions); - branch_instructions.push_back(instruction_ptr(new instruction_slide( - cpat->params.size()))); - - int new_tag = type->constructors[cpat->constr].tag; - if(jump_instruction->tag_mappings.find(new_tag) != - jump_instruction->tag_mappings.end()) - throw type_error("technically not a type error: duplicate pattern"); - - jump_instruction->tag_mappings[new_tag] = - jump_instruction->branches.size(); - jump_instruction->branches.push_back(std::move(branch_instructions)); - } - } - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) == - jump_instruction->tag_mappings.end()) - throw type_error("non-total pattern"); - } -} - -void pattern_var::print(std::ostream& to) const { - to << var; -} - -void pattern_var::match(type_ptr t, type_mgr& mgr, type_env& env) const { - env.bind(var, t); -} - -void pattern_constr::print(std::ostream& to) const { - to << constr; - for(auto& param : params) { - to << " " << param; - } -} - -void pattern_constr::match(type_ptr t, type_mgr& mgr, type_env& env) const { - type_ptr constructor_type = env.lookup(constr); - if(!constructor_type) { - throw type_error(std::string("pattern using unknown constructor ") + constr); - } - - for(int i = 0; i < params.size(); i++) { - type_arr* arr = dynamic_cast(constructor_type.get()); - if(!arr) throw type_error("too many parameters in constructor pattern"); - - env.bind(params[i], arr->left); - constructor_type = arr->right; - } - - mgr.unify(t, constructor_type); -} diff --git a/code/compiler/08/ast.hpp b/code/compiler/08/ast.hpp deleted file mode 100644 index c88fc99..0000000 --- a/code/compiler/08/ast.hpp +++ /dev/null @@ -1,141 +0,0 @@ -#pragma once -#include -#include -#include "type.hpp" -#include "type_env.hpp" -#include "binop.hpp" -#include "instruction.hpp" -#include "env.hpp" - -struct ast { - type_ptr node_type; - - virtual ~ast() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual type_ptr typecheck(type_mgr& mgr, const type_env& env) const = 0; - virtual void resolve(const type_mgr& mgr) const = 0; - virtual void compile(const env_ptr& env, - std::vector& into) const = 0; - - type_ptr typecheck_common(type_mgr& mgr, const type_env& env); - void resolve_common(const type_mgr& mgr); -}; - -using ast_ptr = std::unique_ptr; - -struct pattern { - virtual ~pattern() = default; - - virtual void print(std::ostream& to) const = 0; - virtual void match(type_ptr t, type_mgr& mgr, type_env& 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) - : value(v) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_lid : public ast { - std::string id; - - explicit ast_lid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_uid : public ast { - std::string id; - - explicit ast_uid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - 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) - : op(o), left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - 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) - : left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_case : public ast { - ast_ptr of; - std::vector branches; - - ast_case(ast_ptr o, std::vector b) - : of(std::move(o)), branches(std::move(b)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct pattern_var : public pattern { - std::string var; - - pattern_var(std::string v) - : var(std::move(v)) {} - - void print(std::ostream &to) const; - void match(type_ptr t, type_mgr& mgr, type_env& env) const; -}; - -struct pattern_constr : public pattern { - std::string constr; - std::vector params; - - pattern_constr(std::string c, std::vector p) - : constr(std::move(c)), params(std::move(p)) {} - - void print(std::ostream &to) const; - void match(type_ptr t, type_mgr&, type_env& env) const; -}; diff --git a/code/compiler/08/binop.cpp b/code/compiler/08/binop.cpp deleted file mode 100644 index 3a5f0ca..0000000 --- a/code/compiler/08/binop.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "binop.hpp" - -std::string op_name(binop op) { - switch(op) { - case PLUS: return "+"; - case MINUS: return "-"; - case TIMES: return "*"; - case DIVIDE: return "/"; - } - return "??"; -} - -std::string op_action(binop op) { - switch(op) { - case PLUS: return "plus"; - case MINUS: return "minus"; - case TIMES: return "times"; - case DIVIDE: return "divide"; - } - return "??"; -} diff --git a/code/compiler/08/binop.hpp b/code/compiler/08/binop.hpp deleted file mode 100644 index 8d07858..0000000 --- a/code/compiler/08/binop.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -std::string op_name(binop op); -std::string op_action(binop op); diff --git a/code/compiler/08/definition.cpp b/code/compiler/08/definition.cpp deleted file mode 100644 index fe116c8..0000000 --- a/code/compiler/08/definition.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "definition.hpp" -#include "error.hpp" -#include "ast.hpp" -#include "llvm_context.hpp" -#include -#include -#include - -void definition_defn::typecheck_first(type_mgr& mgr, type_env& env) { - return_type = mgr.new_type(); - type_ptr full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - full_type = type_ptr(new type_arr(param_type, full_type)); - param_types.push_back(param_type); - } - - env.bind(name, full_type); -} - -void definition_defn::typecheck_second(type_mgr& mgr, const type_env& env) const { - type_env new_env = env.scope(); - auto param_it = params.begin(); - auto type_it = param_types.rbegin(); - - while(param_it != params.end() && type_it != param_types.rend()) { - new_env.bind(*param_it, *type_it); - param_it++; - type_it++; - } - - type_ptr body_type = body->typecheck_common(mgr, new_env); - mgr.unify(return_type, body_type); -} - -void definition_defn::resolve(const type_mgr& mgr) { - type_var* var; - body->resolve_common(mgr); - - return_type = mgr.resolve(return_type, var); - if(var) throw type_error("ambiguously typed program"); - for(auto& param_type : param_types) { - param_type = mgr.resolve(param_type, var); - if(var) throw type_error("ambiguously typed program"); - } -} - -void definition_defn::compile() { - env_ptr new_env = env_ptr(new env_offset(0, nullptr)); - for(auto it = params.rbegin(); it != params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - body->compile(new_env, instructions); - instructions.push_back(instruction_ptr(new instruction_update(params.size()))); - instructions.push_back(instruction_ptr(new instruction_pop(params.size()))); -} -void definition_defn::gen_llvm_first(llvm_context& ctx) { - generated_function = ctx.create_custom_function(name, params.size()); -} - -void definition_defn::gen_llvm_second(llvm_context& ctx) { - ctx.builder.SetInsertPoint(&generated_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, generated_function); - } - ctx.builder.CreateRetVoid(); -} - -void definition_data::typecheck_first(type_mgr& mgr, type_env& env) { - type_data* this_type = new type_data(name); - type_ptr return_type = type_ptr(this_type); - int next_tag = 0; - - for(auto& constructor : constructors) { - constructor->tag = next_tag; - this_type->constructors[constructor->name] = { next_tag++ }; - - 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)); - full_type = type_ptr(new type_arr(type, full_type)); - } - - env.bind(constructor->name, full_type); - } -} - -void definition_data::typecheck_second(type_mgr& mgr, const type_env& env) const { - // Nothing -} - -void definition_data::resolve(const type_mgr& mgr) { - // Nothing -} - -void definition_data::compile() { - -} - -void definition_data::gen_llvm_first(llvm_context& ctx) { - for(auto& constructor : constructors) { - auto new_function = - ctx.create_custom_function(constructor->name, constructor->types.size()); - ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); - ctx.create_pack(new_function, - ctx.create_size(constructor->types.size()), - ctx.create_i8(constructor->tag) - ); - ctx.builder.CreateRetVoid(); - } -} - -void definition_data::gen_llvm_second(llvm_context& ctx) { - // Nothing -} diff --git a/code/compiler/08/definition.hpp b/code/compiler/08/definition.hpp deleted file mode 100644 index 6004d2f..0000000 --- a/code/compiler/08/definition.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once -#include -#include -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "type_env.hpp" - -struct ast; -using ast_ptr = std::unique_ptr; - -struct definition { - virtual ~definition() = default; - - virtual void typecheck_first(type_mgr& mgr, type_env& env) = 0; - virtual void typecheck_second(type_mgr& mgr, const type_env& env) const = 0; - virtual void resolve(const type_mgr& mgr) = 0; - virtual void compile() = 0; - virtual void gen_llvm_first(llvm_context& ctx) = 0; - virtual void gen_llvm_second(llvm_context& ctx) = 0; -}; - -using definition_ptr = std::unique_ptr; - -struct constructor { - std::string name; - std::vector types; - int8_t tag; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition_defn : public definition { - std::string name; - std::vector params; - ast_ptr body; - - type_ptr return_type; - std::vector param_types; - - std::vector instructions; - - llvm::Function* generated_function; - - definition_defn(std::string n, std::vector p, ast_ptr b) - : name(std::move(n)), params(std::move(p)), body(std::move(b)) { - - } - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr); - void compile(); - void gen_llvm_first(llvm_context& ctx); - void gen_llvm_second(llvm_context& ctx); -}; - -struct definition_data : public definition { - std::string name; - std::vector constructors; - - definition_data(std::string n, std::vector cs) - : name(std::move(n)), constructors(std::move(cs)) {} - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr); - void compile(); - void gen_llvm_first(llvm_context& ctx); - void gen_llvm_second(llvm_context& ctx); -}; diff --git a/code/compiler/08/env.cpp b/code/compiler/08/env.cpp deleted file mode 100644 index 818cf5d..0000000 --- a/code/compiler/08/env.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "env.hpp" - -int env_var::get_offset(const std::string& name) const { - if(name == this->name) return 0; - if(parent) return parent->get_offset(name) + 1; - throw 0; -} - -bool env_var::has_variable(const std::string& name) const { - if(name == this->name) return true; - if(parent) return parent->has_variable(name); - return false; -} - -int env_offset::get_offset(const std::string& name) const { - if(parent) return parent->get_offset(name) + offset; - throw 0; -} - -bool env_offset::has_variable(const std::string& name) const { - if(parent) return parent->has_variable(name); - return false; -} diff --git a/code/compiler/08/env.hpp b/code/compiler/08/env.hpp deleted file mode 100644 index a8fbbec..0000000 --- a/code/compiler/08/env.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include - -struct env { - virtual ~env() = default; - - virtual int get_offset(const std::string& name) const = 0; - virtual bool has_variable(const std::string& name) const = 0; -}; - -using env_ptr = std::shared_ptr; - -struct env_var : public env { - std::string name; - env_ptr parent; - - env_var(std::string& n, env_ptr p) - : name(std::move(n)), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; - -struct env_offset : public env { - int offset; - env_ptr parent; - - env_offset(int o, env_ptr p) - : offset(o), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; diff --git a/code/compiler/08/error.cpp b/code/compiler/08/error.cpp deleted file mode 100644 index f5125e3..0000000 --- a/code/compiler/08/error.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "error.hpp" - -const char* type_error::what() const noexcept { - return "an error occured while checking the types of the program"; -} diff --git a/code/compiler/08/error.hpp b/code/compiler/08/error.hpp deleted file mode 100644 index 5bfbc7e..0000000 --- a/code/compiler/08/error.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_error : std::exception { - std::string description; - - type_error(std::string d) - : description(std::move(d)) {} - - const char* what() const noexcept override; -}; - -struct unification_error : public type_error { - type_ptr left; - type_ptr right; - - unification_error(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)), - type_error("failed to unify types") {} -}; diff --git a/code/compiler/08/examples/bad1.txt b/code/compiler/08/examples/bad1.txt deleted file mode 100644 index 86d4bc4..0000000 --- a/code/compiler/08/examples/bad1.txt +++ /dev/null @@ -1,2 +0,0 @@ -data Bool = { True, False } -defn main = { 3 + True } diff --git a/code/compiler/08/examples/bad2.txt b/code/compiler/08/examples/bad2.txt deleted file mode 100644 index def8785..0000000 --- a/code/compiler/08/examples/bad2.txt +++ /dev/null @@ -1 +0,0 @@ -defn main = { 1 2 3 4 5 } diff --git a/code/compiler/08/examples/bad3.txt b/code/compiler/08/examples/bad3.txt deleted file mode 100644 index 6f82b3d..0000000 --- a/code/compiler/08/examples/bad3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } - -defn head l = { - case l of { - Nil -> { 0 } - Cons x y z -> { x } - } -} diff --git a/code/compiler/08/examples/runtime1.c b/code/compiler/08/examples/runtime1.c deleted file mode 100644 index 0157051..0000000 --- a/code/compiler/08/examples/runtime1.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "../runtime.h" - -void f_add(struct stack* s) { - struct node_num* left = (struct node_num*) eval(stack_peek(s, 0)); - struct node_num* right = (struct node_num*) eval(stack_peek(s, 1)); - stack_push(s, (struct node_base*) alloc_num(left->value + right->value)); -} - -void f_main(struct stack* s) { - // PushInt 320 - stack_push(s, (struct node_base*) alloc_num(320)); - - // PushInt 6 - stack_push(s, (struct node_base*) alloc_num(6)); - - // PushGlobal f_add (the function for +) - stack_push(s, (struct node_base*) alloc_global(f_add, 2)); - - struct node_base* left; - struct node_base* right; - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); -} diff --git a/code/compiler/08/examples/works1.txt b/code/compiler/08/examples/works1.txt deleted file mode 100644 index a2d647f..0000000 --- a/code/compiler/08/examples/works1.txt +++ /dev/null @@ -1,2 +0,0 @@ -defn main = { sum 320 6 } -defn sum x y = { x + y } diff --git a/code/compiler/08/examples/works2.txt b/code/compiler/08/examples/works2.txt deleted file mode 100644 index 8332fde..0000000 --- a/code/compiler/08/examples/works2.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn add x y = { x + y } -defn double x = { add x x } -defn main = { double 163 } diff --git a/code/compiler/08/examples/works3.txt b/code/compiler/08/examples/works3.txt deleted file mode 100644 index 13514dd..0000000 --- a/code/compiler/08/examples/works3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } -defn length l = { - case l of { - Nil -> { 0 } - Cons x xs -> { 1 + length xs } - } -} -defn main = { length (Cons 1 (Cons 2 (Cons 3 Nil))) } diff --git a/code/compiler/08/examples/works4.txt b/code/compiler/08/examples/works4.txt deleted file mode 100644 index 7674691..0000000 --- a/code/compiler/08/examples/works4.txt +++ /dev/null @@ -1,16 +0,0 @@ -data List = { Nil, Cons Int List } - -defn add x y = { x + y } -defn mul x y = { x * y } - -defn foldr f b l = { - case l of { - Nil -> { b } - Cons x xs -> { f x (foldr f b xs) } - } -} - -defn main = { - foldr add 0 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) + - foldr mul 1 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) -} diff --git a/code/compiler/08/examples/works5.txt b/code/compiler/08/examples/works5.txt deleted file mode 100644 index 3a8aff5..0000000 --- a/code/compiler/08/examples/works5.txt +++ /dev/null @@ -1,17 +0,0 @@ -data List = { Nil, Cons Int List } - -defn sumZip l m = { - case l of { - Nil -> { 0 } - Cons x xs -> { - case m of { - Nil -> { 0 } - Cons y ys -> { x + y + sumZip xs ys } - } - } - } -} - -defn ones = { Cons 1 ones } - -defn main = { sumZip ones (Cons 1 (Cons 2 (Cons 3 Nil))) } diff --git a/code/compiler/08/instruction.cpp b/code/compiler/08/instruction.cpp deleted file mode 100644 index 23f4258..0000000 --- a/code/compiler/08/instruction.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include "instruction.hpp" -#include "llvm_context.hpp" -#include -#include - -using namespace llvm; - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void instruction_pushint::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushInt(" << value << ")" << std::endl; -} - -void instruction_pushint::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_num(ctx.create_i32(value))); -} - -void instruction_pushglobal::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushGlobal(" << name << ")" << std::endl; -} - -void instruction_pushglobal::gen_llvm(llvm_context& ctx, Function* f) const { - auto& global_f = ctx.custom_functions.at("f_" + name); - auto arity = ctx.create_i32(global_f->arity); - ctx.create_push(f, ctx.create_global(global_f->function, arity)); -} - -void instruction_push::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Push(" << offset << ")" << std::endl; -} - -void instruction_push::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_peek(f, ctx.create_size(offset))); -} - -void instruction_pop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pop(" << count << ")" << std::endl; -} - -void instruction_pop::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_popn(f, ctx.create_size(count)); -} - -void instruction_mkapp::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "MkApp()" << std::endl; -} - -void instruction_mkapp::gen_llvm(llvm_context& ctx, Function* f) const { - auto left = ctx.create_pop(f); - auto right = ctx.create_pop(f); - ctx.create_push(f, ctx.create_app(left, right)); -} - -void instruction_update::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Update(" << offset << ")" << std::endl; -} - -void instruction_update::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_update(f, ctx.create_size(offset)); -} - -void instruction_pack::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pack(" << tag << ", " << size << ")" << std::endl; -} - -void instruction_pack::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_pack(f, ctx.create_size(size), ctx.create_i8(tag)); -} - -void instruction_split::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Split()" << std::endl; -} - -void instruction_split::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_split(f, ctx.create_size(size)); -} - -void instruction_jump::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Jump(" << std::endl; - for(auto& instruction_set : branches) { - for(auto& instruction : instruction_set) { - instruction->print(indent + 2, to); - } - to << std::endl; - } - print_indent(indent, to); - to << ")" << std::endl; -} - -void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const { - auto top_node = ctx.create_peek(f, ctx.create_size(0)); - auto tag = ctx.unwrap_data_tag(top_node); - auto safety_block = BasicBlock::Create(ctx.ctx, "safety", f); - auto switch_op = ctx.builder.CreateSwitch(tag, safety_block, tag_mappings.size()); - std::vector blocks; - - for(auto& branch : branches) { - auto branch_block = BasicBlock::Create(ctx.ctx, "branch", f); - ctx.builder.SetInsertPoint(branch_block); - for(auto& instruction : branch) { - instruction->gen_llvm(ctx, f); - } - ctx.builder.CreateBr(safety_block); - blocks.push_back(branch_block); - } - - for(auto& mapping : tag_mappings) { - switch_op->addCase(ctx.create_i8(mapping.first), blocks[mapping.second]); - } - - ctx.builder.SetInsertPoint(safety_block); -} - -void instruction_slide::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Slide(" << offset << ")" << std::endl; -} - -void instruction_slide::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_slide(f, ctx.create_size(offset)); -} - -void instruction_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BinOp(" << op_action(op) << ")" << std::endl; -} - -void instruction_binop::gen_llvm(llvm_context& ctx, Function* f) const { - auto left_int = ctx.unwrap_num(ctx.create_pop(f)); - auto right_int = ctx.unwrap_num(ctx.create_pop(f)); - llvm::Value* result; - switch(op) { - case PLUS: result = ctx.builder.CreateAdd(left_int, right_int); break; - case MINUS: result = ctx.builder.CreateSub(left_int, right_int); break; - case TIMES: result = ctx.builder.CreateMul(left_int, right_int); break; - case DIVIDE: result = ctx.builder.CreateSDiv(left_int, right_int); break; - } - ctx.create_push(f, ctx.create_num(result)); -} - -void instruction_eval::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Eval()" << std::endl; -} - -void instruction_eval::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_eval(ctx.create_pop(f))); -} - -void instruction_alloc::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Alloc(" << amount << ")" << std::endl; -} - -void instruction_alloc::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_alloc(f, ctx.create_size(amount)); -} - -void instruction_unwind::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Unwind()" << std::endl; -} - -void instruction_unwind::gen_llvm(llvm_context& ctx, Function* f) const { - // Nothing -} diff --git a/code/compiler/08/instruction.hpp b/code/compiler/08/instruction.hpp deleted file mode 100644 index abe2409..0000000 --- a/code/compiler/08/instruction.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include "binop.hpp" -#include "llvm_context.hpp" - -struct instruction { - virtual ~instruction() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual void gen_llvm(llvm_context& ctx, llvm::Function* f) const = 0; -}; - -using instruction_ptr = std::unique_ptr; - -struct instruction_pushint : public instruction { - int value; - - instruction_pushint(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pushglobal : public instruction { - std::string name; - - instruction_pushglobal(std::string n) - : name(std::move(n)) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_push : public instruction { - int offset; - - instruction_push(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pop : public instruction { - int count; - - instruction_pop(int c) - : count(c) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_mkapp : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_update : public instruction { - int offset; - - instruction_update(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pack : public instruction { - int tag; - int size; - - instruction_pack(int t, int s) - : tag(t), size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_split : public instruction { - int size; - - instruction_split(int s) - : size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_jump : public instruction { - std::vector> branches; - std::map tag_mappings; - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_slide : public instruction { - int offset; - - instruction_slide(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_binop : public instruction { - binop op; - - instruction_binop(binop o) - : op(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_eval : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_alloc : public instruction { - int amount; - - instruction_alloc(int a) - : amount(a) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_unwind : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; diff --git a/code/compiler/08/llvm_context.cpp b/code/compiler/08/llvm_context.cpp deleted file mode 100644 index b2982f9..0000000 --- a/code/compiler/08/llvm_context.cpp +++ /dev/null @@ -1,252 +0,0 @@ -#include "llvm_context.hpp" -#include - -using namespace llvm; - -void llvm_context::create_types() { - stack_type = StructType::create(ctx, "stack"); - stack_ptr_type = PointerType::getUnqual(stack_type); - tag_type = IntegerType::getInt8Ty(ctx); - struct_types["node_base"] = StructType::create(ctx, "node_base"); - struct_types["node_app"] = StructType::create(ctx, "node_app"); - struct_types["node_num"] = StructType::create(ctx, "node_num"); - struct_types["node_global"] = StructType::create(ctx, "node_global"); - struct_types["node_ind"] = StructType::create(ctx, "node_ind"); - struct_types["node_data"] = StructType::create(ctx, "node_data"); - node_ptr_type = PointerType::getUnqual(struct_types.at("node_base")); - function_type = FunctionType::get(Type::getVoidTy(ctx), { stack_ptr_type }, false); - - struct_types.at("node_base")->setBody( - IntegerType::getInt32Ty(ctx) - ); - struct_types.at("node_app")->setBody( - struct_types.at("node_base"), - node_ptr_type, - node_ptr_type - ); - struct_types.at("node_num")->setBody( - struct_types.at("node_base"), - IntegerType::getInt32Ty(ctx) - ); - struct_types.at("node_global")->setBody( - struct_types.at("node_base"), - FunctionType::get(Type::getVoidTy(ctx), { stack_ptr_type }, false) - ); - struct_types.at("node_ind")->setBody( - struct_types.at("node_base"), - node_ptr_type - ); - struct_types.at("node_data")->setBody( - struct_types.at("node_base"), - IntegerType::getInt8Ty(ctx), - PointerType::getUnqual(node_ptr_type) - ); -} - -void llvm_context::create_functions() { - auto void_type = Type::getVoidTy(ctx); - auto sizet_type = IntegerType::get(ctx, sizeof(size_t) * 8); - functions["stack_init"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_init", - &module - ); - functions["stack_free"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_free", - &module - ); - functions["stack_push"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_push", - &module - ); - functions["stack_pop"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_pop", - &module - ); - functions["stack_peek"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_peek", - &module - ); - functions["stack_popn"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_popn", - &module - ); - functions["stack_slide"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_slide", - &module - ); - functions["stack_update"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_update", - &module - ); - functions["stack_alloc"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_alloc", - &module - ); - functions["stack_pack"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, sizet_type, tag_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_pack", - &module - ); - functions["stack_split"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_split", - &module - ); - - auto int32_type = IntegerType::getInt32Ty(ctx); - functions["alloc_app"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_app", - &module - ); - functions["alloc_num"] = Function::Create( - FunctionType::get(node_ptr_type, { int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_num", - &module - ); - functions["alloc_global"] = Function::Create( - FunctionType::get(node_ptr_type, { function_type, int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_global", - &module - ); - functions["alloc_ind"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_ind", - &module - ); - - functions["eval"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "eval", - &module - ); -} - -ConstantInt* llvm_context::create_i8(int8_t i) { - return ConstantInt::get(ctx, APInt(8, i)); -} -ConstantInt* llvm_context::create_i32(int32_t i) { - return ConstantInt::get(ctx, APInt(32, i)); -} -ConstantInt* llvm_context::create_size(size_t i) { - return ConstantInt::get(ctx, APInt(sizeof(size_t) * 8, i)); -} - -Value* llvm_context::create_pop(Function* f) { - auto pop_f = functions.at("stack_pop"); - return builder.CreateCall(pop_f, { f->arg_begin() }); -} -Value* llvm_context::create_peek(Function* f, Value* off) { - auto peek_f = functions.at("stack_peek"); - return builder.CreateCall(peek_f, { f->arg_begin(), off }); -} -void llvm_context::create_push(Function* f, Value* v) { - auto push_f = functions.at("stack_push"); - builder.CreateCall(push_f, { f->arg_begin(), v }); -} -void llvm_context::create_popn(Function* f, Value* off) { - auto popn_f = functions.at("stack_popn"); - builder.CreateCall(popn_f, { f->arg_begin(), off }); -} -void llvm_context::create_update(Function* f, Value* off) { - auto update_f = functions.at("stack_update"); - builder.CreateCall(update_f, { f->arg_begin(), off }); -} -void llvm_context::create_pack(Function* f, Value* c, Value* t) { - auto pack_f = functions.at("stack_pack"); - builder.CreateCall(pack_f, { f->arg_begin(), c, t }); -} -void llvm_context::create_split(Function* f, Value* c) { - auto split_f = functions.at("stack_split"); - builder.CreateCall(split_f, { f->arg_begin(), c }); -} -void llvm_context::create_slide(Function* f, Value* off) { - auto slide_f = functions.at("stack_slide"); - builder.CreateCall(slide_f, { f->arg_begin(), off }); -} -void llvm_context::create_alloc(Function* f, Value* n) { - auto alloc_f = functions.at("stack_alloc"); - builder.CreateCall(alloc_f, { f->arg_begin(), n }); -} - -Value* llvm_context::create_eval(Value* e) { - auto eval_f = functions.at("eval"); - return builder.CreateCall(eval_f, { e }); -} - -Value* llvm_context::unwrap_num(Value* v) { - auto num_ptr_type = PointerType::getUnqual(struct_types.at("node_num")); - auto cast = builder.CreatePointerCast(v, num_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto int_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(int_ptr); -} -Value* llvm_context::create_num(Value* v) { - auto alloc_num_f = functions.at("alloc_num"); - return builder.CreateCall(alloc_num_f, { v }); -} - -Value* llvm_context::unwrap_data_tag(Value* v) { - auto data_ptr_type = PointerType::getUnqual(struct_types.at("node_data")); - auto cast = builder.CreatePointerCast(v, data_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto tag_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(tag_ptr); -} - -Value* llvm_context::create_global(Value* f, Value* a) { - auto alloc_global_f = functions.at("alloc_global"); - return builder.CreateCall(alloc_global_f, { f, a }); -} - -Value* llvm_context::create_app(Value* l, Value* r) { - auto alloc_app_f = functions.at("alloc_app"); - return builder.CreateCall(alloc_app_f, { l, r }); -} - -llvm::Function* llvm_context::create_custom_function(std::string name, int32_t arity) { - auto void_type = llvm::Type::getVoidTy(ctx); - auto function_type = - llvm::FunctionType::get(void_type, { stack_ptr_type }, false); - auto new_function = llvm::Function::Create( - function_type, - llvm::Function::LinkageTypes::ExternalLinkage, - "f_" + name, - &module - ); - auto start_block = llvm::BasicBlock::Create(ctx, "entry", new_function); - - auto new_custom_f = custom_function_ptr(new custom_function()); - new_custom_f->arity = arity; - new_custom_f->function = new_function; - custom_functions["f_" + name] = std::move(new_custom_f); - - return new_function; -} diff --git a/code/compiler/08/llvm_context.hpp b/code/compiler/08/llvm_context.hpp deleted file mode 100644 index ca75dca..0000000 --- a/code/compiler/08/llvm_context.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -struct llvm_context { - struct custom_function { - llvm::Function* function; - int32_t arity; - }; - - using custom_function_ptr = std::unique_ptr; - - llvm::LLVMContext ctx; - llvm::IRBuilder<> builder; - llvm::Module module; - - std::map custom_functions; - std::map functions; - std::map struct_types; - - llvm::StructType* stack_type; - llvm::PointerType* stack_ptr_type; - llvm::PointerType* node_ptr_type; - llvm::IntegerType* tag_type; - llvm::FunctionType* function_type; - - llvm_context() - : builder(ctx), module("bloglang", ctx) { - create_types(); - create_functions(); - } - - void create_types(); - void create_functions(); - - llvm::ConstantInt* create_i8(int8_t); - llvm::ConstantInt* create_i32(int32_t); - llvm::ConstantInt* create_size(size_t); - - llvm::Value* create_pop(llvm::Function*); - llvm::Value* create_peek(llvm::Function*, llvm::Value*); - void create_push(llvm::Function*, llvm::Value*); - void create_popn(llvm::Function*, llvm::Value*); - void create_update(llvm::Function*, llvm::Value*); - void create_pack(llvm::Function*, llvm::Value*, llvm::Value*); - void create_split(llvm::Function*, llvm::Value*); - void create_slide(llvm::Function*, llvm::Value*); - void create_alloc(llvm::Function*, llvm::Value*); - - llvm::Value* create_eval(llvm::Value*); - - llvm::Value* unwrap_num(llvm::Value*); - llvm::Value* create_num(llvm::Value*); - - llvm::Value* unwrap_data_tag(llvm::Value*); - - llvm::Value* create_global(llvm::Value*, llvm::Value*); - - llvm::Value* create_app(llvm::Value*, llvm::Value*); - - llvm::Function* create_custom_function(std::string name, int32_t arity); -}; diff --git a/code/compiler/08/main.cpp b/code/compiler/08/main.cpp deleted file mode 100644 index 3f50c32..0000000 --- a/code/compiler/08/main.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "ast.hpp" -#include -#include "binop.hpp" -#include "definition.hpp" -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "parser.hpp" -#include "error.hpp" -#include "type.hpp" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetMachine.h" - -void yy::parser::error(const std::string& msg) { - std::cout << "An error occured: " << msg << std::endl; -} - -extern std::vector program; - -void typecheck_program( - const std::vector& prog, - type_mgr& mgr, type_env& env) { - type_ptr int_type = type_ptr(new type_base("Int")); - 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); - env.bind("/", binop_type); - - for(auto& def : prog) { - def->typecheck_first(mgr, env); - } - - for(auto& def : prog) { - def->typecheck_second(mgr, env); - } - - for(auto& pair : env.names) { - std::cout << pair.first << ": "; - pair.second->print(mgr, std::cout); - std::cout << std::endl; - } - - for(auto& def : prog) { - def->resolve(mgr); - } -} - -void compile_program(const std::vector& prog) { - for(auto& def : prog) { - def->compile(); - - definition_defn* defn = dynamic_cast(def.get()); - if(!defn) continue; - for(auto& instruction : defn->instructions) { - instruction->print(0, std::cout); - } - std::cout << std::endl; - } -} - -void gen_llvm_internal_op(llvm_context& ctx, binop op) { - auto new_function = ctx.create_custom_function(op_action(op), 2); - std::vector instructions; - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_binop(op))); - ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.builder.CreateRetVoid(); -} - -void output_llvm(llvm_context& ctx, const std::string& filename) { - std::string targetTriple = llvm::sys::getDefaultTargetTriple(); - - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmParser(); - llvm::InitializeNativeTargetAsmPrinter(); - - std::string error; - const llvm::Target* target = - llvm::TargetRegistry::lookupTarget(targetTriple, error); - if (!target) { - std::cerr << error << std::endl; - } else { - std::string cpu = "generic"; - std::string features = ""; - llvm::TargetOptions options; - llvm::TargetMachine* targetMachine = - target->createTargetMachine(targetTriple, cpu, features, - options, llvm::Optional()); - - ctx.module.setDataLayout(targetMachine->createDataLayout()); - ctx.module.setTargetTriple(targetTriple); - - std::error_code ec; - llvm::raw_fd_ostream file(filename, ec, llvm::sys::fs::F_None); - if (ec) { - throw 0; - } else { - llvm::TargetMachine::CodeGenFileType type = llvm::TargetMachine::CGFT_ObjectFile; - llvm::legacy::PassManager pm; - if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) { - throw 0; - } else { - pm.run(ctx.module); - file.close(); - } - } - } -} - -void gen_llvm(const std::vector& prog) { - llvm_context ctx; - gen_llvm_internal_op(ctx, PLUS); - gen_llvm_internal_op(ctx, MINUS); - gen_llvm_internal_op(ctx, TIMES); - gen_llvm_internal_op(ctx, DIVIDE); - - for(auto& definition : prog) { - definition->gen_llvm_first(ctx); - } - - for(auto& definition : prog) { - definition->gen_llvm_second(ctx); - } - ctx.module.print(llvm::outs(), nullptr); - output_llvm(ctx, "program.o"); -} - -int main() { - yy::parser parser; - type_mgr mgr; - type_env env; - - parser.parse(); - for(auto& definition : program) { - definition_defn* def = dynamic_cast(definition.get()); - if(!def) continue; - - std::cout << def->name; - for(auto& param : def->params) std::cout << " " << param; - std::cout << ":" << std::endl; - - def->body->print(1, std::cout); - } - try { - typecheck_program(program, mgr, env); - compile_program(program); - gen_llvm(program); - } catch(unification_error& err) { - std::cout << "failed to unify types: " << std::endl; - std::cout << " (1) \033[34m"; - err.left->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - std::cout << " (2) \033[32m"; - err.right->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - } catch(type_error& err) { - std::cout << "failed to type check program: " << err.description << std::endl; - } -} diff --git a/code/compiler/08/parser.y b/code/compiler/08/parser.y deleted file mode 100644 index 088648d..0000000 --- a/code/compiler/08/parser.y +++ /dev/null @@ -1,141 +0,0 @@ -%{ -#include -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" - -std::vector program; -extern yy::parser::symbol_type yylex(); - -%} - -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%type > lowercaseParams uppercaseParams -%type > program definitions -%type > branches -%type > constructors -%type aAdd aMul case app appBase -%type definition defn data -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { program = std::move($1); } - ; - -definitions - : definitions definition { $$ = std::move($1); $$.push_back(std::move($2)); } - | definition { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -definition - : defn { $$ = std::move($1); } - | data { $$ = std::move($1); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6))); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -uppercaseParams - : %empty { $$ = std::vector(); } - | uppercaseParams UID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } - ; - -branches - : branches branch { $$ = std::move($1); $$.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } - ; - -data - : DATA UID EQUAL OCURLY constructors CCURLY - { $$ = definition_ptr(new definition_data(std::move($2), std::move($5))); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID uppercaseParams - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - diff --git a/code/compiler/08/runtime.c b/code/compiler/08/runtime.c deleted file mode 100644 index ebae7ae..0000000 --- a/code/compiler/08/runtime.c +++ /dev/null @@ -1,183 +0,0 @@ -#include -#include -#include -#include -#include "runtime.h" - -struct node_base* alloc_node() { - struct node_base* new_node = malloc(sizeof(struct node_app)); - assert(new_node != NULL); - return new_node; -} - -struct node_app* alloc_app(struct node_base* l, struct node_base* r) { - struct node_app* node = (struct node_app*) alloc_node(); - node->base.tag = NODE_APP; - node->left = l; - node->right = r; - return node; -} - -struct node_num* alloc_num(int32_t n) { - struct node_num* node = (struct node_num*) alloc_node(); - node->base.tag = NODE_NUM; - node->value = n; - return node; -} - -struct node_global* alloc_global(void (*f)(struct stack*), int32_t a) { - struct node_global* node = (struct node_global*) alloc_node(); - node->base.tag = NODE_GLOBAL; - node->arity = a; - node->function = f; - return node; -} - -struct node_ind* alloc_ind(struct node_base* n) { - struct node_ind* node = (struct node_ind*) alloc_node(); - node->base.tag = NODE_IND; - node->next = n; - return node; -} - -void stack_init(struct stack* s) { - s->size = 4; - s->count = 0; - s->data = malloc(sizeof(*s->data) * s->size); - assert(s->data != NULL); -} - -void stack_free(struct stack* s) { - free(s->data); -} - -void stack_push(struct stack* s, struct node_base* n) { - while(s->count >= s->size) { - s->data = realloc(s->data, sizeof(*s->data) * (s->size *= 2)); - assert(s->data != NULL); - } - s->data[s->count++] = n; -} - -struct node_base* stack_pop(struct stack* s) { - assert(s->count > 0); - return s->data[--s->count]; -} - -struct node_base* stack_peek(struct stack* s, size_t o) { - assert(s->count > o); - return s->data[s->count - o - 1]; -} - -void stack_popn(struct stack* s, size_t n) { - assert(s->count >= n); - s->count -= n; -} - -void stack_slide(struct stack* s, size_t n) { - assert(s->count > n); - s->data[s->count - n - 1] = s->data[s->count - 1]; - s->count -= n; -} - -void stack_update(struct stack* s, size_t o) { - assert(s->count > o + 1); - struct node_ind* ind = (struct node_ind*) s->data[s->count - o - 2]; - ind->base.tag = NODE_IND; - ind->next = s->data[s->count -= 1]; -} - -void stack_alloc(struct stack* s, size_t o) { - while(o--) { - stack_push(s, (struct node_base*) alloc_ind(NULL)); - } -} - -void stack_pack(struct stack* s, size_t n, int8_t t) { - assert(s->count >= n); - - struct node_base** data = malloc(sizeof(*data) * n); - assert(data != NULL); - memcpy(data, &s->data[s->count - n], n * sizeof(*data)); - - struct node_data* new_node = (struct node_data*) alloc_node(); - new_node->array = data; - new_node->base.tag = NODE_DATA; - new_node->tag = t; - - stack_popn(s, n); - stack_push(s, (struct node_base*) new_node); -} - -void stack_split(struct stack* s, size_t n) { - struct node_data* node = (struct node_data*) stack_pop(s); - for(size_t i = 0; i < n; i++) { - stack_push(s, node->array[i]); - } -} - -void unwind(struct stack* s) { - while(1) { - struct node_base* peek = stack_peek(s, 0); - if(peek->tag == NODE_APP) { - struct node_app* n = (struct node_app*) peek; - stack_push(s, n->left); - } else if(peek->tag == NODE_GLOBAL) { - struct node_global* n = (struct node_global*) peek; - assert(s->count > n->arity); - - for(size_t i = 1; i <= n->arity; i++) { - s->data[s->count - i] - = ((struct node_app*) s->data[s->count - i - 1])->right; - } - - n->function(s); - } else if(peek->tag == NODE_IND) { - struct node_ind* n = (struct node_ind*) peek; - stack_pop(s); - stack_push(s, n->next); - } else { - break; - } - } -} - -struct node_base* eval(struct node_base* n) { - struct stack program_stack; - stack_init(&program_stack); - stack_push(&program_stack, n); - unwind(&program_stack); - struct node_base* result = stack_pop(&program_stack); - stack_free(&program_stack); - return result; -} - -extern void f_main(struct stack* s); - -void print_node(struct node_base* n) { - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - print_node(app->left); - putchar(' '); - print_node(app->right); - } else if(n->tag == NODE_DATA) { - printf("(Packed)"); - } else if(n->tag == NODE_GLOBAL) { - struct node_global* global = (struct node_global*) n; - printf("(Global: %p)", global->function); - } else if(n->tag == NODE_IND) { - print_node(((struct node_ind*) n)->next); - } else if(n->tag == NODE_NUM) { - struct node_num* num = (struct node_num*) n; - printf("%d", num->value); - } -} - -int main(int argc, char** argv) { - struct node_global* first_node = alloc_global(f_main, 0); - struct node_base* result = eval((struct node_base*) first_node); - - printf("Result: "); - print_node(result); - putchar('\n'); -} diff --git a/code/compiler/08/runtime.h b/code/compiler/08/runtime.h deleted file mode 100644 index baaaaae..0000000 --- a/code/compiler/08/runtime.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once -#include - -struct stack; - -enum node_tag { - NODE_APP, - NODE_NUM, - NODE_GLOBAL, - NODE_IND, - NODE_DATA -}; - -struct node_base { - enum node_tag tag; -}; - -struct node_app { - struct node_base base; - struct node_base* left; - struct node_base* right; -}; - -struct node_num { - struct node_base base; - int32_t value; -}; - -struct node_global { - struct node_base base; - int32_t arity; - void (*function)(struct stack*); -}; - -struct node_ind { - struct node_base base; - struct node_base* next; -}; - -struct node_data { - struct node_base base; - int8_t tag; - struct node_base** array; -}; - -struct node_base* alloc_node(); -struct node_app* alloc_app(struct node_base* l, struct node_base* r); -struct node_num* alloc_num(int32_t n); -struct node_global* alloc_global(void (*f)(struct stack*), int32_t a); -struct node_ind* alloc_ind(struct node_base* n); - -struct stack { - size_t size; - size_t count; - struct node_base** data; -}; - -void stack_init(struct stack* s); -void stack_free(struct stack* s); -void stack_push(struct stack* s, struct node_base* n); -struct node_base* stack_pop(struct stack* s); -struct node_base* stack_peek(struct stack* s, size_t o); -void stack_popn(struct stack* s, size_t n); -void stack_slide(struct stack* s, size_t n); -void stack_update(struct stack* s, size_t o); -void stack_alloc(struct stack* s, size_t o); -void stack_pack(struct stack* s, size_t n, int8_t t); -void stack_split(struct stack* s, size_t n); - -struct node_base* eval(struct node_base* n); diff --git a/code/compiler/08/scanner.l b/code/compiler/08/scanner.l deleted file mode 100644 index c8a4429..0000000 --- a/code/compiler/08/scanner.l +++ /dev/null @@ -1,35 +0,0 @@ -%option noyywrap - -%{ -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" - -#define YY_DECL yy::parser::symbol_type yylex() - -%} - -%% - -[ \n]+ {} -\+ { return yy::parser::make_PLUS(); } -\* { return yy::parser::make_TIMES(); } -- { return yy::parser::make_MINUS(); } -\/ { return yy::parser::make_DIVIDE(); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } -defn { return yy::parser::make_DEFN(); } -data { return yy::parser::make_DATA(); } -case { return yy::parser::make_CASE(); } -of { return yy::parser::make_OF(); } -\{ { return yy::parser::make_OCURLY(); } -\} { return yy::parser::make_CCURLY(); } -\( { return yy::parser::make_OPAREN(); } -\) { return yy::parser::make_CPAREN(); } -, { return yy::parser::make_COMMA(); } --> { return yy::parser::make_ARROW(); } -= { return yy::parser::make_EQUAL(); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } - -%% diff --git a/code/compiler/08/type.cpp b/code/compiler/08/type.cpp deleted file mode 100644 index f5868d5..0000000 --- a/code/compiler/08/type.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "type.hpp" -#include -#include -#include "error.hpp" - -void type_var::print(const type_mgr& mgr, std::ostream& to) const { - auto it = mgr.types.find(name); - if(it != mgr.types.end()) { - it->second->print(mgr, to); - } else { - to << name; - } -} - -void type_base::print(const type_mgr& mgr, std::ostream& to) const { - to << name; -} - -void type_arr::print(const type_mgr& mgr, std::ostream& to) const { - left->print(mgr, to); - to << " -> ("; - right->print(mgr, to); - to << ")"; -} - -std::string type_mgr::new_type_name() { - int temp = last_id++; - std::string str = ""; - - while(temp != -1) { - str += (char) ('a' + (temp % 26)); - temp = temp / 26 - 1; - } - - std::reverse(str.begin(), str.end()); - return str; -} - -type_ptr type_mgr::new_type() { - return type_ptr(new type_var(new_type_name())); -} - -type_ptr type_mgr::new_arrow_type() { - return type_ptr(new type_arr(new_type(), new_type())); -} - -type_ptr type_mgr::resolve(type_ptr t, type_var*& var) const { - type_var* cast; - - var = nullptr; - while((cast = dynamic_cast(t.get()))) { - auto it = types.find(cast->name); - - if(it == types.end()) { - var = cast; - break; - } - t = it->second; - } - - return t; -} - -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; - - l = resolve(l, lvar); - r = resolve(r, rvar); - - if(lvar) { - bind(lvar->name, r); - return; - } else if(rvar) { - bind(rvar->name, l); - return; - } else if((larr = dynamic_cast(l.get())) && - (rarr = dynamic_cast(r.get()))) { - unify(larr->left, rarr->left); - unify(larr->right, rarr->right); - return; - } else if((lid = dynamic_cast(l.get())) && - (rid = dynamic_cast(r.get()))) { - if(lid->name == rid->name) return; - } - - throw unification_error(l, r); -} - -void type_mgr::bind(const std::string& s, type_ptr t) { - type_var* other = dynamic_cast(t.get()); - - if(other && other->name == s) return; - types[s] = t; -} diff --git a/code/compiler/08/type.hpp b/code/compiler/08/type.hpp deleted file mode 100644 index 09e525f..0000000 --- a/code/compiler/08/type.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once -#include -#include - -struct type_mgr; - -struct type { - virtual ~type() = default; - - virtual void print(const type_mgr& mgr, std::ostream& to) const = 0; -}; - -using type_ptr = std::shared_ptr; - -struct type_var : public type { - std::string name; - - type_var(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_base : public type { - std::string name; - - type_base(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_data : public type_base { - struct constructor { - int tag; - }; - - std::map constructors; - - type_data(std::string n) - : type_base(std::move(n)) {} -}; - -struct type_arr : public type { - type_ptr left; - type_ptr right; - - type_arr(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_mgr { - int last_id = 0; - std::map types; - - std::string new_type_name(); - type_ptr new_type(); - type_ptr new_arrow_type(); - - void unify(type_ptr l, type_ptr r); - type_ptr resolve(type_ptr t, type_var*& var) const; - void bind(const std::string& s, type_ptr t); -}; diff --git a/code/compiler/08/type_env.cpp b/code/compiler/08/type_env.cpp deleted file mode 100644 index c11a759..0000000 --- a/code/compiler/08/type_env.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "type_env.hpp" - -type_ptr type_env::lookup(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second; - if(parent) return parent->lookup(name); - return nullptr; -} - -void type_env::bind(const std::string& name, type_ptr t) { - names[name] = t; -} - -type_env type_env::scope() const { - return type_env(this); -} diff --git a/code/compiler/08/type_env.hpp b/code/compiler/08/type_env.hpp deleted file mode 100644 index 6470bdd..0000000 --- a/code/compiler/08/type_env.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_env { - std::map names; - type_env const* parent = nullptr; - - type_env(type_env const* p) - : parent(p) {} - type_env() : type_env(nullptr) {} - - type_ptr lookup(const std::string& name) const; - void bind(const std::string& name, type_ptr t); - type_env scope() const; -}; diff --git a/code/compiler/09/CMakeLists.txt b/code/compiler/09/CMakeLists.txt deleted file mode 100644 index 1347f11..0000000 --- a/code/compiler/09/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(compiler) - -# Find all the required packages -find_package(BISON) -find_package(FLEX) -find_package(LLVM REQUIRED CONFIG) - -# Set up the flex and bison targets -bison_target(parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser.y - ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp - COMPILE_FLAGS "-d") -flex_target(scanner - ${CMAKE_CURRENT_SOURCE_DIR}/scanner.l - ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp) -add_flex_bison_dependency(scanner parser) - -# Find all the relevant LLVM components -llvm_map_components_to_libnames(LLVM_LIBS core x86asmparser x86codegen) - -# Create compiler executable -add_executable(compiler - ast.cpp ast.hpp definition.cpp - llvm_context.cpp llvm_context.hpp - type_env.cpp type_env.hpp - env.cpp env.hpp - type.cpp type.hpp - error.cpp error.hpp - binop.cpp binop.hpp - instruction.cpp instruction.hpp - ${BISON_parser_OUTPUTS} - ${FLEX_scanner_OUTPUTS} - main.cpp -) - -# Configure compiler executable -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) -target_include_directories(compiler PUBLIC ${LLVM_INCLUDE_DIRS}) -target_compile_definitions(compiler PUBLIC ${LLVM_DEFINITIONS}) -target_link_libraries(compiler ${LLVM_LIBS}) diff --git a/code/compiler/09/ast.cpp b/code/compiler/09/ast.cpp deleted file mode 100644 index 453a12b..0000000 --- a/code/compiler/09/ast.cpp +++ /dev/null @@ -1,264 +0,0 @@ -#include "ast.hpp" -#include -#include "binop.hpp" -#include "error.hpp" - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -type_ptr ast::typecheck_common(type_mgr& mgr, const type_env& env) { - node_type = typecheck(mgr, env); - return node_type; -} - -void ast::resolve_common(const type_mgr& mgr) { - type_var* var; - type_ptr resolved_type = mgr.resolve(node_type, var); - if(var) throw type_error("ambiguously typed program"); - - resolve(mgr); - node_type = std::move(resolved_type); -} - -void ast_int::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "INT: " << value << std::endl; -} - -type_ptr ast_int::typecheck(type_mgr& mgr, const type_env& env) const { - return type_ptr(new type_base("Int")); -} - -void ast_int::resolve(const type_mgr& mgr) const { - -} - -void ast_int::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushint(value))); -} - -void ast_lid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LID: " << id << std::endl; -} - -type_ptr ast_lid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -void ast_lid::resolve(const type_mgr& mgr) const { - -} - -void ast_lid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr( - env->has_variable(id) ? - (instruction*) new instruction_push(env->get_offset(id)) : - (instruction*) new instruction_pushglobal(id))); -} - -void ast_uid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "UID: " << id << std::endl; -} - -type_ptr ast_uid::typecheck(type_mgr& mgr, const type_env& env) const { - return env.lookup(id); -} - -void ast_uid::resolve(const type_mgr& mgr) const { - -} - -void ast_uid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushglobal(id))); -} - -void ast_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BINOP: " << op_name(op) << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -type_ptr ast_binop::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck_common(mgr, env); - type_ptr rtype = right->typecheck_common(mgr, env); - type_ptr ftype = env.lookup(op_name(op)); - if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op)); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow_one = type_ptr(new type_arr(rtype, return_type)); - type_ptr arrow_two = type_ptr(new type_arr(ltype, arrow_one)); - - mgr.unify(arrow_two, ftype); - return return_type; -} - -void ast_binop::resolve(const type_mgr& mgr) const { - left->resolve_common(mgr); - right->resolve_common(mgr); -} - -void ast_binop::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - - into.push_back(instruction_ptr(new instruction_pushglobal(op_action(op)))); - into.push_back(instruction_ptr(new instruction_mkapp())); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_app::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "APP:" << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) const { - type_ptr ltype = left->typecheck_common(mgr, env); - type_ptr rtype = right->typecheck_common(mgr, env); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); - mgr.unify(arrow, ltype); - return return_type; -} - -void ast_app::resolve(const type_mgr& mgr) const { - left->resolve_common(mgr); - right->resolve_common(mgr); -} - -void ast_app::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_case::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "CASE: " << std::endl; - for(auto& branch : branches) { - print_indent(indent + 1, to); - branch->pat->print(to); - to << std::endl; - branch->expr->print(indent + 2, to); - } -} - -type_ptr ast_case::typecheck(type_mgr& mgr, const type_env& env) const { - type_var* var; - type_ptr case_type = mgr.resolve(of->typecheck_common(mgr, env), var); - type_ptr branch_type = mgr.new_type(); - - for(auto& branch : branches) { - type_env new_env = env.scope(); - branch->pat->match(case_type, mgr, new_env); - type_ptr curr_branch_type = branch->expr->typecheck_common(mgr, new_env); - mgr.unify(branch_type, curr_branch_type); - } - - case_type = mgr.resolve(case_type, var); - if(!dynamic_cast(case_type.get())) { - throw type_error("attempting case analysis of non-data type"); - } - - return branch_type; -} - -void ast_case::resolve(const type_mgr& mgr) const { - of->resolve_common(mgr); - for(auto& branch : branches) { - branch->expr->resolve_common(mgr); - } -} - -void ast_case::compile(const env_ptr& env, std::vector& into) const { - type_data* type = dynamic_cast(of->node_type.get()); - - of->compile(env, into); - into.push_back(instruction_ptr(new instruction_eval())); - - instruction_jump* jump_instruction = new instruction_jump(); - into.push_back(instruction_ptr(jump_instruction)); - for(auto& branch : branches) { - std::vector branch_instructions; - pattern_var* vpat; - pattern_constr* cpat; - - if((vpat = dynamic_cast(branch->pat.get()))) { - branch->expr->compile(env_ptr(new env_offset(1, env)), branch_instructions); - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) != - jump_instruction->tag_mappings.end()) - break; - - jump_instruction->tag_mappings[constr_pair.second.tag] = - jump_instruction->branches.size(); - } - jump_instruction->branches.push_back(std::move(branch_instructions)); - } else if((cpat = dynamic_cast(branch->pat.get()))) { - env_ptr new_env = env; - for(auto it = cpat->params.rbegin(); it != cpat->params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - - branch_instructions.push_back(instruction_ptr(new instruction_split( - cpat->params.size()))); - branch->expr->compile(new_env, branch_instructions); - branch_instructions.push_back(instruction_ptr(new instruction_slide( - cpat->params.size()))); - - int new_tag = type->constructors[cpat->constr].tag; - if(jump_instruction->tag_mappings.find(new_tag) != - jump_instruction->tag_mappings.end()) - throw type_error("technically not a type error: duplicate pattern"); - - jump_instruction->tag_mappings[new_tag] = - jump_instruction->branches.size(); - jump_instruction->branches.push_back(std::move(branch_instructions)); - } - } - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) == - jump_instruction->tag_mappings.end()) - throw type_error("non-total pattern"); - } -} - -void pattern_var::print(std::ostream& to) const { - to << var; -} - -void pattern_var::match(type_ptr t, type_mgr& mgr, type_env& env) const { - env.bind(var, t); -} - -void pattern_constr::print(std::ostream& to) const { - to << constr; - for(auto& param : params) { - to << " " << param; - } -} - -void pattern_constr::match(type_ptr t, type_mgr& mgr, type_env& env) const { - type_ptr constructor_type = env.lookup(constr); - if(!constructor_type) { - throw type_error(std::string("pattern using unknown constructor ") + constr); - } - - for(int i = 0; i < params.size(); i++) { - type_arr* arr = dynamic_cast(constructor_type.get()); - if(!arr) throw type_error("too many parameters in constructor pattern"); - - env.bind(params[i], arr->left); - constructor_type = arr->right; - } - - mgr.unify(t, constructor_type); -} diff --git a/code/compiler/09/ast.hpp b/code/compiler/09/ast.hpp deleted file mode 100644 index c88fc99..0000000 --- a/code/compiler/09/ast.hpp +++ /dev/null @@ -1,141 +0,0 @@ -#pragma once -#include -#include -#include "type.hpp" -#include "type_env.hpp" -#include "binop.hpp" -#include "instruction.hpp" -#include "env.hpp" - -struct ast { - type_ptr node_type; - - virtual ~ast() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual type_ptr typecheck(type_mgr& mgr, const type_env& env) const = 0; - virtual void resolve(const type_mgr& mgr) const = 0; - virtual void compile(const env_ptr& env, - std::vector& into) const = 0; - - type_ptr typecheck_common(type_mgr& mgr, const type_env& env); - void resolve_common(const type_mgr& mgr); -}; - -using ast_ptr = std::unique_ptr; - -struct pattern { - virtual ~pattern() = default; - - virtual void print(std::ostream& to) const = 0; - virtual void match(type_ptr t, type_mgr& mgr, type_env& 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) - : value(v) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_lid : public ast { - std::string id; - - explicit ast_lid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_uid : public ast { - std::string id; - - explicit ast_uid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - 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) - : op(o), left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - 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) - : left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_case : public ast { - ast_ptr of; - std::vector branches; - - ast_case(ast_ptr o, std::vector b) - : of(std::move(o)), branches(std::move(b)) {} - - void print(int indent, std::ostream& to) const; - type_ptr typecheck(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr) const; - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct pattern_var : public pattern { - std::string var; - - pattern_var(std::string v) - : var(std::move(v)) {} - - void print(std::ostream &to) const; - void match(type_ptr t, type_mgr& mgr, type_env& env) const; -}; - -struct pattern_constr : public pattern { - std::string constr; - std::vector params; - - pattern_constr(std::string c, std::vector p) - : constr(std::move(c)), params(std::move(p)) {} - - void print(std::ostream &to) const; - void match(type_ptr t, type_mgr&, type_env& env) const; -}; diff --git a/code/compiler/09/binop.cpp b/code/compiler/09/binop.cpp deleted file mode 100644 index 3a5f0ca..0000000 --- a/code/compiler/09/binop.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "binop.hpp" - -std::string op_name(binop op) { - switch(op) { - case PLUS: return "+"; - case MINUS: return "-"; - case TIMES: return "*"; - case DIVIDE: return "/"; - } - return "??"; -} - -std::string op_action(binop op) { - switch(op) { - case PLUS: return "plus"; - case MINUS: return "minus"; - case TIMES: return "times"; - case DIVIDE: return "divide"; - } - return "??"; -} diff --git a/code/compiler/09/binop.hpp b/code/compiler/09/binop.hpp deleted file mode 100644 index 8d07858..0000000 --- a/code/compiler/09/binop.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -std::string op_name(binop op); -std::string op_action(binop op); diff --git a/code/compiler/09/definition.cpp b/code/compiler/09/definition.cpp deleted file mode 100644 index 9c100b0..0000000 --- a/code/compiler/09/definition.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "definition.hpp" -#include "error.hpp" -#include "ast.hpp" -#include "instruction.hpp" -#include "llvm_context.hpp" -#include -#include -#include - -void definition_defn::typecheck_first(type_mgr& mgr, type_env& env) { - return_type = mgr.new_type(); - type_ptr full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - full_type = type_ptr(new type_arr(param_type, full_type)); - param_types.push_back(param_type); - } - - env.bind(name, full_type); -} - -void definition_defn::typecheck_second(type_mgr& mgr, const type_env& env) const { - type_env new_env = env.scope(); - auto param_it = params.begin(); - auto type_it = param_types.rbegin(); - - while(param_it != params.end() && type_it != param_types.rend()) { - new_env.bind(*param_it, *type_it); - param_it++; - type_it++; - } - - type_ptr body_type = body->typecheck_common(mgr, new_env); - mgr.unify(return_type, body_type); -} - -void definition_defn::resolve(const type_mgr& mgr) { - type_var* var; - body->resolve_common(mgr); - - return_type = mgr.resolve(return_type, var); - if(var) throw type_error("ambiguously typed program"); - for(auto& param_type : param_types) { - param_type = mgr.resolve(param_type, var); - if(var) throw type_error("ambiguously typed program"); - } -} - -void definition_defn::compile() { - env_ptr new_env = env_ptr(new env_offset(0, nullptr)); - for(auto it = params.rbegin(); it != params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - body->compile(new_env, instructions); - instructions.push_back(instruction_ptr(new instruction_update(params.size()))); - instructions.push_back(instruction_ptr(new instruction_pop(params.size()))); -} -void definition_defn::gen_llvm_first(llvm_context& ctx) { - generated_function = ctx.create_custom_function(name, params.size()); -} - -void definition_defn::gen_llvm_second(llvm_context& ctx) { - ctx.builder.SetInsertPoint(&generated_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, generated_function); - } - ctx.builder.CreateRetVoid(); -} - -void definition_data::typecheck_first(type_mgr& mgr, type_env& env) { - type_data* this_type = new type_data(name); - type_ptr return_type = type_ptr(this_type); - int next_tag = 0; - - for(auto& constructor : constructors) { - constructor->tag = next_tag; - this_type->constructors[constructor->name] = { next_tag++ }; - - 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)); - full_type = type_ptr(new type_arr(type, full_type)); - } - - env.bind(constructor->name, full_type); - } -} - -void definition_data::typecheck_second(type_mgr& mgr, const type_env& env) const { - // Nothing -} - -void definition_data::resolve(const type_mgr& mgr) { - // Nothing -} - -void definition_data::compile() { - -} - -void definition_data::gen_llvm_first(llvm_context& ctx) { - for(auto& constructor : constructors) { - auto new_function = - ctx.create_custom_function(constructor->name, constructor->types.size()); - std::vector instructions; - instructions.push_back(instruction_ptr( - new instruction_pack(constructor->tag, constructor->types.size()) - )); - instructions.push_back(instruction_ptr(new instruction_update(0))); - ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); - for (auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.builder.CreateRetVoid(); - } -} - -void definition_data::gen_llvm_second(llvm_context& ctx) { - // Nothing -} diff --git a/code/compiler/09/definition.hpp b/code/compiler/09/definition.hpp deleted file mode 100644 index 6004d2f..0000000 --- a/code/compiler/09/definition.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once -#include -#include -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "type_env.hpp" - -struct ast; -using ast_ptr = std::unique_ptr; - -struct definition { - virtual ~definition() = default; - - virtual void typecheck_first(type_mgr& mgr, type_env& env) = 0; - virtual void typecheck_second(type_mgr& mgr, const type_env& env) const = 0; - virtual void resolve(const type_mgr& mgr) = 0; - virtual void compile() = 0; - virtual void gen_llvm_first(llvm_context& ctx) = 0; - virtual void gen_llvm_second(llvm_context& ctx) = 0; -}; - -using definition_ptr = std::unique_ptr; - -struct constructor { - std::string name; - std::vector types; - int8_t tag; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition_defn : public definition { - std::string name; - std::vector params; - ast_ptr body; - - type_ptr return_type; - std::vector param_types; - - std::vector instructions; - - llvm::Function* generated_function; - - definition_defn(std::string n, std::vector p, ast_ptr b) - : name(std::move(n)), params(std::move(p)), body(std::move(b)) { - - } - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr); - void compile(); - void gen_llvm_first(llvm_context& ctx); - void gen_llvm_second(llvm_context& ctx); -}; - -struct definition_data : public definition { - std::string name; - std::vector constructors; - - definition_data(std::string n, std::vector cs) - : name(std::move(n)), constructors(std::move(cs)) {} - - void typecheck_first(type_mgr& mgr, type_env& env); - void typecheck_second(type_mgr& mgr, const type_env& env) const; - void resolve(const type_mgr& mgr); - void compile(); - void gen_llvm_first(llvm_context& ctx); - void gen_llvm_second(llvm_context& ctx); -}; diff --git a/code/compiler/09/env.cpp b/code/compiler/09/env.cpp deleted file mode 100644 index 818cf5d..0000000 --- a/code/compiler/09/env.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "env.hpp" - -int env_var::get_offset(const std::string& name) const { - if(name == this->name) return 0; - if(parent) return parent->get_offset(name) + 1; - throw 0; -} - -bool env_var::has_variable(const std::string& name) const { - if(name == this->name) return true; - if(parent) return parent->has_variable(name); - return false; -} - -int env_offset::get_offset(const std::string& name) const { - if(parent) return parent->get_offset(name) + offset; - throw 0; -} - -bool env_offset::has_variable(const std::string& name) const { - if(parent) return parent->has_variable(name); - return false; -} diff --git a/code/compiler/09/env.hpp b/code/compiler/09/env.hpp deleted file mode 100644 index a8fbbec..0000000 --- a/code/compiler/09/env.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include - -struct env { - virtual ~env() = default; - - virtual int get_offset(const std::string& name) const = 0; - virtual bool has_variable(const std::string& name) const = 0; -}; - -using env_ptr = std::shared_ptr; - -struct env_var : public env { - std::string name; - env_ptr parent; - - env_var(std::string& n, env_ptr p) - : name(std::move(n)), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; - -struct env_offset : public env { - int offset; - env_ptr parent; - - env_offset(int o, env_ptr p) - : offset(o), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; diff --git a/code/compiler/09/error.cpp b/code/compiler/09/error.cpp deleted file mode 100644 index f5125e3..0000000 --- a/code/compiler/09/error.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "error.hpp" - -const char* type_error::what() const noexcept { - return "an error occured while checking the types of the program"; -} diff --git a/code/compiler/09/error.hpp b/code/compiler/09/error.hpp deleted file mode 100644 index 5bfbc7e..0000000 --- a/code/compiler/09/error.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_error : std::exception { - std::string description; - - type_error(std::string d) - : description(std::move(d)) {} - - const char* what() const noexcept override; -}; - -struct unification_error : public type_error { - type_ptr left; - type_ptr right; - - unification_error(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)), - type_error("failed to unify types") {} -}; diff --git a/code/compiler/09/examples/bad1.txt b/code/compiler/09/examples/bad1.txt deleted file mode 100644 index 86d4bc4..0000000 --- a/code/compiler/09/examples/bad1.txt +++ /dev/null @@ -1,2 +0,0 @@ -data Bool = { True, False } -defn main = { 3 + True } diff --git a/code/compiler/09/examples/bad2.txt b/code/compiler/09/examples/bad2.txt deleted file mode 100644 index def8785..0000000 --- a/code/compiler/09/examples/bad2.txt +++ /dev/null @@ -1 +0,0 @@ -defn main = { 1 2 3 4 5 } diff --git a/code/compiler/09/examples/bad3.txt b/code/compiler/09/examples/bad3.txt deleted file mode 100644 index 6f82b3d..0000000 --- a/code/compiler/09/examples/bad3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } - -defn head l = { - case l of { - Nil -> { 0 } - Cons x y z -> { x } - } -} diff --git a/code/compiler/09/examples/primes.txt b/code/compiler/09/examples/primes.txt deleted file mode 100644 index 9394668..0000000 --- a/code/compiler/09/examples/primes.txt +++ /dev/null @@ -1,129 +0,0 @@ -data List = { Nil, Cons Nat List } -data Bool = { True, False } -data Nat = { O, S Nat } - -defn ifN c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn ifL c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn toInt n = { - case n of { - O -> { 0 } - S np -> { 1 + toInt np } - } -} - -defn lte n m = { - case m of { - O -> { - case n of { - O -> { True } - S np -> { False } - } - } - S mp -> { - case n of { - O -> { True } - S np -> { lte np mp } - } - } - } -} - -defn minus n m = { - case m of { - O -> { n } - S mp -> { - case n of { - O -> { O } - S np -> { - minus np mp - } - } - } - } -} - -defn mod n m = { - ifN (lte m n) (mod (minus n m) m) n -} - -defn notDivisibleBy n m = { - case (mod m n) of { - O -> { False } - S mp -> { True } - } -} - -defn filter f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { ifL (f x) (Cons x (filter f xs)) (filter f xs) } - } -} - -defn map f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { Cons (f x) (map f xs) } - } -} - -defn nats = { - Cons (S (S O)) (map S nats) -} - -defn primesRec l = { - case l of { - Nil -> { Nil } - Cons p xs -> { Cons p (primesRec (filter (notDivisibleBy p) xs)) } - } -} - -defn primes = { - primesRec nats -} - -defn take n l = { - case l of { - Nil -> { Nil } - Cons x xs -> { - case n of { - O -> { Nil } - S np -> { Cons x (take np xs) } - } - } - } -} - -defn head l = { - case l of { - Nil -> { O } - Cons x xs -> { x } - } -} - -defn reverseAcc a l = { - case l of { - Nil -> { a } - Cons x xs -> { reverseAcc (Cons x a) xs } - } -} - -defn reverse l = { - reverseAcc Nil l -} - -defn main = { - toInt (head (reverse (take ((S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) primes))) -} diff --git a/code/compiler/09/examples/runtime1.c b/code/compiler/09/examples/runtime1.c deleted file mode 100644 index 0157051..0000000 --- a/code/compiler/09/examples/runtime1.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "../runtime.h" - -void f_add(struct stack* s) { - struct node_num* left = (struct node_num*) eval(stack_peek(s, 0)); - struct node_num* right = (struct node_num*) eval(stack_peek(s, 1)); - stack_push(s, (struct node_base*) alloc_num(left->value + right->value)); -} - -void f_main(struct stack* s) { - // PushInt 320 - stack_push(s, (struct node_base*) alloc_num(320)); - - // PushInt 6 - stack_push(s, (struct node_base*) alloc_num(6)); - - // PushGlobal f_add (the function for +) - stack_push(s, (struct node_base*) alloc_global(f_add, 2)); - - struct node_base* left; - struct node_base* right; - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); -} diff --git a/code/compiler/09/examples/works1.txt b/code/compiler/09/examples/works1.txt deleted file mode 100644 index a2d647f..0000000 --- a/code/compiler/09/examples/works1.txt +++ /dev/null @@ -1,2 +0,0 @@ -defn main = { sum 320 6 } -defn sum x y = { x + y } diff --git a/code/compiler/09/examples/works2.txt b/code/compiler/09/examples/works2.txt deleted file mode 100644 index 8332fde..0000000 --- a/code/compiler/09/examples/works2.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn add x y = { x + y } -defn double x = { add x x } -defn main = { double 163 } diff --git a/code/compiler/09/examples/works3.txt b/code/compiler/09/examples/works3.txt deleted file mode 100644 index 13514dd..0000000 --- a/code/compiler/09/examples/works3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } -defn length l = { - case l of { - Nil -> { 0 } - Cons x xs -> { 1 + length xs } - } -} -defn main = { length (Cons 1 (Cons 2 (Cons 3 Nil))) } diff --git a/code/compiler/09/examples/works4.txt b/code/compiler/09/examples/works4.txt deleted file mode 100644 index 7674691..0000000 --- a/code/compiler/09/examples/works4.txt +++ /dev/null @@ -1,16 +0,0 @@ -data List = { Nil, Cons Int List } - -defn add x y = { x + y } -defn mul x y = { x * y } - -defn foldr f b l = { - case l of { - Nil -> { b } - Cons x xs -> { f x (foldr f b xs) } - } -} - -defn main = { - foldr add 0 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) + - foldr mul 1 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) -} diff --git a/code/compiler/09/examples/works5.txt b/code/compiler/09/examples/works5.txt deleted file mode 100644 index 3a8aff5..0000000 --- a/code/compiler/09/examples/works5.txt +++ /dev/null @@ -1,17 +0,0 @@ -data List = { Nil, Cons Int List } - -defn sumZip l m = { - case l of { - Nil -> { 0 } - Cons x xs -> { - case m of { - Nil -> { 0 } - Cons y ys -> { x + y + sumZip xs ys } - } - } - } -} - -defn ones = { Cons 1 ones } - -defn main = { sumZip ones (Cons 1 (Cons 2 (Cons 3 Nil))) } diff --git a/code/compiler/09/instruction.cpp b/code/compiler/09/instruction.cpp deleted file mode 100644 index c2b050a..0000000 --- a/code/compiler/09/instruction.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include "instruction.hpp" -#include "llvm_context.hpp" -#include -#include - -using namespace llvm; - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void instruction_pushint::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushInt(" << value << ")" << std::endl; -} - -void instruction_pushint::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_num(f, ctx.create_i32(value))); -} - -void instruction_pushglobal::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushGlobal(" << name << ")" << std::endl; -} - -void instruction_pushglobal::gen_llvm(llvm_context& ctx, Function* f) const { - auto& global_f = ctx.custom_functions.at("f_" + name); - auto arity = ctx.create_i32(global_f->arity); - ctx.create_push(f, ctx.create_global(f, global_f->function, arity)); -} - -void instruction_push::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Push(" << offset << ")" << std::endl; -} - -void instruction_push::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_peek(f, ctx.create_size(offset))); -} - -void instruction_pop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pop(" << count << ")" << std::endl; -} - -void instruction_pop::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_popn(f, ctx.create_size(count)); -} - -void instruction_mkapp::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "MkApp()" << std::endl; -} - -void instruction_mkapp::gen_llvm(llvm_context& ctx, Function* f) const { - auto left = ctx.create_pop(f); - auto right = ctx.create_pop(f); - ctx.create_push(f, ctx.create_app(f, left, right)); -} - -void instruction_update::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Update(" << offset << ")" << std::endl; -} - -void instruction_update::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_update(f, ctx.create_size(offset)); -} - -void instruction_pack::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pack(" << tag << ", " << size << ")" << std::endl; -} - -void instruction_pack::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_pack(f, ctx.create_size(size), ctx.create_i8(tag)); -} - -void instruction_split::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Split()" << std::endl; -} - -void instruction_split::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_split(f, ctx.create_size(size)); -} - -void instruction_jump::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Jump(" << std::endl; - for(auto& instruction_set : branches) { - for(auto& instruction : instruction_set) { - instruction->print(indent + 2, to); - } - to << std::endl; - } - print_indent(indent, to); - to << ")" << std::endl; -} - -void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const { - auto top_node = ctx.create_peek(f, ctx.create_size(0)); - auto tag = ctx.unwrap_data_tag(top_node); - auto safety_block = BasicBlock::Create(ctx.ctx, "safety", f); - auto switch_op = ctx.builder.CreateSwitch(tag, safety_block, tag_mappings.size()); - std::vector blocks; - - for(auto& branch : branches) { - auto branch_block = BasicBlock::Create(ctx.ctx, "branch", f); - ctx.builder.SetInsertPoint(branch_block); - for(auto& instruction : branch) { - instruction->gen_llvm(ctx, f); - } - ctx.builder.CreateBr(safety_block); - blocks.push_back(branch_block); - } - - for(auto& mapping : tag_mappings) { - switch_op->addCase(ctx.create_i8(mapping.first), blocks[mapping.second]); - } - - ctx.builder.SetInsertPoint(safety_block); -} - -void instruction_slide::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Slide(" << offset << ")" << std::endl; -} - -void instruction_slide::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_slide(f, ctx.create_size(offset)); -} - -void instruction_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BinOp(" << op_action(op) << ")" << std::endl; -} - -void instruction_binop::gen_llvm(llvm_context& ctx, Function* f) const { - auto left_int = ctx.unwrap_num(ctx.create_pop(f)); - auto right_int = ctx.unwrap_num(ctx.create_pop(f)); - llvm::Value* result; - switch(op) { - case PLUS: result = ctx.builder.CreateAdd(left_int, right_int); break; - case MINUS: result = ctx.builder.CreateSub(left_int, right_int); break; - case TIMES: result = ctx.builder.CreateMul(left_int, right_int); break; - case DIVIDE: result = ctx.builder.CreateSDiv(left_int, right_int); break; - } - ctx.create_push(f, ctx.create_num(f, result)); -} - -void instruction_eval::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Eval()" << std::endl; -} - -void instruction_eval::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_unwind(f); -} - -void instruction_alloc::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Alloc(" << amount << ")" << std::endl; -} - -void instruction_alloc::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_alloc(f, ctx.create_size(amount)); -} - -void instruction_unwind::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Unwind()" << std::endl; -} - -void instruction_unwind::gen_llvm(llvm_context& ctx, Function* f) const { - // Nothing -} diff --git a/code/compiler/09/instruction.hpp b/code/compiler/09/instruction.hpp deleted file mode 100644 index abe2409..0000000 --- a/code/compiler/09/instruction.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include "binop.hpp" -#include "llvm_context.hpp" - -struct instruction { - virtual ~instruction() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual void gen_llvm(llvm_context& ctx, llvm::Function* f) const = 0; -}; - -using instruction_ptr = std::unique_ptr; - -struct instruction_pushint : public instruction { - int value; - - instruction_pushint(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pushglobal : public instruction { - std::string name; - - instruction_pushglobal(std::string n) - : name(std::move(n)) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_push : public instruction { - int offset; - - instruction_push(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pop : public instruction { - int count; - - instruction_pop(int c) - : count(c) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_mkapp : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_update : public instruction { - int offset; - - instruction_update(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pack : public instruction { - int tag; - int size; - - instruction_pack(int t, int s) - : tag(t), size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_split : public instruction { - int size; - - instruction_split(int s) - : size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_jump : public instruction { - std::vector> branches; - std::map tag_mappings; - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_slide : public instruction { - int offset; - - instruction_slide(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_binop : public instruction { - binop op; - - instruction_binop(binop o) - : op(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_eval : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_alloc : public instruction { - int amount; - - instruction_alloc(int a) - : amount(a) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_unwind : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; diff --git a/code/compiler/09/llvm_context.cpp b/code/compiler/09/llvm_context.cpp deleted file mode 100644 index 45dcb50..0000000 --- a/code/compiler/09/llvm_context.cpp +++ /dev/null @@ -1,278 +0,0 @@ -#include "llvm_context.hpp" -#include - -using namespace llvm; - -void llvm_context::create_types() { - stack_type = StructType::create(ctx, "stack"); - gmachine_type = StructType::create(ctx, "gmachine"); - stack_ptr_type = PointerType::getUnqual(stack_type); - gmachine_ptr_type = PointerType::getUnqual(gmachine_type); - tag_type = IntegerType::getInt8Ty(ctx); - struct_types["node_base"] = StructType::create(ctx, "node_base"); - struct_types["node_app"] = StructType::create(ctx, "node_app"); - struct_types["node_num"] = StructType::create(ctx, "node_num"); - struct_types["node_global"] = StructType::create(ctx, "node_global"); - struct_types["node_ind"] = StructType::create(ctx, "node_ind"); - struct_types["node_data"] = StructType::create(ctx, "node_data"); - node_ptr_type = PointerType::getUnqual(struct_types.at("node_base")); - function_type = FunctionType::get(Type::getVoidTy(ctx), { gmachine_ptr_type }, false); - - gmachine_type->setBody( - stack_ptr_type, - node_ptr_type, - IntegerType::getInt64Ty(ctx), - IntegerType::getInt64Ty(ctx) - ); - struct_types.at("node_base")->setBody( - IntegerType::getInt32Ty(ctx), - IntegerType::getInt8Ty(ctx), - node_ptr_type - ); - struct_types.at("node_app")->setBody( - struct_types.at("node_base"), - node_ptr_type, - node_ptr_type - ); - struct_types.at("node_num")->setBody( - struct_types.at("node_base"), - IntegerType::getInt32Ty(ctx) - ); - struct_types.at("node_global")->setBody( - struct_types.at("node_base"), - FunctionType::get(Type::getVoidTy(ctx), { stack_ptr_type }, false) - ); - struct_types.at("node_ind")->setBody( - struct_types.at("node_base"), - node_ptr_type - ); - struct_types.at("node_data")->setBody( - struct_types.at("node_base"), - IntegerType::getInt8Ty(ctx), - PointerType::getUnqual(node_ptr_type) - ); -} - -void llvm_context::create_functions() { - auto void_type = Type::getVoidTy(ctx); - auto sizet_type = IntegerType::get(ctx, sizeof(size_t) * 8); - functions["stack_init"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_init", - &module - ); - functions["stack_free"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_free", - &module - ); - functions["stack_push"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_push", - &module - ); - functions["stack_pop"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_pop", - &module - ); - functions["stack_peek"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_peek", - &module - ); - functions["stack_popn"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_popn", - &module - ); - functions["gmachine_slide"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_slide", - &module - ); - functions["gmachine_update"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_update", - &module - ); - functions["gmachine_alloc"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_alloc", - &module - ); - functions["gmachine_pack"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type, tag_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_pack", - &module - ); - functions["gmachine_split"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_split", - &module - ); - functions["gmachine_track"] = Function::Create( - FunctionType::get(node_ptr_type, { gmachine_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_track", - &module - ); - - auto int32_type = IntegerType::getInt32Ty(ctx); - functions["alloc_app"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_app", - &module - ); - functions["alloc_num"] = Function::Create( - FunctionType::get(node_ptr_type, { int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_num", - &module - ); - functions["alloc_global"] = Function::Create( - FunctionType::get(node_ptr_type, { function_type, int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_global", - &module - ); - functions["alloc_ind"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_ind", - &module - ); - - functions["unwind"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "unwind", - &module - ); -} - -ConstantInt* llvm_context::create_i8(int8_t i) { - return ConstantInt::get(ctx, APInt(8, i)); -} -ConstantInt* llvm_context::create_i32(int32_t i) { - return ConstantInt::get(ctx, APInt(32, i)); -} -ConstantInt* llvm_context::create_size(size_t i) { - return ConstantInt::get(ctx, APInt(sizeof(size_t) * 8, i)); -} - -Value* llvm_context::create_pop(Function* f) { - auto pop_f = functions.at("stack_pop"); - return builder.CreateCall(pop_f, { unwrap_gmachine_stack_ptr(f->arg_begin()) }); -} -Value* llvm_context::create_peek(Function* f, Value* off) { - auto peek_f = functions.at("stack_peek"); - return builder.CreateCall(peek_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off }); -} -void llvm_context::create_push(Function* f, Value* v) { - auto push_f = functions.at("stack_push"); - builder.CreateCall(push_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), v }); -} -void llvm_context::create_popn(Function* f, Value* off) { - auto popn_f = functions.at("stack_popn"); - builder.CreateCall(popn_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off }); -} -void llvm_context::create_update(Function* f, Value* off) { - auto update_f = functions.at("gmachine_update"); - builder.CreateCall(update_f, { f->arg_begin(), off }); -} -void llvm_context::create_pack(Function* f, Value* c, Value* t) { - auto pack_f = functions.at("gmachine_pack"); - builder.CreateCall(pack_f, { f->arg_begin(), c, t }); -} -void llvm_context::create_split(Function* f, Value* c) { - auto split_f = functions.at("gmachine_split"); - builder.CreateCall(split_f, { f->arg_begin(), c }); -} -void llvm_context::create_slide(Function* f, Value* off) { - auto slide_f = functions.at("gmachine_slide"); - builder.CreateCall(slide_f, { f->arg_begin(), off }); -} -void llvm_context::create_alloc(Function* f, Value* n) { - auto alloc_f = functions.at("gmachine_alloc"); - builder.CreateCall(alloc_f, { f->arg_begin(), n }); -} -Value* llvm_context::create_track(Function* f, Value* v) { - auto track_f = functions.at("gmachine_track"); - return builder.CreateCall(track_f, { f->arg_begin(), v }); -} - -void llvm_context::create_unwind(Function* f) { - auto unwind_f = functions.at("unwind"); - builder.CreateCall(unwind_f, { f->args().begin() }); -} - -Value* llvm_context::unwrap_gmachine_stack_ptr(Value* g) { - auto offset_0 = create_i32(0); - return builder.CreateGEP(g, { offset_0, offset_0 }); -} - -Value* llvm_context::unwrap_num(Value* v) { - auto num_ptr_type = PointerType::getUnqual(struct_types.at("node_num")); - auto cast = builder.CreatePointerCast(v, num_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto int_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(int_ptr); -} -Value* llvm_context::create_num(Function* f, Value* v) { - auto alloc_num_f = functions.at("alloc_num"); - auto alloc_num_call = builder.CreateCall(alloc_num_f, { v }); - return create_track(f, alloc_num_call); -} - -Value* llvm_context::unwrap_data_tag(Value* v) { - auto data_ptr_type = PointerType::getUnqual(struct_types.at("node_data")); - auto cast = builder.CreatePointerCast(v, data_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto tag_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(tag_ptr); -} - -Value* llvm_context::create_global(Function* f, Value* gf, Value* a) { - auto alloc_global_f = functions.at("alloc_global"); - auto alloc_global_call = builder.CreateCall(alloc_global_f, { gf, a }); - return create_track(f, alloc_global_call); -} - -Value* llvm_context::create_app(Function* f, Value* l, Value* r) { - auto alloc_app_f = functions.at("alloc_app"); - auto alloc_app_call = builder.CreateCall(alloc_app_f, { l, r }); - return create_track(f, alloc_app_call); -} - -llvm::Function* llvm_context::create_custom_function(std::string name, int32_t arity) { - auto void_type = llvm::Type::getVoidTy(ctx); - auto new_function = llvm::Function::Create( - function_type, - llvm::Function::LinkageTypes::ExternalLinkage, - "f_" + name, - &module - ); - auto start_block = llvm::BasicBlock::Create(ctx, "entry", new_function); - - auto new_custom_f = custom_function_ptr(new custom_function()); - new_custom_f->arity = arity; - new_custom_f->function = new_function; - custom_functions["f_" + name] = std::move(new_custom_f); - - return new_function; -} diff --git a/code/compiler/09/llvm_context.hpp b/code/compiler/09/llvm_context.hpp deleted file mode 100644 index fbe4cc1..0000000 --- a/code/compiler/09/llvm_context.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -struct llvm_context { - struct custom_function { - llvm::Function* function; - int32_t arity; - }; - - using custom_function_ptr = std::unique_ptr; - - llvm::LLVMContext ctx; - llvm::IRBuilder<> builder; - llvm::Module module; - - std::map custom_functions; - std::map functions; - std::map struct_types; - - llvm::StructType* stack_type; - llvm::StructType* gmachine_type; - llvm::PointerType* stack_ptr_type; - llvm::PointerType* gmachine_ptr_type; - llvm::PointerType* node_ptr_type; - llvm::IntegerType* tag_type; - llvm::FunctionType* function_type; - - llvm_context() - : builder(ctx), module("bloglang", ctx) { - create_types(); - create_functions(); - } - - void create_types(); - void create_functions(); - - llvm::ConstantInt* create_i8(int8_t); - llvm::ConstantInt* create_i32(int32_t); - llvm::ConstantInt* create_size(size_t); - - llvm::Value* create_pop(llvm::Function*); - llvm::Value* create_peek(llvm::Function*, llvm::Value*); - void create_push(llvm::Function*, llvm::Value*); - void create_popn(llvm::Function*, llvm::Value*); - void create_update(llvm::Function*, llvm::Value*); - void create_pack(llvm::Function*, llvm::Value*, llvm::Value*); - void create_split(llvm::Function*, llvm::Value*); - void create_slide(llvm::Function*, llvm::Value*); - void create_alloc(llvm::Function*, llvm::Value*); - llvm::Value* create_track(llvm::Function*, llvm::Value*); - - void create_unwind(llvm::Function*); - - llvm::Value* unwrap_gmachine_stack_ptr(llvm::Value*); - - llvm::Value* unwrap_num(llvm::Value*); - llvm::Value* create_num(llvm::Function*, llvm::Value*); - - llvm::Value* unwrap_data_tag(llvm::Value*); - - llvm::Value* create_global(llvm::Function*, llvm::Value*, llvm::Value*); - - llvm::Value* create_app(llvm::Function*, llvm::Value*, llvm::Value*); - - llvm::Function* create_custom_function(std::string name, int32_t arity); -}; diff --git a/code/compiler/09/main.cpp b/code/compiler/09/main.cpp deleted file mode 100644 index 2b01f61..0000000 --- a/code/compiler/09/main.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "ast.hpp" -#include -#include "binop.hpp" -#include "definition.hpp" -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "parser.hpp" -#include "error.hpp" -#include "type.hpp" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetMachine.h" - -void yy::parser::error(const std::string& msg) { - std::cout << "An error occured: " << msg << std::endl; -} - -extern std::vector program; - -void typecheck_program( - const std::vector& prog, - type_mgr& mgr, type_env& env) { - type_ptr int_type = type_ptr(new type_base("Int")); - 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); - env.bind("/", binop_type); - - for(auto& def : prog) { - def->typecheck_first(mgr, env); - } - - for(auto& def : prog) { - def->typecheck_second(mgr, env); - } - - for(auto& pair : env.names) { - std::cout << pair.first << ": "; - pair.second->print(mgr, std::cout); - std::cout << std::endl; - } - - for(auto& def : prog) { - def->resolve(mgr); - } -} - -void compile_program(const std::vector& prog) { - for(auto& def : prog) { - def->compile(); - - definition_defn* defn = dynamic_cast(def.get()); - if(!defn) continue; - for(auto& instruction : defn->instructions) { - instruction->print(0, std::cout); - } - std::cout << std::endl; - } -} - -void gen_llvm_internal_op(llvm_context& ctx, binop op) { - auto new_function = ctx.create_custom_function(op_action(op), 2); - std::vector instructions; - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_binop(op))); - instructions.push_back(instruction_ptr(new instruction_update(2))); - instructions.push_back(instruction_ptr(new instruction_pop(2))); - ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.builder.CreateRetVoid(); -} - -void output_llvm(llvm_context& ctx, const std::string& filename) { - std::string targetTriple = llvm::sys::getDefaultTargetTriple(); - - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmParser(); - llvm::InitializeNativeTargetAsmPrinter(); - - std::string error; - const llvm::Target* target = - llvm::TargetRegistry::lookupTarget(targetTriple, error); - if (!target) { - std::cerr << error << std::endl; - } else { - std::string cpu = "generic"; - std::string features = ""; - llvm::TargetOptions options; - llvm::TargetMachine* targetMachine = - target->createTargetMachine(targetTriple, cpu, features, - options, llvm::Optional()); - - ctx.module.setDataLayout(targetMachine->createDataLayout()); - ctx.module.setTargetTriple(targetTriple); - - std::error_code ec; - llvm::raw_fd_ostream file(filename, ec, llvm::sys::fs::F_None); - if (ec) { - throw 0; - } else { - llvm::TargetMachine::CodeGenFileType type = llvm::TargetMachine::CGFT_ObjectFile; - llvm::legacy::PassManager pm; - if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) { - throw 0; - } else { - pm.run(ctx.module); - file.close(); - } - } - } -} - -void gen_llvm(const std::vector& prog) { - llvm_context ctx; - gen_llvm_internal_op(ctx, PLUS); - gen_llvm_internal_op(ctx, MINUS); - gen_llvm_internal_op(ctx, TIMES); - gen_llvm_internal_op(ctx, DIVIDE); - - for(auto& definition : prog) { - definition->gen_llvm_first(ctx); - } - - for(auto& definition : prog) { - definition->gen_llvm_second(ctx); - } - ctx.module.print(llvm::outs(), nullptr); - output_llvm(ctx, "program.o"); -} - -int main() { - yy::parser parser; - type_mgr mgr; - type_env env; - - parser.parse(); - for(auto& definition : program) { - definition_defn* def = dynamic_cast(definition.get()); - if(!def) continue; - - std::cout << def->name; - for(auto& param : def->params) std::cout << " " << param; - std::cout << ":" << std::endl; - - def->body->print(1, std::cout); - } - try { - typecheck_program(program, mgr, env); - compile_program(program); - gen_llvm(program); - } catch(unification_error& err) { - std::cout << "failed to unify types: " << std::endl; - std::cout << " (1) \033[34m"; - err.left->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - std::cout << " (2) \033[32m"; - err.right->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - } catch(type_error& err) { - std::cout << "failed to type check program: " << err.description << std::endl; - } -} diff --git a/code/compiler/09/parser.y b/code/compiler/09/parser.y deleted file mode 100644 index 088648d..0000000 --- a/code/compiler/09/parser.y +++ /dev/null @@ -1,141 +0,0 @@ -%{ -#include -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" - -std::vector program; -extern yy::parser::symbol_type yylex(); - -%} - -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%type > lowercaseParams uppercaseParams -%type > program definitions -%type > branches -%type > constructors -%type aAdd aMul case app appBase -%type definition defn data -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { program = std::move($1); } - ; - -definitions - : definitions definition { $$ = std::move($1); $$.push_back(std::move($2)); } - | definition { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -definition - : defn { $$ = std::move($1); } - | data { $$ = std::move($1); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6))); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -uppercaseParams - : %empty { $$ = std::vector(); } - | uppercaseParams UID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } - ; - -branches - : branches branch { $$ = std::move($1); $$.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } - ; - -data - : DATA UID EQUAL OCURLY constructors CCURLY - { $$ = definition_ptr(new definition_data(std::move($2), std::move($5))); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID uppercaseParams - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - diff --git a/code/compiler/09/runtime.c b/code/compiler/09/runtime.c deleted file mode 100644 index 7b8a7c3..0000000 --- a/code/compiler/09/runtime.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include -#include -#include -#include "runtime.h" - -struct node_base* alloc_node() { - struct node_base* new_node = malloc(sizeof(struct node_app)); - new_node->gc_next = NULL; - new_node->gc_reachable = 0; - assert(new_node != NULL); - return new_node; -} - -struct node_app* alloc_app(struct node_base* l, struct node_base* r) { - struct node_app* node = (struct node_app*) alloc_node(); - node->base.tag = NODE_APP; - node->left = l; - node->right = r; - return node; -} - -struct node_num* alloc_num(int32_t n) { - struct node_num* node = (struct node_num*) alloc_node(); - node->base.tag = NODE_NUM; - node->value = n; - return node; -} - -struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a) { - struct node_global* node = (struct node_global*) alloc_node(); - node->base.tag = NODE_GLOBAL; - node->arity = a; - node->function = f; - return node; -} - -struct node_ind* alloc_ind(struct node_base* n) { - struct node_ind* node = (struct node_ind*) alloc_node(); - node->base.tag = NODE_IND; - node->next = n; - return node; -} - -void free_node_direct(struct node_base* n) { - if(n->tag == NODE_DATA) { - free(((struct node_data*) n)->array); - } -} - -void gc_visit_node(struct node_base* n) { - if(n->gc_reachable) return; - n->gc_reachable = 1; - - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - gc_visit_node(app->left); - gc_visit_node(app->right); - } if(n->tag == NODE_IND) { - struct node_ind* ind = (struct node_ind*) n; - gc_visit_node(ind->next); - } if(n->tag == NODE_DATA) { - struct node_data* data = (struct node_data*) n; - struct node_base** to_visit = data->array; - while(*to_visit) { - gc_visit_node(*to_visit); - to_visit++; - } - } -} - -void stack_init(struct stack* s) { - s->size = 4; - s->count = 0; - s->data = malloc(sizeof(*s->data) * s->size); - assert(s->data != NULL); -} - -void stack_free(struct stack* s) { - free(s->data); -} - -void stack_push(struct stack* s, struct node_base* n) { - while(s->count >= s->size) { - s->data = realloc(s->data, sizeof(*s->data) * (s->size *= 2)); - assert(s->data != NULL); - } - s->data[s->count++] = n; -} - -struct node_base* stack_pop(struct stack* s) { - assert(s->count > 0); - return s->data[--s->count]; -} - -struct node_base* stack_peek(struct stack* s, size_t o) { - assert(s->count > o); - return s->data[s->count - o - 1]; -} - -void stack_popn(struct stack* s, size_t n) { - assert(s->count >= n); - s->count -= n; -} - -void gmachine_init(struct gmachine* g) { - stack_init(&g->stack); - g->gc_nodes = NULL; - g->gc_node_count = 0; - g->gc_node_threshold = 128; -} - -void gmachine_free(struct gmachine* g) { - stack_free(&g->stack); - struct node_base* to_free = g->gc_nodes; - struct node_base* next; - - while(to_free) { - next = to_free->gc_next; - free_node_direct(to_free); - free(to_free); - to_free = next; - } -} - -void gmachine_slide(struct gmachine* g, size_t n) { - assert(g->stack.count > n); - g->stack.data[g->stack.count - n - 1] = g->stack.data[g->stack.count - 1]; - g->stack.count -= n; -} - -void gmachine_update(struct gmachine* g, size_t o) { - assert(g->stack.count > o + 1); - struct node_ind* ind = - (struct node_ind*) g->stack.data[g->stack.count - o - 2]; - ind->base.tag = NODE_IND; - ind->next = g->stack.data[g->stack.count -= 1]; -} - -void gmachine_alloc(struct gmachine* g, size_t o) { - while(o--) { - stack_push(&g->stack, - gmachine_track(g, (struct node_base*) alloc_ind(NULL))); - } -} - -void gmachine_pack(struct gmachine* g, size_t n, int8_t t) { - assert(g->stack.count >= n); - - struct node_base** data = malloc(sizeof(*data) * (n + 1)); - assert(data != NULL); - memcpy(data, &g->stack.data[g->stack.count - n], n * sizeof(*data)); - data[n] = NULL; - - struct node_data* new_node = (struct node_data*) alloc_node(); - new_node->array = data; - new_node->base.tag = NODE_DATA; - new_node->tag = t; - - stack_popn(&g->stack, n); - stack_push(&g->stack, gmachine_track(g, (struct node_base*) new_node)); -} - -void gmachine_split(struct gmachine* g, size_t n) { - struct node_data* node = (struct node_data*) stack_pop(&g->stack); - for(size_t i = 0; i < n; i++) { - stack_push(&g->stack, node->array[i]); - } -} - -struct node_base* gmachine_track(struct gmachine* g, struct node_base* b) { - g->gc_node_count++; - b->gc_next = g->gc_nodes; - g->gc_nodes = b; - - if(g->gc_node_count >= g->gc_node_threshold) { - uint64_t nodes_before = g->gc_node_count; - gc_visit_node(b); - gmachine_gc(g); - g->gc_node_threshold = g->gc_node_count * 2; - } - - return b; -} - -void gmachine_gc(struct gmachine* g) { - for(size_t i = 0; i < g->stack.count; i++) { - gc_visit_node(g->stack.data[i]); - } - - struct node_base** head_ptr = &g->gc_nodes; - while(*head_ptr) { - if((*head_ptr)->gc_reachable) { - (*head_ptr)->gc_reachable = 0; - head_ptr = &(*head_ptr)->gc_next; - } else { - struct node_base* to_free = *head_ptr; - *head_ptr = to_free->gc_next; - free_node_direct(to_free); - free(to_free); - g->gc_node_count--; - } - } -} - -void unwind(struct gmachine* g) { - struct stack* s = &g->stack; - - while(1) { - struct node_base* peek = stack_peek(s, 0); - if(peek->tag == NODE_APP) { - struct node_app* n = (struct node_app*) peek; - stack_push(s, n->left); - } else if(peek->tag == NODE_GLOBAL) { - struct node_global* n = (struct node_global*) peek; - assert(s->count > n->arity); - - for(size_t i = 1; i <= n->arity; i++) { - s->data[s->count - i] - = ((struct node_app*) s->data[s->count - i - 1])->right; - } - - n->function(g); - } else if(peek->tag == NODE_IND) { - struct node_ind* n = (struct node_ind*) peek; - stack_pop(s); - stack_push(s, n->next); - } else { - break; - } - } -} - -extern void f_main(struct gmachine* s); - -void print_node(struct node_base* n) { - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - print_node(app->left); - putchar(' '); - print_node(app->right); - } else if(n->tag == NODE_DATA) { - printf("(Packed)"); - } else if(n->tag == NODE_GLOBAL) { - struct node_global* global = (struct node_global*) n; - printf("(Global: %p)", global->function); - } else if(n->tag == NODE_IND) { - print_node(((struct node_ind*) n)->next); - } else if(n->tag == NODE_NUM) { - struct node_num* num = (struct node_num*) n; - printf("%d", num->value); - } -} - -int main(int argc, char** argv) { - struct gmachine gmachine; - struct node_global* first_node = alloc_global(f_main, 0); - struct node_base* result; - - gmachine_init(&gmachine); - gmachine_track(&gmachine, (struct node_base*) first_node); - stack_push(&gmachine.stack, (struct node_base*) first_node); - unwind(&gmachine); - result = stack_pop(&gmachine.stack); - printf("Result: "); - print_node(result); - putchar('\n'); - gmachine_free(&gmachine); -} diff --git a/code/compiler/09/runtime.h b/code/compiler/09/runtime.h deleted file mode 100644 index 030a27c..0000000 --- a/code/compiler/09/runtime.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include - -struct gmachine; - -enum node_tag { - NODE_APP, - NODE_NUM, - NODE_GLOBAL, - NODE_IND, - NODE_DATA -}; - -struct node_base { - enum node_tag tag; - int8_t gc_reachable; - struct node_base* gc_next; -}; - -struct node_app { - struct node_base base; - struct node_base* left; - struct node_base* right; -}; - -struct node_num { - struct node_base base; - int32_t value; -}; - -struct node_global { - struct node_base base; - int32_t arity; - void (*function)(struct gmachine*); -}; - -struct node_ind { - struct node_base base; - struct node_base* next; -}; - -struct node_data { - struct node_base base; - int8_t tag; - struct node_base** array; -}; - -struct node_base* alloc_node(); -struct node_app* alloc_app(struct node_base* l, struct node_base* r); -struct node_num* alloc_num(int32_t n); -struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a); -struct node_ind* alloc_ind(struct node_base* n); -void free_node_direct(struct node_base*); -void gc_visit_node(struct node_base*); - -struct stack { - size_t size; - size_t count; - struct node_base** data; -}; - -void stack_init(struct stack* s); -void stack_free(struct stack* s); -void stack_push(struct stack* s, struct node_base* n); -struct node_base* stack_pop(struct stack* s); -struct node_base* stack_peek(struct stack* s, size_t o); -void stack_popn(struct stack* s, size_t n); - -struct gmachine { - struct stack stack; - struct node_base* gc_nodes; - int64_t gc_node_count; - int64_t gc_node_threshold; -}; - -void gmachine_init(struct gmachine* g); -void gmachine_free(struct gmachine* g); -void gmachine_slide(struct gmachine* g, size_t n); -void gmachine_update(struct gmachine* g, size_t o); -void gmachine_alloc(struct gmachine* g, size_t o); -void gmachine_pack(struct gmachine* g, size_t n, int8_t t); -void gmachine_split(struct gmachine* g, size_t n); -struct node_base* gmachine_track(struct gmachine* g, struct node_base* b); -void gmachine_gc(struct gmachine* g); diff --git a/code/compiler/09/scanner.l b/code/compiler/09/scanner.l deleted file mode 100644 index c8a4429..0000000 --- a/code/compiler/09/scanner.l +++ /dev/null @@ -1,35 +0,0 @@ -%option noyywrap - -%{ -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" - -#define YY_DECL yy::parser::symbol_type yylex() - -%} - -%% - -[ \n]+ {} -\+ { return yy::parser::make_PLUS(); } -\* { return yy::parser::make_TIMES(); } -- { return yy::parser::make_MINUS(); } -\/ { return yy::parser::make_DIVIDE(); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } -defn { return yy::parser::make_DEFN(); } -data { return yy::parser::make_DATA(); } -case { return yy::parser::make_CASE(); } -of { return yy::parser::make_OF(); } -\{ { return yy::parser::make_OCURLY(); } -\} { return yy::parser::make_CCURLY(); } -\( { return yy::parser::make_OPAREN(); } -\) { return yy::parser::make_CPAREN(); } -, { return yy::parser::make_COMMA(); } --> { return yy::parser::make_ARROW(); } -= { return yy::parser::make_EQUAL(); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } - -%% diff --git a/code/compiler/09/type.cpp b/code/compiler/09/type.cpp deleted file mode 100644 index f5868d5..0000000 --- a/code/compiler/09/type.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "type.hpp" -#include -#include -#include "error.hpp" - -void type_var::print(const type_mgr& mgr, std::ostream& to) const { - auto it = mgr.types.find(name); - if(it != mgr.types.end()) { - it->second->print(mgr, to); - } else { - to << name; - } -} - -void type_base::print(const type_mgr& mgr, std::ostream& to) const { - to << name; -} - -void type_arr::print(const type_mgr& mgr, std::ostream& to) const { - left->print(mgr, to); - to << " -> ("; - right->print(mgr, to); - to << ")"; -} - -std::string type_mgr::new_type_name() { - int temp = last_id++; - std::string str = ""; - - while(temp != -1) { - str += (char) ('a' + (temp % 26)); - temp = temp / 26 - 1; - } - - std::reverse(str.begin(), str.end()); - return str; -} - -type_ptr type_mgr::new_type() { - return type_ptr(new type_var(new_type_name())); -} - -type_ptr type_mgr::new_arrow_type() { - return type_ptr(new type_arr(new_type(), new_type())); -} - -type_ptr type_mgr::resolve(type_ptr t, type_var*& var) const { - type_var* cast; - - var = nullptr; - while((cast = dynamic_cast(t.get()))) { - auto it = types.find(cast->name); - - if(it == types.end()) { - var = cast; - break; - } - t = it->second; - } - - return t; -} - -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; - - l = resolve(l, lvar); - r = resolve(r, rvar); - - if(lvar) { - bind(lvar->name, r); - return; - } else if(rvar) { - bind(rvar->name, l); - return; - } else if((larr = dynamic_cast(l.get())) && - (rarr = dynamic_cast(r.get()))) { - unify(larr->left, rarr->left); - unify(larr->right, rarr->right); - return; - } else if((lid = dynamic_cast(l.get())) && - (rid = dynamic_cast(r.get()))) { - if(lid->name == rid->name) return; - } - - throw unification_error(l, r); -} - -void type_mgr::bind(const std::string& s, type_ptr t) { - type_var* other = dynamic_cast(t.get()); - - if(other && other->name == s) return; - types[s] = t; -} diff --git a/code/compiler/09/type.hpp b/code/compiler/09/type.hpp deleted file mode 100644 index 09e525f..0000000 --- a/code/compiler/09/type.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once -#include -#include - -struct type_mgr; - -struct type { - virtual ~type() = default; - - virtual void print(const type_mgr& mgr, std::ostream& to) const = 0; -}; - -using type_ptr = std::shared_ptr; - -struct type_var : public type { - std::string name; - - type_var(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_base : public type { - std::string name; - - type_base(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_data : public type_base { - struct constructor { - int tag; - }; - - std::map constructors; - - type_data(std::string n) - : type_base(std::move(n)) {} -}; - -struct type_arr : public type { - type_ptr left; - type_ptr right; - - type_arr(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_mgr { - int last_id = 0; - std::map types; - - std::string new_type_name(); - type_ptr new_type(); - type_ptr new_arrow_type(); - - void unify(type_ptr l, type_ptr r); - type_ptr resolve(type_ptr t, type_var*& var) const; - void bind(const std::string& s, type_ptr t); -}; diff --git a/code/compiler/09/type_env.cpp b/code/compiler/09/type_env.cpp deleted file mode 100644 index c11a759..0000000 --- a/code/compiler/09/type_env.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "type_env.hpp" - -type_ptr type_env::lookup(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second; - if(parent) return parent->lookup(name); - return nullptr; -} - -void type_env::bind(const std::string& name, type_ptr t) { - names[name] = t; -} - -type_env type_env::scope() const { - return type_env(this); -} diff --git a/code/compiler/09/type_env.hpp b/code/compiler/09/type_env.hpp deleted file mode 100644 index 6470bdd..0000000 --- a/code/compiler/09/type_env.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_env { - std::map names; - type_env const* parent = nullptr; - - type_env(type_env const* p) - : parent(p) {} - type_env() : type_env(nullptr) {} - - type_ptr lookup(const std::string& name) const; - void bind(const std::string& name, type_ptr t); - type_env scope() const; -}; diff --git a/code/compiler/10/CMakeLists.txt b/code/compiler/10/CMakeLists.txt deleted file mode 100644 index a16b8f9..0000000 --- a/code/compiler/10/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(compiler) - -# Find all the required packages -find_package(BISON) -find_package(FLEX) -find_package(LLVM REQUIRED CONFIG) - -# Set up the flex and bison targets -bison_target(parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser.y - ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp - COMPILE_FLAGS "-d") -flex_target(scanner - ${CMAKE_CURRENT_SOURCE_DIR}/scanner.l - ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp) -add_flex_bison_dependency(scanner parser) - -# Find all the relevant LLVM components -llvm_map_components_to_libnames(LLVM_LIBS core x86asmparser x86codegen) - -# Create compiler executable -add_executable(compiler - ast.cpp ast.hpp definition.cpp - llvm_context.cpp llvm_context.hpp - type_env.cpp type_env.hpp - env.cpp env.hpp - type.cpp type.hpp - error.cpp error.hpp - binop.cpp binop.hpp - instruction.cpp instruction.hpp - graph.cpp graph.hpp - ${BISON_parser_OUTPUTS} - ${FLEX_scanner_OUTPUTS} - main.cpp -) - -# Configure compiler executable -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) -target_include_directories(compiler PUBLIC ${LLVM_INCLUDE_DIRS}) -target_compile_definitions(compiler PUBLIC ${LLVM_DEFINITIONS}) -target_link_libraries(compiler ${LLVM_LIBS}) diff --git a/code/compiler/10/ast.cpp b/code/compiler/10/ast.cpp deleted file mode 100644 index b55c347..0000000 --- a/code/compiler/10/ast.cpp +++ /dev/null @@ -1,266 +0,0 @@ -#include "ast.hpp" -#include -#include "binop.hpp" -#include "error.hpp" -#include "type_env.hpp" - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void ast_int::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "INT: " << value << std::endl; -} - -void ast_int::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; -} - -type_ptr ast_int::typecheck(type_mgr& mgr) { - return type_ptr(new type_base("Int")); -} - -void ast_int::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushint(value))); -} - -void ast_lid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LID: " << id << std::endl; -} - -void ast_lid::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - if(env->lookup(id) == nullptr) into.insert(id); -} - -type_ptr ast_lid::typecheck(type_mgr& mgr) { - return env->lookup(id)->instantiate(mgr); -} - -void ast_lid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr( - env->has_variable(id) ? - (instruction*) new instruction_push(env->get_offset(id)) : - (instruction*) new instruction_pushglobal(id))); -} - -void ast_uid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "UID: " << id << std::endl; -} - -void ast_uid::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; -} - -type_ptr ast_uid::typecheck(type_mgr& mgr) { - return env->lookup(id)->instantiate(mgr); -} - -void ast_uid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushglobal(id))); -} - -void ast_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BINOP: " << op_name(op) << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -void ast_binop::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - left->find_free(mgr, env, into); - right->find_free(mgr, env, into); -} - -type_ptr ast_binop::typecheck(type_mgr& mgr) { - type_ptr ltype = left->typecheck(mgr); - type_ptr rtype = right->typecheck(mgr); - type_ptr ftype = env->lookup(op_name(op))->instantiate(mgr); - if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op)); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow_one = type_ptr(new type_arr(rtype, return_type)); - type_ptr arrow_two = type_ptr(new type_arr(ltype, arrow_one)); - - mgr.unify(arrow_two, ftype); - return return_type; -} - -void ast_binop::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - - into.push_back(instruction_ptr(new instruction_pushglobal(op_action(op)))); - into.push_back(instruction_ptr(new instruction_mkapp())); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_app::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "APP:" << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -void ast_app::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - left->find_free(mgr, env, into); - right->find_free(mgr, env, into); -} - -type_ptr ast_app::typecheck(type_mgr& mgr) { - type_ptr ltype = left->typecheck(mgr); - type_ptr rtype = right->typecheck(mgr); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); - mgr.unify(arrow, ltype); - return return_type; -} - -void ast_app::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_case::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "CASE: " << std::endl; - for(auto& branch : branches) { - print_indent(indent + 1, to); - branch->pat->print(to); - to << std::endl; - branch->expr->print(indent + 2, to); - } -} - -void ast_case::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - of->find_free(mgr, env, into); - for(auto& branch : branches) { - type_env_ptr new_env = type_scope(env); - branch->pat->insert_bindings(mgr, new_env); - branch->expr->find_free(mgr, new_env, into); - } -} - -type_ptr ast_case::typecheck(type_mgr& mgr) { - type_var* var; - type_ptr case_type = mgr.resolve(of->typecheck(mgr), var); - type_ptr branch_type = mgr.new_type(); - - for(auto& branch : branches) { - branch->pat->typecheck(case_type, mgr, branch->expr->env); - type_ptr curr_branch_type = branch->expr->typecheck(mgr); - mgr.unify(branch_type, curr_branch_type); - } - - input_type = mgr.resolve(case_type, var); - if(!dynamic_cast(input_type.get())) { - throw type_error("attempting case analysis of non-data type"); - } - - return branch_type; -} - -void ast_case::compile(const env_ptr& env, std::vector& into) const { - type_data* type = dynamic_cast(input_type.get()); - - of->compile(env, into); - into.push_back(instruction_ptr(new instruction_eval())); - - instruction_jump* jump_instruction = new instruction_jump(); - into.push_back(instruction_ptr(jump_instruction)); - for(auto& branch : branches) { - std::vector branch_instructions; - pattern_var* vpat; - pattern_constr* cpat; - - if((vpat = dynamic_cast(branch->pat.get()))) { - branch->expr->compile(env_ptr(new env_offset(1, env)), branch_instructions); - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) != - jump_instruction->tag_mappings.end()) - break; - - jump_instruction->tag_mappings[constr_pair.second.tag] = - jump_instruction->branches.size(); - } - jump_instruction->branches.push_back(std::move(branch_instructions)); - } else if((cpat = dynamic_cast(branch->pat.get()))) { - env_ptr new_env = env; - for(auto it = cpat->params.rbegin(); it != cpat->params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - - branch_instructions.push_back(instruction_ptr(new instruction_split( - cpat->params.size()))); - branch->expr->compile(new_env, branch_instructions); - branch_instructions.push_back(instruction_ptr(new instruction_slide( - cpat->params.size()))); - - int new_tag = type->constructors[cpat->constr].tag; - if(jump_instruction->tag_mappings.find(new_tag) != - jump_instruction->tag_mappings.end()) - throw type_error("technically not a type error: duplicate pattern"); - - jump_instruction->tag_mappings[new_tag] = - jump_instruction->branches.size(); - jump_instruction->branches.push_back(std::move(branch_instructions)); - } - } - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) == - jump_instruction->tag_mappings.end()) - throw type_error("non-total pattern"); - } -} - -void pattern_var::print(std::ostream& to) const { - to << var; -} - -void pattern_var::insert_bindings(type_mgr& mgr, type_env_ptr& env) const { - env->bind(var, mgr.new_type()); -} - -void pattern_var::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { - mgr.unify(env->lookup(var)->instantiate(mgr), t); -} - -void pattern_constr::print(std::ostream& to) const { - to << constr; - for(auto& param : params) { - to << " " << param; - } -} - -void pattern_constr::insert_bindings(type_mgr& mgr, type_env_ptr& env) const { - for(auto& param : params) { - env->bind(param, mgr.new_type()); - } -} - -void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { - type_ptr constructor_type = env->lookup(constr)->instantiate(mgr); - if(!constructor_type) { - throw type_error(std::string("pattern using unknown constructor ") + constr); - } - - for(auto& param : params) { - type_arr* arr = dynamic_cast(constructor_type.get()); - if(!arr) throw type_error("too many parameters in constructor pattern"); - - mgr.unify(env->lookup(param)->instantiate(mgr), arr->left); - constructor_type = arr->right; - } - - mgr.unify(t, constructor_type); -} diff --git a/code/compiler/10/ast.hpp b/code/compiler/10/ast.hpp deleted file mode 100644 index 6c66636..0000000 --- a/code/compiler/10/ast.hpp +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once -#include -#include -#include -#include "type.hpp" -#include "type_env.hpp" -#include "binop.hpp" -#include "instruction.hpp" -#include "env.hpp" - -struct ast { - type_env_ptr env; - - virtual ~ast() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual void find_free(type_mgr& mgr, - type_env_ptr& env, std::set& into) = 0; - virtual type_ptr typecheck(type_mgr& mgr) = 0; - virtual void compile(const env_ptr& env, - std::vector& into) const = 0; -}; - -using ast_ptr = std::unique_ptr; - -struct pattern { - virtual ~pattern() = default; - - virtual void print(std::ostream& to) const = 0; - virtual void insert_bindings(type_mgr& mgr, type_env_ptr& env) 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) - : value(v) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_lid : public ast { - std::string id; - - explicit ast_lid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_uid : public ast { - std::string id; - - explicit ast_uid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - 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) - : op(o), left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - 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) - : left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - 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) - : of(std::move(o)), branches(std::move(b)) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct pattern_var : public pattern { - std::string var; - - pattern_var(std::string v) - : var(std::move(v)) {} - - void print(std::ostream &to) const; - void insert_bindings(type_mgr& mgr, type_env_ptr& env) 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) - : constr(std::move(c)), params(std::move(p)) {} - - void print(std::ostream &to) const; - virtual void insert_bindings(type_mgr& mgr, type_env_ptr& env) const; - virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const; -}; diff --git a/code/compiler/10/binop.cpp b/code/compiler/10/binop.cpp deleted file mode 100644 index 3a5f0ca..0000000 --- a/code/compiler/10/binop.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "binop.hpp" - -std::string op_name(binop op) { - switch(op) { - case PLUS: return "+"; - case MINUS: return "-"; - case TIMES: return "*"; - case DIVIDE: return "/"; - } - return "??"; -} - -std::string op_action(binop op) { - switch(op) { - case PLUS: return "plus"; - case MINUS: return "minus"; - case TIMES: return "times"; - case DIVIDE: return "divide"; - } - return "??"; -} diff --git a/code/compiler/10/binop.hpp b/code/compiler/10/binop.hpp deleted file mode 100644 index 8d07858..0000000 --- a/code/compiler/10/binop.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -std::string op_name(binop op); -std::string op_action(binop op); diff --git a/code/compiler/10/definition.cpp b/code/compiler/10/definition.cpp deleted file mode 100644 index 91b0178..0000000 --- a/code/compiler/10/definition.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "definition.hpp" -#include "error.hpp" -#include "ast.hpp" -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "type.hpp" -#include "type_env.hpp" -#include -#include -#include - -void definition_defn::find_free(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - - var_env = type_scope(env); - return_type = mgr.new_type(); - full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - full_type = type_ptr(new type_arr(param_type, full_type)); - var_env->bind(*it, param_type); - } - - body->find_free(mgr, var_env, free_variables); -} - -void definition_defn::insert_types(type_mgr& mgr) { - env->bind(name, full_type); -} - -void definition_defn::typecheck(type_mgr& mgr) { - type_ptr body_type = body->typecheck(mgr); - mgr.unify(return_type, body_type); -} - -void definition_defn::compile() { - env_ptr new_env = env_ptr(new env_offset(0, nullptr)); - for(auto it = params.rbegin(); it != params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - body->compile(new_env, instructions); - instructions.push_back(instruction_ptr(new instruction_update(params.size()))); - instructions.push_back(instruction_ptr(new instruction_pop(params.size()))); -} - -void definition_defn::declare_llvm(llvm_context& ctx) { - generated_function = ctx.create_custom_function(name, params.size()); -} - -void definition_defn::generate_llvm(llvm_context& ctx) { - ctx.builder.SetInsertPoint(&generated_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, generated_function); - } - ctx.builder.CreateRetVoid(); -} - -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_ptr return_type = env->lookup_type(name); - type_data* this_type = static_cast(return_type.get()); - int next_tag = 0; - - for(auto& constructor : constructors) { - constructor->tag = next_tag; - this_type->constructors[constructor->name] = { next_tag++ }; - - type_ptr full_type = return_type; - for(auto it = constructor->types.rbegin(); it != constructor->types.rend(); it++) { - type_ptr type = env->lookup_type(*it); - if(!type) throw 0; - full_type = type_ptr(new type_arr(type, full_type)); - } - - env->bind(constructor->name, full_type); - } -} - -void definition_data::generate_llvm(llvm_context& ctx) { - for(auto& constructor : constructors) { - auto new_function = - ctx.create_custom_function(constructor->name, constructor->types.size()); - std::vector instructions; - instructions.push_back(instruction_ptr( - new instruction_pack(constructor->tag, constructor->types.size()) - )); - instructions.push_back(instruction_ptr(new instruction_update(0))); - ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); - for (auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.builder.CreateRetVoid(); - } -} diff --git a/code/compiler/10/definition.hpp b/code/compiler/10/definition.hpp deleted file mode 100644 index b72bed6..0000000 --- a/code/compiler/10/definition.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -#include -#include -#include -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "type_env.hpp" - -struct ast; -using ast_ptr = std::unique_ptr; - -struct constructor { - std::string name; - std::vector types; - int8_t tag; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition_defn { - std::string name; - std::vector params; - ast_ptr body; - - type_env_ptr env; - type_env_ptr var_env; - std::set free_variables; - type_ptr full_type; - type_ptr return_type; - - std::vector instructions; - - llvm::Function* generated_function; - - definition_defn(std::string n, std::vector p, ast_ptr b) - : name(std::move(n)), params(std::move(p)), body(std::move(b)) { - - } - - void find_free(type_mgr& mgr, type_env_ptr& env); - void insert_types(type_mgr& mgr); - void typecheck(type_mgr& mgr); - void compile(); - void declare_llvm(llvm_context& ctx); - void generate_llvm(llvm_context& ctx); -}; - -using definition_defn_ptr = std::unique_ptr; - -struct definition_data { - std::string name; - std::vector constructors; - - type_env_ptr env; - - definition_data(std::string n, std::vector cs) - : name(std::move(n)), constructors(std::move(cs)) {} - - void insert_types(type_mgr& mgr, type_env_ptr& env); - void insert_constructors() const; - void generate_llvm(llvm_context& ctx); -}; - -using definition_data_ptr = std::unique_ptr; diff --git a/code/compiler/10/env.cpp b/code/compiler/10/env.cpp deleted file mode 100644 index 818cf5d..0000000 --- a/code/compiler/10/env.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "env.hpp" - -int env_var::get_offset(const std::string& name) const { - if(name == this->name) return 0; - if(parent) return parent->get_offset(name) + 1; - throw 0; -} - -bool env_var::has_variable(const std::string& name) const { - if(name == this->name) return true; - if(parent) return parent->has_variable(name); - return false; -} - -int env_offset::get_offset(const std::string& name) const { - if(parent) return parent->get_offset(name) + offset; - throw 0; -} - -bool env_offset::has_variable(const std::string& name) const { - if(parent) return parent->has_variable(name); - return false; -} diff --git a/code/compiler/10/env.hpp b/code/compiler/10/env.hpp deleted file mode 100644 index a8fbbec..0000000 --- a/code/compiler/10/env.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include - -struct env { - virtual ~env() = default; - - virtual int get_offset(const std::string& name) const = 0; - virtual bool has_variable(const std::string& name) const = 0; -}; - -using env_ptr = std::shared_ptr; - -struct env_var : public env { - std::string name; - env_ptr parent; - - env_var(std::string& n, env_ptr p) - : name(std::move(n)), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; - -struct env_offset : public env { - int offset; - env_ptr parent; - - env_offset(int o, env_ptr p) - : offset(o), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; diff --git a/code/compiler/10/error.cpp b/code/compiler/10/error.cpp deleted file mode 100644 index f5125e3..0000000 --- a/code/compiler/10/error.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "error.hpp" - -const char* type_error::what() const noexcept { - return "an error occured while checking the types of the program"; -} diff --git a/code/compiler/10/error.hpp b/code/compiler/10/error.hpp deleted file mode 100644 index 5bfbc7e..0000000 --- a/code/compiler/10/error.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_error : std::exception { - std::string description; - - type_error(std::string d) - : description(std::move(d)) {} - - const char* what() const noexcept override; -}; - -struct unification_error : public type_error { - type_ptr left; - type_ptr right; - - unification_error(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)), - type_error("failed to unify types") {} -}; diff --git a/code/compiler/10/examples/bad1.txt b/code/compiler/10/examples/bad1.txt deleted file mode 100644 index 86d4bc4..0000000 --- a/code/compiler/10/examples/bad1.txt +++ /dev/null @@ -1,2 +0,0 @@ -data Bool = { True, False } -defn main = { 3 + True } diff --git a/code/compiler/10/examples/bad2.txt b/code/compiler/10/examples/bad2.txt deleted file mode 100644 index def8785..0000000 --- a/code/compiler/10/examples/bad2.txt +++ /dev/null @@ -1 +0,0 @@ -defn main = { 1 2 3 4 5 } diff --git a/code/compiler/10/examples/bad3.txt b/code/compiler/10/examples/bad3.txt deleted file mode 100644 index 6f82b3d..0000000 --- a/code/compiler/10/examples/bad3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } - -defn head l = { - case l of { - Nil -> { 0 } - Cons x y z -> { x } - } -} diff --git a/code/compiler/10/examples/if.txt b/code/compiler/10/examples/if.txt deleted file mode 100644 index c00df35..0000000 --- a/code/compiler/10/examples/if.txt +++ /dev/null @@ -1,8 +0,0 @@ -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/code/compiler/10/examples/primes.txt b/code/compiler/10/examples/primes.txt deleted file mode 100644 index 9394668..0000000 --- a/code/compiler/10/examples/primes.txt +++ /dev/null @@ -1,129 +0,0 @@ -data List = { Nil, Cons Nat List } -data Bool = { True, False } -data Nat = { O, S Nat } - -defn ifN c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn ifL c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn toInt n = { - case n of { - O -> { 0 } - S np -> { 1 + toInt np } - } -} - -defn lte n m = { - case m of { - O -> { - case n of { - O -> { True } - S np -> { False } - } - } - S mp -> { - case n of { - O -> { True } - S np -> { lte np mp } - } - } - } -} - -defn minus n m = { - case m of { - O -> { n } - S mp -> { - case n of { - O -> { O } - S np -> { - minus np mp - } - } - } - } -} - -defn mod n m = { - ifN (lte m n) (mod (minus n m) m) n -} - -defn notDivisibleBy n m = { - case (mod m n) of { - O -> { False } - S mp -> { True } - } -} - -defn filter f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { ifL (f x) (Cons x (filter f xs)) (filter f xs) } - } -} - -defn map f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { Cons (f x) (map f xs) } - } -} - -defn nats = { - Cons (S (S O)) (map S nats) -} - -defn primesRec l = { - case l of { - Nil -> { Nil } - Cons p xs -> { Cons p (primesRec (filter (notDivisibleBy p) xs)) } - } -} - -defn primes = { - primesRec nats -} - -defn take n l = { - case l of { - Nil -> { Nil } - Cons x xs -> { - case n of { - O -> { Nil } - S np -> { Cons x (take np xs) } - } - } - } -} - -defn head l = { - case l of { - Nil -> { O } - Cons x xs -> { x } - } -} - -defn reverseAcc a l = { - case l of { - Nil -> { a } - Cons x xs -> { reverseAcc (Cons x a) xs } - } -} - -defn reverse l = { - reverseAcc Nil l -} - -defn main = { - toInt (head (reverse (take ((S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) primes))) -} diff --git a/code/compiler/10/examples/runtime1.c b/code/compiler/10/examples/runtime1.c deleted file mode 100644 index 0157051..0000000 --- a/code/compiler/10/examples/runtime1.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "../runtime.h" - -void f_add(struct stack* s) { - struct node_num* left = (struct node_num*) eval(stack_peek(s, 0)); - struct node_num* right = (struct node_num*) eval(stack_peek(s, 1)); - stack_push(s, (struct node_base*) alloc_num(left->value + right->value)); -} - -void f_main(struct stack* s) { - // PushInt 320 - stack_push(s, (struct node_base*) alloc_num(320)); - - // PushInt 6 - stack_push(s, (struct node_base*) alloc_num(6)); - - // PushGlobal f_add (the function for +) - stack_push(s, (struct node_base*) alloc_global(f_add, 2)); - - struct node_base* left; - struct node_base* right; - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); -} diff --git a/code/compiler/10/examples/works1.txt b/code/compiler/10/examples/works1.txt deleted file mode 100644 index a2d647f..0000000 --- a/code/compiler/10/examples/works1.txt +++ /dev/null @@ -1,2 +0,0 @@ -defn main = { sum 320 6 } -defn sum x y = { x + y } diff --git a/code/compiler/10/examples/works2.txt b/code/compiler/10/examples/works2.txt deleted file mode 100644 index 8332fde..0000000 --- a/code/compiler/10/examples/works2.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn add x y = { x + y } -defn double x = { add x x } -defn main = { double 163 } diff --git a/code/compiler/10/examples/works3.txt b/code/compiler/10/examples/works3.txt deleted file mode 100644 index 13514dd..0000000 --- a/code/compiler/10/examples/works3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } -defn length l = { - case l of { - Nil -> { 0 } - Cons x xs -> { 1 + length xs } - } -} -defn main = { length (Cons 1 (Cons 2 (Cons 3 Nil))) } diff --git a/code/compiler/10/examples/works4.txt b/code/compiler/10/examples/works4.txt deleted file mode 100644 index 7674691..0000000 --- a/code/compiler/10/examples/works4.txt +++ /dev/null @@ -1,16 +0,0 @@ -data List = { Nil, Cons Int List } - -defn add x y = { x + y } -defn mul x y = { x * y } - -defn foldr f b l = { - case l of { - Nil -> { b } - Cons x xs -> { f x (foldr f b xs) } - } -} - -defn main = { - foldr add 0 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) + - foldr mul 1 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) -} diff --git a/code/compiler/10/examples/works5.txt b/code/compiler/10/examples/works5.txt deleted file mode 100644 index 3a8aff5..0000000 --- a/code/compiler/10/examples/works5.txt +++ /dev/null @@ -1,17 +0,0 @@ -data List = { Nil, Cons Int List } - -defn sumZip l m = { - case l of { - Nil -> { 0 } - Cons x xs -> { - case m of { - Nil -> { 0 } - Cons y ys -> { x + y + sumZip xs ys } - } - } - } -} - -defn ones = { Cons 1 ones } - -defn main = { sumZip ones (Cons 1 (Cons 2 (Cons 3 Nil))) } diff --git a/code/compiler/10/graph.cpp b/code/compiler/10/graph.cpp deleted file mode 100644 index c648acd..0000000 --- a/code/compiler/10/graph.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "graph.hpp" - -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/code/compiler/10/graph.hpp b/code/compiler/10/graph.hpp deleted file mode 100644 index 2db8d7c..0000000 --- a/code/compiler/10/graph.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using function = std::string; - -struct group { - std::set members; -}; - -using group_ptr = std::unique_ptr; - -class function_graph { - using group_id = size_t; - - struct group_data { - std::set functions; - std::set adjacency_list; - size_t indegree; - }; - - using data_ptr = std::shared_ptr; - using edge = std::pair; - using group_edge = std::pair; - - std::map> adjacency_lists; - std::set edges; - - std::set compute_transitive_edges(); - void create_groups( - const std::set&, - std::map&, - std::map&); - void create_edges( - std::map&, - std::map&); - std::vector generate_order( - std::map&, - std::map&); - - public: - std::set& add_function(const function& f); - void add_edge(const function& from, const function& to); - std::vector compute_order(); -}; diff --git a/code/compiler/10/instruction.cpp b/code/compiler/10/instruction.cpp deleted file mode 100644 index c2b050a..0000000 --- a/code/compiler/10/instruction.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include "instruction.hpp" -#include "llvm_context.hpp" -#include -#include - -using namespace llvm; - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void instruction_pushint::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushInt(" << value << ")" << std::endl; -} - -void instruction_pushint::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_num(f, ctx.create_i32(value))); -} - -void instruction_pushglobal::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushGlobal(" << name << ")" << std::endl; -} - -void instruction_pushglobal::gen_llvm(llvm_context& ctx, Function* f) const { - auto& global_f = ctx.custom_functions.at("f_" + name); - auto arity = ctx.create_i32(global_f->arity); - ctx.create_push(f, ctx.create_global(f, global_f->function, arity)); -} - -void instruction_push::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Push(" << offset << ")" << std::endl; -} - -void instruction_push::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_peek(f, ctx.create_size(offset))); -} - -void instruction_pop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pop(" << count << ")" << std::endl; -} - -void instruction_pop::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_popn(f, ctx.create_size(count)); -} - -void instruction_mkapp::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "MkApp()" << std::endl; -} - -void instruction_mkapp::gen_llvm(llvm_context& ctx, Function* f) const { - auto left = ctx.create_pop(f); - auto right = ctx.create_pop(f); - ctx.create_push(f, ctx.create_app(f, left, right)); -} - -void instruction_update::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Update(" << offset << ")" << std::endl; -} - -void instruction_update::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_update(f, ctx.create_size(offset)); -} - -void instruction_pack::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pack(" << tag << ", " << size << ")" << std::endl; -} - -void instruction_pack::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_pack(f, ctx.create_size(size), ctx.create_i8(tag)); -} - -void instruction_split::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Split()" << std::endl; -} - -void instruction_split::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_split(f, ctx.create_size(size)); -} - -void instruction_jump::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Jump(" << std::endl; - for(auto& instruction_set : branches) { - for(auto& instruction : instruction_set) { - instruction->print(indent + 2, to); - } - to << std::endl; - } - print_indent(indent, to); - to << ")" << std::endl; -} - -void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const { - auto top_node = ctx.create_peek(f, ctx.create_size(0)); - auto tag = ctx.unwrap_data_tag(top_node); - auto safety_block = BasicBlock::Create(ctx.ctx, "safety", f); - auto switch_op = ctx.builder.CreateSwitch(tag, safety_block, tag_mappings.size()); - std::vector blocks; - - for(auto& branch : branches) { - auto branch_block = BasicBlock::Create(ctx.ctx, "branch", f); - ctx.builder.SetInsertPoint(branch_block); - for(auto& instruction : branch) { - instruction->gen_llvm(ctx, f); - } - ctx.builder.CreateBr(safety_block); - blocks.push_back(branch_block); - } - - for(auto& mapping : tag_mappings) { - switch_op->addCase(ctx.create_i8(mapping.first), blocks[mapping.second]); - } - - ctx.builder.SetInsertPoint(safety_block); -} - -void instruction_slide::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Slide(" << offset << ")" << std::endl; -} - -void instruction_slide::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_slide(f, ctx.create_size(offset)); -} - -void instruction_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BinOp(" << op_action(op) << ")" << std::endl; -} - -void instruction_binop::gen_llvm(llvm_context& ctx, Function* f) const { - auto left_int = ctx.unwrap_num(ctx.create_pop(f)); - auto right_int = ctx.unwrap_num(ctx.create_pop(f)); - llvm::Value* result; - switch(op) { - case PLUS: result = ctx.builder.CreateAdd(left_int, right_int); break; - case MINUS: result = ctx.builder.CreateSub(left_int, right_int); break; - case TIMES: result = ctx.builder.CreateMul(left_int, right_int); break; - case DIVIDE: result = ctx.builder.CreateSDiv(left_int, right_int); break; - } - ctx.create_push(f, ctx.create_num(f, result)); -} - -void instruction_eval::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Eval()" << std::endl; -} - -void instruction_eval::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_unwind(f); -} - -void instruction_alloc::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Alloc(" << amount << ")" << std::endl; -} - -void instruction_alloc::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_alloc(f, ctx.create_size(amount)); -} - -void instruction_unwind::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Unwind()" << std::endl; -} - -void instruction_unwind::gen_llvm(llvm_context& ctx, Function* f) const { - // Nothing -} diff --git a/code/compiler/10/instruction.hpp b/code/compiler/10/instruction.hpp deleted file mode 100644 index abe2409..0000000 --- a/code/compiler/10/instruction.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include "binop.hpp" -#include "llvm_context.hpp" - -struct instruction { - virtual ~instruction() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual void gen_llvm(llvm_context& ctx, llvm::Function* f) const = 0; -}; - -using instruction_ptr = std::unique_ptr; - -struct instruction_pushint : public instruction { - int value; - - instruction_pushint(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pushglobal : public instruction { - std::string name; - - instruction_pushglobal(std::string n) - : name(std::move(n)) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_push : public instruction { - int offset; - - instruction_push(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pop : public instruction { - int count; - - instruction_pop(int c) - : count(c) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_mkapp : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_update : public instruction { - int offset; - - instruction_update(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pack : public instruction { - int tag; - int size; - - instruction_pack(int t, int s) - : tag(t), size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_split : public instruction { - int size; - - instruction_split(int s) - : size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_jump : public instruction { - std::vector> branches; - std::map tag_mappings; - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_slide : public instruction { - int offset; - - instruction_slide(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_binop : public instruction { - binop op; - - instruction_binop(binop o) - : op(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_eval : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_alloc : public instruction { - int amount; - - instruction_alloc(int a) - : amount(a) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_unwind : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; diff --git a/code/compiler/10/llvm_context.cpp b/code/compiler/10/llvm_context.cpp deleted file mode 100644 index 45dcb50..0000000 --- a/code/compiler/10/llvm_context.cpp +++ /dev/null @@ -1,278 +0,0 @@ -#include "llvm_context.hpp" -#include - -using namespace llvm; - -void llvm_context::create_types() { - stack_type = StructType::create(ctx, "stack"); - gmachine_type = StructType::create(ctx, "gmachine"); - stack_ptr_type = PointerType::getUnqual(stack_type); - gmachine_ptr_type = PointerType::getUnqual(gmachine_type); - tag_type = IntegerType::getInt8Ty(ctx); - struct_types["node_base"] = StructType::create(ctx, "node_base"); - struct_types["node_app"] = StructType::create(ctx, "node_app"); - struct_types["node_num"] = StructType::create(ctx, "node_num"); - struct_types["node_global"] = StructType::create(ctx, "node_global"); - struct_types["node_ind"] = StructType::create(ctx, "node_ind"); - struct_types["node_data"] = StructType::create(ctx, "node_data"); - node_ptr_type = PointerType::getUnqual(struct_types.at("node_base")); - function_type = FunctionType::get(Type::getVoidTy(ctx), { gmachine_ptr_type }, false); - - gmachine_type->setBody( - stack_ptr_type, - node_ptr_type, - IntegerType::getInt64Ty(ctx), - IntegerType::getInt64Ty(ctx) - ); - struct_types.at("node_base")->setBody( - IntegerType::getInt32Ty(ctx), - IntegerType::getInt8Ty(ctx), - node_ptr_type - ); - struct_types.at("node_app")->setBody( - struct_types.at("node_base"), - node_ptr_type, - node_ptr_type - ); - struct_types.at("node_num")->setBody( - struct_types.at("node_base"), - IntegerType::getInt32Ty(ctx) - ); - struct_types.at("node_global")->setBody( - struct_types.at("node_base"), - FunctionType::get(Type::getVoidTy(ctx), { stack_ptr_type }, false) - ); - struct_types.at("node_ind")->setBody( - struct_types.at("node_base"), - node_ptr_type - ); - struct_types.at("node_data")->setBody( - struct_types.at("node_base"), - IntegerType::getInt8Ty(ctx), - PointerType::getUnqual(node_ptr_type) - ); -} - -void llvm_context::create_functions() { - auto void_type = Type::getVoidTy(ctx); - auto sizet_type = IntegerType::get(ctx, sizeof(size_t) * 8); - functions["stack_init"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_init", - &module - ); - functions["stack_free"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_free", - &module - ); - functions["stack_push"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_push", - &module - ); - functions["stack_pop"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_pop", - &module - ); - functions["stack_peek"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_peek", - &module - ); - functions["stack_popn"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_popn", - &module - ); - functions["gmachine_slide"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_slide", - &module - ); - functions["gmachine_update"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_update", - &module - ); - functions["gmachine_alloc"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_alloc", - &module - ); - functions["gmachine_pack"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type, tag_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_pack", - &module - ); - functions["gmachine_split"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_split", - &module - ); - functions["gmachine_track"] = Function::Create( - FunctionType::get(node_ptr_type, { gmachine_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_track", - &module - ); - - auto int32_type = IntegerType::getInt32Ty(ctx); - functions["alloc_app"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_app", - &module - ); - functions["alloc_num"] = Function::Create( - FunctionType::get(node_ptr_type, { int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_num", - &module - ); - functions["alloc_global"] = Function::Create( - FunctionType::get(node_ptr_type, { function_type, int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_global", - &module - ); - functions["alloc_ind"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_ind", - &module - ); - - functions["unwind"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "unwind", - &module - ); -} - -ConstantInt* llvm_context::create_i8(int8_t i) { - return ConstantInt::get(ctx, APInt(8, i)); -} -ConstantInt* llvm_context::create_i32(int32_t i) { - return ConstantInt::get(ctx, APInt(32, i)); -} -ConstantInt* llvm_context::create_size(size_t i) { - return ConstantInt::get(ctx, APInt(sizeof(size_t) * 8, i)); -} - -Value* llvm_context::create_pop(Function* f) { - auto pop_f = functions.at("stack_pop"); - return builder.CreateCall(pop_f, { unwrap_gmachine_stack_ptr(f->arg_begin()) }); -} -Value* llvm_context::create_peek(Function* f, Value* off) { - auto peek_f = functions.at("stack_peek"); - return builder.CreateCall(peek_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off }); -} -void llvm_context::create_push(Function* f, Value* v) { - auto push_f = functions.at("stack_push"); - builder.CreateCall(push_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), v }); -} -void llvm_context::create_popn(Function* f, Value* off) { - auto popn_f = functions.at("stack_popn"); - builder.CreateCall(popn_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off }); -} -void llvm_context::create_update(Function* f, Value* off) { - auto update_f = functions.at("gmachine_update"); - builder.CreateCall(update_f, { f->arg_begin(), off }); -} -void llvm_context::create_pack(Function* f, Value* c, Value* t) { - auto pack_f = functions.at("gmachine_pack"); - builder.CreateCall(pack_f, { f->arg_begin(), c, t }); -} -void llvm_context::create_split(Function* f, Value* c) { - auto split_f = functions.at("gmachine_split"); - builder.CreateCall(split_f, { f->arg_begin(), c }); -} -void llvm_context::create_slide(Function* f, Value* off) { - auto slide_f = functions.at("gmachine_slide"); - builder.CreateCall(slide_f, { f->arg_begin(), off }); -} -void llvm_context::create_alloc(Function* f, Value* n) { - auto alloc_f = functions.at("gmachine_alloc"); - builder.CreateCall(alloc_f, { f->arg_begin(), n }); -} -Value* llvm_context::create_track(Function* f, Value* v) { - auto track_f = functions.at("gmachine_track"); - return builder.CreateCall(track_f, { f->arg_begin(), v }); -} - -void llvm_context::create_unwind(Function* f) { - auto unwind_f = functions.at("unwind"); - builder.CreateCall(unwind_f, { f->args().begin() }); -} - -Value* llvm_context::unwrap_gmachine_stack_ptr(Value* g) { - auto offset_0 = create_i32(0); - return builder.CreateGEP(g, { offset_0, offset_0 }); -} - -Value* llvm_context::unwrap_num(Value* v) { - auto num_ptr_type = PointerType::getUnqual(struct_types.at("node_num")); - auto cast = builder.CreatePointerCast(v, num_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto int_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(int_ptr); -} -Value* llvm_context::create_num(Function* f, Value* v) { - auto alloc_num_f = functions.at("alloc_num"); - auto alloc_num_call = builder.CreateCall(alloc_num_f, { v }); - return create_track(f, alloc_num_call); -} - -Value* llvm_context::unwrap_data_tag(Value* v) { - auto data_ptr_type = PointerType::getUnqual(struct_types.at("node_data")); - auto cast = builder.CreatePointerCast(v, data_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto tag_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(tag_ptr); -} - -Value* llvm_context::create_global(Function* f, Value* gf, Value* a) { - auto alloc_global_f = functions.at("alloc_global"); - auto alloc_global_call = builder.CreateCall(alloc_global_f, { gf, a }); - return create_track(f, alloc_global_call); -} - -Value* llvm_context::create_app(Function* f, Value* l, Value* r) { - auto alloc_app_f = functions.at("alloc_app"); - auto alloc_app_call = builder.CreateCall(alloc_app_f, { l, r }); - return create_track(f, alloc_app_call); -} - -llvm::Function* llvm_context::create_custom_function(std::string name, int32_t arity) { - auto void_type = llvm::Type::getVoidTy(ctx); - auto new_function = llvm::Function::Create( - function_type, - llvm::Function::LinkageTypes::ExternalLinkage, - "f_" + name, - &module - ); - auto start_block = llvm::BasicBlock::Create(ctx, "entry", new_function); - - auto new_custom_f = custom_function_ptr(new custom_function()); - new_custom_f->arity = arity; - new_custom_f->function = new_function; - custom_functions["f_" + name] = std::move(new_custom_f); - - return new_function; -} diff --git a/code/compiler/10/llvm_context.hpp b/code/compiler/10/llvm_context.hpp deleted file mode 100644 index fbe4cc1..0000000 --- a/code/compiler/10/llvm_context.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -struct llvm_context { - struct custom_function { - llvm::Function* function; - int32_t arity; - }; - - using custom_function_ptr = std::unique_ptr; - - llvm::LLVMContext ctx; - llvm::IRBuilder<> builder; - llvm::Module module; - - std::map custom_functions; - std::map functions; - std::map struct_types; - - llvm::StructType* stack_type; - llvm::StructType* gmachine_type; - llvm::PointerType* stack_ptr_type; - llvm::PointerType* gmachine_ptr_type; - llvm::PointerType* node_ptr_type; - llvm::IntegerType* tag_type; - llvm::FunctionType* function_type; - - llvm_context() - : builder(ctx), module("bloglang", ctx) { - create_types(); - create_functions(); - } - - void create_types(); - void create_functions(); - - llvm::ConstantInt* create_i8(int8_t); - llvm::ConstantInt* create_i32(int32_t); - llvm::ConstantInt* create_size(size_t); - - llvm::Value* create_pop(llvm::Function*); - llvm::Value* create_peek(llvm::Function*, llvm::Value*); - void create_push(llvm::Function*, llvm::Value*); - void create_popn(llvm::Function*, llvm::Value*); - void create_update(llvm::Function*, llvm::Value*); - void create_pack(llvm::Function*, llvm::Value*, llvm::Value*); - void create_split(llvm::Function*, llvm::Value*); - void create_slide(llvm::Function*, llvm::Value*); - void create_alloc(llvm::Function*, llvm::Value*); - llvm::Value* create_track(llvm::Function*, llvm::Value*); - - void create_unwind(llvm::Function*); - - llvm::Value* unwrap_gmachine_stack_ptr(llvm::Value*); - - llvm::Value* unwrap_num(llvm::Value*); - llvm::Value* create_num(llvm::Function*, llvm::Value*); - - llvm::Value* unwrap_data_tag(llvm::Value*); - - llvm::Value* create_global(llvm::Function*, llvm::Value*, llvm::Value*); - - llvm::Value* create_app(llvm::Function*, llvm::Value*, llvm::Value*); - - llvm::Function* create_custom_function(std::string name, int32_t arity); -}; diff --git a/code/compiler/10/main.cpp b/code/compiler/10/main.cpp deleted file mode 100644 index bc181d6..0000000 --- a/code/compiler/10/main.cpp +++ /dev/null @@ -1,204 +0,0 @@ -#include "ast.hpp" -#include -#include "binop.hpp" -#include "definition.hpp" -#include "graph.hpp" -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "parser.hpp" -#include "error.hpp" -#include "type.hpp" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetMachine.h" - -void yy::parser::error(const std::string& msg) { - std::cout << "An error occured: " << msg << std::endl; -} - -extern std::map defs_data; -extern std::map defs_defn; - -void typecheck_program( - const std::map& defs_data, - 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); - env->bind("/", binop_type); - - for(auto& def_data : defs_data) { - def_data.second->insert_types(mgr, env); - } - for(auto& def_data : defs_data) { - def_data.second->insert_constructors(); - } - - function_graph dependency_graph; - - for(auto& def_defn : defs_defn) { - def_defn.second->find_free(mgr, env); - dependency_graph.add_function(def_defn.second->name); - - for(auto& dependency : def_defn.second->free_variables) { - if(defs_defn.find(dependency) == defs_defn.end()) - throw 0; - dependency_graph.add_edge(def_defn.second->name, dependency); - } - } - - std::vector groups = dependency_graph.compute_order(); - for(auto it = groups.rbegin(); it != groups.rend(); it++) { - auto& group = *it; - for(auto& def_defnn_name : group->members) { - auto& def_defn = defs_defn.find(def_defnn_name)->second; - def_defn->insert_types(mgr); - } - 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); - } - } - - for(auto& pair : env->names) { - std::cout << pair.first << ": "; - pair.second->print(mgr, std::cout); - std::cout << std::endl; - } -} - -void compile_program(const std::map& defs_defn) { - for(auto& def_defn : defs_defn) { - def_defn.second->compile(); - - for(auto& instruction : def_defn.second->instructions) { - instruction->print(0, std::cout); - } - std::cout << std::endl; - } -} - -void gen_llvm_internal_op(llvm_context& ctx, binop op) { - auto new_function = ctx.create_custom_function(op_action(op), 2); - std::vector instructions; - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_binop(op))); - instructions.push_back(instruction_ptr(new instruction_update(2))); - instructions.push_back(instruction_ptr(new instruction_pop(2))); - ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.builder.CreateRetVoid(); -} - -void output_llvm(llvm_context& ctx, const std::string& filename) { - std::string targetTriple = llvm::sys::getDefaultTargetTriple(); - - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmParser(); - llvm::InitializeNativeTargetAsmPrinter(); - - std::string error; - const llvm::Target* target = - llvm::TargetRegistry::lookupTarget(targetTriple, error); - if (!target) { - std::cerr << error << std::endl; - } else { - std::string cpu = "generic"; - std::string features = ""; - llvm::TargetOptions options; - llvm::TargetMachine* targetMachine = - target->createTargetMachine(targetTriple, cpu, features, - options, llvm::Optional()); - - ctx.module.setDataLayout(targetMachine->createDataLayout()); - ctx.module.setTargetTriple(targetTriple); - - std::error_code ec; - llvm::raw_fd_ostream file(filename, ec, llvm::sys::fs::F_None); - if (ec) { - throw 0; - } else { - llvm::TargetMachine::CodeGenFileType type = llvm::TargetMachine::CGFT_ObjectFile; - llvm::legacy::PassManager pm; - if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) { - throw 0; - } else { - pm.run(ctx.module); - file.close(); - } - } - } -} - -void gen_llvm( - const std::map& defs_data, - const std::map& defs_defn) { - llvm_context ctx; - gen_llvm_internal_op(ctx, PLUS); - gen_llvm_internal_op(ctx, MINUS); - gen_llvm_internal_op(ctx, TIMES); - gen_llvm_internal_op(ctx, DIVIDE); - - for(auto& def_data : defs_data) { - def_data.second->generate_llvm(ctx); - } - for(auto& def_defn : defs_defn) { - def_defn.second->declare_llvm(ctx); - } - for(auto& def_defn : defs_defn) { - def_defn.second->generate_llvm(ctx); - } - - ctx.module.print(llvm::outs(), nullptr); - output_llvm(ctx, "program.o"); -} - -int main() { - yy::parser parser; - type_mgr mgr; - type_env_ptr env(new type_env); - - parser.parse(); - for(auto& def_defn : defs_defn) { - std::cout << def_defn.second->name; - for(auto& param : def_defn.second->params) std::cout << " " << param; - std::cout << ":" << std::endl; - - def_defn.second->body->print(1, std::cout); - } - try { - typecheck_program(defs_data, defs_defn, mgr, env); - compile_program(defs_defn); - gen_llvm(defs_data, defs_defn); - } catch(unification_error& err) { - std::cout << "failed to unify types: " << std::endl; - std::cout << " (1) \033[34m"; - err.left->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - std::cout << " (2) \033[32m"; - err.right->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - } catch(type_error& err) { - std::cout << "failed to type check program: " << err.description << std::endl; - } -} diff --git a/code/compiler/10/parser.y b/code/compiler/10/parser.y deleted file mode 100644 index 57f4be9..0000000 --- a/code/compiler/10/parser.y +++ /dev/null @@ -1,144 +0,0 @@ -%{ -#include -#include -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" - -std::map defs_data; -std::map defs_defn; - -extern yy::parser::symbol_type yylex(); - -%} - -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%type > lowercaseParams uppercaseParams -%type > branches -%type > constructors -%type aAdd aMul case app appBase -%type data -%type defn -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { } - ; - -definitions - : definitions definition { } - | definition { } - ; - -definition - : defn { auto name = $1->name; defs_defn[name] = std::move($1); } - | data { auto name = $1->name; defs_data[name] = std::move($1); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_defn_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6))); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -uppercaseParams - : %empty { $$ = std::vector(); } - | uppercaseParams UID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } - ; - -branches - : branches branch { $$ = std::move($1); $$.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } - ; - -data - : DATA UID EQUAL OCURLY constructors CCURLY - { $$ = definition_data_ptr(new definition_data(std::move($2), std::move($5))); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID uppercaseParams - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - diff --git a/code/compiler/10/runtime.c b/code/compiler/10/runtime.c deleted file mode 100644 index 7b8a7c3..0000000 --- a/code/compiler/10/runtime.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include -#include -#include -#include "runtime.h" - -struct node_base* alloc_node() { - struct node_base* new_node = malloc(sizeof(struct node_app)); - new_node->gc_next = NULL; - new_node->gc_reachable = 0; - assert(new_node != NULL); - return new_node; -} - -struct node_app* alloc_app(struct node_base* l, struct node_base* r) { - struct node_app* node = (struct node_app*) alloc_node(); - node->base.tag = NODE_APP; - node->left = l; - node->right = r; - return node; -} - -struct node_num* alloc_num(int32_t n) { - struct node_num* node = (struct node_num*) alloc_node(); - node->base.tag = NODE_NUM; - node->value = n; - return node; -} - -struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a) { - struct node_global* node = (struct node_global*) alloc_node(); - node->base.tag = NODE_GLOBAL; - node->arity = a; - node->function = f; - return node; -} - -struct node_ind* alloc_ind(struct node_base* n) { - struct node_ind* node = (struct node_ind*) alloc_node(); - node->base.tag = NODE_IND; - node->next = n; - return node; -} - -void free_node_direct(struct node_base* n) { - if(n->tag == NODE_DATA) { - free(((struct node_data*) n)->array); - } -} - -void gc_visit_node(struct node_base* n) { - if(n->gc_reachable) return; - n->gc_reachable = 1; - - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - gc_visit_node(app->left); - gc_visit_node(app->right); - } if(n->tag == NODE_IND) { - struct node_ind* ind = (struct node_ind*) n; - gc_visit_node(ind->next); - } if(n->tag == NODE_DATA) { - struct node_data* data = (struct node_data*) n; - struct node_base** to_visit = data->array; - while(*to_visit) { - gc_visit_node(*to_visit); - to_visit++; - } - } -} - -void stack_init(struct stack* s) { - s->size = 4; - s->count = 0; - s->data = malloc(sizeof(*s->data) * s->size); - assert(s->data != NULL); -} - -void stack_free(struct stack* s) { - free(s->data); -} - -void stack_push(struct stack* s, struct node_base* n) { - while(s->count >= s->size) { - s->data = realloc(s->data, sizeof(*s->data) * (s->size *= 2)); - assert(s->data != NULL); - } - s->data[s->count++] = n; -} - -struct node_base* stack_pop(struct stack* s) { - assert(s->count > 0); - return s->data[--s->count]; -} - -struct node_base* stack_peek(struct stack* s, size_t o) { - assert(s->count > o); - return s->data[s->count - o - 1]; -} - -void stack_popn(struct stack* s, size_t n) { - assert(s->count >= n); - s->count -= n; -} - -void gmachine_init(struct gmachine* g) { - stack_init(&g->stack); - g->gc_nodes = NULL; - g->gc_node_count = 0; - g->gc_node_threshold = 128; -} - -void gmachine_free(struct gmachine* g) { - stack_free(&g->stack); - struct node_base* to_free = g->gc_nodes; - struct node_base* next; - - while(to_free) { - next = to_free->gc_next; - free_node_direct(to_free); - free(to_free); - to_free = next; - } -} - -void gmachine_slide(struct gmachine* g, size_t n) { - assert(g->stack.count > n); - g->stack.data[g->stack.count - n - 1] = g->stack.data[g->stack.count - 1]; - g->stack.count -= n; -} - -void gmachine_update(struct gmachine* g, size_t o) { - assert(g->stack.count > o + 1); - struct node_ind* ind = - (struct node_ind*) g->stack.data[g->stack.count - o - 2]; - ind->base.tag = NODE_IND; - ind->next = g->stack.data[g->stack.count -= 1]; -} - -void gmachine_alloc(struct gmachine* g, size_t o) { - while(o--) { - stack_push(&g->stack, - gmachine_track(g, (struct node_base*) alloc_ind(NULL))); - } -} - -void gmachine_pack(struct gmachine* g, size_t n, int8_t t) { - assert(g->stack.count >= n); - - struct node_base** data = malloc(sizeof(*data) * (n + 1)); - assert(data != NULL); - memcpy(data, &g->stack.data[g->stack.count - n], n * sizeof(*data)); - data[n] = NULL; - - struct node_data* new_node = (struct node_data*) alloc_node(); - new_node->array = data; - new_node->base.tag = NODE_DATA; - new_node->tag = t; - - stack_popn(&g->stack, n); - stack_push(&g->stack, gmachine_track(g, (struct node_base*) new_node)); -} - -void gmachine_split(struct gmachine* g, size_t n) { - struct node_data* node = (struct node_data*) stack_pop(&g->stack); - for(size_t i = 0; i < n; i++) { - stack_push(&g->stack, node->array[i]); - } -} - -struct node_base* gmachine_track(struct gmachine* g, struct node_base* b) { - g->gc_node_count++; - b->gc_next = g->gc_nodes; - g->gc_nodes = b; - - if(g->gc_node_count >= g->gc_node_threshold) { - uint64_t nodes_before = g->gc_node_count; - gc_visit_node(b); - gmachine_gc(g); - g->gc_node_threshold = g->gc_node_count * 2; - } - - return b; -} - -void gmachine_gc(struct gmachine* g) { - for(size_t i = 0; i < g->stack.count; i++) { - gc_visit_node(g->stack.data[i]); - } - - struct node_base** head_ptr = &g->gc_nodes; - while(*head_ptr) { - if((*head_ptr)->gc_reachable) { - (*head_ptr)->gc_reachable = 0; - head_ptr = &(*head_ptr)->gc_next; - } else { - struct node_base* to_free = *head_ptr; - *head_ptr = to_free->gc_next; - free_node_direct(to_free); - free(to_free); - g->gc_node_count--; - } - } -} - -void unwind(struct gmachine* g) { - struct stack* s = &g->stack; - - while(1) { - struct node_base* peek = stack_peek(s, 0); - if(peek->tag == NODE_APP) { - struct node_app* n = (struct node_app*) peek; - stack_push(s, n->left); - } else if(peek->tag == NODE_GLOBAL) { - struct node_global* n = (struct node_global*) peek; - assert(s->count > n->arity); - - for(size_t i = 1; i <= n->arity; i++) { - s->data[s->count - i] - = ((struct node_app*) s->data[s->count - i - 1])->right; - } - - n->function(g); - } else if(peek->tag == NODE_IND) { - struct node_ind* n = (struct node_ind*) peek; - stack_pop(s); - stack_push(s, n->next); - } else { - break; - } - } -} - -extern void f_main(struct gmachine* s); - -void print_node(struct node_base* n) { - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - print_node(app->left); - putchar(' '); - print_node(app->right); - } else if(n->tag == NODE_DATA) { - printf("(Packed)"); - } else if(n->tag == NODE_GLOBAL) { - struct node_global* global = (struct node_global*) n; - printf("(Global: %p)", global->function); - } else if(n->tag == NODE_IND) { - print_node(((struct node_ind*) n)->next); - } else if(n->tag == NODE_NUM) { - struct node_num* num = (struct node_num*) n; - printf("%d", num->value); - } -} - -int main(int argc, char** argv) { - struct gmachine gmachine; - struct node_global* first_node = alloc_global(f_main, 0); - struct node_base* result; - - gmachine_init(&gmachine); - gmachine_track(&gmachine, (struct node_base*) first_node); - stack_push(&gmachine.stack, (struct node_base*) first_node); - unwind(&gmachine); - result = stack_pop(&gmachine.stack); - printf("Result: "); - print_node(result); - putchar('\n'); - gmachine_free(&gmachine); -} diff --git a/code/compiler/10/runtime.h b/code/compiler/10/runtime.h deleted file mode 100644 index 030a27c..0000000 --- a/code/compiler/10/runtime.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include - -struct gmachine; - -enum node_tag { - NODE_APP, - NODE_NUM, - NODE_GLOBAL, - NODE_IND, - NODE_DATA -}; - -struct node_base { - enum node_tag tag; - int8_t gc_reachable; - struct node_base* gc_next; -}; - -struct node_app { - struct node_base base; - struct node_base* left; - struct node_base* right; -}; - -struct node_num { - struct node_base base; - int32_t value; -}; - -struct node_global { - struct node_base base; - int32_t arity; - void (*function)(struct gmachine*); -}; - -struct node_ind { - struct node_base base; - struct node_base* next; -}; - -struct node_data { - struct node_base base; - int8_t tag; - struct node_base** array; -}; - -struct node_base* alloc_node(); -struct node_app* alloc_app(struct node_base* l, struct node_base* r); -struct node_num* alloc_num(int32_t n); -struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a); -struct node_ind* alloc_ind(struct node_base* n); -void free_node_direct(struct node_base*); -void gc_visit_node(struct node_base*); - -struct stack { - size_t size; - size_t count; - struct node_base** data; -}; - -void stack_init(struct stack* s); -void stack_free(struct stack* s); -void stack_push(struct stack* s, struct node_base* n); -struct node_base* stack_pop(struct stack* s); -struct node_base* stack_peek(struct stack* s, size_t o); -void stack_popn(struct stack* s, size_t n); - -struct gmachine { - struct stack stack; - struct node_base* gc_nodes; - int64_t gc_node_count; - int64_t gc_node_threshold; -}; - -void gmachine_init(struct gmachine* g); -void gmachine_free(struct gmachine* g); -void gmachine_slide(struct gmachine* g, size_t n); -void gmachine_update(struct gmachine* g, size_t o); -void gmachine_alloc(struct gmachine* g, size_t o); -void gmachine_pack(struct gmachine* g, size_t n, int8_t t); -void gmachine_split(struct gmachine* g, size_t n); -struct node_base* gmachine_track(struct gmachine* g, struct node_base* b); -void gmachine_gc(struct gmachine* g); diff --git a/code/compiler/10/scanner.l b/code/compiler/10/scanner.l deleted file mode 100644 index c8a4429..0000000 --- a/code/compiler/10/scanner.l +++ /dev/null @@ -1,35 +0,0 @@ -%option noyywrap - -%{ -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" - -#define YY_DECL yy::parser::symbol_type yylex() - -%} - -%% - -[ \n]+ {} -\+ { return yy::parser::make_PLUS(); } -\* { return yy::parser::make_TIMES(); } -- { return yy::parser::make_MINUS(); } -\/ { return yy::parser::make_DIVIDE(); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } -defn { return yy::parser::make_DEFN(); } -data { return yy::parser::make_DATA(); } -case { return yy::parser::make_CASE(); } -of { return yy::parser::make_OF(); } -\{ { return yy::parser::make_OCURLY(); } -\} { return yy::parser::make_CCURLY(); } -\( { return yy::parser::make_OPAREN(); } -\) { return yy::parser::make_CPAREN(); } -, { return yy::parser::make_COMMA(); } --> { return yy::parser::make_ARROW(); } -= { return yy::parser::make_EQUAL(); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } - -%% diff --git a/code/compiler/10/type.cpp b/code/compiler/10/type.cpp deleted file mode 100644 index d355e87..0000000 --- a/code/compiler/10/type.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "type.hpp" -#include -#include -#include -#include "error.hpp" - -void type_scheme::print(const type_mgr& mgr, std::ostream& to) const { - if(forall.size() != 0) { - to << "forall "; - for(auto& var : forall) { - to << var << " "; - } - to << ". "; - } - monotype->print(mgr, to); -} - -type_ptr substitute(const type_mgr& mgr, const std::map& subst, const type_ptr& t) { - type_var* var; - type_ptr resolved = mgr.resolve(t, var); - if(var) { - auto subst_it = subst.find(var->name); - if(subst_it == subst.end()) return resolved; - return subst_it->second; - } else if(type_arr* arr = dynamic_cast(t.get())) { - auto left_result = substitute(mgr, subst, arr->left); - 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)); - } - return t; -} - -type_ptr type_scheme::instantiate(type_mgr& mgr) const { - if(forall.size() == 0) return monotype; - std::map subst; - for(auto& var : forall) { - subst[var] = mgr.new_type(); - } - return substitute(mgr, subst, monotype); -} - -void type_var::print(const type_mgr& mgr, std::ostream& to) const { - auto it = mgr.types.find(name); - if(it != mgr.types.end()) { - it->second->print(mgr, to); - } else { - to << name; - } -} - -void type_base::print(const type_mgr& mgr, std::ostream& to) const { - to << name; -} - -void type_arr::print(const type_mgr& mgr, std::ostream& to) const { - left->print(mgr, to); - to << " -> ("; - right->print(mgr, to); - to << ")"; -} - -std::string type_mgr::new_type_name() { - int temp = last_id++; - std::string str = ""; - - while(temp != -1) { - str += (char) ('a' + (temp % 26)); - temp = temp / 26 - 1; - } - - std::reverse(str.begin(), str.end()); - return str; -} - -type_ptr type_mgr::new_type() { - return type_ptr(new type_var(new_type_name())); -} - -type_ptr type_mgr::new_arrow_type() { - return type_ptr(new type_arr(new_type(), new_type())); -} - -type_ptr type_mgr::resolve(type_ptr t, type_var*& var) const { - type_var* cast; - - var = nullptr; - while((cast = dynamic_cast(t.get()))) { - auto it = types.find(cast->name); - - if(it == types.end()) { - var = cast; - break; - } - t = it->second; - } - - return t; -} - -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; - - l = resolve(l, lvar); - r = resolve(r, rvar); - - if(lvar) { - bind(lvar->name, r); - return; - } else if(rvar) { - bind(rvar->name, l); - return; - } else if((larr = dynamic_cast(l.get())) && - (rarr = dynamic_cast(r.get()))) { - unify(larr->left, rarr->left); - unify(larr->right, rarr->right); - return; - } else if((lid = dynamic_cast(l.get())) && - (rid = dynamic_cast(r.get()))) { - if(lid->name == rid->name) return; - } - - throw unification_error(l, r); -} - -void type_mgr::bind(const std::string& s, type_ptr t) { - type_var* other = dynamic_cast(t.get()); - - if(other && other->name == s) return; - types[s] = t; -} - -void type_mgr::find_free(const type_ptr& t, std::set& into) const { - type_var* var; - type_ptr resolved = resolve(t, var); - - if(var) { - into.insert(var->name); - } else if(type_arr* arr = dynamic_cast(resolved.get())) { - find_free(arr->left, into); - find_free(arr->right, into); - } -} diff --git a/code/compiler/10/type.hpp b/code/compiler/10/type.hpp deleted file mode 100644 index 94c4f85..0000000 --- a/code/compiler/10/type.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -struct type_mgr; - -struct type { - virtual ~type() = default; - - virtual void print(const type_mgr& mgr, std::ostream& to) const = 0; -}; - -using type_ptr = std::shared_ptr; - -struct type_scheme { - std::vector forall; - type_ptr monotype; - - type_scheme(type_ptr type) : forall(), monotype(std::move(type)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; - type_ptr instantiate(type_mgr& mgr) const; -}; - -using type_scheme_ptr = std::shared_ptr; - -struct type_var : public type { - std::string name; - - type_var(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_base : public type { - std::string name; - - type_base(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_data : public type_base { - struct constructor { - int tag; - }; - - std::map constructors; - - type_data(std::string n) - : type_base(std::move(n)) {} -}; - -struct type_arr : public type { - type_ptr left; - type_ptr right; - - type_arr(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_mgr { - int last_id = 0; - std::map types; - - std::string new_type_name(); - type_ptr new_type(); - type_ptr new_arrow_type(); - - void unify(type_ptr l, type_ptr r); - type_ptr resolve(type_ptr t, type_var*& var) const; - void bind(const std::string& s, type_ptr t); - void find_free(const type_ptr& t, std::set& into) const; -}; diff --git a/code/compiler/10/type_env.cpp b/code/compiler/10/type_env.cpp deleted file mode 100644 index 3e654be..0000000 --- a/code/compiler/10/type_env.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "type_env.hpp" -#include "type.hpp" - -type_scheme_ptr type_env::lookup(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second; - if(parent) return parent->lookup(name); - 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)); -} - -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; - if(names_it->second->forall.size() > 0) throw 0; - - std::set free_variables; - mgr.find_free(names_it->second->monotype, free_variables); - for(auto& free : free_variables) { - names_it->second->forall.push_back(free); - } -} - -type_env_ptr type_scope(type_env_ptr parent) { - return type_env_ptr(new type_env(std::move(parent))); -} diff --git a/code/compiler/10/type_env.hpp b/code/compiler/10/type_env.hpp deleted file mode 100644 index ca91ef7..0000000 --- a/code/compiler/10/type_env.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include -#include "type.hpp" - -struct type_env; -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); -}; - - -type_env_ptr type_scope(type_env_ptr parent); diff --git a/code/compiler/11/CMakeLists.txt b/code/compiler/11/CMakeLists.txt deleted file mode 100644 index c3fb2ef..0000000 --- a/code/compiler/11/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(compiler) - -# Find all the required packages -find_package(BISON) -find_package(FLEX) -find_package(LLVM REQUIRED CONFIG) - -# Set up the flex and bison targets -bison_target(parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser.y - ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp - COMPILE_FLAGS "-d") -flex_target(scanner - ${CMAKE_CURRENT_SOURCE_DIR}/scanner.l - ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp) -add_flex_bison_dependency(scanner parser) - -# Find all the relevant LLVM components -llvm_map_components_to_libnames(LLVM_LIBS core x86asmparser x86codegen) - -# Create compiler executable -add_executable(compiler - 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 - type.cpp type.hpp - error.cpp error.hpp - binop.cpp binop.hpp - instruction.cpp instruction.hpp - graph.cpp graph.hpp - ${BISON_parser_OUTPUTS} - ${FLEX_scanner_OUTPUTS} - main.cpp -) - -# Configure compiler executable -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) -target_include_directories(compiler PUBLIC ${LLVM_INCLUDE_DIRS}) -target_compile_definitions(compiler PUBLIC ${LLVM_DEFINITIONS}) -target_link_libraries(compiler ${LLVM_LIBS}) diff --git a/code/compiler/11/ast.cpp b/code/compiler/11/ast.cpp deleted file mode 100644 index 5bdd00c..0000000 --- a/code/compiler/11/ast.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "ast.hpp" -#include -#include "binop.hpp" -#include "error.hpp" -#include "type_env.hpp" - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void ast_int::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "INT: " << value << std::endl; -} - -void ast_int::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; -} - -type_ptr ast_int::typecheck(type_mgr& mgr) { - return type_ptr(new type_app(env->lookup_type("Int"))); -} - -void ast_int::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushint(value))); -} - -void ast_lid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LID: " << id << std::endl; -} - -void ast_lid::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - if(env->lookup(id) == nullptr) into.insert(id); -} - -type_ptr ast_lid::typecheck(type_mgr& mgr) { - return env->lookup(id)->instantiate(mgr); -} - -void ast_lid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr( - env->has_variable(id) ? - (instruction*) new instruction_push(env->get_offset(id)) : - (instruction*) new instruction_pushglobal(id))); -} - -void ast_uid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "UID: " << id << std::endl; -} - -void ast_uid::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; -} - -type_ptr ast_uid::typecheck(type_mgr& mgr) { - return env->lookup(id)->instantiate(mgr); -} - -void ast_uid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushglobal(id))); -} - -void ast_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BINOP: " << op_name(op) << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -void ast_binop::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - left->find_free(mgr, env, into); - right->find_free(mgr, env, into); -} - -type_ptr ast_binop::typecheck(type_mgr& mgr) { - type_ptr ltype = left->typecheck(mgr); - type_ptr rtype = right->typecheck(mgr); - type_ptr ftype = env->lookup(op_name(op))->instantiate(mgr); - if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op)); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow_one = type_ptr(new type_arr(rtype, return_type)); - type_ptr arrow_two = type_ptr(new type_arr(ltype, arrow_one)); - - mgr.unify(arrow_two, ftype); - return return_type; -} - -void ast_binop::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - - into.push_back(instruction_ptr(new instruction_pushglobal(op_action(op)))); - into.push_back(instruction_ptr(new instruction_mkapp())); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_app::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "APP:" << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -void ast_app::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - left->find_free(mgr, env, into); - right->find_free(mgr, env, into); -} - -type_ptr ast_app::typecheck(type_mgr& mgr) { - type_ptr ltype = left->typecheck(mgr); - type_ptr rtype = right->typecheck(mgr); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); - mgr.unify(arrow, ltype); - return return_type; -} - -void ast_app::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_case::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "CASE: " << std::endl; - for(auto& branch : branches) { - print_indent(indent + 1, to); - branch->pat->print(to); - to << std::endl; - branch->expr->print(indent + 2, to); - } -} - -void ast_case::find_free(type_mgr& mgr, type_env_ptr& env, std::set& into) { - this->env = env; - of->find_free(mgr, env, into); - for(auto& branch : branches) { - type_env_ptr new_env = type_scope(env); - branch->pat->insert_bindings(mgr, new_env); - branch->expr->find_free(mgr, new_env, into); - } -} - -type_ptr ast_case::typecheck(type_mgr& mgr) { - type_var* var; - type_ptr case_type = mgr.resolve(of->typecheck(mgr), var); - type_ptr branch_type = mgr.new_type(); - - for(auto& branch : branches) { - branch->pat->typecheck(case_type, mgr, branch->expr->env); - type_ptr curr_branch_type = branch->expr->typecheck(mgr); - mgr.unify(branch_type, curr_branch_type); - } - - input_type = mgr.resolve(case_type, var); - type_app* app_type; - if(!(app_type = dynamic_cast(input_type.get())) || - !dynamic_cast(app_type->constructor.get())) { - throw type_error("attempting case analysis of non-data type"); - } - - return branch_type; -} - -void ast_case::compile(const env_ptr& env, std::vector& into) const { - type_app* app_type = dynamic_cast(input_type.get()); - type_data* type = dynamic_cast(app_type->constructor.get()); - - of->compile(env, into); - into.push_back(instruction_ptr(new instruction_eval())); - - instruction_jump* jump_instruction = new instruction_jump(); - into.push_back(instruction_ptr(jump_instruction)); - for(auto& branch : branches) { - std::vector branch_instructions; - pattern_var* vpat; - pattern_constr* cpat; - - if((vpat = dynamic_cast(branch->pat.get()))) { - branch->expr->compile(env_ptr(new env_offset(1, env)), branch_instructions); - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) != - jump_instruction->tag_mappings.end()) - break; - - jump_instruction->tag_mappings[constr_pair.second.tag] = - jump_instruction->branches.size(); - } - jump_instruction->branches.push_back(std::move(branch_instructions)); - } else if((cpat = dynamic_cast(branch->pat.get()))) { - env_ptr new_env = env; - for(auto it = cpat->params.rbegin(); it != cpat->params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - - branch_instructions.push_back(instruction_ptr(new instruction_split( - cpat->params.size()))); - branch->expr->compile(new_env, branch_instructions); - branch_instructions.push_back(instruction_ptr(new instruction_slide( - cpat->params.size()))); - - int new_tag = type->constructors[cpat->constr].tag; - if(jump_instruction->tag_mappings.find(new_tag) != - jump_instruction->tag_mappings.end()) - throw type_error("technically not a type error: duplicate pattern"); - - jump_instruction->tag_mappings[new_tag] = - jump_instruction->branches.size(); - jump_instruction->branches.push_back(std::move(branch_instructions)); - } - } - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) == - jump_instruction->tag_mappings.end()) - throw type_error("non-total pattern"); - } -} - -void pattern_var::print(std::ostream& to) const { - to << var; -} - -void pattern_var::insert_bindings(type_mgr& mgr, type_env_ptr& env) const { - env->bind(var, mgr.new_type()); -} - -void pattern_var::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { - mgr.unify(env->lookup(var)->instantiate(mgr), t); -} - -void pattern_constr::print(std::ostream& to) const { - to << constr; - for(auto& param : params) { - to << " " << param; - } -} - -void pattern_constr::insert_bindings(type_mgr& mgr, type_env_ptr& env) const { - for(auto& param : params) { - env->bind(param, mgr.new_type()); - } -} - -void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { - type_ptr constructor_type = env->lookup(constr)->instantiate(mgr); - if(!constructor_type) { - throw type_error(std::string("pattern using unknown constructor ") + constr); - } - - for(auto& param : params) { - type_arr* arr = dynamic_cast(constructor_type.get()); - if(!arr) throw type_error("too many parameters in constructor pattern"); - - mgr.unify(env->lookup(param)->instantiate(mgr), arr->left); - constructor_type = arr->right; - } - - mgr.unify(t, constructor_type); -} diff --git a/code/compiler/11/ast.hpp b/code/compiler/11/ast.hpp deleted file mode 100644 index 6c66636..0000000 --- a/code/compiler/11/ast.hpp +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once -#include -#include -#include -#include "type.hpp" -#include "type_env.hpp" -#include "binop.hpp" -#include "instruction.hpp" -#include "env.hpp" - -struct ast { - type_env_ptr env; - - virtual ~ast() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual void find_free(type_mgr& mgr, - type_env_ptr& env, std::set& into) = 0; - virtual type_ptr typecheck(type_mgr& mgr) = 0; - virtual void compile(const env_ptr& env, - std::vector& into) const = 0; -}; - -using ast_ptr = std::unique_ptr; - -struct pattern { - virtual ~pattern() = default; - - virtual void print(std::ostream& to) const = 0; - virtual void insert_bindings(type_mgr& mgr, type_env_ptr& env) 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) - : value(v) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_lid : public ast { - std::string id; - - explicit ast_lid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct ast_uid : public ast { - std::string id; - - explicit ast_uid(std::string i) - : id(std::move(i)) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - 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) - : op(o), left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - 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) - : left(std::move(l)), right(std::move(r)) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - 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) - : of(std::move(o)), branches(std::move(b)) {} - - void print(int indent, std::ostream& to) const; - void find_free(type_mgr& mgr, type_env_ptr& env, std::set& into); - type_ptr typecheck(type_mgr& mgr); - void compile(const env_ptr& env, std::vector& into) const; -}; - -struct pattern_var : public pattern { - std::string var; - - pattern_var(std::string v) - : var(std::move(v)) {} - - void print(std::ostream &to) const; - void insert_bindings(type_mgr& mgr, type_env_ptr& env) 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) - : constr(std::move(c)), params(std::move(p)) {} - - void print(std::ostream &to) const; - virtual void insert_bindings(type_mgr& mgr, type_env_ptr& env) const; - virtual void typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const; -}; diff --git a/code/compiler/11/binop.cpp b/code/compiler/11/binop.cpp deleted file mode 100644 index 3a5f0ca..0000000 --- a/code/compiler/11/binop.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "binop.hpp" - -std::string op_name(binop op) { - switch(op) { - case PLUS: return "+"; - case MINUS: return "-"; - case TIMES: return "*"; - case DIVIDE: return "/"; - } - return "??"; -} - -std::string op_action(binop op) { - switch(op) { - case PLUS: return "plus"; - case MINUS: return "minus"; - case TIMES: return "times"; - case DIVIDE: return "divide"; - } - return "??"; -} diff --git a/code/compiler/11/binop.hpp b/code/compiler/11/binop.hpp deleted file mode 100644 index 8d07858..0000000 --- a/code/compiler/11/binop.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -std::string op_name(binop op); -std::string op_action(binop op); diff --git a/code/compiler/11/definition.cpp b/code/compiler/11/definition.cpp deleted file mode 100644 index 5f820b7..0000000 --- a/code/compiler/11/definition.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "definition.hpp" -#include "error.hpp" -#include "ast.hpp" -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "type.hpp" -#include "type_env.hpp" -#include -#include -#include - -void definition_defn::find_free(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - - var_env = type_scope(env); - return_type = mgr.new_type(); - full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - full_type = type_ptr(new type_arr(param_type, full_type)); - var_env->bind(*it, param_type); - } - - body->find_free(mgr, var_env, free_variables); -} - -void definition_defn::insert_types(type_mgr& mgr) { - env->bind(name, full_type); -} - -void definition_defn::typecheck(type_mgr& mgr) { - type_ptr body_type = body->typecheck(mgr); - mgr.unify(return_type, body_type); -} - -void definition_defn::compile() { - env_ptr new_env = env_ptr(new env_offset(0, nullptr)); - for(auto it = params.rbegin(); it != params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - body->compile(new_env, instructions); - instructions.push_back(instruction_ptr(new instruction_update(params.size()))); - instructions.push_back(instruction_ptr(new instruction_pop(params.size()))); -} - -void definition_defn::declare_llvm(llvm_context& ctx) { - generated_function = ctx.create_custom_function(name, params.size()); -} - -void definition_defn::generate_llvm(llvm_context& ctx) { - ctx.builder.SetInsertPoint(&generated_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, generated_function); - } - ctx.builder.CreateRetVoid(); -} - -void definition_data::insert_types(type_env_ptr& env) { - this->env = env; - env->bind_type(name, type_ptr(new type_data(name, vars.size()))); -} - -void definition_data::insert_constructors() const { - type_ptr this_type_ptr = env->lookup_type(name); - type_data* this_type = static_cast(this_type_ptr.get()); - int next_tag = 0; - - std::set var_set; - type_app* return_app = new type_app(std::move(this_type_ptr)); - type_ptr return_type(return_app); - for(auto& var : vars) { - if(var_set.find(var) != var_set.end()) throw 0; - var_set.insert(var); - return_app->arguments.push_back(type_ptr(new type_var(var))); - } - - for(auto& constructor : constructors) { - constructor->tag = next_tag; - this_type->constructors[constructor->name] = { next_tag++ }; - - type_ptr full_type = return_type; - for(auto it = constructor->types.rbegin(); it != constructor->types.rend(); it++) { - type_ptr type = (*it)->to_type(var_set, env); - full_type = type_ptr(new type_arr(type, full_type)); - } - - type_scheme_ptr full_scheme(new type_scheme(std::move(full_type))); - full_scheme->forall.insert(full_scheme->forall.begin(), vars.begin(), vars.end()); - env->bind(constructor->name, full_scheme); - } -} - -void definition_data::generate_llvm(llvm_context& ctx) { - for(auto& constructor : constructors) { - auto new_function = - ctx.create_custom_function(constructor->name, constructor->types.size()); - std::vector instructions; - instructions.push_back(instruction_ptr( - new instruction_pack(constructor->tag, constructor->types.size()) - )); - instructions.push_back(instruction_ptr(new instruction_update(0))); - ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); - for (auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.builder.CreateRetVoid(); - } -} diff --git a/code/compiler/11/definition.hpp b/code/compiler/11/definition.hpp deleted file mode 100644 index c14ec0f..0000000 --- a/code/compiler/11/definition.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#include -#include -#include -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "parsed_type.hpp" -#include "type_env.hpp" - -struct ast; -using ast_ptr = std::unique_ptr; - -struct constructor { - std::string name; - std::vector types; - int8_t tag; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition_defn { - std::string name; - std::vector params; - ast_ptr body; - - type_env_ptr env; - type_env_ptr var_env; - std::set free_variables; - type_ptr full_type; - type_ptr return_type; - - std::vector instructions; - - llvm::Function* generated_function; - - definition_defn(std::string n, std::vector p, ast_ptr b) - : name(std::move(n)), params(std::move(p)), body(std::move(b)) { - - } - - void find_free(type_mgr& mgr, type_env_ptr& env); - void insert_types(type_mgr& mgr); - void typecheck(type_mgr& mgr); - void compile(); - void declare_llvm(llvm_context& ctx); - void generate_llvm(llvm_context& ctx); -}; - -using definition_defn_ptr = std::unique_ptr; - -struct definition_data { - std::string name; - std::vector vars; - std::vector constructors; - - type_env_ptr env; - - definition_data( - std::string n, - std::vector vs, - std::vector cs) - : name(std::move(n)), vars(std::move(vs)), constructors(std::move(cs)) {} - - void insert_types(type_env_ptr& env); - void insert_constructors() const; - void generate_llvm(llvm_context& ctx); -}; - -using definition_data_ptr = std::unique_ptr; diff --git a/code/compiler/11/env.cpp b/code/compiler/11/env.cpp deleted file mode 100644 index 818cf5d..0000000 --- a/code/compiler/11/env.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "env.hpp" - -int env_var::get_offset(const std::string& name) const { - if(name == this->name) return 0; - if(parent) return parent->get_offset(name) + 1; - throw 0; -} - -bool env_var::has_variable(const std::string& name) const { - if(name == this->name) return true; - if(parent) return parent->has_variable(name); - return false; -} - -int env_offset::get_offset(const std::string& name) const { - if(parent) return parent->get_offset(name) + offset; - throw 0; -} - -bool env_offset::has_variable(const std::string& name) const { - if(parent) return parent->has_variable(name); - return false; -} diff --git a/code/compiler/11/env.hpp b/code/compiler/11/env.hpp deleted file mode 100644 index a8fbbec..0000000 --- a/code/compiler/11/env.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include - -struct env { - virtual ~env() = default; - - virtual int get_offset(const std::string& name) const = 0; - virtual bool has_variable(const std::string& name) const = 0; -}; - -using env_ptr = std::shared_ptr; - -struct env_var : public env { - std::string name; - env_ptr parent; - - env_var(std::string& n, env_ptr p) - : name(std::move(n)), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; - -struct env_offset : public env { - int offset; - env_ptr parent; - - env_offset(int o, env_ptr p) - : offset(o), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; diff --git a/code/compiler/11/error.cpp b/code/compiler/11/error.cpp deleted file mode 100644 index f5125e3..0000000 --- a/code/compiler/11/error.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "error.hpp" - -const char* type_error::what() const noexcept { - return "an error occured while checking the types of the program"; -} diff --git a/code/compiler/11/error.hpp b/code/compiler/11/error.hpp deleted file mode 100644 index 5bfbc7e..0000000 --- a/code/compiler/11/error.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_error : std::exception { - std::string description; - - type_error(std::string d) - : description(std::move(d)) {} - - const char* what() const noexcept override; -}; - -struct unification_error : public type_error { - type_ptr left; - type_ptr right; - - unification_error(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)), - type_error("failed to unify types") {} -}; diff --git a/code/compiler/11/examples/bad1.txt b/code/compiler/11/examples/bad1.txt deleted file mode 100644 index 86d4bc4..0000000 --- a/code/compiler/11/examples/bad1.txt +++ /dev/null @@ -1,2 +0,0 @@ -data Bool = { True, False } -defn main = { 3 + True } diff --git a/code/compiler/11/examples/bad2.txt b/code/compiler/11/examples/bad2.txt deleted file mode 100644 index def8785..0000000 --- a/code/compiler/11/examples/bad2.txt +++ /dev/null @@ -1 +0,0 @@ -defn main = { 1 2 3 4 5 } diff --git a/code/compiler/11/examples/bad3.txt b/code/compiler/11/examples/bad3.txt deleted file mode 100644 index 6f82b3d..0000000 --- a/code/compiler/11/examples/bad3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } - -defn head l = { - case l of { - Nil -> { 0 } - Cons x y z -> { x } - } -} diff --git a/code/compiler/11/examples/if.txt b/code/compiler/11/examples/if.txt deleted file mode 100644 index c00df35..0000000 --- a/code/compiler/11/examples/if.txt +++ /dev/null @@ -1,8 +0,0 @@ -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/code/compiler/11/examples/list.txt b/code/compiler/11/examples/list.txt deleted file mode 100644 index 159bd1c..0000000 --- a/code/compiler/11/examples/list.txt +++ /dev/null @@ -1,32 +0,0 @@ -data List a = { Nil, Cons a (List a) } - -defn map f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { Cons (f x) (map f xs) } - } -} - -defn foldl f b l = { - case l of { - Nil -> { b } - Cons x xs -> { foldl f (f b x) xs } - } -} - -defn foldr f b l = { - case l of { - Nil -> { b } - Cons x xs -> { f x (foldr f b xs) } - } -} - -defn list = { Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil))) } - -defn add x y = { x + y } -defn sum l = { foldr add 0 l } - -defn skipAdd x y = { y + 1 } -defn length l = { foldr skipAdd 0 l } - -defn main = { sum list + length list } diff --git a/code/compiler/11/examples/mutual_recursion.txt b/code/compiler/11/examples/mutual_recursion.txt deleted file mode 100644 index 7fabf43..0000000 --- a/code/compiler/11/examples/mutual_recursion.txt +++ /dev/null @@ -1,25 +0,0 @@ -data Bool = { True, False } -data List = { Nil, Cons Int List } - -defn if c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn oddEven l e = { - case l of { - Nil -> { e } - Cons x xs -> { evenOdd xs e } - } -} - -defn evenOdd l e = { - case l of { - Nil -> { e } - Cons x xs -> { oddEven xs e } - } -} - -defn main = { if (oddEven (Cons 1 (Cons 2 (Cons 3 Nil))) True) (oddEven (Cons 1 (Cons 2 (Cons 3 Nil))) 1) 3 } diff --git a/code/compiler/11/examples/pair.txt b/code/compiler/11/examples/pair.txt deleted file mode 100644 index 3ed8362..0000000 --- a/code/compiler/11/examples/pair.txt +++ /dev/null @@ -1,17 +0,0 @@ -data Pair a b = { MkPair a b } - -defn fst p = { - case p of { - MkPair a b -> { a } - } -} - -defn snd p = { - case p of { - MkPair a b -> { b } - } -} - -defn pair = { MkPair 1 (MkPair 2 3) } - -defn main = { fst pair + snd (snd pair) } diff --git a/code/compiler/11/examples/primes.txt b/code/compiler/11/examples/primes.txt deleted file mode 100644 index 8421849..0000000 --- a/code/compiler/11/examples/primes.txt +++ /dev/null @@ -1,122 +0,0 @@ -data List = { Nil, Cons Nat List } -data Bool = { True, False } -data Nat = { O, S Nat } - -defn if c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn toInt n = { - case n of { - O -> { 0 } - S np -> { 1 + toInt np } - } -} - -defn lte n m = { - case m of { - O -> { - case n of { - O -> { True } - S np -> { False } - } - } - S mp -> { - case n of { - O -> { True } - S np -> { lte np mp } - } - } - } -} - -defn minus n m = { - case m of { - O -> { n } - S mp -> { - case n of { - O -> { O } - S np -> { - minus np mp - } - } - } - } -} - -defn mod n m = { - if (lte m n) (mod (minus n m) m) n -} - -defn notDivisibleBy n m = { - case (mod m n) of { - O -> { False } - S mp -> { True } - } -} - -defn filter f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { if (f x) (Cons x (filter f xs)) (filter f xs) } - } -} - -defn map f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { Cons (f x) (map f xs) } - } -} - -defn nats = { - Cons (S (S O)) (map S nats) -} - -defn primesRec l = { - case l of { - Nil -> { Nil } - Cons p xs -> { Cons p (primesRec (filter (notDivisibleBy p) xs)) } - } -} - -defn primes = { - primesRec nats -} - -defn take n l = { - case l of { - Nil -> { Nil } - Cons x xs -> { - case n of { - O -> { Nil } - S np -> { Cons x (take np xs) } - } - } - } -} - -defn head l = { - case l of { - Nil -> { O } - Cons x xs -> { x } - } -} - -defn reverseAcc a l = { - case l of { - Nil -> { a } - Cons x xs -> { reverseAcc (Cons x a) xs } - } -} - -defn reverse l = { - reverseAcc Nil l -} - -defn main = { - toInt (head (reverse (take ((S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) primes))) -} diff --git a/code/compiler/11/examples/runtime1.c b/code/compiler/11/examples/runtime1.c deleted file mode 100644 index 0157051..0000000 --- a/code/compiler/11/examples/runtime1.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "../runtime.h" - -void f_add(struct stack* s) { - struct node_num* left = (struct node_num*) eval(stack_peek(s, 0)); - struct node_num* right = (struct node_num*) eval(stack_peek(s, 1)); - stack_push(s, (struct node_base*) alloc_num(left->value + right->value)); -} - -void f_main(struct stack* s) { - // PushInt 320 - stack_push(s, (struct node_base*) alloc_num(320)); - - // PushInt 6 - stack_push(s, (struct node_base*) alloc_num(6)); - - // PushGlobal f_add (the function for +) - stack_push(s, (struct node_base*) alloc_global(f_add, 2)); - - struct node_base* left; - struct node_base* right; - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); -} diff --git a/code/compiler/11/examples/works1.txt b/code/compiler/11/examples/works1.txt deleted file mode 100644 index a2d647f..0000000 --- a/code/compiler/11/examples/works1.txt +++ /dev/null @@ -1,2 +0,0 @@ -defn main = { sum 320 6 } -defn sum x y = { x + y } diff --git a/code/compiler/11/examples/works2.txt b/code/compiler/11/examples/works2.txt deleted file mode 100644 index 8332fde..0000000 --- a/code/compiler/11/examples/works2.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn add x y = { x + y } -defn double x = { add x x } -defn main = { double 163 } diff --git a/code/compiler/11/examples/works3.txt b/code/compiler/11/examples/works3.txt deleted file mode 100644 index cfd2ef3..0000000 --- a/code/compiler/11/examples/works3.txt +++ /dev/null @@ -1,9 +0,0 @@ -data List a = { Nil, Cons a (List a) } -data Bool = { True, False } -defn length l = { - case l of { - Nil -> { 0 } - Cons x xs -> { 1 + length xs } - } -} -defn main = { length (Cons 1 (Cons 2 (Cons 3 Nil))) + length (Cons True (Cons False (Cons True Nil))) } diff --git a/code/compiler/11/examples/works4.txt b/code/compiler/11/examples/works4.txt deleted file mode 100644 index 7674691..0000000 --- a/code/compiler/11/examples/works4.txt +++ /dev/null @@ -1,16 +0,0 @@ -data List = { Nil, Cons Int List } - -defn add x y = { x + y } -defn mul x y = { x * y } - -defn foldr f b l = { - case l of { - Nil -> { b } - Cons x xs -> { f x (foldr f b xs) } - } -} - -defn main = { - foldr add 0 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) + - foldr mul 1 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) -} diff --git a/code/compiler/11/examples/works5.txt b/code/compiler/11/examples/works5.txt deleted file mode 100644 index 3a8aff5..0000000 --- a/code/compiler/11/examples/works5.txt +++ /dev/null @@ -1,17 +0,0 @@ -data List = { Nil, Cons Int List } - -defn sumZip l m = { - case l of { - Nil -> { 0 } - Cons x xs -> { - case m of { - Nil -> { 0 } - Cons y ys -> { x + y + sumZip xs ys } - } - } - } -} - -defn ones = { Cons 1 ones } - -defn main = { sumZip ones (Cons 1 (Cons 2 (Cons 3 Nil))) } diff --git a/code/compiler/11/graph.cpp b/code/compiler/11/graph.cpp deleted file mode 100644 index c648acd..0000000 --- a/code/compiler/11/graph.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "graph.hpp" - -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/code/compiler/11/graph.hpp b/code/compiler/11/graph.hpp deleted file mode 100644 index 2db8d7c..0000000 --- a/code/compiler/11/graph.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using function = std::string; - -struct group { - std::set members; -}; - -using group_ptr = std::unique_ptr; - -class function_graph { - using group_id = size_t; - - struct group_data { - std::set functions; - std::set adjacency_list; - size_t indegree; - }; - - using data_ptr = std::shared_ptr; - using edge = std::pair; - using group_edge = std::pair; - - std::map> adjacency_lists; - std::set edges; - - std::set compute_transitive_edges(); - void create_groups( - const std::set&, - std::map&, - std::map&); - void create_edges( - std::map&, - std::map&); - std::vector generate_order( - std::map&, - std::map&); - - public: - std::set& add_function(const function& f); - void add_edge(const function& from, const function& to); - std::vector compute_order(); -}; diff --git a/code/compiler/11/instruction.cpp b/code/compiler/11/instruction.cpp deleted file mode 100644 index c2b050a..0000000 --- a/code/compiler/11/instruction.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include "instruction.hpp" -#include "llvm_context.hpp" -#include -#include - -using namespace llvm; - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void instruction_pushint::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushInt(" << value << ")" << std::endl; -} - -void instruction_pushint::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_num(f, ctx.create_i32(value))); -} - -void instruction_pushglobal::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushGlobal(" << name << ")" << std::endl; -} - -void instruction_pushglobal::gen_llvm(llvm_context& ctx, Function* f) const { - auto& global_f = ctx.custom_functions.at("f_" + name); - auto arity = ctx.create_i32(global_f->arity); - ctx.create_push(f, ctx.create_global(f, global_f->function, arity)); -} - -void instruction_push::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Push(" << offset << ")" << std::endl; -} - -void instruction_push::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_peek(f, ctx.create_size(offset))); -} - -void instruction_pop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pop(" << count << ")" << std::endl; -} - -void instruction_pop::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_popn(f, ctx.create_size(count)); -} - -void instruction_mkapp::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "MkApp()" << std::endl; -} - -void instruction_mkapp::gen_llvm(llvm_context& ctx, Function* f) const { - auto left = ctx.create_pop(f); - auto right = ctx.create_pop(f); - ctx.create_push(f, ctx.create_app(f, left, right)); -} - -void instruction_update::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Update(" << offset << ")" << std::endl; -} - -void instruction_update::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_update(f, ctx.create_size(offset)); -} - -void instruction_pack::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pack(" << tag << ", " << size << ")" << std::endl; -} - -void instruction_pack::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_pack(f, ctx.create_size(size), ctx.create_i8(tag)); -} - -void instruction_split::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Split()" << std::endl; -} - -void instruction_split::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_split(f, ctx.create_size(size)); -} - -void instruction_jump::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Jump(" << std::endl; - for(auto& instruction_set : branches) { - for(auto& instruction : instruction_set) { - instruction->print(indent + 2, to); - } - to << std::endl; - } - print_indent(indent, to); - to << ")" << std::endl; -} - -void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const { - auto top_node = ctx.create_peek(f, ctx.create_size(0)); - auto tag = ctx.unwrap_data_tag(top_node); - auto safety_block = BasicBlock::Create(ctx.ctx, "safety", f); - auto switch_op = ctx.builder.CreateSwitch(tag, safety_block, tag_mappings.size()); - std::vector blocks; - - for(auto& branch : branches) { - auto branch_block = BasicBlock::Create(ctx.ctx, "branch", f); - ctx.builder.SetInsertPoint(branch_block); - for(auto& instruction : branch) { - instruction->gen_llvm(ctx, f); - } - ctx.builder.CreateBr(safety_block); - blocks.push_back(branch_block); - } - - for(auto& mapping : tag_mappings) { - switch_op->addCase(ctx.create_i8(mapping.first), blocks[mapping.second]); - } - - ctx.builder.SetInsertPoint(safety_block); -} - -void instruction_slide::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Slide(" << offset << ")" << std::endl; -} - -void instruction_slide::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_slide(f, ctx.create_size(offset)); -} - -void instruction_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BinOp(" << op_action(op) << ")" << std::endl; -} - -void instruction_binop::gen_llvm(llvm_context& ctx, Function* f) const { - auto left_int = ctx.unwrap_num(ctx.create_pop(f)); - auto right_int = ctx.unwrap_num(ctx.create_pop(f)); - llvm::Value* result; - switch(op) { - case PLUS: result = ctx.builder.CreateAdd(left_int, right_int); break; - case MINUS: result = ctx.builder.CreateSub(left_int, right_int); break; - case TIMES: result = ctx.builder.CreateMul(left_int, right_int); break; - case DIVIDE: result = ctx.builder.CreateSDiv(left_int, right_int); break; - } - ctx.create_push(f, ctx.create_num(f, result)); -} - -void instruction_eval::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Eval()" << std::endl; -} - -void instruction_eval::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_unwind(f); -} - -void instruction_alloc::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Alloc(" << amount << ")" << std::endl; -} - -void instruction_alloc::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_alloc(f, ctx.create_size(amount)); -} - -void instruction_unwind::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Unwind()" << std::endl; -} - -void instruction_unwind::gen_llvm(llvm_context& ctx, Function* f) const { - // Nothing -} diff --git a/code/compiler/11/instruction.hpp b/code/compiler/11/instruction.hpp deleted file mode 100644 index abe2409..0000000 --- a/code/compiler/11/instruction.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include "binop.hpp" -#include "llvm_context.hpp" - -struct instruction { - virtual ~instruction() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual void gen_llvm(llvm_context& ctx, llvm::Function* f) const = 0; -}; - -using instruction_ptr = std::unique_ptr; - -struct instruction_pushint : public instruction { - int value; - - instruction_pushint(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pushglobal : public instruction { - std::string name; - - instruction_pushglobal(std::string n) - : name(std::move(n)) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_push : public instruction { - int offset; - - instruction_push(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pop : public instruction { - int count; - - instruction_pop(int c) - : count(c) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_mkapp : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_update : public instruction { - int offset; - - instruction_update(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pack : public instruction { - int tag; - int size; - - instruction_pack(int t, int s) - : tag(t), size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_split : public instruction { - int size; - - instruction_split(int s) - : size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_jump : public instruction { - std::vector> branches; - std::map tag_mappings; - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_slide : public instruction { - int offset; - - instruction_slide(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_binop : public instruction { - binop op; - - instruction_binop(binop o) - : op(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_eval : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_alloc : public instruction { - int amount; - - instruction_alloc(int a) - : amount(a) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_unwind : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; diff --git a/code/compiler/11/llvm_context.cpp b/code/compiler/11/llvm_context.cpp deleted file mode 100644 index 45dcb50..0000000 --- a/code/compiler/11/llvm_context.cpp +++ /dev/null @@ -1,278 +0,0 @@ -#include "llvm_context.hpp" -#include - -using namespace llvm; - -void llvm_context::create_types() { - stack_type = StructType::create(ctx, "stack"); - gmachine_type = StructType::create(ctx, "gmachine"); - stack_ptr_type = PointerType::getUnqual(stack_type); - gmachine_ptr_type = PointerType::getUnqual(gmachine_type); - tag_type = IntegerType::getInt8Ty(ctx); - struct_types["node_base"] = StructType::create(ctx, "node_base"); - struct_types["node_app"] = StructType::create(ctx, "node_app"); - struct_types["node_num"] = StructType::create(ctx, "node_num"); - struct_types["node_global"] = StructType::create(ctx, "node_global"); - struct_types["node_ind"] = StructType::create(ctx, "node_ind"); - struct_types["node_data"] = StructType::create(ctx, "node_data"); - node_ptr_type = PointerType::getUnqual(struct_types.at("node_base")); - function_type = FunctionType::get(Type::getVoidTy(ctx), { gmachine_ptr_type }, false); - - gmachine_type->setBody( - stack_ptr_type, - node_ptr_type, - IntegerType::getInt64Ty(ctx), - IntegerType::getInt64Ty(ctx) - ); - struct_types.at("node_base")->setBody( - IntegerType::getInt32Ty(ctx), - IntegerType::getInt8Ty(ctx), - node_ptr_type - ); - struct_types.at("node_app")->setBody( - struct_types.at("node_base"), - node_ptr_type, - node_ptr_type - ); - struct_types.at("node_num")->setBody( - struct_types.at("node_base"), - IntegerType::getInt32Ty(ctx) - ); - struct_types.at("node_global")->setBody( - struct_types.at("node_base"), - FunctionType::get(Type::getVoidTy(ctx), { stack_ptr_type }, false) - ); - struct_types.at("node_ind")->setBody( - struct_types.at("node_base"), - node_ptr_type - ); - struct_types.at("node_data")->setBody( - struct_types.at("node_base"), - IntegerType::getInt8Ty(ctx), - PointerType::getUnqual(node_ptr_type) - ); -} - -void llvm_context::create_functions() { - auto void_type = Type::getVoidTy(ctx); - auto sizet_type = IntegerType::get(ctx, sizeof(size_t) * 8); - functions["stack_init"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_init", - &module - ); - functions["stack_free"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_free", - &module - ); - functions["stack_push"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_push", - &module - ); - functions["stack_pop"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_pop", - &module - ); - functions["stack_peek"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_peek", - &module - ); - functions["stack_popn"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_popn", - &module - ); - functions["gmachine_slide"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_slide", - &module - ); - functions["gmachine_update"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_update", - &module - ); - functions["gmachine_alloc"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_alloc", - &module - ); - functions["gmachine_pack"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type, tag_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_pack", - &module - ); - functions["gmachine_split"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_split", - &module - ); - functions["gmachine_track"] = Function::Create( - FunctionType::get(node_ptr_type, { gmachine_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_track", - &module - ); - - auto int32_type = IntegerType::getInt32Ty(ctx); - functions["alloc_app"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_app", - &module - ); - functions["alloc_num"] = Function::Create( - FunctionType::get(node_ptr_type, { int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_num", - &module - ); - functions["alloc_global"] = Function::Create( - FunctionType::get(node_ptr_type, { function_type, int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_global", - &module - ); - functions["alloc_ind"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_ind", - &module - ); - - functions["unwind"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "unwind", - &module - ); -} - -ConstantInt* llvm_context::create_i8(int8_t i) { - return ConstantInt::get(ctx, APInt(8, i)); -} -ConstantInt* llvm_context::create_i32(int32_t i) { - return ConstantInt::get(ctx, APInt(32, i)); -} -ConstantInt* llvm_context::create_size(size_t i) { - return ConstantInt::get(ctx, APInt(sizeof(size_t) * 8, i)); -} - -Value* llvm_context::create_pop(Function* f) { - auto pop_f = functions.at("stack_pop"); - return builder.CreateCall(pop_f, { unwrap_gmachine_stack_ptr(f->arg_begin()) }); -} -Value* llvm_context::create_peek(Function* f, Value* off) { - auto peek_f = functions.at("stack_peek"); - return builder.CreateCall(peek_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off }); -} -void llvm_context::create_push(Function* f, Value* v) { - auto push_f = functions.at("stack_push"); - builder.CreateCall(push_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), v }); -} -void llvm_context::create_popn(Function* f, Value* off) { - auto popn_f = functions.at("stack_popn"); - builder.CreateCall(popn_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off }); -} -void llvm_context::create_update(Function* f, Value* off) { - auto update_f = functions.at("gmachine_update"); - builder.CreateCall(update_f, { f->arg_begin(), off }); -} -void llvm_context::create_pack(Function* f, Value* c, Value* t) { - auto pack_f = functions.at("gmachine_pack"); - builder.CreateCall(pack_f, { f->arg_begin(), c, t }); -} -void llvm_context::create_split(Function* f, Value* c) { - auto split_f = functions.at("gmachine_split"); - builder.CreateCall(split_f, { f->arg_begin(), c }); -} -void llvm_context::create_slide(Function* f, Value* off) { - auto slide_f = functions.at("gmachine_slide"); - builder.CreateCall(slide_f, { f->arg_begin(), off }); -} -void llvm_context::create_alloc(Function* f, Value* n) { - auto alloc_f = functions.at("gmachine_alloc"); - builder.CreateCall(alloc_f, { f->arg_begin(), n }); -} -Value* llvm_context::create_track(Function* f, Value* v) { - auto track_f = functions.at("gmachine_track"); - return builder.CreateCall(track_f, { f->arg_begin(), v }); -} - -void llvm_context::create_unwind(Function* f) { - auto unwind_f = functions.at("unwind"); - builder.CreateCall(unwind_f, { f->args().begin() }); -} - -Value* llvm_context::unwrap_gmachine_stack_ptr(Value* g) { - auto offset_0 = create_i32(0); - return builder.CreateGEP(g, { offset_0, offset_0 }); -} - -Value* llvm_context::unwrap_num(Value* v) { - auto num_ptr_type = PointerType::getUnqual(struct_types.at("node_num")); - auto cast = builder.CreatePointerCast(v, num_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto int_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(int_ptr); -} -Value* llvm_context::create_num(Function* f, Value* v) { - auto alloc_num_f = functions.at("alloc_num"); - auto alloc_num_call = builder.CreateCall(alloc_num_f, { v }); - return create_track(f, alloc_num_call); -} - -Value* llvm_context::unwrap_data_tag(Value* v) { - auto data_ptr_type = PointerType::getUnqual(struct_types.at("node_data")); - auto cast = builder.CreatePointerCast(v, data_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto tag_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(tag_ptr); -} - -Value* llvm_context::create_global(Function* f, Value* gf, Value* a) { - auto alloc_global_f = functions.at("alloc_global"); - auto alloc_global_call = builder.CreateCall(alloc_global_f, { gf, a }); - return create_track(f, alloc_global_call); -} - -Value* llvm_context::create_app(Function* f, Value* l, Value* r) { - auto alloc_app_f = functions.at("alloc_app"); - auto alloc_app_call = builder.CreateCall(alloc_app_f, { l, r }); - return create_track(f, alloc_app_call); -} - -llvm::Function* llvm_context::create_custom_function(std::string name, int32_t arity) { - auto void_type = llvm::Type::getVoidTy(ctx); - auto new_function = llvm::Function::Create( - function_type, - llvm::Function::LinkageTypes::ExternalLinkage, - "f_" + name, - &module - ); - auto start_block = llvm::BasicBlock::Create(ctx, "entry", new_function); - - auto new_custom_f = custom_function_ptr(new custom_function()); - new_custom_f->arity = arity; - new_custom_f->function = new_function; - custom_functions["f_" + name] = std::move(new_custom_f); - - return new_function; -} diff --git a/code/compiler/11/llvm_context.hpp b/code/compiler/11/llvm_context.hpp deleted file mode 100644 index fbe4cc1..0000000 --- a/code/compiler/11/llvm_context.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -struct llvm_context { - struct custom_function { - llvm::Function* function; - int32_t arity; - }; - - using custom_function_ptr = std::unique_ptr; - - llvm::LLVMContext ctx; - llvm::IRBuilder<> builder; - llvm::Module module; - - std::map custom_functions; - std::map functions; - std::map struct_types; - - llvm::StructType* stack_type; - llvm::StructType* gmachine_type; - llvm::PointerType* stack_ptr_type; - llvm::PointerType* gmachine_ptr_type; - llvm::PointerType* node_ptr_type; - llvm::IntegerType* tag_type; - llvm::FunctionType* function_type; - - llvm_context() - : builder(ctx), module("bloglang", ctx) { - create_types(); - create_functions(); - } - - void create_types(); - void create_functions(); - - llvm::ConstantInt* create_i8(int8_t); - llvm::ConstantInt* create_i32(int32_t); - llvm::ConstantInt* create_size(size_t); - - llvm::Value* create_pop(llvm::Function*); - llvm::Value* create_peek(llvm::Function*, llvm::Value*); - void create_push(llvm::Function*, llvm::Value*); - void create_popn(llvm::Function*, llvm::Value*); - void create_update(llvm::Function*, llvm::Value*); - void create_pack(llvm::Function*, llvm::Value*, llvm::Value*); - void create_split(llvm::Function*, llvm::Value*); - void create_slide(llvm::Function*, llvm::Value*); - void create_alloc(llvm::Function*, llvm::Value*); - llvm::Value* create_track(llvm::Function*, llvm::Value*); - - void create_unwind(llvm::Function*); - - llvm::Value* unwrap_gmachine_stack_ptr(llvm::Value*); - - llvm::Value* unwrap_num(llvm::Value*); - llvm::Value* create_num(llvm::Function*, llvm::Value*); - - llvm::Value* unwrap_data_tag(llvm::Value*); - - llvm::Value* create_global(llvm::Function*, llvm::Value*, llvm::Value*); - - llvm::Value* create_app(llvm::Function*, llvm::Value*, llvm::Value*); - - llvm::Function* create_custom_function(std::string name, int32_t arity); -}; diff --git a/code/compiler/11/main.cpp b/code/compiler/11/main.cpp deleted file mode 100644 index 45a3e8b..0000000 --- a/code/compiler/11/main.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#include "ast.hpp" -#include -#include "binop.hpp" -#include "definition.hpp" -#include "graph.hpp" -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "parser.hpp" -#include "error.hpp" -#include "type.hpp" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetMachine.h" - -void yy::parser::error(const std::string& msg) { - std::cout << "An error occured: " << msg << std::endl; -} - -extern std::map defs_data; -extern std::map defs_defn; - -void typecheck_program( - const std::map& defs_data, - 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 int_type_app = type_ptr(new type_app(int_type)); - - type_ptr binop_type = type_ptr(new type_arr( - int_type_app, - type_ptr(new type_arr(int_type_app, int_type_app)))); - env->bind("+", binop_type); - env->bind("-", binop_type); - env->bind("*", binop_type); - env->bind("/", binop_type); - - for(auto& def_data : defs_data) { - def_data.second->insert_types(env); - } - for(auto& def_data : defs_data) { - def_data.second->insert_constructors(); - } - - function_graph dependency_graph; - - for(auto& def_defn : defs_defn) { - def_defn.second->find_free(mgr, env); - dependency_graph.add_function(def_defn.second->name); - - for(auto& dependency : def_defn.second->free_variables) { - if(defs_defn.find(dependency) == defs_defn.end()) - throw 0; - dependency_graph.add_edge(def_defn.second->name, dependency); - } - } - - std::vector groups = dependency_graph.compute_order(); - for(auto it = groups.rbegin(); it != groups.rend(); it++) { - auto& group = *it; - for(auto& def_defnn_name : group->members) { - auto& def_defn = defs_defn.find(def_defnn_name)->second; - def_defn->insert_types(mgr); - } - 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); - } - } - - for(auto& pair : env->names) { - std::cout << pair.first << ": "; - pair.second->print(mgr, std::cout); - std::cout << std::endl; - } -} - -void compile_program(const std::map& defs_defn) { - for(auto& def_defn : defs_defn) { - def_defn.second->compile(); - - for(auto& instruction : def_defn.second->instructions) { - instruction->print(0, std::cout); - } - std::cout << std::endl; - } -} - -void gen_llvm_internal_op(llvm_context& ctx, binop op) { - auto new_function = ctx.create_custom_function(op_action(op), 2); - std::vector instructions; - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_binop(op))); - instructions.push_back(instruction_ptr(new instruction_update(2))); - instructions.push_back(instruction_ptr(new instruction_pop(2))); - ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.builder.CreateRetVoid(); -} - -void output_llvm(llvm_context& ctx, const std::string& filename) { - std::string targetTriple = llvm::sys::getDefaultTargetTriple(); - - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmParser(); - llvm::InitializeNativeTargetAsmPrinter(); - - std::string error; - const llvm::Target* target = - llvm::TargetRegistry::lookupTarget(targetTriple, error); - if (!target) { - std::cerr << error << std::endl; - } else { - std::string cpu = "generic"; - std::string features = ""; - llvm::TargetOptions options; - llvm::TargetMachine* targetMachine = - target->createTargetMachine(targetTriple, cpu, features, - options, llvm::Optional()); - - ctx.module.setDataLayout(targetMachine->createDataLayout()); - ctx.module.setTargetTriple(targetTriple); - - std::error_code ec; - llvm::raw_fd_ostream file(filename, ec, llvm::sys::fs::F_None); - if (ec) { - throw 0; - } else { - llvm::CodeGenFileType type = llvm::CGFT_ObjectFile; - llvm::legacy::PassManager pm; - if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) { - throw 0; - } else { - pm.run(ctx.module); - file.close(); - } - } - } -} - -void gen_llvm( - const std::map& defs_data, - const std::map& defs_defn) { - llvm_context ctx; - gen_llvm_internal_op(ctx, PLUS); - gen_llvm_internal_op(ctx, MINUS); - gen_llvm_internal_op(ctx, TIMES); - gen_llvm_internal_op(ctx, DIVIDE); - - for(auto& def_data : defs_data) { - def_data.second->generate_llvm(ctx); - } - for(auto& def_defn : defs_defn) { - def_defn.second->declare_llvm(ctx); - } - for(auto& def_defn : defs_defn) { - def_defn.second->generate_llvm(ctx); - } - - ctx.module.print(llvm::outs(), nullptr); - output_llvm(ctx, "program.o"); -} - -int main() { - yy::parser parser; - type_mgr mgr; - type_env_ptr env(new type_env); - - parser.parse(); - for(auto& def_defn : defs_defn) { - std::cout << def_defn.second->name; - for(auto& param : def_defn.second->params) std::cout << " " << param; - std::cout << ":" << std::endl; - - def_defn.second->body->print(1, std::cout); - } - try { - typecheck_program(defs_data, defs_defn, mgr, env); - compile_program(defs_defn); - gen_llvm(defs_data, defs_defn); - } catch(unification_error& err) { - std::cout << "failed to unify types: " << std::endl; - std::cout << " (1) \033[34m"; - err.left->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - std::cout << " (2) \033[32m"; - err.right->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - } catch(type_error& err) { - std::cout << "failed to type check program: " << err.description << std::endl; - } -} diff --git a/code/compiler/11/parsed_type.cpp b/code/compiler/11/parsed_type.cpp deleted file mode 100644 index c69e50a..0000000 --- a/code/compiler/11/parsed_type.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#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; - if(base_type->arity != arguments.size()) 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 deleted file mode 100644 index 96c0fcc..0000000 --- a/code/compiler/11/parsed_type.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#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/parser.y b/code/compiler/11/parser.y deleted file mode 100644 index 686e79e..0000000 --- a/code/compiler/11/parser.y +++ /dev/null @@ -1,163 +0,0 @@ -%{ -#include -#include -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" -#include "parsed_type.hpp" - -std::map defs_data; -std::map defs_defn; - -extern yy::parser::symbol_type yylex(); - -%} - -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%type > lowercaseParams -%type > branches -%type > constructors -%type > typeList -%type type nonArrowType typeListElement -%type aAdd aMul case app appBase -%type data -%type defn -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { } - ; - -definitions - : definitions definition { } - | definition { } - ; - -definition - : defn { auto name = $1->name; defs_defn[name] = std::move($1); } - | data { auto name = $1->name; defs_data[name] = std::move($1); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_defn_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6))); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } - ; - -branches - : branches branch { $$ = std::move($1); $$.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } - ; - -data - : DATA UID lowercaseParams EQUAL OCURLY constructors CCURLY - { $$ = definition_data_ptr(new definition_data(std::move($2), std::move($3), std::move($6))); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID typeList - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - -type - : nonArrowType ARROW type { $$ = parsed_type_ptr(new parsed_type_arr(std::move($1), std::move($3))); } - | nonArrowType { $$ = std::move($1); } - ; - -nonArrowType - : UID typeList { $$ = parsed_type_ptr(new parsed_type_app(std::move($1), std::move($2))); } - | LID { $$ = parsed_type_ptr(new parsed_type_var(std::move($1))); } - | OPAREN type CPAREN { $$ = std::move($2); } - ; - -typeListElement - : OPAREN type CPAREN { $$ = std::move($2); } - | UID { $$ = parsed_type_ptr(new parsed_type_app(std::move($1), {})); } - | LID { $$ = parsed_type_ptr(new parsed_type_var(std::move($1))); } - ; - -typeList - : %empty { $$ = std::vector(); } - | typeList typeListElement { $$ = std::move($1); $$.push_back(std::move($2)); } - ; diff --git a/code/compiler/11/runtime.c b/code/compiler/11/runtime.c deleted file mode 100644 index 7b8a7c3..0000000 --- a/code/compiler/11/runtime.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include -#include -#include -#include "runtime.h" - -struct node_base* alloc_node() { - struct node_base* new_node = malloc(sizeof(struct node_app)); - new_node->gc_next = NULL; - new_node->gc_reachable = 0; - assert(new_node != NULL); - return new_node; -} - -struct node_app* alloc_app(struct node_base* l, struct node_base* r) { - struct node_app* node = (struct node_app*) alloc_node(); - node->base.tag = NODE_APP; - node->left = l; - node->right = r; - return node; -} - -struct node_num* alloc_num(int32_t n) { - struct node_num* node = (struct node_num*) alloc_node(); - node->base.tag = NODE_NUM; - node->value = n; - return node; -} - -struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a) { - struct node_global* node = (struct node_global*) alloc_node(); - node->base.tag = NODE_GLOBAL; - node->arity = a; - node->function = f; - return node; -} - -struct node_ind* alloc_ind(struct node_base* n) { - struct node_ind* node = (struct node_ind*) alloc_node(); - node->base.tag = NODE_IND; - node->next = n; - return node; -} - -void free_node_direct(struct node_base* n) { - if(n->tag == NODE_DATA) { - free(((struct node_data*) n)->array); - } -} - -void gc_visit_node(struct node_base* n) { - if(n->gc_reachable) return; - n->gc_reachable = 1; - - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - gc_visit_node(app->left); - gc_visit_node(app->right); - } if(n->tag == NODE_IND) { - struct node_ind* ind = (struct node_ind*) n; - gc_visit_node(ind->next); - } if(n->tag == NODE_DATA) { - struct node_data* data = (struct node_data*) n; - struct node_base** to_visit = data->array; - while(*to_visit) { - gc_visit_node(*to_visit); - to_visit++; - } - } -} - -void stack_init(struct stack* s) { - s->size = 4; - s->count = 0; - s->data = malloc(sizeof(*s->data) * s->size); - assert(s->data != NULL); -} - -void stack_free(struct stack* s) { - free(s->data); -} - -void stack_push(struct stack* s, struct node_base* n) { - while(s->count >= s->size) { - s->data = realloc(s->data, sizeof(*s->data) * (s->size *= 2)); - assert(s->data != NULL); - } - s->data[s->count++] = n; -} - -struct node_base* stack_pop(struct stack* s) { - assert(s->count > 0); - return s->data[--s->count]; -} - -struct node_base* stack_peek(struct stack* s, size_t o) { - assert(s->count > o); - return s->data[s->count - o - 1]; -} - -void stack_popn(struct stack* s, size_t n) { - assert(s->count >= n); - s->count -= n; -} - -void gmachine_init(struct gmachine* g) { - stack_init(&g->stack); - g->gc_nodes = NULL; - g->gc_node_count = 0; - g->gc_node_threshold = 128; -} - -void gmachine_free(struct gmachine* g) { - stack_free(&g->stack); - struct node_base* to_free = g->gc_nodes; - struct node_base* next; - - while(to_free) { - next = to_free->gc_next; - free_node_direct(to_free); - free(to_free); - to_free = next; - } -} - -void gmachine_slide(struct gmachine* g, size_t n) { - assert(g->stack.count > n); - g->stack.data[g->stack.count - n - 1] = g->stack.data[g->stack.count - 1]; - g->stack.count -= n; -} - -void gmachine_update(struct gmachine* g, size_t o) { - assert(g->stack.count > o + 1); - struct node_ind* ind = - (struct node_ind*) g->stack.data[g->stack.count - o - 2]; - ind->base.tag = NODE_IND; - ind->next = g->stack.data[g->stack.count -= 1]; -} - -void gmachine_alloc(struct gmachine* g, size_t o) { - while(o--) { - stack_push(&g->stack, - gmachine_track(g, (struct node_base*) alloc_ind(NULL))); - } -} - -void gmachine_pack(struct gmachine* g, size_t n, int8_t t) { - assert(g->stack.count >= n); - - struct node_base** data = malloc(sizeof(*data) * (n + 1)); - assert(data != NULL); - memcpy(data, &g->stack.data[g->stack.count - n], n * sizeof(*data)); - data[n] = NULL; - - struct node_data* new_node = (struct node_data*) alloc_node(); - new_node->array = data; - new_node->base.tag = NODE_DATA; - new_node->tag = t; - - stack_popn(&g->stack, n); - stack_push(&g->stack, gmachine_track(g, (struct node_base*) new_node)); -} - -void gmachine_split(struct gmachine* g, size_t n) { - struct node_data* node = (struct node_data*) stack_pop(&g->stack); - for(size_t i = 0; i < n; i++) { - stack_push(&g->stack, node->array[i]); - } -} - -struct node_base* gmachine_track(struct gmachine* g, struct node_base* b) { - g->gc_node_count++; - b->gc_next = g->gc_nodes; - g->gc_nodes = b; - - if(g->gc_node_count >= g->gc_node_threshold) { - uint64_t nodes_before = g->gc_node_count; - gc_visit_node(b); - gmachine_gc(g); - g->gc_node_threshold = g->gc_node_count * 2; - } - - return b; -} - -void gmachine_gc(struct gmachine* g) { - for(size_t i = 0; i < g->stack.count; i++) { - gc_visit_node(g->stack.data[i]); - } - - struct node_base** head_ptr = &g->gc_nodes; - while(*head_ptr) { - if((*head_ptr)->gc_reachable) { - (*head_ptr)->gc_reachable = 0; - head_ptr = &(*head_ptr)->gc_next; - } else { - struct node_base* to_free = *head_ptr; - *head_ptr = to_free->gc_next; - free_node_direct(to_free); - free(to_free); - g->gc_node_count--; - } - } -} - -void unwind(struct gmachine* g) { - struct stack* s = &g->stack; - - while(1) { - struct node_base* peek = stack_peek(s, 0); - if(peek->tag == NODE_APP) { - struct node_app* n = (struct node_app*) peek; - stack_push(s, n->left); - } else if(peek->tag == NODE_GLOBAL) { - struct node_global* n = (struct node_global*) peek; - assert(s->count > n->arity); - - for(size_t i = 1; i <= n->arity; i++) { - s->data[s->count - i] - = ((struct node_app*) s->data[s->count - i - 1])->right; - } - - n->function(g); - } else if(peek->tag == NODE_IND) { - struct node_ind* n = (struct node_ind*) peek; - stack_pop(s); - stack_push(s, n->next); - } else { - break; - } - } -} - -extern void f_main(struct gmachine* s); - -void print_node(struct node_base* n) { - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - print_node(app->left); - putchar(' '); - print_node(app->right); - } else if(n->tag == NODE_DATA) { - printf("(Packed)"); - } else if(n->tag == NODE_GLOBAL) { - struct node_global* global = (struct node_global*) n; - printf("(Global: %p)", global->function); - } else if(n->tag == NODE_IND) { - print_node(((struct node_ind*) n)->next); - } else if(n->tag == NODE_NUM) { - struct node_num* num = (struct node_num*) n; - printf("%d", num->value); - } -} - -int main(int argc, char** argv) { - struct gmachine gmachine; - struct node_global* first_node = alloc_global(f_main, 0); - struct node_base* result; - - gmachine_init(&gmachine); - gmachine_track(&gmachine, (struct node_base*) first_node); - stack_push(&gmachine.stack, (struct node_base*) first_node); - unwind(&gmachine); - result = stack_pop(&gmachine.stack); - printf("Result: "); - print_node(result); - putchar('\n'); - gmachine_free(&gmachine); -} diff --git a/code/compiler/11/runtime.h b/code/compiler/11/runtime.h deleted file mode 100644 index 030a27c..0000000 --- a/code/compiler/11/runtime.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include - -struct gmachine; - -enum node_tag { - NODE_APP, - NODE_NUM, - NODE_GLOBAL, - NODE_IND, - NODE_DATA -}; - -struct node_base { - enum node_tag tag; - int8_t gc_reachable; - struct node_base* gc_next; -}; - -struct node_app { - struct node_base base; - struct node_base* left; - struct node_base* right; -}; - -struct node_num { - struct node_base base; - int32_t value; -}; - -struct node_global { - struct node_base base; - int32_t arity; - void (*function)(struct gmachine*); -}; - -struct node_ind { - struct node_base base; - struct node_base* next; -}; - -struct node_data { - struct node_base base; - int8_t tag; - struct node_base** array; -}; - -struct node_base* alloc_node(); -struct node_app* alloc_app(struct node_base* l, struct node_base* r); -struct node_num* alloc_num(int32_t n); -struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a); -struct node_ind* alloc_ind(struct node_base* n); -void free_node_direct(struct node_base*); -void gc_visit_node(struct node_base*); - -struct stack { - size_t size; - size_t count; - struct node_base** data; -}; - -void stack_init(struct stack* s); -void stack_free(struct stack* s); -void stack_push(struct stack* s, struct node_base* n); -struct node_base* stack_pop(struct stack* s); -struct node_base* stack_peek(struct stack* s, size_t o); -void stack_popn(struct stack* s, size_t n); - -struct gmachine { - struct stack stack; - struct node_base* gc_nodes; - int64_t gc_node_count; - int64_t gc_node_threshold; -}; - -void gmachine_init(struct gmachine* g); -void gmachine_free(struct gmachine* g); -void gmachine_slide(struct gmachine* g, size_t n); -void gmachine_update(struct gmachine* g, size_t o); -void gmachine_alloc(struct gmachine* g, size_t o); -void gmachine_pack(struct gmachine* g, size_t n, int8_t t); -void gmachine_split(struct gmachine* g, size_t n); -struct node_base* gmachine_track(struct gmachine* g, struct node_base* b); -void gmachine_gc(struct gmachine* g); diff --git a/code/compiler/11/scanner.l b/code/compiler/11/scanner.l deleted file mode 100644 index c8a4429..0000000 --- a/code/compiler/11/scanner.l +++ /dev/null @@ -1,35 +0,0 @@ -%option noyywrap - -%{ -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" - -#define YY_DECL yy::parser::symbol_type yylex() - -%} - -%% - -[ \n]+ {} -\+ { return yy::parser::make_PLUS(); } -\* { return yy::parser::make_TIMES(); } -- { return yy::parser::make_MINUS(); } -\/ { return yy::parser::make_DIVIDE(); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } -defn { return yy::parser::make_DEFN(); } -data { return yy::parser::make_DATA(); } -case { return yy::parser::make_CASE(); } -of { return yy::parser::make_OF(); } -\{ { return yy::parser::make_OCURLY(); } -\} { return yy::parser::make_CCURLY(); } -\( { return yy::parser::make_OPAREN(); } -\) { return yy::parser::make_CPAREN(); } -, { return yy::parser::make_COMMA(); } --> { return yy::parser::make_ARROW(); } -= { return yy::parser::make_EQUAL(); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } - -%% diff --git a/code/compiler/11/test.cpp b/code/compiler/11/test.cpp deleted file mode 100644 index 7972fa3..0000000 --- a/code/compiler/11/test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "graph.hpp" - -int main() { - function_graph graph; - graph.add_edge("f", "g"); - graph.add_edge("g", "h"); - graph.add_edge("h", "f"); - - graph.add_edge("i", "j"); - graph.add_edge("j", "i"); - - graph.add_edge("j", "f"); - - graph.add_edge("x", "f"); - graph.add_edge("x", "i"); - - for(auto& group : graph.compute_order()) { - std::cout << "Group: " << std::endl; - for(auto& member : group->members) { - std::cout << member << std::endl; - } - } -} diff --git a/code/compiler/11/type.cpp b/code/compiler/11/type.cpp deleted file mode 100644 index 05e85c6..0000000 --- a/code/compiler/11/type.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include "type.hpp" -#include -#include -#include -#include -#include "error.hpp" - -void type_scheme::print(const type_mgr& mgr, std::ostream& to) const { - if(forall.size() != 0) { - to << "forall "; - for(auto& var : forall) { - to << var << " "; - } - to << ". "; - } - monotype->print(mgr, to); -} - -type_ptr type_scheme::instantiate(type_mgr& mgr) const { - if(forall.size() == 0) return monotype; - std::map subst; - for(auto& var : forall) { - subst[var] = mgr.new_type(); - } - return mgr.substitute(subst, monotype); -} - -void type_var::print(const type_mgr& mgr, std::ostream& to) const { - auto it = mgr.types.find(name); - if(it != mgr.types.end()) { - it->second->print(mgr, to); - } else { - to << name; - } -} - -void type_base::print(const type_mgr& mgr, std::ostream& to) const { - to << name; -} - -void type_arr::print(const type_mgr& mgr, std::ostream& to) const { - left->print(mgr, to); - to << " -> ("; - right->print(mgr, 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() { - int temp = last_id++; - std::string str = ""; - - while(temp != -1) { - str += (char) ('a' + (temp % 26)); - temp = temp / 26 - 1; - } - - std::reverse(str.begin(), str.end()); - return str; -} - -type_ptr type_mgr::new_type() { - return type_ptr(new type_var(new_type_name())); -} - -type_ptr type_mgr::new_arrow_type() { - return type_ptr(new type_arr(new_type(), new_type())); -} - -type_ptr type_mgr::resolve(type_ptr t, type_var*& var) const { - type_var* cast; - - var = nullptr; - while((cast = dynamic_cast(t.get()))) { - auto it = types.find(cast->name); - - if(it == types.end()) { - var = cast; - break; - } - t = it->second; - } - - return t; -} - -void type_mgr::unify(type_ptr l, type_ptr r) { - type_var *lvar, *rvar; - type_arr *larr, *rarr; - type_base *lid, *rid; - type_app *lapp, *rapp; - - l = resolve(l, lvar); - r = resolve(r, rvar); - - if(lvar) { - bind(lvar->name, r); - return; - } else if(rvar) { - bind(rvar->name, l); - return; - } else if((larr = dynamic_cast(l.get())) && - (rarr = dynamic_cast(r.get()))) { - unify(larr->left, rarr->left); - unify(larr->right, rarr->right); - return; - } else if((lid = dynamic_cast(l.get())) && - (rid = dynamic_cast(r.get()))) { - if(lid->name == rid->name && lid->arity == rid->arity) 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); -} - -type_ptr type_mgr::substitute(const std::map& subst, const type_ptr& t) const { - type_ptr temp = t; - while(type_var* var = dynamic_cast(temp.get())) { - auto subst_it = subst.find(var->name); - if(subst_it != subst.end()) return subst_it->second; - auto var_it = types.find(var->name); - if(var_it == types.end()) return t; - temp = var_it->second; - } - - if(type_arr* arr = dynamic_cast(temp.get())) { - auto left_result = substitute(subst, arr->left); - auto right_result = substitute(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(temp.get())) { - auto constructor_result = substitute(subst, app->constructor); - bool arg_changed = false; - std::vector new_args; - for(auto& arg : app->arguments) { - auto arg_result = substitute(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; -} - -void type_mgr::bind(const std::string& s, type_ptr t) { - type_var* other = dynamic_cast(t.get()); - - if(other && other->name == s) return; - types[s] = t; -} - -void type_mgr::find_free(const type_ptr& t, std::set& into) const { - type_var* var; - type_ptr resolved = resolve(t, var); - - if(var) { - into.insert(var->name); - } 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 deleted file mode 100644 index 4583f45..0000000 --- a/code/compiler/11/type.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -struct type_mgr; - -struct type { - virtual ~type() = default; - - virtual void print(const type_mgr& mgr, std::ostream& to) const = 0; -}; - -using type_ptr = std::shared_ptr; - -struct type_scheme { - std::vector forall; - type_ptr monotype; - - type_scheme(type_ptr type) : forall(), monotype(std::move(type)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; - type_ptr instantiate(type_mgr& mgr) const; -}; - -using type_scheme_ptr = std::shared_ptr; - -struct type_var : public type { - std::string name; - - type_var(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_base : public type { - std::string name; - int32_t arity; - - 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; -}; - -struct type_data : public type_base { - struct constructor { - int tag; - }; - - std::map constructors; - - type_data(std::string n, int32_t a = 0) - : type_base(std::move(n), a) {} -}; - -struct type_arr : public type { - type_ptr left; - type_ptr right; - - type_arr(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - 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; - - std::string new_type_name(); - type_ptr new_type(); - type_ptr new_arrow_type(); - - void unify(type_ptr l, type_ptr r); - type_ptr substitute( - const std::map& subst, - const type_ptr& t) const; - type_ptr resolve(type_ptr t, type_var*& var) const; - void bind(const std::string& s, type_ptr t); - void find_free(const type_ptr& t, std::set& into) const; -}; diff --git a/code/compiler/11/type_env.cpp b/code/compiler/11/type_env.cpp deleted file mode 100644 index 3e654be..0000000 --- a/code/compiler/11/type_env.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "type_env.hpp" -#include "type.hpp" - -type_scheme_ptr type_env::lookup(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second; - if(parent) return parent->lookup(name); - 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)); -} - -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; - if(names_it->second->forall.size() > 0) throw 0; - - std::set free_variables; - mgr.find_free(names_it->second->monotype, free_variables); - for(auto& free : free_variables) { - names_it->second->forall.push_back(free); - } -} - -type_env_ptr type_scope(type_env_ptr parent) { - return type_env_ptr(new type_env(std::move(parent))); -} diff --git a/code/compiler/11/type_env.hpp b/code/compiler/11/type_env.hpp deleted file mode 100644 index ca91ef7..0000000 --- a/code/compiler/11/type_env.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include -#include "type.hpp" - -struct type_env; -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); -}; - - -type_env_ptr type_scope(type_env_ptr parent); diff --git a/code/compiler/12/CMakeLists.txt b/code/compiler/12/CMakeLists.txt deleted file mode 100644 index 8a3f3c1..0000000 --- a/code/compiler/12/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(compiler) - -# Find all the required packages -find_package(BISON) -find_package(FLEX) -find_package(LLVM REQUIRED CONFIG) - -# Set up the flex and bison targets -bison_target(parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser.y - ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp - COMPILE_FLAGS "-d") -flex_target(scanner - ${CMAKE_CURRENT_SOURCE_DIR}/scanner.l - ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp) -add_flex_bison_dependency(scanner parser) - -# Find all the relevant LLVM components -llvm_map_components_to_libnames(LLVM_LIBS core x86asmparser x86codegen) - -# Create compiler executable -add_executable(compiler - 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 - type.cpp type.hpp - error.cpp error.hpp - binop.cpp binop.hpp - instruction.cpp instruction.hpp - graph.cpp graph.hpp - global_scope.cpp global_scope.hpp - ${BISON_parser_OUTPUTS} - ${FLEX_scanner_OUTPUTS} - main.cpp -) - -# Configure compiler executable -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) -target_include_directories(compiler PUBLIC ${LLVM_INCLUDE_DIRS}) -target_compile_definitions(compiler PUBLIC ${LLVM_DEFINITIONS}) -target_link_libraries(compiler ${LLVM_LIBS}) diff --git a/code/compiler/12/ast.cpp b/code/compiler/12/ast.cpp deleted file mode 100644 index 0beec14..0000000 --- a/code/compiler/12/ast.cpp +++ /dev/null @@ -1,437 +0,0 @@ -#include "ast.hpp" -#include -#include "binop.hpp" -#include "error.hpp" -#include "type_env.hpp" -#include "env.hpp" - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void ast_int::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "INT: " << value << std::endl; -} - -void ast_int::find_free(std::set& into) { - -} - -type_ptr ast_int::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - return type_ptr(new type_app(env->lookup_type("Int"))); -} - -void ast_int::translate(global_scope& scope) { - -} - -void ast_int::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushint(value))); -} - -void ast_lid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LID: " << id << std::endl; -} - -void ast_lid::find_free(std::set& into) { - into.insert(id); -} - -type_ptr ast_lid::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - return env->lookup(id)->instantiate(mgr); -} - -void ast_lid::translate(global_scope& scope) { - -} - -void ast_lid::compile(const env_ptr& env, std::vector& into) const { - auto mangled_name = this->env->get_mangled_name(id); - into.push_back(instruction_ptr( - (env->has_variable(mangled_name) && !this->env->is_global(id)) ? - (instruction*) new instruction_push(env->get_offset(mangled_name)) : - (instruction*) new instruction_pushglobal(mangled_name))); -} - -void ast_uid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "UID: " << id << std::endl; -} - -void ast_uid::find_free(std::set& into) { - -} - -type_ptr ast_uid::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - return env->lookup(id)->instantiate(mgr); -} - -void ast_uid::translate(global_scope& scope) { - -} - -void ast_uid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr( - new instruction_pushglobal(this->env->get_mangled_name(id)))); -} - -void ast_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BINOP: " << op_name(op) << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -void ast_binop::find_free(std::set& into) { - left->find_free(into); - right->find_free(into); -} - -type_ptr ast_binop::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - type_ptr ltype = left->typecheck(mgr, env); - type_ptr rtype = right->typecheck(mgr, env); - type_ptr ftype = env->lookup(op_name(op))->instantiate(mgr); - if(!ftype) throw type_error(std::string("unknown binary operator ") + op_name(op)); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow_one = type_ptr(new type_arr(rtype, return_type)); - type_ptr arrow_two = type_ptr(new type_arr(ltype, arrow_one)); - - mgr.unify(arrow_two, ftype); - return return_type; -} - -void ast_binop::translate(global_scope& scope) { - left->translate(scope); - right->translate(scope); -} - -void ast_binop::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - - into.push_back(instruction_ptr(new instruction_pushglobal(op_action(op)))); - into.push_back(instruction_ptr(new instruction_mkapp())); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_app::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "APP:" << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -void ast_app::find_free(std::set& into) { - left->find_free(into); - right->find_free(into); -} - -type_ptr ast_app::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - type_ptr ltype = left->typecheck(mgr, env); - type_ptr rtype = right->typecheck(mgr, env); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); - mgr.unify(arrow, ltype); - return return_type; -} - -void ast_app::translate(global_scope& scope) { - left->translate(scope); - right->translate(scope); -} - -void ast_app::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_case::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "CASE: " << std::endl; - for(auto& branch : branches) { - print_indent(indent + 1, to); - branch->pat->print(to); - to << std::endl; - branch->expr->print(indent + 2, to); - } -} - -void ast_case::find_free(std::set& into) { - of->find_free(into); - for(auto& branch : branches) { - std::set free_in_branch; - std::set pattern_variables; - branch->pat->find_variables(pattern_variables); - branch->expr->find_free(free_in_branch); - for(auto& free : free_in_branch) { - if(pattern_variables.find(free) == pattern_variables.end()) - into.insert(free); - } - } -} - -type_ptr ast_case::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - type_var* var; - type_ptr case_type = mgr.resolve(of->typecheck(mgr, env), var); - type_ptr branch_type = mgr.new_type(); - - for(auto& branch : branches) { - type_env_ptr new_env = type_scope(env); - branch->pat->typecheck(case_type, mgr, new_env); - type_ptr curr_branch_type = branch->expr->typecheck(mgr, new_env); - mgr.unify(branch_type, curr_branch_type); - } - - input_type = mgr.resolve(case_type, var); - type_app* app_type; - if(!(app_type = dynamic_cast(input_type.get())) || - !dynamic_cast(app_type->constructor.get())) { - throw type_error("attempting case analysis of non-data type"); - } - - return branch_type; -} - -void ast_case::translate(global_scope& scope) { - of->translate(scope); - for(auto& branch : branches) { - branch->expr->translate(scope); - } -} - -void ast_case::compile(const env_ptr& env, std::vector& into) const { - type_app* app_type = dynamic_cast(input_type.get()); - type_data* type = dynamic_cast(app_type->constructor.get()); - - of->compile(env, into); - into.push_back(instruction_ptr(new instruction_eval())); - - instruction_jump* jump_instruction = new instruction_jump(); - into.push_back(instruction_ptr(jump_instruction)); - for(auto& branch : branches) { - std::vector branch_instructions; - pattern_var* vpat; - pattern_constr* cpat; - - if((vpat = dynamic_cast(branch->pat.get()))) { - branch->expr->compile(env_ptr(new env_offset(1, env)), branch_instructions); - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) != - jump_instruction->tag_mappings.end()) - break; - - jump_instruction->tag_mappings[constr_pair.second.tag] = - jump_instruction->branches.size(); - } - jump_instruction->branches.push_back(std::move(branch_instructions)); - } else if((cpat = dynamic_cast(branch->pat.get()))) { - env_ptr new_env = env; - for(auto it = cpat->params.rbegin(); it != cpat->params.rend(); it++) { - new_env = env_ptr(new env_var(branch->expr->env->get_mangled_name(*it), new_env)); - } - - branch_instructions.push_back(instruction_ptr(new instruction_split( - cpat->params.size()))); - branch->expr->compile(new_env, branch_instructions); - branch_instructions.push_back(instruction_ptr(new instruction_slide( - cpat->params.size()))); - - int new_tag = type->constructors[cpat->constr].tag; - if(jump_instruction->tag_mappings.find(new_tag) != - jump_instruction->tag_mappings.end()) - throw type_error("technically not a type error: duplicate pattern"); - - jump_instruction->tag_mappings[new_tag] = - jump_instruction->branches.size(); - jump_instruction->branches.push_back(std::move(branch_instructions)); - } - } - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) == - jump_instruction->tag_mappings.end()) - throw type_error("non-total pattern"); - } -} - -void ast_let::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LET: " << std::endl; - in->print(indent + 1, to); -} - -void ast_let::find_free(std::set& into) { - definitions.find_free(into); - std::set all_free; - in->find_free(all_free); - for(auto& free_var : all_free) { - if(definitions.defs_defn.find(free_var) == definitions.defs_defn.end()) - into.insert(free_var); - } -} - -type_ptr ast_let::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - definitions.typecheck(mgr, env); - return in->typecheck(mgr, definitions.env); -} - -void ast_let::translate(global_scope& scope) { - for(auto& def : definitions.defs_data) { - def.second->into_globals(scope); - } - for(auto& def : definitions.defs_defn) { - size_t original_params = def.second->params.size(); - std::string original_name = def.second->name; - auto& global_definition = def.second->into_global(scope); - size_t captured = global_definition.params.size() - original_params; - - type_env_ptr mangled_env = type_scope(env); - mangled_env->bind(def.first, env->lookup(def.first), visibility::global); - mangled_env->set_mangled_name(def.first, global_definition.name); - - ast_ptr global_app(new ast_lid(original_name)); - global_app->env = mangled_env; - for(auto& param : global_definition.params) { - if(!(captured--)) break; - ast_ptr new_arg(new ast_lid(param)); - new_arg->env = env; - global_app = ast_ptr(new ast_app(std::move(global_app), std::move(new_arg))); - global_app->env = env; - } - translated_definitions.push_back({ def.first, std::move(global_app) }); - } - in->translate(scope); -} - -void ast_let::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_alloc(translated_definitions.size()))); - env_ptr new_env = env; - for(auto& def : translated_definitions) { - new_env = env_ptr(new env_var(definitions.env->get_mangled_name(def.first), std::move(new_env))); - } - int offset = translated_definitions.size() - 1; - for(auto& def : translated_definitions) { - def.second->compile(new_env, into); - into.push_back(instruction_ptr(new instruction_update(offset--))); - } - in->compile(new_env, into); - into.push_back(instruction_ptr(new instruction_slide(translated_definitions.size()))); -} - -void ast_lambda::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LAMBDA"; - for(auto& param : params) { - to << " " << param; - } - to << std::endl; - body->print(indent+1, to); -} - -void ast_lambda::find_free(std::set& into) { - body->find_free(free_variables); - for(auto& param : params) { - free_variables.erase(param); - } - into.insert(free_variables.begin(), free_variables.end()); -} - -type_ptr ast_lambda::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - var_env = type_scope(env); - type_ptr return_type = mgr.new_type(); - type_ptr full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - var_env->bind(*it, param_type); - full_type = type_ptr(new type_arr(std::move(param_type), full_type)); - } - - mgr.unify(return_type, body->typecheck(mgr, var_env)); - return full_type; -} - -void ast_lambda::translate(global_scope& scope) { - std::vector function_params; - for(auto& free_variable : free_variables) { - if(env->is_global(free_variable)) continue; - function_params.push_back(free_variable); - } - size_t captured_count = function_params.size(); - function_params.insert(function_params.end(), params.begin(), params.end()); - - auto& new_function = scope.add_function("lambda", std::move(function_params), std::move(body)); - type_env_ptr mangled_env = type_scope(env); - mangled_env->bind("lambda", type_scheme_ptr(nullptr), visibility::global); - mangled_env->set_mangled_name("lambda", new_function.name); - ast_ptr new_application = ast_ptr(new ast_lid("lambda")); - new_application->env = mangled_env; - - for(auto& param : new_function.params) { - if(!(captured_count--)) break; - ast_ptr new_arg = ast_ptr(new ast_lid(param)); - new_arg->env = env; - new_application = ast_ptr(new ast_app(std::move(new_application), std::move(new_arg))); - new_application->env = env; - } - translated = std::move(new_application); -} - -void ast_lambda::compile(const env_ptr& env, std::vector& into) const { - translated->compile(env, into); -} - -void pattern_var::print(std::ostream& to) const { - to << var; -} - -void pattern_var::find_variables(std::set& into) const { - into.insert(var); -} - -void pattern_var::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { - env->bind(var, t); -} - -void pattern_constr::print(std::ostream& to) const { - to << constr; - for(auto& param : params) { - to << " " << param; - } -} - -void pattern_constr::find_variables(std::set& into) const { - into.insert(params.begin(), params.end()); -} - -void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { - type_scheme_ptr constructor_type_scheme = env->lookup(constr); - if(!constructor_type_scheme) { - throw type_error(std::string("pattern using unknown constructor ") + constr); - } - type_ptr constructor_type = constructor_type_scheme->instantiate(mgr); - - for(auto& param : params) { - type_arr* arr = dynamic_cast(constructor_type.get()); - if(!arr) throw type_error("too many parameters in constructor pattern"); - - env->bind(param, arr->left); - constructor_type = arr->right; - } - - mgr.unify(t, constructor_type); -} diff --git a/code/compiler/12/ast.hpp b/code/compiler/12/ast.hpp deleted file mode 100644 index 1e2f8b5..0000000 --- a/code/compiler/12/ast.hpp +++ /dev/null @@ -1,189 +0,0 @@ -#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 "global_scope.hpp" - -struct ast { - type_env_ptr env; - - 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 { - 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) - : 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) - : 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) - : 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) - : 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) - : 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) - : 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) - : 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) - : 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) - : 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) - : 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; -}; diff --git a/code/compiler/12/binop.cpp b/code/compiler/12/binop.cpp deleted file mode 100644 index 3a5f0ca..0000000 --- a/code/compiler/12/binop.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "binop.hpp" - -std::string op_name(binop op) { - switch(op) { - case PLUS: return "+"; - case MINUS: return "-"; - case TIMES: return "*"; - case DIVIDE: return "/"; - } - return "??"; -} - -std::string op_action(binop op) { - switch(op) { - case PLUS: return "plus"; - case MINUS: return "minus"; - case TIMES: return "times"; - case DIVIDE: return "divide"; - } - return "??"; -} diff --git a/code/compiler/12/binop.hpp b/code/compiler/12/binop.hpp deleted file mode 100644 index 8d07858..0000000 --- a/code/compiler/12/binop.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -std::string op_name(binop op); -std::string op_action(binop op); diff --git a/code/compiler/12/definition.cpp b/code/compiler/12/definition.cpp deleted file mode 100644 index c6e69ae..0000000 --- a/code/compiler/12/definition.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "definition.hpp" -#include "error.hpp" -#include "ast.hpp" -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "type.hpp" -#include "type_env.hpp" -#include "graph.hpp" -#include -#include -#include - -void definition_defn::find_free() { - body->find_free(free_variables); - for(auto& param : params) { - free_variables.erase(param); - } -} - -void definition_defn::insert_types(type_mgr& mgr, type_env_ptr& env, visibility v) { - this->env = env; - var_env = type_scope(env); - return_type = mgr.new_type(); - full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - full_type = type_ptr(new type_arr(param_type, full_type)); - var_env->bind(*it, param_type); - } - env->bind(name, full_type, v); -} - -void definition_defn::typecheck(type_mgr& mgr) { - type_ptr body_type = body->typecheck(mgr, var_env); - mgr.unify(return_type, body_type); -} - - -global_function& definition_defn::into_global(global_scope& scope) { - std::vector all_params; - for(auto& free : free_variables) { - if(env->is_global(free)) continue; - all_params.push_back(free); - } - all_params.insert(all_params.end(), params.begin(), params.end()); - body->translate(scope); - return scope.add_function(name, std::move(all_params), std::move(body)); -} - -void definition_data::insert_types(type_env_ptr& env) { - this->env = env; - env->bind_type(name, type_ptr(new type_data(name, vars.size()))); -} - -void definition_data::insert_constructors() const { - type_ptr this_type_ptr = env->lookup_type(name); - type_data* this_type = static_cast(this_type_ptr.get()); - int next_tag = 0; - - std::set var_set; - type_app* return_app = new type_app(std::move(this_type_ptr)); - type_ptr return_type(return_app); - for(auto& var : vars) { - if(var_set.find(var) != var_set.end()) throw 0; - var_set.insert(var); - return_app->arguments.push_back(type_ptr(new type_var(var))); - } - - for(auto& constructor : constructors) { - constructor->tag = next_tag; - this_type->constructors[constructor->name] = { next_tag++ }; - - type_ptr full_type = return_type; - for(auto it = constructor->types.rbegin(); it != constructor->types.rend(); it++) { - type_ptr type = (*it)->to_type(var_set, env); - full_type = type_ptr(new type_arr(type, full_type)); - } - - type_scheme_ptr full_scheme(new type_scheme(std::move(full_type))); - full_scheme->forall.insert(full_scheme->forall.begin(), vars.begin(), vars.end()); - env->bind(constructor->name, full_scheme); - } -} - -void definition_data::into_globals(global_scope& scope) { - for(auto& constructor : constructors) { - global_constructor& c = scope.add_constructor( - constructor->name, constructor->tag, constructor->types.size()); - env->set_mangled_name(constructor->name, c.name); - } -} - -void definition_group::find_free(std::set& into) { - for(auto& def_pair : defs_defn) { - def_pair.second->find_free(); - for(auto& free_var : def_pair.second->free_variables) { - if(defs_defn.find(free_var) == defs_defn.end()) { - into.insert(free_var); - } else { - def_pair.second->nearby_variables.insert(free_var); - } - } - } -} - -void definition_group::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = type_scope(env); - - for(auto& def_data : defs_data) { - def_data.second->insert_types(this->env); - } - for(auto& def_data : defs_data) { - def_data.second->insert_constructors(); - } - - function_graph dependency_graph; - - for(auto& def_defn : defs_defn) { - def_defn.second->find_free(); - dependency_graph.add_function(def_defn.second->name); - - for(auto& dependency : def_defn.second->nearby_variables) { - if(defs_defn.find(dependency) == defs_defn.end()) - throw 0; - dependency_graph.add_edge(def_defn.second->name, dependency); - } - } - - std::vector groups = dependency_graph.compute_order(); - for(auto it = groups.rbegin(); it != groups.rend(); it++) { - auto& group = *it; - for(auto& def_defnn_name : group->members) { - auto& def_defn = defs_defn.find(def_defnn_name)->second; - def_defn->insert_types(mgr, this->env, vis); - } - 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) { - this->env->generalize(def_defnn_name, *group, mgr); - } - } -} diff --git a/code/compiler/12/definition.hpp b/code/compiler/12/definition.hpp deleted file mode 100644 index 44828d3..0000000 --- a/code/compiler/12/definition.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "parsed_type.hpp" -#include "type_env.hpp" -#include "global_scope.hpp" - -struct ast; -using ast_ptr = std::unique_ptr; - -struct constructor { - std::string name; - std::vector types; - int8_t tag; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition_defn { - std::string name; - std::vector params; - ast_ptr body; - - type_env_ptr env; - type_env_ptr var_env; - std::set free_variables; - std::set nearby_variables; - type_ptr full_type; - type_ptr return_type; - - definition_defn(std::string n, std::vector p, ast_ptr b) - : name(std::move(n)), params(std::move(p)), body(std::move(b)) { - - } - - void find_free(); - void insert_types(type_mgr& mgr, type_env_ptr& env, visibility v); - void typecheck(type_mgr& mgr); - - global_function& into_global(global_scope& scope); -}; - -using definition_defn_ptr = std::unique_ptr; - -struct definition_data { - std::string name; - std::vector vars; - std::vector constructors; - - type_env_ptr env; - - definition_data( - std::string n, - std::vector vs, - std::vector cs) - : name(std::move(n)), vars(std::move(vs)), constructors(std::move(cs)) {} - - void insert_types(type_env_ptr& env); - void insert_constructors() const; - - void into_globals(global_scope& scope); -}; - -using definition_data_ptr = std::unique_ptr; - -struct definition_group { - std::map defs_data; - std::map defs_defn; - visibility vis; - type_env_ptr env; - - definition_group(visibility v = visibility::local) : vis(v) {} - - void find_free(std::set& into); - void typecheck(type_mgr& mgr, type_env_ptr& env); -}; diff --git a/code/compiler/12/env.cpp b/code/compiler/12/env.cpp deleted file mode 100644 index 818cf5d..0000000 --- a/code/compiler/12/env.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "env.hpp" - -int env_var::get_offset(const std::string& name) const { - if(name == this->name) return 0; - if(parent) return parent->get_offset(name) + 1; - throw 0; -} - -bool env_var::has_variable(const std::string& name) const { - if(name == this->name) return true; - if(parent) return parent->has_variable(name); - return false; -} - -int env_offset::get_offset(const std::string& name) const { - if(parent) return parent->get_offset(name) + offset; - throw 0; -} - -bool env_offset::has_variable(const std::string& name) const { - if(parent) return parent->has_variable(name); - return false; -} diff --git a/code/compiler/12/env.hpp b/code/compiler/12/env.hpp deleted file mode 100644 index 9d0dfbe..0000000 --- a/code/compiler/12/env.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include - -struct env { - virtual ~env() = default; - - virtual int get_offset(const std::string& name) const = 0; - virtual bool has_variable(const std::string& name) const = 0; -}; - -using env_ptr = std::shared_ptr; - -struct env_var : public env { - std::string name; - env_ptr parent; - - env_var(std::string n, env_ptr p) - : name(std::move(n)), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; - -struct env_offset : public env { - int offset; - env_ptr parent; - - env_offset(int o, env_ptr p) - : offset(o), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; diff --git a/code/compiler/12/error.cpp b/code/compiler/12/error.cpp deleted file mode 100644 index f5125e3..0000000 --- a/code/compiler/12/error.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "error.hpp" - -const char* type_error::what() const noexcept { - return "an error occured while checking the types of the program"; -} diff --git a/code/compiler/12/error.hpp b/code/compiler/12/error.hpp deleted file mode 100644 index 5bfbc7e..0000000 --- a/code/compiler/12/error.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include "type.hpp" - -struct type_error : std::exception { - std::string description; - - type_error(std::string d) - : description(std::move(d)) {} - - const char* what() const noexcept override; -}; - -struct unification_error : public type_error { - type_ptr left; - type_ptr right; - - unification_error(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)), - type_error("failed to unify types") {} -}; diff --git a/code/compiler/12/examples/bad1.txt b/code/compiler/12/examples/bad1.txt deleted file mode 100644 index 86d4bc4..0000000 --- a/code/compiler/12/examples/bad1.txt +++ /dev/null @@ -1,2 +0,0 @@ -data Bool = { True, False } -defn main = { 3 + True } diff --git a/code/compiler/12/examples/bad2.txt b/code/compiler/12/examples/bad2.txt deleted file mode 100644 index def8785..0000000 --- a/code/compiler/12/examples/bad2.txt +++ /dev/null @@ -1 +0,0 @@ -defn main = { 1 2 3 4 5 } diff --git a/code/compiler/12/examples/bad3.txt b/code/compiler/12/examples/bad3.txt deleted file mode 100644 index 6f82b3d..0000000 --- a/code/compiler/12/examples/bad3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } - -defn head l = { - case l of { - Nil -> { 0 } - Cons x y z -> { x } - } -} diff --git a/code/compiler/12/examples/fixpoint.txt b/code/compiler/12/examples/fixpoint.txt deleted file mode 100644 index aba81e8..0000000 --- a/code/compiler/12/examples/fixpoint.txt +++ /dev/null @@ -1,17 +0,0 @@ -data List a = { Nil, Cons a (List a) } - -defn fix f = { let { defn x = { f x } } in { x } } -defn fixpointOnes fo = { Cons 1 fo } -defn sumTwo l = { - case l of { - Nil -> { 0 } - Cons x xs -> { - x + case xs of { - Nil -> { 0 } - Cons y ys -> { y } - } - } - } -} - -defn main = { sumTwo (fix fixpointOnes) } diff --git a/code/compiler/12/examples/if.txt b/code/compiler/12/examples/if.txt deleted file mode 100644 index c00df35..0000000 --- a/code/compiler/12/examples/if.txt +++ /dev/null @@ -1,8 +0,0 @@ -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/code/compiler/12/examples/lambda.txt b/code/compiler/12/examples/lambda.txt deleted file mode 100644 index 35deace..0000000 --- a/code/compiler/12/examples/lambda.txt +++ /dev/null @@ -1,19 +0,0 @@ -data List a = { Nil, Cons a (List a) } - -defn sum l = { - case l of { - Nil -> { 0 } - Cons x xs -> { x + sum xs} - } -} - -defn map f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { Cons (f x) (map f xs) } - } -} - -defn main = { - sum (map \x -> { x * x } (map (\x -> { x + x }) (Cons 1 (Cons 2 (Cons 3 Nil))))) -} diff --git a/code/compiler/12/examples/letin.txt b/code/compiler/12/examples/letin.txt deleted file mode 100644 index 9e163b2..0000000 --- a/code/compiler/12/examples/letin.txt +++ /dev/null @@ -1,47 +0,0 @@ -data Bool = { True, False } - -data List a = { Nil, Cons a (List a) } - -defn if c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn mergeUntil l r p = { - let { - defn mergeLeft nl nr = { - case nl of { - Nil -> { Nil } - Cons x xs -> { if (p x) (Cons x (mergeRight xs nr)) Nil } - } - } - defn mergeRight nl nr = { - case nr of { - Nil -> { Nil } - Cons x xs -> { if (p x) (Cons x (mergeLeft nl xs)) Nil } - } - } - } in { - mergeLeft l r - } -} - -defn const x y = { x } - -defn sum l = { - case l of { - Nil -> { 0 } - Cons x xs -> { x + sum xs } - } -} - -defn main = { - let { - defn firstList = { Cons 1 (Cons 3 (Cons 5 Nil)) } - defn secondList = { Cons 2 (Cons 4 (Cons 6 Nil)) } - } in { - sum (mergeUntil firstList secondList (const True)) - } -} diff --git a/code/compiler/12/examples/list.txt b/code/compiler/12/examples/list.txt deleted file mode 100644 index 159bd1c..0000000 --- a/code/compiler/12/examples/list.txt +++ /dev/null @@ -1,32 +0,0 @@ -data List a = { Nil, Cons a (List a) } - -defn map f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { Cons (f x) (map f xs) } - } -} - -defn foldl f b l = { - case l of { - Nil -> { b } - Cons x xs -> { foldl f (f b x) xs } - } -} - -defn foldr f b l = { - case l of { - Nil -> { b } - Cons x xs -> { f x (foldr f b xs) } - } -} - -defn list = { Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil))) } - -defn add x y = { x + y } -defn sum l = { foldr add 0 l } - -defn skipAdd x y = { y + 1 } -defn length l = { foldr skipAdd 0 l } - -defn main = { sum list + length list } diff --git a/code/compiler/12/examples/mutual_recursion.txt b/code/compiler/12/examples/mutual_recursion.txt deleted file mode 100644 index 7fabf43..0000000 --- a/code/compiler/12/examples/mutual_recursion.txt +++ /dev/null @@ -1,25 +0,0 @@ -data Bool = { True, False } -data List = { Nil, Cons Int List } - -defn if c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn oddEven l e = { - case l of { - Nil -> { e } - Cons x xs -> { evenOdd xs e } - } -} - -defn evenOdd l e = { - case l of { - Nil -> { e } - Cons x xs -> { oddEven xs e } - } -} - -defn main = { if (oddEven (Cons 1 (Cons 2 (Cons 3 Nil))) True) (oddEven (Cons 1 (Cons 2 (Cons 3 Nil))) 1) 3 } diff --git a/code/compiler/12/examples/packed.txt b/code/compiler/12/examples/packed.txt deleted file mode 100644 index 8f25f71..0000000 --- a/code/compiler/12/examples/packed.txt +++ /dev/null @@ -1,23 +0,0 @@ -data Pair a b = { Pair a b } - -defn packer = { - let { - data Packed a = { Packed a } - defn pack a = { Packed a } - defn unpack p = { - case p of { - Packed a -> { a } - } - } - } in { - Pair pack unpack - } -} - -defn main = { - case packer of { - Pair pack unpack -> { - unpack (pack 3) - } - } -} diff --git a/code/compiler/12/examples/pair.txt b/code/compiler/12/examples/pair.txt deleted file mode 100644 index 3ed8362..0000000 --- a/code/compiler/12/examples/pair.txt +++ /dev/null @@ -1,17 +0,0 @@ -data Pair a b = { MkPair a b } - -defn fst p = { - case p of { - MkPair a b -> { a } - } -} - -defn snd p = { - case p of { - MkPair a b -> { b } - } -} - -defn pair = { MkPair 1 (MkPair 2 3) } - -defn main = { fst pair + snd (snd pair) } diff --git a/code/compiler/12/examples/primes.txt b/code/compiler/12/examples/primes.txt deleted file mode 100644 index 8421849..0000000 --- a/code/compiler/12/examples/primes.txt +++ /dev/null @@ -1,122 +0,0 @@ -data List = { Nil, Cons Nat List } -data Bool = { True, False } -data Nat = { O, S Nat } - -defn if c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn toInt n = { - case n of { - O -> { 0 } - S np -> { 1 + toInt np } - } -} - -defn lte n m = { - case m of { - O -> { - case n of { - O -> { True } - S np -> { False } - } - } - S mp -> { - case n of { - O -> { True } - S np -> { lte np mp } - } - } - } -} - -defn minus n m = { - case m of { - O -> { n } - S mp -> { - case n of { - O -> { O } - S np -> { - minus np mp - } - } - } - } -} - -defn mod n m = { - if (lte m n) (mod (minus n m) m) n -} - -defn notDivisibleBy n m = { - case (mod m n) of { - O -> { False } - S mp -> { True } - } -} - -defn filter f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { if (f x) (Cons x (filter f xs)) (filter f xs) } - } -} - -defn map f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { Cons (f x) (map f xs) } - } -} - -defn nats = { - Cons (S (S O)) (map S nats) -} - -defn primesRec l = { - case l of { - Nil -> { Nil } - Cons p xs -> { Cons p (primesRec (filter (notDivisibleBy p) xs)) } - } -} - -defn primes = { - primesRec nats -} - -defn take n l = { - case l of { - Nil -> { Nil } - Cons x xs -> { - case n of { - O -> { Nil } - S np -> { Cons x (take np xs) } - } - } - } -} - -defn head l = { - case l of { - Nil -> { O } - Cons x xs -> { x } - } -} - -defn reverseAcc a l = { - case l of { - Nil -> { a } - Cons x xs -> { reverseAcc (Cons x a) xs } - } -} - -defn reverse l = { - reverseAcc Nil l -} - -defn main = { - toInt (head (reverse (take ((S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) primes))) -} diff --git a/code/compiler/12/examples/runtime1.c b/code/compiler/12/examples/runtime1.c deleted file mode 100644 index 0157051..0000000 --- a/code/compiler/12/examples/runtime1.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "../runtime.h" - -void f_add(struct stack* s) { - struct node_num* left = (struct node_num*) eval(stack_peek(s, 0)); - struct node_num* right = (struct node_num*) eval(stack_peek(s, 1)); - stack_push(s, (struct node_base*) alloc_num(left->value + right->value)); -} - -void f_main(struct stack* s) { - // PushInt 320 - stack_push(s, (struct node_base*) alloc_num(320)); - - // PushInt 6 - stack_push(s, (struct node_base*) alloc_num(6)); - - // PushGlobal f_add (the function for +) - stack_push(s, (struct node_base*) alloc_global(f_add, 2)); - - struct node_base* left; - struct node_base* right; - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); -} diff --git a/code/compiler/12/examples/works1.txt b/code/compiler/12/examples/works1.txt deleted file mode 100644 index a2d647f..0000000 --- a/code/compiler/12/examples/works1.txt +++ /dev/null @@ -1,2 +0,0 @@ -defn main = { sum 320 6 } -defn sum x y = { x + y } diff --git a/code/compiler/12/examples/works2.txt b/code/compiler/12/examples/works2.txt deleted file mode 100644 index 8332fde..0000000 --- a/code/compiler/12/examples/works2.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn add x y = { x + y } -defn double x = { add x x } -defn main = { double 163 } diff --git a/code/compiler/12/examples/works3.txt b/code/compiler/12/examples/works3.txt deleted file mode 100644 index cfd2ef3..0000000 --- a/code/compiler/12/examples/works3.txt +++ /dev/null @@ -1,9 +0,0 @@ -data List a = { Nil, Cons a (List a) } -data Bool = { True, False } -defn length l = { - case l of { - Nil -> { 0 } - Cons x xs -> { 1 + length xs } - } -} -defn main = { length (Cons 1 (Cons 2 (Cons 3 Nil))) + length (Cons True (Cons False (Cons True Nil))) } diff --git a/code/compiler/12/examples/works4.txt b/code/compiler/12/examples/works4.txt deleted file mode 100644 index 7674691..0000000 --- a/code/compiler/12/examples/works4.txt +++ /dev/null @@ -1,16 +0,0 @@ -data List = { Nil, Cons Int List } - -defn add x y = { x + y } -defn mul x y = { x * y } - -defn foldr f b l = { - case l of { - Nil -> { b } - Cons x xs -> { f x (foldr f b xs) } - } -} - -defn main = { - foldr add 0 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) + - foldr mul 1 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) -} diff --git a/code/compiler/12/examples/works5.txt b/code/compiler/12/examples/works5.txt deleted file mode 100644 index 3a8aff5..0000000 --- a/code/compiler/12/examples/works5.txt +++ /dev/null @@ -1,17 +0,0 @@ -data List = { Nil, Cons Int List } - -defn sumZip l m = { - case l of { - Nil -> { 0 } - Cons x xs -> { - case m of { - Nil -> { 0 } - Cons y ys -> { x + y + sumZip xs ys } - } - } - } -} - -defn ones = { Cons 1 ones } - -defn main = { sumZip ones (Cons 1 (Cons 2 (Cons 3 Nil))) } diff --git a/code/compiler/12/global_scope.cpp b/code/compiler/12/global_scope.cpp deleted file mode 100644 index 2107703..0000000 --- a/code/compiler/12/global_scope.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "global_scope.hpp" -#include "ast.hpp" - -void global_function::compile() { - env_ptr new_env = env_ptr(new env_offset(0, nullptr)); - for(auto it = params.rbegin(); it != params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - body->compile(new_env, instructions); - instructions.push_back(instruction_ptr(new instruction_update(params.size()))); - instructions.push_back(instruction_ptr(new instruction_pop(params.size()))); -} - -void global_function::declare_llvm(llvm_context& ctx) { - generated_function = ctx.create_custom_function(name, params.size()); -} - -void global_function::generate_llvm(llvm_context& ctx) { - ctx.builder.SetInsertPoint(&generated_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, generated_function); - } - ctx.builder.CreateRetVoid(); -} - -void global_constructor::generate_llvm(llvm_context& ctx) { - auto new_function = - ctx.create_custom_function(name, arity); - std::vector instructions; - instructions.push_back(instruction_ptr(new instruction_pack(tag, arity))); - instructions.push_back(instruction_ptr(new instruction_update(0))); - ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); - for (auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.builder.CreateRetVoid(); -} - -global_function& global_scope::add_function(std::string n, std::vector ps, ast_ptr b) { - global_function* new_function = new global_function(mangle_name(n), std::move(ps), std::move(b)); - functions.push_back(global_function_ptr(new_function)); - return *new_function; -} - -global_constructor& global_scope::add_constructor(std::string n, int8_t t, size_t a) { - global_constructor* new_constructor = new global_constructor(mangle_name(n), t, a); - constructors.push_back(global_constructor_ptr(new_constructor)); - return *new_constructor; -} - -void global_scope::compile() { - for(auto& function : functions) { - function->compile(); - } -} - -void global_scope::generate_llvm(llvm_context& ctx) { - for(auto& constructor : constructors) { - constructor->generate_llvm(ctx); - } - for(auto& function : functions) { - function->declare_llvm(ctx); - } - for(auto& function : functions) { - function->generate_llvm(ctx); - } -} - -std::string global_scope::mangle_name(const std::string& n) { - auto occurence_it = occurence_count.find(n); - int occurence = 0; - if(occurence_it != occurence_count.end()) { - occurence = occurence_it->second + 1; - } - occurence_count[n] = occurence; - - std::string final_name = n; - if (occurence != 0) { - final_name += "_"; - final_name += std::to_string(occurence); - } - return final_name; -} diff --git a/code/compiler/12/global_scope.hpp b/code/compiler/12/global_scope.hpp deleted file mode 100644 index 9f75ce3..0000000 --- a/code/compiler/12/global_scope.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include "instruction.hpp" - -struct ast; -using ast_ptr = std::unique_ptr; - -struct global_function { - std::string name; - std::vector params; - ast_ptr body; - - std::vector instructions; - llvm::Function* generated_function; - - global_function(std::string n, std::vector ps, ast_ptr b) - : name(std::move(n)), params(std::move(ps)), body(std::move(b)) {} - - void compile(); - void declare_llvm(llvm_context& ctx); - void generate_llvm(llvm_context& ctx); -}; - -using global_function_ptr = std::unique_ptr; - -struct global_constructor { - std::string name; - int8_t tag; - size_t arity; - - global_constructor(std::string n, int8_t t, size_t a) - : name(std::move(n)), tag(t), arity(a) {} - - void generate_llvm(llvm_context& ctx); -}; - -using global_constructor_ptr = std::unique_ptr; - -struct global_scope { - std::map occurence_count; - std::vector functions; - std::vector constructors; - - global_function& add_function(std::string n, std::vector ps, ast_ptr b); - global_constructor& add_constructor(std::string n, int8_t t, size_t a); - - void compile(); - void generate_llvm(llvm_context& ctx); - - private: - std::string mangle_name(const std::string& n); -}; diff --git a/code/compiler/12/graph.cpp b/code/compiler/12/graph.cpp deleted file mode 100644 index c648acd..0000000 --- a/code/compiler/12/graph.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "graph.hpp" - -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/code/compiler/12/graph.hpp b/code/compiler/12/graph.hpp deleted file mode 100644 index 2807442..0000000 --- a/code/compiler/12/graph.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -using function = std::string; - -struct group { - std::set members; -}; - -using group_ptr = std::unique_ptr; - -class function_graph { - using group_id = size_t; - - struct group_data { - std::set functions; - std::set adjacency_list; - size_t indegree; - }; - - using data_ptr = std::shared_ptr; - using edge = std::pair; - using group_edge = std::pair; - - std::map> adjacency_lists; - std::set edges; - - std::set compute_transitive_edges(); - void create_groups( - const std::set&, - std::map&, - std::map&); - void create_edges( - std::map&, - std::map&); - std::vector generate_order( - std::map&, - std::map&); - - public: - std::set& add_function(const function& f); - void add_edge(const function& from, const function& to); - std::vector compute_order(); -}; diff --git a/code/compiler/12/instruction.cpp b/code/compiler/12/instruction.cpp deleted file mode 100644 index c2b050a..0000000 --- a/code/compiler/12/instruction.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include "instruction.hpp" -#include "llvm_context.hpp" -#include -#include - -using namespace llvm; - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void instruction_pushint::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushInt(" << value << ")" << std::endl; -} - -void instruction_pushint::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_num(f, ctx.create_i32(value))); -} - -void instruction_pushglobal::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushGlobal(" << name << ")" << std::endl; -} - -void instruction_pushglobal::gen_llvm(llvm_context& ctx, Function* f) const { - auto& global_f = ctx.custom_functions.at("f_" + name); - auto arity = ctx.create_i32(global_f->arity); - ctx.create_push(f, ctx.create_global(f, global_f->function, arity)); -} - -void instruction_push::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Push(" << offset << ")" << std::endl; -} - -void instruction_push::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_peek(f, ctx.create_size(offset))); -} - -void instruction_pop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pop(" << count << ")" << std::endl; -} - -void instruction_pop::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_popn(f, ctx.create_size(count)); -} - -void instruction_mkapp::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "MkApp()" << std::endl; -} - -void instruction_mkapp::gen_llvm(llvm_context& ctx, Function* f) const { - auto left = ctx.create_pop(f); - auto right = ctx.create_pop(f); - ctx.create_push(f, ctx.create_app(f, left, right)); -} - -void instruction_update::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Update(" << offset << ")" << std::endl; -} - -void instruction_update::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_update(f, ctx.create_size(offset)); -} - -void instruction_pack::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pack(" << tag << ", " << size << ")" << std::endl; -} - -void instruction_pack::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_pack(f, ctx.create_size(size), ctx.create_i8(tag)); -} - -void instruction_split::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Split()" << std::endl; -} - -void instruction_split::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_split(f, ctx.create_size(size)); -} - -void instruction_jump::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Jump(" << std::endl; - for(auto& instruction_set : branches) { - for(auto& instruction : instruction_set) { - instruction->print(indent + 2, to); - } - to << std::endl; - } - print_indent(indent, to); - to << ")" << std::endl; -} - -void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const { - auto top_node = ctx.create_peek(f, ctx.create_size(0)); - auto tag = ctx.unwrap_data_tag(top_node); - auto safety_block = BasicBlock::Create(ctx.ctx, "safety", f); - auto switch_op = ctx.builder.CreateSwitch(tag, safety_block, tag_mappings.size()); - std::vector blocks; - - for(auto& branch : branches) { - auto branch_block = BasicBlock::Create(ctx.ctx, "branch", f); - ctx.builder.SetInsertPoint(branch_block); - for(auto& instruction : branch) { - instruction->gen_llvm(ctx, f); - } - ctx.builder.CreateBr(safety_block); - blocks.push_back(branch_block); - } - - for(auto& mapping : tag_mappings) { - switch_op->addCase(ctx.create_i8(mapping.first), blocks[mapping.second]); - } - - ctx.builder.SetInsertPoint(safety_block); -} - -void instruction_slide::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Slide(" << offset << ")" << std::endl; -} - -void instruction_slide::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_slide(f, ctx.create_size(offset)); -} - -void instruction_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BinOp(" << op_action(op) << ")" << std::endl; -} - -void instruction_binop::gen_llvm(llvm_context& ctx, Function* f) const { - auto left_int = ctx.unwrap_num(ctx.create_pop(f)); - auto right_int = ctx.unwrap_num(ctx.create_pop(f)); - llvm::Value* result; - switch(op) { - case PLUS: result = ctx.builder.CreateAdd(left_int, right_int); break; - case MINUS: result = ctx.builder.CreateSub(left_int, right_int); break; - case TIMES: result = ctx.builder.CreateMul(left_int, right_int); break; - case DIVIDE: result = ctx.builder.CreateSDiv(left_int, right_int); break; - } - ctx.create_push(f, ctx.create_num(f, result)); -} - -void instruction_eval::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Eval()" << std::endl; -} - -void instruction_eval::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_unwind(f); -} - -void instruction_alloc::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Alloc(" << amount << ")" << std::endl; -} - -void instruction_alloc::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_alloc(f, ctx.create_size(amount)); -} - -void instruction_unwind::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Unwind()" << std::endl; -} - -void instruction_unwind::gen_llvm(llvm_context& ctx, Function* f) const { - // Nothing -} diff --git a/code/compiler/12/instruction.hpp b/code/compiler/12/instruction.hpp deleted file mode 100644 index abe2409..0000000 --- a/code/compiler/12/instruction.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include "binop.hpp" -#include "llvm_context.hpp" - -struct instruction { - virtual ~instruction() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual void gen_llvm(llvm_context& ctx, llvm::Function* f) const = 0; -}; - -using instruction_ptr = std::unique_ptr; - -struct instruction_pushint : public instruction { - int value; - - instruction_pushint(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pushglobal : public instruction { - std::string name; - - instruction_pushglobal(std::string n) - : name(std::move(n)) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_push : public instruction { - int offset; - - instruction_push(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pop : public instruction { - int count; - - instruction_pop(int c) - : count(c) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_mkapp : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_update : public instruction { - int offset; - - instruction_update(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pack : public instruction { - int tag; - int size; - - instruction_pack(int t, int s) - : tag(t), size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_split : public instruction { - int size; - - instruction_split(int s) - : size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_jump : public instruction { - std::vector> branches; - std::map tag_mappings; - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_slide : public instruction { - int offset; - - instruction_slide(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_binop : public instruction { - binop op; - - instruction_binop(binop o) - : op(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_eval : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_alloc : public instruction { - int amount; - - instruction_alloc(int a) - : amount(a) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_unwind : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; diff --git a/code/compiler/12/llvm_context.cpp b/code/compiler/12/llvm_context.cpp deleted file mode 100644 index 45dcb50..0000000 --- a/code/compiler/12/llvm_context.cpp +++ /dev/null @@ -1,278 +0,0 @@ -#include "llvm_context.hpp" -#include - -using namespace llvm; - -void llvm_context::create_types() { - stack_type = StructType::create(ctx, "stack"); - gmachine_type = StructType::create(ctx, "gmachine"); - stack_ptr_type = PointerType::getUnqual(stack_type); - gmachine_ptr_type = PointerType::getUnqual(gmachine_type); - tag_type = IntegerType::getInt8Ty(ctx); - struct_types["node_base"] = StructType::create(ctx, "node_base"); - struct_types["node_app"] = StructType::create(ctx, "node_app"); - struct_types["node_num"] = StructType::create(ctx, "node_num"); - struct_types["node_global"] = StructType::create(ctx, "node_global"); - struct_types["node_ind"] = StructType::create(ctx, "node_ind"); - struct_types["node_data"] = StructType::create(ctx, "node_data"); - node_ptr_type = PointerType::getUnqual(struct_types.at("node_base")); - function_type = FunctionType::get(Type::getVoidTy(ctx), { gmachine_ptr_type }, false); - - gmachine_type->setBody( - stack_ptr_type, - node_ptr_type, - IntegerType::getInt64Ty(ctx), - IntegerType::getInt64Ty(ctx) - ); - struct_types.at("node_base")->setBody( - IntegerType::getInt32Ty(ctx), - IntegerType::getInt8Ty(ctx), - node_ptr_type - ); - struct_types.at("node_app")->setBody( - struct_types.at("node_base"), - node_ptr_type, - node_ptr_type - ); - struct_types.at("node_num")->setBody( - struct_types.at("node_base"), - IntegerType::getInt32Ty(ctx) - ); - struct_types.at("node_global")->setBody( - struct_types.at("node_base"), - FunctionType::get(Type::getVoidTy(ctx), { stack_ptr_type }, false) - ); - struct_types.at("node_ind")->setBody( - struct_types.at("node_base"), - node_ptr_type - ); - struct_types.at("node_data")->setBody( - struct_types.at("node_base"), - IntegerType::getInt8Ty(ctx), - PointerType::getUnqual(node_ptr_type) - ); -} - -void llvm_context::create_functions() { - auto void_type = Type::getVoidTy(ctx); - auto sizet_type = IntegerType::get(ctx, sizeof(size_t) * 8); - functions["stack_init"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_init", - &module - ); - functions["stack_free"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_free", - &module - ); - functions["stack_push"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_push", - &module - ); - functions["stack_pop"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_pop", - &module - ); - functions["stack_peek"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_peek", - &module - ); - functions["stack_popn"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_popn", - &module - ); - functions["gmachine_slide"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_slide", - &module - ); - functions["gmachine_update"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_update", - &module - ); - functions["gmachine_alloc"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_alloc", - &module - ); - functions["gmachine_pack"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type, tag_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_pack", - &module - ); - functions["gmachine_split"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_split", - &module - ); - functions["gmachine_track"] = Function::Create( - FunctionType::get(node_ptr_type, { gmachine_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_track", - &module - ); - - auto int32_type = IntegerType::getInt32Ty(ctx); - functions["alloc_app"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_app", - &module - ); - functions["alloc_num"] = Function::Create( - FunctionType::get(node_ptr_type, { int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_num", - &module - ); - functions["alloc_global"] = Function::Create( - FunctionType::get(node_ptr_type, { function_type, int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_global", - &module - ); - functions["alloc_ind"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_ind", - &module - ); - - functions["unwind"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "unwind", - &module - ); -} - -ConstantInt* llvm_context::create_i8(int8_t i) { - return ConstantInt::get(ctx, APInt(8, i)); -} -ConstantInt* llvm_context::create_i32(int32_t i) { - return ConstantInt::get(ctx, APInt(32, i)); -} -ConstantInt* llvm_context::create_size(size_t i) { - return ConstantInt::get(ctx, APInt(sizeof(size_t) * 8, i)); -} - -Value* llvm_context::create_pop(Function* f) { - auto pop_f = functions.at("stack_pop"); - return builder.CreateCall(pop_f, { unwrap_gmachine_stack_ptr(f->arg_begin()) }); -} -Value* llvm_context::create_peek(Function* f, Value* off) { - auto peek_f = functions.at("stack_peek"); - return builder.CreateCall(peek_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off }); -} -void llvm_context::create_push(Function* f, Value* v) { - auto push_f = functions.at("stack_push"); - builder.CreateCall(push_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), v }); -} -void llvm_context::create_popn(Function* f, Value* off) { - auto popn_f = functions.at("stack_popn"); - builder.CreateCall(popn_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off }); -} -void llvm_context::create_update(Function* f, Value* off) { - auto update_f = functions.at("gmachine_update"); - builder.CreateCall(update_f, { f->arg_begin(), off }); -} -void llvm_context::create_pack(Function* f, Value* c, Value* t) { - auto pack_f = functions.at("gmachine_pack"); - builder.CreateCall(pack_f, { f->arg_begin(), c, t }); -} -void llvm_context::create_split(Function* f, Value* c) { - auto split_f = functions.at("gmachine_split"); - builder.CreateCall(split_f, { f->arg_begin(), c }); -} -void llvm_context::create_slide(Function* f, Value* off) { - auto slide_f = functions.at("gmachine_slide"); - builder.CreateCall(slide_f, { f->arg_begin(), off }); -} -void llvm_context::create_alloc(Function* f, Value* n) { - auto alloc_f = functions.at("gmachine_alloc"); - builder.CreateCall(alloc_f, { f->arg_begin(), n }); -} -Value* llvm_context::create_track(Function* f, Value* v) { - auto track_f = functions.at("gmachine_track"); - return builder.CreateCall(track_f, { f->arg_begin(), v }); -} - -void llvm_context::create_unwind(Function* f) { - auto unwind_f = functions.at("unwind"); - builder.CreateCall(unwind_f, { f->args().begin() }); -} - -Value* llvm_context::unwrap_gmachine_stack_ptr(Value* g) { - auto offset_0 = create_i32(0); - return builder.CreateGEP(g, { offset_0, offset_0 }); -} - -Value* llvm_context::unwrap_num(Value* v) { - auto num_ptr_type = PointerType::getUnqual(struct_types.at("node_num")); - auto cast = builder.CreatePointerCast(v, num_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto int_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(int_ptr); -} -Value* llvm_context::create_num(Function* f, Value* v) { - auto alloc_num_f = functions.at("alloc_num"); - auto alloc_num_call = builder.CreateCall(alloc_num_f, { v }); - return create_track(f, alloc_num_call); -} - -Value* llvm_context::unwrap_data_tag(Value* v) { - auto data_ptr_type = PointerType::getUnqual(struct_types.at("node_data")); - auto cast = builder.CreatePointerCast(v, data_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto tag_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(tag_ptr); -} - -Value* llvm_context::create_global(Function* f, Value* gf, Value* a) { - auto alloc_global_f = functions.at("alloc_global"); - auto alloc_global_call = builder.CreateCall(alloc_global_f, { gf, a }); - return create_track(f, alloc_global_call); -} - -Value* llvm_context::create_app(Function* f, Value* l, Value* r) { - auto alloc_app_f = functions.at("alloc_app"); - auto alloc_app_call = builder.CreateCall(alloc_app_f, { l, r }); - return create_track(f, alloc_app_call); -} - -llvm::Function* llvm_context::create_custom_function(std::string name, int32_t arity) { - auto void_type = llvm::Type::getVoidTy(ctx); - auto new_function = llvm::Function::Create( - function_type, - llvm::Function::LinkageTypes::ExternalLinkage, - "f_" + name, - &module - ); - auto start_block = llvm::BasicBlock::Create(ctx, "entry", new_function); - - auto new_custom_f = custom_function_ptr(new custom_function()); - new_custom_f->arity = arity; - new_custom_f->function = new_function; - custom_functions["f_" + name] = std::move(new_custom_f); - - return new_function; -} diff --git a/code/compiler/12/llvm_context.hpp b/code/compiler/12/llvm_context.hpp deleted file mode 100644 index fbe4cc1..0000000 --- a/code/compiler/12/llvm_context.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -struct llvm_context { - struct custom_function { - llvm::Function* function; - int32_t arity; - }; - - using custom_function_ptr = std::unique_ptr; - - llvm::LLVMContext ctx; - llvm::IRBuilder<> builder; - llvm::Module module; - - std::map custom_functions; - std::map functions; - std::map struct_types; - - llvm::StructType* stack_type; - llvm::StructType* gmachine_type; - llvm::PointerType* stack_ptr_type; - llvm::PointerType* gmachine_ptr_type; - llvm::PointerType* node_ptr_type; - llvm::IntegerType* tag_type; - llvm::FunctionType* function_type; - - llvm_context() - : builder(ctx), module("bloglang", ctx) { - create_types(); - create_functions(); - } - - void create_types(); - void create_functions(); - - llvm::ConstantInt* create_i8(int8_t); - llvm::ConstantInt* create_i32(int32_t); - llvm::ConstantInt* create_size(size_t); - - llvm::Value* create_pop(llvm::Function*); - llvm::Value* create_peek(llvm::Function*, llvm::Value*); - void create_push(llvm::Function*, llvm::Value*); - void create_popn(llvm::Function*, llvm::Value*); - void create_update(llvm::Function*, llvm::Value*); - void create_pack(llvm::Function*, llvm::Value*, llvm::Value*); - void create_split(llvm::Function*, llvm::Value*); - void create_slide(llvm::Function*, llvm::Value*); - void create_alloc(llvm::Function*, llvm::Value*); - llvm::Value* create_track(llvm::Function*, llvm::Value*); - - void create_unwind(llvm::Function*); - - llvm::Value* unwrap_gmachine_stack_ptr(llvm::Value*); - - llvm::Value* unwrap_num(llvm::Value*); - llvm::Value* create_num(llvm::Function*, llvm::Value*); - - llvm::Value* unwrap_data_tag(llvm::Value*); - - llvm::Value* create_global(llvm::Function*, llvm::Value*, llvm::Value*); - - llvm::Value* create_app(llvm::Function*, llvm::Value*, llvm::Value*); - - llvm::Function* create_custom_function(std::string name, int32_t arity); -}; diff --git a/code/compiler/12/main.cpp b/code/compiler/12/main.cpp deleted file mode 100644 index 238f075..0000000 --- a/code/compiler/12/main.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "ast.hpp" -#include -#include "binop.hpp" -#include "definition.hpp" -#include "graph.hpp" -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "parser.hpp" -#include "error.hpp" -#include "type.hpp" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetMachine.h" - -void yy::parser::error(const std::string& msg) { - std::cout << "An error occured: " << msg << std::endl; -} - -extern definition_group global_defs; - -void typecheck_program( - definition_group& defs, - 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 int_type_app = type_ptr(new type_app(int_type)); - - type_ptr binop_type = type_ptr(new type_arr( - int_type_app, - type_ptr(new type_arr(int_type_app, int_type_app)))); - env->bind("+", binop_type, visibility::global); - env->bind("-", binop_type, visibility::global); - env->bind("*", binop_type, visibility::global); - env->bind("/", binop_type, visibility::global); - - std::set free; - defs.find_free(free); - defs.typecheck(mgr, env); - - for(auto& pair : defs.env->names) { - std::cout << pair.first << ": "; - pair.second.type->print(mgr, std::cout); - std::cout << std::endl; - } -} - -global_scope translate_program(definition_group& group) { - global_scope scope; - for(auto& data : group.defs_data) { - data.second->into_globals(scope); - } - for(auto& defn : group.defs_defn) { - auto& function = defn.second->into_global(scope); - function.body->env->parent->set_mangled_name(defn.first, function.name); - } - return scope; -} - -void gen_llvm_internal_op(llvm_context& ctx, binop op) { - auto new_function = ctx.create_custom_function(op_action(op), 2); - std::vector instructions; - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_binop(op))); - instructions.push_back(instruction_ptr(new instruction_update(2))); - instructions.push_back(instruction_ptr(new instruction_pop(2))); - ctx.builder.SetInsertPoint(&new_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.builder.CreateRetVoid(); -} - -void output_llvm(llvm_context& ctx, const std::string& filename) { - std::string targetTriple = llvm::sys::getDefaultTargetTriple(); - - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmParser(); - llvm::InitializeNativeTargetAsmPrinter(); - - std::string error; - const llvm::Target* target = - llvm::TargetRegistry::lookupTarget(targetTriple, error); - if (!target) { - std::cerr << error << std::endl; - } else { - std::string cpu = "generic"; - std::string features = ""; - llvm::TargetOptions options; - llvm::TargetMachine* targetMachine = - target->createTargetMachine(targetTriple, cpu, features, - options, llvm::Optional()); - - ctx.module.setDataLayout(targetMachine->createDataLayout()); - ctx.module.setTargetTriple(targetTriple); - - std::error_code ec; - llvm::raw_fd_ostream file(filename, ec, llvm::sys::fs::F_None); - if (ec) { - throw 0; - } else { - llvm::CodeGenFileType type = llvm::CGFT_ObjectFile; - llvm::legacy::PassManager pm; - if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) { - throw 0; - } else { - pm.run(ctx.module); - file.close(); - } - } - } -} - -void gen_llvm(global_scope& scope) { - llvm_context ctx; - gen_llvm_internal_op(ctx, PLUS); - gen_llvm_internal_op(ctx, MINUS); - gen_llvm_internal_op(ctx, TIMES); - gen_llvm_internal_op(ctx, DIVIDE); - - scope.generate_llvm(ctx); - - ctx.module.print(llvm::outs(), nullptr); - output_llvm(ctx, "program.o"); -} - -int main() { - yy::parser parser; - type_mgr mgr; - type_env_ptr env(new type_env); - - parser.parse(); - for(auto& def_defn : global_defs.defs_defn) { - std::cout << def_defn.second->name; - for(auto& param : def_defn.second->params) std::cout << " " << param; - std::cout << ":" << std::endl; - - def_defn.second->body->print(1, std::cout); - } - try { - typecheck_program(global_defs, mgr, env); - global_scope scope = translate_program(global_defs); - scope.compile(); - gen_llvm(scope); - } catch(unification_error& err) { - std::cout << "failed to unify types: " << std::endl; - std::cout << " (1) \033[34m"; - err.left->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - std::cout << " (2) \033[32m"; - err.right->print(mgr, std::cout); - std::cout << "\033[0m" << std::endl; - } catch(type_error& err) { - std::cout << "failed to type check program: " << err.description << std::endl; - } -} diff --git a/code/compiler/12/parsed_type.cpp b/code/compiler/12/parsed_type.cpp deleted file mode 100644 index c69e50a..0000000 --- a/code/compiler/12/parsed_type.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#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; - if(base_type->arity != arguments.size()) 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/12/parsed_type.hpp b/code/compiler/12/parsed_type.hpp deleted file mode 100644 index 96c0fcc..0000000 --- a/code/compiler/12/parsed_type.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#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/12/parser.y b/code/compiler/12/parser.y deleted file mode 100644 index 2dc1744..0000000 --- a/code/compiler/12/parser.y +++ /dev/null @@ -1,174 +0,0 @@ -%{ -#include -#include -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" -#include "parsed_type.hpp" - -definition_group global_defs; - -extern yy::parser::symbol_type yylex(); - -%} - -%token BACKSLASH -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token LET -%token IN -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%type > lowercaseParams -%type > branches -%type > constructors -%type > typeList -%type definitions -%type type nonArrowType typeListElement -%type aAdd aMul case let lambda app appBase -%type data -%type defn -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { global_defs = std::move($1); global_defs.vis = visibility::global; } - ; - -definitions - : definitions defn { $$ = std::move($1); auto name = $2->name; $$.defs_defn[name] = std::move($2); } - | definitions data { $$ = std::move($1); auto name = $2->name; $$.defs_data[name] = std::move($2); } - | %empty { $$ = definition_group(); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_defn_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6))); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3))); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3))); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3))); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3))); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2))); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1))); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1))); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - | let { $$ = std::move($1); } - | lambda { $$ = std::move($1); } - ; - -let - : LET OCURLY definitions CCURLY IN OCURLY aAdd CCURLY - { $$ = ast_ptr(new ast_let(std::move($3), std::move($7))); } - ; - -lambda - : BACKSLASH lowercaseParams ARROW OCURLY aAdd CCURLY - { $$ = ast_ptr(new ast_lambda(std::move($2), std::move($5))); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5))); } - ; - -branches - : branches branch { $$ = std::move($1); $$.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1))); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2))); } - ; - -data - : DATA UID lowercaseParams EQUAL OCURLY constructors CCURLY - { $$ = definition_data_ptr(new definition_data(std::move($2), std::move($3), std::move($6))); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID typeList - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - -type - : nonArrowType ARROW type { $$ = parsed_type_ptr(new parsed_type_arr(std::move($1), std::move($3))); } - | nonArrowType { $$ = std::move($1); } - ; - -nonArrowType - : UID typeList { $$ = parsed_type_ptr(new parsed_type_app(std::move($1), std::move($2))); } - | LID { $$ = parsed_type_ptr(new parsed_type_var(std::move($1))); } - | OPAREN type CPAREN { $$ = std::move($2); } - ; - -typeListElement - : OPAREN type CPAREN { $$ = std::move($2); } - | UID { $$ = parsed_type_ptr(new parsed_type_app(std::move($1), {})); } - | LID { $$ = parsed_type_ptr(new parsed_type_var(std::move($1))); } - ; - -typeList - : %empty { $$ = std::vector(); } - | typeList typeListElement { $$ = std::move($1); $$.push_back(std::move($2)); } - ; diff --git a/code/compiler/12/runtime.c b/code/compiler/12/runtime.c deleted file mode 100644 index 7b8a7c3..0000000 --- a/code/compiler/12/runtime.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include -#include -#include -#include "runtime.h" - -struct node_base* alloc_node() { - struct node_base* new_node = malloc(sizeof(struct node_app)); - new_node->gc_next = NULL; - new_node->gc_reachable = 0; - assert(new_node != NULL); - return new_node; -} - -struct node_app* alloc_app(struct node_base* l, struct node_base* r) { - struct node_app* node = (struct node_app*) alloc_node(); - node->base.tag = NODE_APP; - node->left = l; - node->right = r; - return node; -} - -struct node_num* alloc_num(int32_t n) { - struct node_num* node = (struct node_num*) alloc_node(); - node->base.tag = NODE_NUM; - node->value = n; - return node; -} - -struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a) { - struct node_global* node = (struct node_global*) alloc_node(); - node->base.tag = NODE_GLOBAL; - node->arity = a; - node->function = f; - return node; -} - -struct node_ind* alloc_ind(struct node_base* n) { - struct node_ind* node = (struct node_ind*) alloc_node(); - node->base.tag = NODE_IND; - node->next = n; - return node; -} - -void free_node_direct(struct node_base* n) { - if(n->tag == NODE_DATA) { - free(((struct node_data*) n)->array); - } -} - -void gc_visit_node(struct node_base* n) { - if(n->gc_reachable) return; - n->gc_reachable = 1; - - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - gc_visit_node(app->left); - gc_visit_node(app->right); - } if(n->tag == NODE_IND) { - struct node_ind* ind = (struct node_ind*) n; - gc_visit_node(ind->next); - } if(n->tag == NODE_DATA) { - struct node_data* data = (struct node_data*) n; - struct node_base** to_visit = data->array; - while(*to_visit) { - gc_visit_node(*to_visit); - to_visit++; - } - } -} - -void stack_init(struct stack* s) { - s->size = 4; - s->count = 0; - s->data = malloc(sizeof(*s->data) * s->size); - assert(s->data != NULL); -} - -void stack_free(struct stack* s) { - free(s->data); -} - -void stack_push(struct stack* s, struct node_base* n) { - while(s->count >= s->size) { - s->data = realloc(s->data, sizeof(*s->data) * (s->size *= 2)); - assert(s->data != NULL); - } - s->data[s->count++] = n; -} - -struct node_base* stack_pop(struct stack* s) { - assert(s->count > 0); - return s->data[--s->count]; -} - -struct node_base* stack_peek(struct stack* s, size_t o) { - assert(s->count > o); - return s->data[s->count - o - 1]; -} - -void stack_popn(struct stack* s, size_t n) { - assert(s->count >= n); - s->count -= n; -} - -void gmachine_init(struct gmachine* g) { - stack_init(&g->stack); - g->gc_nodes = NULL; - g->gc_node_count = 0; - g->gc_node_threshold = 128; -} - -void gmachine_free(struct gmachine* g) { - stack_free(&g->stack); - struct node_base* to_free = g->gc_nodes; - struct node_base* next; - - while(to_free) { - next = to_free->gc_next; - free_node_direct(to_free); - free(to_free); - to_free = next; - } -} - -void gmachine_slide(struct gmachine* g, size_t n) { - assert(g->stack.count > n); - g->stack.data[g->stack.count - n - 1] = g->stack.data[g->stack.count - 1]; - g->stack.count -= n; -} - -void gmachine_update(struct gmachine* g, size_t o) { - assert(g->stack.count > o + 1); - struct node_ind* ind = - (struct node_ind*) g->stack.data[g->stack.count - o - 2]; - ind->base.tag = NODE_IND; - ind->next = g->stack.data[g->stack.count -= 1]; -} - -void gmachine_alloc(struct gmachine* g, size_t o) { - while(o--) { - stack_push(&g->stack, - gmachine_track(g, (struct node_base*) alloc_ind(NULL))); - } -} - -void gmachine_pack(struct gmachine* g, size_t n, int8_t t) { - assert(g->stack.count >= n); - - struct node_base** data = malloc(sizeof(*data) * (n + 1)); - assert(data != NULL); - memcpy(data, &g->stack.data[g->stack.count - n], n * sizeof(*data)); - data[n] = NULL; - - struct node_data* new_node = (struct node_data*) alloc_node(); - new_node->array = data; - new_node->base.tag = NODE_DATA; - new_node->tag = t; - - stack_popn(&g->stack, n); - stack_push(&g->stack, gmachine_track(g, (struct node_base*) new_node)); -} - -void gmachine_split(struct gmachine* g, size_t n) { - struct node_data* node = (struct node_data*) stack_pop(&g->stack); - for(size_t i = 0; i < n; i++) { - stack_push(&g->stack, node->array[i]); - } -} - -struct node_base* gmachine_track(struct gmachine* g, struct node_base* b) { - g->gc_node_count++; - b->gc_next = g->gc_nodes; - g->gc_nodes = b; - - if(g->gc_node_count >= g->gc_node_threshold) { - uint64_t nodes_before = g->gc_node_count; - gc_visit_node(b); - gmachine_gc(g); - g->gc_node_threshold = g->gc_node_count * 2; - } - - return b; -} - -void gmachine_gc(struct gmachine* g) { - for(size_t i = 0; i < g->stack.count; i++) { - gc_visit_node(g->stack.data[i]); - } - - struct node_base** head_ptr = &g->gc_nodes; - while(*head_ptr) { - if((*head_ptr)->gc_reachable) { - (*head_ptr)->gc_reachable = 0; - head_ptr = &(*head_ptr)->gc_next; - } else { - struct node_base* to_free = *head_ptr; - *head_ptr = to_free->gc_next; - free_node_direct(to_free); - free(to_free); - g->gc_node_count--; - } - } -} - -void unwind(struct gmachine* g) { - struct stack* s = &g->stack; - - while(1) { - struct node_base* peek = stack_peek(s, 0); - if(peek->tag == NODE_APP) { - struct node_app* n = (struct node_app*) peek; - stack_push(s, n->left); - } else if(peek->tag == NODE_GLOBAL) { - struct node_global* n = (struct node_global*) peek; - assert(s->count > n->arity); - - for(size_t i = 1; i <= n->arity; i++) { - s->data[s->count - i] - = ((struct node_app*) s->data[s->count - i - 1])->right; - } - - n->function(g); - } else if(peek->tag == NODE_IND) { - struct node_ind* n = (struct node_ind*) peek; - stack_pop(s); - stack_push(s, n->next); - } else { - break; - } - } -} - -extern void f_main(struct gmachine* s); - -void print_node(struct node_base* n) { - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - print_node(app->left); - putchar(' '); - print_node(app->right); - } else if(n->tag == NODE_DATA) { - printf("(Packed)"); - } else if(n->tag == NODE_GLOBAL) { - struct node_global* global = (struct node_global*) n; - printf("(Global: %p)", global->function); - } else if(n->tag == NODE_IND) { - print_node(((struct node_ind*) n)->next); - } else if(n->tag == NODE_NUM) { - struct node_num* num = (struct node_num*) n; - printf("%d", num->value); - } -} - -int main(int argc, char** argv) { - struct gmachine gmachine; - struct node_global* first_node = alloc_global(f_main, 0); - struct node_base* result; - - gmachine_init(&gmachine); - gmachine_track(&gmachine, (struct node_base*) first_node); - stack_push(&gmachine.stack, (struct node_base*) first_node); - unwind(&gmachine); - result = stack_pop(&gmachine.stack); - printf("Result: "); - print_node(result); - putchar('\n'); - gmachine_free(&gmachine); -} diff --git a/code/compiler/12/runtime.h b/code/compiler/12/runtime.h deleted file mode 100644 index 030a27c..0000000 --- a/code/compiler/12/runtime.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include - -struct gmachine; - -enum node_tag { - NODE_APP, - NODE_NUM, - NODE_GLOBAL, - NODE_IND, - NODE_DATA -}; - -struct node_base { - enum node_tag tag; - int8_t gc_reachable; - struct node_base* gc_next; -}; - -struct node_app { - struct node_base base; - struct node_base* left; - struct node_base* right; -}; - -struct node_num { - struct node_base base; - int32_t value; -}; - -struct node_global { - struct node_base base; - int32_t arity; - void (*function)(struct gmachine*); -}; - -struct node_ind { - struct node_base base; - struct node_base* next; -}; - -struct node_data { - struct node_base base; - int8_t tag; - struct node_base** array; -}; - -struct node_base* alloc_node(); -struct node_app* alloc_app(struct node_base* l, struct node_base* r); -struct node_num* alloc_num(int32_t n); -struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a); -struct node_ind* alloc_ind(struct node_base* n); -void free_node_direct(struct node_base*); -void gc_visit_node(struct node_base*); - -struct stack { - size_t size; - size_t count; - struct node_base** data; -}; - -void stack_init(struct stack* s); -void stack_free(struct stack* s); -void stack_push(struct stack* s, struct node_base* n); -struct node_base* stack_pop(struct stack* s); -struct node_base* stack_peek(struct stack* s, size_t o); -void stack_popn(struct stack* s, size_t n); - -struct gmachine { - struct stack stack; - struct node_base* gc_nodes; - int64_t gc_node_count; - int64_t gc_node_threshold; -}; - -void gmachine_init(struct gmachine* g); -void gmachine_free(struct gmachine* g); -void gmachine_slide(struct gmachine* g, size_t n); -void gmachine_update(struct gmachine* g, size_t o); -void gmachine_alloc(struct gmachine* g, size_t o); -void gmachine_pack(struct gmachine* g, size_t n, int8_t t); -void gmachine_split(struct gmachine* g, size_t n); -struct node_base* gmachine_track(struct gmachine* g, struct node_base* b); -void gmachine_gc(struct gmachine* g); diff --git a/code/compiler/12/scanner.l b/code/compiler/12/scanner.l deleted file mode 100644 index 7b61504..0000000 --- a/code/compiler/12/scanner.l +++ /dev/null @@ -1,38 +0,0 @@ -%option noyywrap - -%{ -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" - -#define YY_DECL yy::parser::symbol_type yylex() - -%} - -%% - -[ \n]+ {} -\\ { return yy::parser::make_BACKSLASH(); } -\+ { return yy::parser::make_PLUS(); } -\* { return yy::parser::make_TIMES(); } -- { return yy::parser::make_MINUS(); } -\/ { return yy::parser::make_DIVIDE(); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext)); } -defn { return yy::parser::make_DEFN(); } -data { return yy::parser::make_DATA(); } -case { return yy::parser::make_CASE(); } -of { return yy::parser::make_OF(); } -let { return yy::parser::make_LET(); } -in { return yy::parser::make_IN(); } -\{ { return yy::parser::make_OCURLY(); } -\} { return yy::parser::make_CCURLY(); } -\( { return yy::parser::make_OPAREN(); } -\) { return yy::parser::make_CPAREN(); } -, { return yy::parser::make_COMMA(); } --> { return yy::parser::make_ARROW(); } -= { return yy::parser::make_EQUAL(); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext)); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext)); } - -%% diff --git a/code/compiler/12/test.cpp b/code/compiler/12/test.cpp deleted file mode 100644 index 7972fa3..0000000 --- a/code/compiler/12/test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "graph.hpp" - -int main() { - function_graph graph; - graph.add_edge("f", "g"); - graph.add_edge("g", "h"); - graph.add_edge("h", "f"); - - graph.add_edge("i", "j"); - graph.add_edge("j", "i"); - - graph.add_edge("j", "f"); - - graph.add_edge("x", "f"); - graph.add_edge("x", "i"); - - for(auto& group : graph.compute_order()) { - std::cout << "Group: " << std::endl; - for(auto& member : group->members) { - std::cout << member << std::endl; - } - } -} diff --git a/code/compiler/12/type.cpp b/code/compiler/12/type.cpp deleted file mode 100644 index c4ff35a..0000000 --- a/code/compiler/12/type.cpp +++ /dev/null @@ -1,219 +0,0 @@ -#include "type.hpp" -#include -#include -#include -#include -#include "error.hpp" - -bool type::is_arrow(const type_mgr& mgr) const { return false; } - -void type_scheme::print(const type_mgr& mgr, std::ostream& to) const { - if(forall.size() != 0) { - to << "forall "; - for(auto& var : forall) { - to << var << " "; - } - to << ". "; - } - monotype->print(mgr, to); -} - -type_ptr type_scheme::instantiate(type_mgr& mgr) const { - if(forall.size() == 0) return monotype; - std::map subst; - for(auto& var : forall) { - subst[var] = mgr.new_type(); - } - return mgr.substitute(subst, monotype); -} - -void type_var::print(const type_mgr& mgr, std::ostream& to) const { - auto it = mgr.types.find(name); - if(it != mgr.types.end()) { - it->second->print(mgr, to); - } else { - to << name; - } -} - -bool type_var::is_arrow(const type_mgr& mgr) const { - auto it = mgr.types.find(name); - if(it != mgr.types.end()) { - return it->second->is_arrow(mgr); - } else { - return false; - } -} - -void type_base::print(const type_mgr& mgr, std::ostream& to) const { - to << name; -} - -void type_arr::print(const type_mgr& mgr, std::ostream& to) const { - bool print_parenths = left->is_arrow(mgr); - if(print_parenths) to << "("; - left->print(mgr, to); - if(print_parenths) to << ")"; - to << " -> "; - right->print(mgr, to); -} - -bool type_arr::is_arrow(const type_mgr& mgr) const { - return true; -} - -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 = ""; - - while(temp != -1) { - str += (char) ('a' + (temp % 26)); - temp = temp / 26 - 1; - } - - std::reverse(str.begin(), str.end()); - return str; -} - -type_ptr type_mgr::new_type() { - return type_ptr(new type_var(new_type_name())); -} - -type_ptr type_mgr::new_arrow_type() { - return type_ptr(new type_arr(new_type(), new_type())); -} - -type_ptr type_mgr::resolve(type_ptr t, type_var*& var) const { - type_var* cast; - - var = nullptr; - while((cast = dynamic_cast(t.get()))) { - auto it = types.find(cast->name); - - if(it == types.end()) { - var = cast; - break; - } - t = it->second; - } - - return t; -} - -void type_mgr::unify(type_ptr l, type_ptr r) { - type_var *lvar, *rvar; - type_arr *larr, *rarr; - type_base *lid, *rid; - type_app *lapp, *rapp; - - l = resolve(l, lvar); - r = resolve(r, rvar); - - if(lvar) { - bind(lvar->name, r); - return; - } else if(rvar) { - bind(rvar->name, l); - return; - } else if((larr = dynamic_cast(l.get())) && - (rarr = dynamic_cast(r.get()))) { - unify(larr->left, rarr->left); - unify(larr->right, rarr->right); - return; - } else if((lid = dynamic_cast(l.get())) && - (rid = dynamic_cast(r.get()))) { - if(lid->name == rid->name && lid->arity == rid->arity) 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); -} - -type_ptr type_mgr::substitute(const std::map& subst, const type_ptr& t) const { - type_ptr temp = t; - while(type_var* var = dynamic_cast(temp.get())) { - auto subst_it = subst.find(var->name); - if(subst_it != subst.end()) return subst_it->second; - auto var_it = types.find(var->name); - if(var_it == types.end()) return t; - temp = var_it->second; - } - - if(type_arr* arr = dynamic_cast(temp.get())) { - auto left_result = substitute(subst, arr->left); - auto right_result = substitute(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(temp.get())) { - auto constructor_result = substitute(subst, app->constructor); - bool arg_changed = false; - std::vector new_args; - for(auto& arg : app->arguments) { - auto arg_result = substitute(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; -} - -void type_mgr::bind(const std::string& s, type_ptr t) { - type_var* other = dynamic_cast(t.get()); - - if(other && other->name == s) return; - types[s] = t; -} - -void type_mgr::find_free(const type_ptr& t, std::set& into) const { - type_var* var; - type_ptr resolved = resolve(t, var); - - if(var) { - into.insert(var->name); - } 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); - } -} - -void type_mgr::find_free(const type_scheme_ptr& t, std::set& into) const { - std::set monotype_free; - type_mgr limited_mgr; - for(auto& binding : types) { - auto existing_position = std::find(t->forall.begin(), t->forall.end(), binding.first); - if(existing_position != t->forall.end()) continue; - limited_mgr.types[binding.first] = binding.second; - } - limited_mgr.find_free(t->monotype, monotype_free); - for(auto& not_free : t->forall) { - monotype_free.erase(not_free); - } - into.insert(monotype_free.begin(), monotype_free.end()); -} diff --git a/code/compiler/12/type.hpp b/code/compiler/12/type.hpp deleted file mode 100644 index 3ab4714..0000000 --- a/code/compiler/12/type.hpp +++ /dev/null @@ -1,99 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -struct type_mgr; - -struct type { - virtual ~type() = default; - - virtual void print(const type_mgr& mgr, std::ostream& to) const = 0; - virtual bool is_arrow(const type_mgr& mgr) const; -}; - -using type_ptr = std::shared_ptr; - -struct type_scheme { - std::vector forall; - type_ptr monotype; - - type_scheme(type_ptr type) : forall(), monotype(std::move(type)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; - type_ptr instantiate(type_mgr& mgr) const; -}; - -using type_scheme_ptr = std::shared_ptr; - -struct type_var : public type { - std::string name; - - type_var(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; - bool is_arrow(const type_mgr& mgr) const; -}; - -struct type_base : public type { - std::string name; - int32_t arity; - - 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; -}; - -struct type_data : public type_base { - struct constructor { - int tag; - }; - - std::map constructors; - - type_data(std::string n, int32_t a = 0) - : type_base(std::move(n), a) {} -}; - -struct type_arr : public type { - type_ptr left; - type_ptr right; - - type_arr(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; - bool is_arrow(const type_mgr& mgr) 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; - - std::string new_type_name(); - type_ptr new_type(); - type_ptr new_arrow_type(); - - void unify(type_ptr l, type_ptr r); - type_ptr substitute( - const std::map& subst, - const type_ptr& t) const; - type_ptr resolve(type_ptr t, type_var*& var) const; - void bind(const std::string& s, type_ptr t); - void find_free(const type_ptr& t, std::set& into) const; - void find_free(const type_scheme_ptr& t, std::set& into) const; -}; diff --git a/code/compiler/12/type_env.cpp b/code/compiler/12/type_env.cpp deleted file mode 100644 index f42e46a..0000000 --- a/code/compiler/12/type_env.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "type_env.hpp" -#include "type.hpp" - -void type_env::find_free(const type_mgr& mgr, std::set& into) const { - if(parent != nullptr) parent->find_free(mgr, into); - for(auto& binding : names) { - mgr.find_free(binding.second.type, into); - } -} - -void type_env::find_free_except(const type_mgr& mgr, const group& avoid, - std::set& into) const { - if(parent != nullptr) parent->find_free(mgr, into); - for(auto& binding : names) { - if(avoid.members.find(binding.first) != avoid.members.end()) continue; - mgr.find_free(binding.second.type, into); - } -} - -type_scheme_ptr type_env::lookup(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second.type; - if(parent) return parent->lookup(name); - return nullptr; -} - -bool type_env::is_global(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second.vis == visibility::global; - if(parent) return parent->is_global(name); - return false; -} - -void type_env::set_mangled_name(const std::string& name, const std::string& mangled) { - auto it = names.find(name); - if(it != names.end()) it->second.mangled_name = mangled; -} - -const std::string& type_env::get_mangled_name(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) - return (it->second.mangled_name != "") ? it->second.mangled_name : name; - if(parent) return parent->get_mangled_name(name); - return name; -} - -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, visibility v) { - type_scheme_ptr new_scheme(new type_scheme(std::move(t))); - names[name] = variable_data(std::move(new_scheme), v, ""); -} - -void type_env::bind(const std::string& name, type_scheme_ptr t, visibility v) { - names[name] = variable_data(std::move(t), v, ""); -} - -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, const group& grp, type_mgr& mgr) { - auto names_it = names.find(name); - if(names_it == names.end()) throw 0; - if(names_it->second.type->forall.size() > 0) throw 0; - - std::set free_in_type; - std::set free_in_env; - mgr.find_free(names_it->second.type->monotype, free_in_type); - find_free_except(mgr, grp, free_in_env); - for(auto& free : free_in_type) { - if(free_in_env.find(free) != free_in_env.end()) continue; - names_it->second.type->forall.push_back(free); - } -} - -type_env_ptr type_scope(type_env_ptr parent) { - return type_env_ptr(new type_env(std::move(parent))); -} diff --git a/code/compiler/12/type_env.hpp b/code/compiler/12/type_env.hpp deleted file mode 100644 index 5292904..0000000 --- a/code/compiler/12/type_env.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once -#include -#include -#include -#include "graph.hpp" -#include "type.hpp" - -struct type_env; -using type_env_ptr = std::shared_ptr; - -enum class visibility { global,local }; - -struct type_env { - struct variable_data { - type_scheme_ptr type; - visibility vis; - std::string mangled_name; - - variable_data() - : variable_data(nullptr, visibility::local, "") {} - variable_data(type_scheme_ptr t, visibility v, std::string n) - : type(std::move(t)), vis(v), mangled_name(std::move(n)) {} - }; - - 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) {} - - void find_free(const type_mgr& mgr, std::set& into) const; - void find_free_except(const type_mgr& mgr, const group& avoid, - std::set& into) const; - type_scheme_ptr lookup(const std::string& name) const; - bool is_global(const std::string& name) const; - void set_mangled_name(const std::string& name, const std::string& mangled); - const std::string& get_mangled_name(const std::string& name) const; - type_ptr lookup_type(const std::string& name) const; - void bind(const std::string& name, type_ptr t, - visibility v = visibility::local); - void bind(const std::string& name, type_scheme_ptr t, - visibility v = visibility::local); - void bind_type(const std::string& type_name, type_ptr t); - void generalize(const std::string& name, const group& grp, type_mgr& mgr); -}; - - -type_env_ptr type_scope(type_env_ptr parent); diff --git a/code/compiler/13/CMakeLists.txt b/code/compiler/13/CMakeLists.txt deleted file mode 100644 index 67a048d..0000000 --- a/code/compiler/13/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -project(compiler) - -# We want C++17 for std::optional -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# Find all the required packages -find_package(BISON) -find_package(FLEX) -find_package(LLVM REQUIRED CONFIG) - -# Set up the flex and bison targets -bison_target(parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser.y - ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp - COMPILE_FLAGS "-d") -flex_target(scanner - ${CMAKE_CURRENT_SOURCE_DIR}/scanner.l - ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp) -add_flex_bison_dependency(scanner parser) - -# Find all the relevant LLVM components -llvm_map_components_to_libnames(LLVM_LIBS core x86asmparser x86codegen) - -# Create compiler executable -add_executable(compiler - 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 - type.cpp type.hpp - error.cpp error.hpp - binop.cpp binop.hpp - instruction.cpp instruction.hpp - graph.cpp graph.hpp - global_scope.cpp global_scope.hpp - parse_driver.cpp parse_driver.hpp - mangler.cpp mangler.hpp - compiler.cpp compiler.hpp - ${BISON_parser_OUTPUTS} - ${FLEX_scanner_OUTPUTS} - main.cpp -) - -# Configure compiler executable -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(compiler PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) -target_include_directories(compiler PUBLIC ${LLVM_INCLUDE_DIRS}) -target_compile_definitions(compiler PUBLIC ${LLVM_DEFINITIONS}) -target_link_libraries(compiler ${LLVM_LIBS}) diff --git a/code/compiler/13/ast.cpp b/code/compiler/13/ast.cpp deleted file mode 100644 index 70c5446..0000000 --- a/code/compiler/13/ast.cpp +++ /dev/null @@ -1,454 +0,0 @@ -#include "ast.hpp" -#include -#include -#include "binop.hpp" -#include "error.hpp" -#include "instruction.hpp" -#include "type.hpp" -#include "type_env.hpp" -#include "env.hpp" - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void ast_int::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "INT: " << value << std::endl; -} - -void ast_int::find_free(std::set& into) { - -} - -type_ptr ast_int::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - return type_ptr(new type_app(env->lookup_type("Int"))); -} - -void ast_int::translate(global_scope& scope) { - -} - -void ast_int::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_pushint(value))); -} - -void ast_lid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LID: " << id << std::endl; -} - -void ast_lid::find_free(std::set& into) { - into.insert(id); -} - -type_ptr ast_lid::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - type_scheme_ptr lid_type = env->lookup(id); - if(!lid_type) - throw type_error("unknown identifier " + id, loc); - return lid_type->instantiate(mgr); -} - -void ast_lid::translate(global_scope& scope) { - -} - -void ast_lid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr( - (this->env->is_global(id)) ? - (instruction*) new instruction_pushglobal(this->env->get_mangled_name(id)) : - (instruction*) new instruction_push(env->get_offset(id)))); -} - -void ast_uid::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "UID: " << id << std::endl; -} - -void ast_uid::find_free(std::set& into) { - -} - -type_ptr ast_uid::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - type_scheme_ptr uid_type = env->lookup(id); - if(!uid_type) - throw type_error("unknown constructor " + id, loc); - return uid_type->instantiate(mgr); -} - -void ast_uid::translate(global_scope& scope) { - -} - -void ast_uid::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr( - new instruction_pushglobal(this->env->get_mangled_name(id)))); -} - -void ast_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BINOP: " << op_name(op) << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -void ast_binop::find_free(std::set& into) { - left->find_free(into); - right->find_free(into); -} - -type_ptr ast_binop::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - type_ptr ltype = left->typecheck(mgr, env); - type_ptr rtype = right->typecheck(mgr, env); - type_ptr ftype = env->lookup(op_name(op))->instantiate(mgr); - if(!ftype) throw type_error("unknown binary operator " + op_name(op), loc); - - // For better type errors, we first require binary function, - // and only then unify each argument. This way, we can - // precisely point out which argument is "wrong". - - type_ptr return_type = mgr.new_type(); - type_ptr second_type = mgr.new_type(); - type_ptr first_type = mgr.new_type(); - type_ptr arrow_one = type_ptr(new type_arr(second_type, return_type)); - type_ptr arrow_two = type_ptr(new type_arr(first_type, arrow_one)); - - mgr.unify(ftype, arrow_two, loc); - mgr.unify(first_type, ltype, left->loc); - mgr.unify(second_type, rtype, right->loc); - return return_type; -} - -void ast_binop::translate(global_scope& scope) { - left->translate(scope); - right->translate(scope); -} - -void ast_binop::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - - auto mangled_name = this->env->get_mangled_name(op_name(op)); - into.push_back(instruction_ptr(new instruction_pushglobal(mangled_name))); - into.push_back(instruction_ptr(new instruction_mkapp())); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_app::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "APP:" << std::endl; - left->print(indent + 1, to); - right->print(indent + 1, to); -} - -void ast_app::find_free(std::set& into) { - left->find_free(into); - right->find_free(into); -} - -type_ptr ast_app::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - type_ptr ltype = left->typecheck(mgr, env); - type_ptr rtype = right->typecheck(mgr, env); - - type_ptr return_type = mgr.new_type(); - type_ptr arrow = type_ptr(new type_arr(rtype, return_type)); - mgr.unify(arrow, ltype, left->loc); - return return_type; -} - -void ast_app::translate(global_scope& scope) { - left->translate(scope); - right->translate(scope); -} - -void ast_app::compile(const env_ptr& env, std::vector& into) const { - right->compile(env, into); - left->compile(env_ptr(new env_offset(1, env)), into); - into.push_back(instruction_ptr(new instruction_mkapp())); -} - -void ast_case::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "CASE: " << std::endl; - for(auto& branch : branches) { - print_indent(indent + 1, to); - branch->pat->print(to); - to << std::endl; - branch->expr->print(indent + 2, to); - } -} - -void ast_case::find_free(std::set& into) { - of->find_free(into); - for(auto& branch : branches) { - std::set free_in_branch; - std::set pattern_variables; - branch->pat->find_variables(pattern_variables); - branch->expr->find_free(free_in_branch); - for(auto& free : free_in_branch) { - if(pattern_variables.find(free) == pattern_variables.end()) - into.insert(free); - } - } -} - -type_ptr ast_case::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - type_var* var; - type_ptr case_type = mgr.resolve(of->typecheck(mgr, env), var); - type_ptr branch_type = mgr.new_type(); - - for(auto& branch : branches) { - type_env_ptr new_env = type_scope(env); - branch->pat->typecheck(case_type, mgr, new_env); - type_ptr curr_branch_type = branch->expr->typecheck(mgr, new_env); - mgr.unify(curr_branch_type, branch_type, branch->expr->loc); - } - - input_type = mgr.resolve(case_type, var); - type_app* app_type; - if(!(app_type = dynamic_cast(input_type.get())) || - !dynamic_cast(app_type->constructor.get())) { - throw type_error("attempting case analysis of non-data type"); - } - - return branch_type; -} - -void ast_case::translate(global_scope& scope) { - of->translate(scope); - for(auto& branch : branches) { - branch->expr->translate(scope); - } -} - -void ast_case::compile(const env_ptr& env, std::vector& into) const { - type_app* app_type = dynamic_cast(input_type.get()); - type_data* type = dynamic_cast(app_type->constructor.get()); - - of->compile(env, into); - into.push_back(instruction_ptr(new instruction_eval())); - - instruction_jump* jump_instruction = new instruction_jump(); - into.push_back(instruction_ptr(jump_instruction)); - for(auto& branch : branches) { - std::vector branch_instructions; - pattern_var* vpat; - pattern_constr* cpat; - - if((vpat = dynamic_cast(branch->pat.get()))) { - branch->expr->compile(env_ptr(new env_offset(1, env)), branch_instructions); - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) != - jump_instruction->tag_mappings.end()) - break; - - jump_instruction->tag_mappings[constr_pair.second.tag] = - jump_instruction->branches.size(); - } - jump_instruction->branches.push_back(std::move(branch_instructions)); - } else if((cpat = dynamic_cast(branch->pat.get()))) { - env_ptr new_env = env; - for(auto it = cpat->params.rbegin(); it != cpat->params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - - branch_instructions.push_back(instruction_ptr(new instruction_split( - cpat->params.size()))); - branch->expr->compile(new_env, branch_instructions); - branch_instructions.push_back(instruction_ptr(new instruction_slide( - cpat->params.size()))); - - int new_tag = type->constructors[cpat->constr].tag; - if(jump_instruction->tag_mappings.find(new_tag) != - jump_instruction->tag_mappings.end()) - throw type_error("technically not a type error: duplicate pattern"); - - jump_instruction->tag_mappings[new_tag] = - jump_instruction->branches.size(); - jump_instruction->branches.push_back(std::move(branch_instructions)); - } - } - - for(auto& constr_pair : type->constructors) { - if(jump_instruction->tag_mappings.find(constr_pair.second.tag) == - jump_instruction->tag_mappings.end()) - throw type_error("non-total pattern"); - } -} - -void ast_let::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LET: " << std::endl; - in->print(indent + 1, to); -} - -void ast_let::find_free(std::set& into) { - definitions.find_free(into); - std::set all_free; - in->find_free(all_free); - for(auto& free_var : all_free) { - if(definitions.defs_defn.find(free_var) == definitions.defs_defn.end()) - into.insert(free_var); - } -} - -type_ptr ast_let::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - definitions.typecheck(mgr, env); - return in->typecheck(mgr, definitions.env); -} - -void ast_let::translate(global_scope& scope) { - for(auto& def : definitions.defs_data) { - def.second->into_globals(scope); - } - for(auto& def : definitions.defs_defn) { - size_t original_params = def.second->params.size(); - std::string original_name = def.second->name; - auto& global_definition = def.second->into_global(scope); - size_t captured = global_definition.params.size() - original_params; - - type_env_ptr mangled_env = type_scope(env); - mangled_env->bind(def.first, env->lookup(def.first), visibility::global); - mangled_env->set_mangled_name(def.first, global_definition.name); - - ast_ptr global_app(new ast_lid(original_name)); - global_app->env = mangled_env; - for(auto& param : global_definition.params) { - if(!(captured--)) break; - ast_ptr new_arg(new ast_lid(param)); - new_arg->env = env; - global_app = ast_ptr(new ast_app(std::move(global_app), std::move(new_arg))); - global_app->env = env; - } - translated_definitions.push_back({ def.first, std::move(global_app) }); - } - in->translate(scope); -} - -void ast_let::compile(const env_ptr& env, std::vector& into) const { - into.push_back(instruction_ptr(new instruction_alloc(translated_definitions.size()))); - env_ptr new_env = env; - for(auto& def : translated_definitions) { - new_env = env_ptr(new env_var(def.first, std::move(new_env))); - } - int offset = translated_definitions.size() - 1; - for(auto& def : translated_definitions) { - def.second->compile(new_env, into); - into.push_back(instruction_ptr(new instruction_update(offset--))); - } - in->compile(new_env, into); - into.push_back(instruction_ptr(new instruction_slide(translated_definitions.size()))); -} - -void ast_lambda::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "LAMBDA"; - for(auto& param : params) { - to << " " << param; - } - to << std::endl; - body->print(indent+1, to); -} - -void ast_lambda::find_free(std::set& into) { - body->find_free(free_variables); - for(auto& param : params) { - free_variables.erase(param); - } - into.insert(free_variables.begin(), free_variables.end()); -} - -type_ptr ast_lambda::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = env; - var_env = type_scope(env); - type_ptr return_type = mgr.new_type(); - type_ptr full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - var_env->bind(*it, param_type); - full_type = type_ptr(new type_arr(std::move(param_type), full_type)); - } - - mgr.unify(return_type, body->typecheck(mgr, var_env), body->loc); - return full_type; -} - -void ast_lambda::translate(global_scope& scope) { - std::vector function_params; - for(auto& free_variable : free_variables) { - if(env->is_global(free_variable)) continue; - function_params.push_back(free_variable); - } - size_t captured_count = function_params.size(); - function_params.insert(function_params.end(), params.begin(), params.end()); - - auto& new_function = scope.add_function("lambda", std::move(function_params), std::move(body)); - type_env_ptr mangled_env = type_scope(env); - mangled_env->bind("lambda", type_scheme_ptr(nullptr), visibility::global); - mangled_env->set_mangled_name("lambda", new_function.name); - ast_ptr new_application = ast_ptr(new ast_lid("lambda")); - new_application->env = mangled_env; - - for(auto& param : new_function.params) { - if(!(captured_count--)) break; - ast_ptr new_arg = ast_ptr(new ast_lid(param)); - new_arg->env = env; - new_application = ast_ptr(new ast_app(std::move(new_application), std::move(new_arg))); - new_application->env = env; - } - translated = std::move(new_application); -} - -void ast_lambda::compile(const env_ptr& env, std::vector& into) const { - translated->compile(env, into); -} - -void pattern_var::print(std::ostream& to) const { - to << var; -} - -void pattern_var::find_variables(std::set& into) const { - into.insert(var); -} - -void pattern_var::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { - env->bind(var, t); -} - -void pattern_constr::print(std::ostream& to) const { - to << constr; - for(auto& param : params) { - to << " " << param; - } -} - -void pattern_constr::find_variables(std::set& into) const { - into.insert(params.begin(), params.end()); -} - -void pattern_constr::typecheck(type_ptr t, type_mgr& mgr, type_env_ptr& env) const { - type_scheme_ptr constructor_type_scheme = env->lookup(constr); - if(!constructor_type_scheme) { - throw type_error("pattern using unknown constructor " + constr, loc); - } - type_ptr constructor_type = constructor_type_scheme->instantiate(mgr); - - for(auto& param : params) { - type_arr* arr = dynamic_cast(constructor_type.get()); - if(!arr) throw type_error("too many parameters in constructor pattern", loc); - - env->bind(param, arr->left); - constructor_type = arr->right; - } - - mgr.unify(t, constructor_type, loc); -} diff --git a/code/compiler/13/ast.hpp b/code/compiler/13/ast.hpp deleted file mode 100644 index 5eeabd2..0000000 --- a/code/compiler/13/ast.hpp +++ /dev/null @@ -1,195 +0,0 @@ -#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; -}; diff --git a/code/compiler/13/binop.cpp b/code/compiler/13/binop.cpp deleted file mode 100644 index 3a5f0ca..0000000 --- a/code/compiler/13/binop.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "binop.hpp" - -std::string op_name(binop op) { - switch(op) { - case PLUS: return "+"; - case MINUS: return "-"; - case TIMES: return "*"; - case DIVIDE: return "/"; - } - return "??"; -} - -std::string op_action(binop op) { - switch(op) { - case PLUS: return "plus"; - case MINUS: return "minus"; - case TIMES: return "times"; - case DIVIDE: return "divide"; - } - return "??"; -} diff --git a/code/compiler/13/binop.hpp b/code/compiler/13/binop.hpp deleted file mode 100644 index d8b44d7..0000000 --- a/code/compiler/13/binop.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include -#include - -enum binop { - PLUS, - MINUS, - TIMES, - DIVIDE -}; - -constexpr binop all_binops[] = { - PLUS, MINUS, TIMES, DIVIDE -}; - -std::string op_name(binop op); -std::string op_action(binop op); diff --git a/code/compiler/13/compiler.cpp b/code/compiler/13/compiler.cpp deleted file mode 100644 index 397e178..0000000 --- a/code/compiler/13/compiler.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "compiler.hpp" -#include "binop.hpp" -#include "error.hpp" -#include "global_scope.hpp" -#include "parse_driver.hpp" -#include "type.hpp" -#include "type_env.hpp" - -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetMachine.h" - -void compiler::add_default_types() { - global_env->bind_type("Int", type_ptr(new type_base("Int"))); -} - -void compiler::add_binop_type(binop op, type_ptr type) { - auto name = mng.new_mangled_name(op_action(op)); - global_env->bind(op_name(op), std::move(type), visibility::global); - global_env->set_mangled_name(op_name(op), name); -} - -void compiler::add_default_function_types() { - type_ptr int_type = global_env->lookup_type("Int"); - assert(int_type != nullptr); - type_ptr int_type_app = type_ptr(new type_app(int_type)); - - type_ptr closed_int_op_type( - new type_arr(int_type_app, type_ptr(new type_arr(int_type_app, int_type_app)))); - - constexpr binop closed_ops[] = { PLUS, MINUS, TIMES, DIVIDE }; - for(auto& op : closed_ops) add_binop_type(op, closed_int_op_type); -} - -void compiler::parse() { - if(!driver()) - throw compiler_error("failed to open file"); -} - -void compiler::typecheck() { - std::set free_variables; - global_defs.find_free(free_variables); - global_defs.typecheck(type_m, global_env); -} - -void compiler::translate() { - for(auto& data : global_defs.defs_data) { - data.second->into_globals(global_scp); - } - for(auto& defn : global_defs.defs_defn) { - auto& function = defn.second->into_global(global_scp); - defn.second->env->set_mangled_name(defn.first, function.name); - } -} - -void compiler::compile() { - global_scp.compile(); -} - -void compiler::create_llvm_binop(binop op) { - auto new_function = - ctx.create_custom_function(global_env->get_mangled_name(op_name(op)), 2); - std::vector instructions; - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_push(1))); - instructions.push_back(instruction_ptr(new instruction_eval())); - instructions.push_back(instruction_ptr(new instruction_binop(op))); - instructions.push_back(instruction_ptr(new instruction_update(2))); - instructions.push_back(instruction_ptr(new instruction_pop(2))); - ctx.get_builder().SetInsertPoint(&new_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.get_builder().CreateRetVoid(); -} - -void compiler::generate_llvm() { - for(auto op : all_binops) { - create_llvm_binop(op); - } - - global_scp.generate_llvm(ctx); -} - -void compiler::output_llvm(const std::string& into) { - std::string targetTriple = llvm::sys::getDefaultTargetTriple(); - - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmParser(); - llvm::InitializeNativeTargetAsmPrinter(); - - std::string error; - const llvm::Target* target = - llvm::TargetRegistry::lookupTarget(targetTriple, error); - if (!target) { - std::cerr << error << std::endl; - } else { - std::string cpu = "generic"; - std::string features = ""; - llvm::TargetOptions options; - std::unique_ptr targetMachine( - target->createTargetMachine(targetTriple, cpu, features, - options, llvm::Optional())); - - ctx.get_module().setDataLayout(targetMachine->createDataLayout()); - ctx.get_module().setTargetTriple(targetTriple); - - std::error_code ec; - llvm::raw_fd_ostream file(into, ec, llvm::sys::fs::F_None); - if (ec) { - throw compiler_error("failed to open object file for writing"); - } else { - llvm::CodeGenFileType type = llvm::CGFT_ObjectFile; - llvm::legacy::PassManager pm; - if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) { - throw compiler_error("failed to add passes to pass manager"); - } else { - pm.run(ctx.get_module()); - file.close(); - } - } - } -} - -compiler::compiler(const std::string& filename) - : file_m(), global_defs(), driver(file_m, global_defs, filename), - global_env(new type_env), type_m(), mng(), global_scp(mng), ctx() { - add_default_types(); - add_default_function_types(); -} - -void compiler::operator()(const std::string& into) { - parse(); - typecheck(); - translate(); - compile(); - generate_llvm(); - output_llvm(into); -} - -file_mgr& compiler::get_file_manager() { - return file_m; -} - -type_mgr& compiler::get_type_manager() { - return type_m; -} diff --git a/code/compiler/13/compiler.hpp b/code/compiler/13/compiler.hpp deleted file mode 100644 index df379ca..0000000 --- a/code/compiler/13/compiler.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "binop.hpp" -#include "parse_driver.hpp" -#include "definition.hpp" -#include "type_env.hpp" -#include "type.hpp" -#include "global_scope.hpp" -#include "mangler.hpp" -#include "llvm_context.hpp" - -class compiler { - private: - file_mgr file_m; - definition_group global_defs; - parse_driver driver; - type_env_ptr global_env; - type_mgr type_m; - mangler mng; - global_scope global_scp; - llvm_context ctx; - - void add_default_types(); - void add_binop_type(binop op, type_ptr type); - void add_default_function_types(); - void parse(); - void typecheck(); - void translate(); - void compile(); - void create_llvm_binop(binop op); - void generate_llvm(); - void output_llvm(const std::string& into); - public: - compiler(const std::string& filename); - void operator()(const std::string& into); - file_mgr& get_file_manager(); - type_mgr& get_type_manager(); -}; diff --git a/code/compiler/13/definition.cpp b/code/compiler/13/definition.cpp deleted file mode 100644 index ae4896d..0000000 --- a/code/compiler/13/definition.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "definition.hpp" -#include -#include "error.hpp" -#include "ast.hpp" -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "type.hpp" -#include "type_env.hpp" -#include "graph.hpp" -#include -#include -#include - -void definition_defn::find_free() { - body->find_free(free_variables); - for(auto& param : params) { - free_variables.erase(param); - } -} - -void definition_defn::insert_types(type_mgr& mgr, type_env_ptr& env, visibility v) { - this->env = env; - var_env = type_scope(env); - return_type = mgr.new_type(); - full_type = return_type; - - for(auto it = params.rbegin(); it != params.rend(); it++) { - type_ptr param_type = mgr.new_type(); - full_type = type_ptr(new type_arr(param_type, full_type)); - var_env->bind(*it, param_type); - } - env->bind(name, full_type, v); -} - -void definition_defn::typecheck(type_mgr& mgr) { - type_ptr body_type = body->typecheck(mgr, var_env); - mgr.unify(return_type, body_type); -} - - -global_function& definition_defn::into_global(global_scope& scope) { - std::vector all_params; - for(auto& free : free_variables) { - if(env->is_global(free)) continue; - all_params.push_back(free); - } - all_params.insert(all_params.end(), params.begin(), params.end()); - body->translate(scope); - return scope.add_function(name, std::move(all_params), std::move(body)); -} - -void definition_data::insert_types(type_env_ptr& env) { - this->env = env; - env->bind_type(name, type_ptr(new type_data(name, vars.size()))); -} - -void definition_data::insert_constructors() const { - type_ptr this_type_ptr = env->lookup_type(name); - type_data* this_type = static_cast(this_type_ptr.get()); - int next_tag = 0; - - std::set var_set; - type_app* return_app = new type_app(std::move(this_type_ptr)); - type_ptr return_type(return_app); - for(auto& var : vars) { - if(var_set.find(var) != var_set.end()) - throw compiler_error( - "type variable " + var + - " used twice in data type definition.", loc); - var_set.insert(var); - return_app->arguments.push_back(type_ptr(new type_var(var))); - } - - for(auto& constructor : constructors) { - constructor->tag = next_tag; - this_type->constructors[constructor->name] = { next_tag++ }; - - type_ptr full_type = return_type; - for(auto it = constructor->types.rbegin(); it != constructor->types.rend(); it++) { - type_ptr type = (*it)->to_type(var_set, env); - full_type = type_ptr(new type_arr(type, full_type)); - } - - type_scheme_ptr full_scheme(new type_scheme(std::move(full_type))); - full_scheme->forall.insert(full_scheme->forall.begin(), vars.begin(), vars.end()); - env->bind(constructor->name, full_scheme, visibility::global); - } -} - -void definition_data::into_globals(global_scope& scope) { - for(auto& constructor : constructors) { - global_constructor& c = scope.add_constructor( - constructor->name, constructor->tag, constructor->types.size()); - env->set_mangled_name(constructor->name, c.name); - } -} - -void definition_group::find_free(std::set& into) { - for(auto& def_pair : defs_defn) { - def_pair.second->find_free(); - for(auto& free_var : def_pair.second->free_variables) { - if(defs_defn.find(free_var) == defs_defn.end()) { - into.insert(free_var); - } else { - def_pair.second->nearby_variables.insert(free_var); - } - } - } -} - -void definition_group::typecheck(type_mgr& mgr, type_env_ptr& env) { - this->env = type_scope(env); - - for(auto& def_data : defs_data) { - def_data.second->insert_types(this->env); - } - for(auto& def_data : defs_data) { - def_data.second->insert_constructors(); - } - - function_graph dependency_graph; - - for(auto& def_defn : defs_defn) { - def_defn.second->find_free(); - dependency_graph.add_function(def_defn.second->name); - - for(auto& dependency : def_defn.second->nearby_variables) { - assert(defs_defn.find(dependency) != defs_defn.end()); - dependency_graph.add_edge(def_defn.second->name, dependency); - } - } - - std::vector groups = dependency_graph.compute_order(); - for(auto it = groups.rbegin(); it != groups.rend(); it++) { - auto& group = *it; - for(auto& def_defnn_name : group->members) { - auto& def_defn = defs_defn.find(def_defnn_name)->second; - def_defn->insert_types(mgr, this->env, vis); - } - 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) { - this->env->generalize(def_defnn_name, *group, mgr); - } - } -} diff --git a/code/compiler/13/definition.hpp b/code/compiler/13/definition.hpp deleted file mode 100644 index a8a6ebc..0000000 --- a/code/compiler/13/definition.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include "instruction.hpp" -#include "llvm_context.hpp" -#include "parsed_type.hpp" -#include "type_env.hpp" -#include "location.hh" -#include "global_scope.hpp" - -struct ast; -using ast_ptr = std::unique_ptr; - -struct constructor { - std::string name; - std::vector types; - int8_t tag; - - constructor(std::string n, std::vector ts) - : name(std::move(n)), types(std::move(ts)) {} -}; - -using constructor_ptr = std::unique_ptr; - -struct definition_defn { - std::string name; - std::vector params; - ast_ptr body; - yy::location loc; - - type_env_ptr env; - type_env_ptr var_env; - std::set free_variables; - std::set nearby_variables; - type_ptr full_type; - type_ptr return_type; - - definition_defn( - std::string n, - std::vector p, - ast_ptr b, - yy::location l = yy::location()) - : name(std::move(n)), params(std::move(p)), body(std::move(b)), loc(std::move(l)) { - - } - - void find_free(); - void insert_types(type_mgr& mgr, type_env_ptr& env, visibility v); - void typecheck(type_mgr& mgr); - - global_function& into_global(global_scope& scope); -}; - -using definition_defn_ptr = std::unique_ptr; - -struct definition_data { - std::string name; - std::vector vars; - std::vector constructors; - yy::location loc; - - type_env_ptr env; - - definition_data( - std::string n, - std::vector vs, - std::vector cs, - yy::location l = yy::location()) - : name(std::move(n)), vars(std::move(vs)), constructors(std::move(cs)), loc(std::move(l)) {} - - void insert_types(type_env_ptr& env); - void insert_constructors() const; - - void into_globals(global_scope& scope); -}; - -using definition_data_ptr = std::unique_ptr; - -struct definition_group { - std::map defs_data; - std::map defs_defn; - visibility vis; - type_env_ptr env; - - definition_group(visibility v = visibility::local) : vis(v) {} - - void find_free(std::set& into); - void typecheck(type_mgr& mgr, type_env_ptr& env); -}; diff --git a/code/compiler/13/env.cpp b/code/compiler/13/env.cpp deleted file mode 100644 index 8bf4401..0000000 --- a/code/compiler/13/env.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "env.hpp" -#include - -int env_var::get_offset(const std::string& name) const { - if(name == this->name) return 0; - assert(parent != nullptr); - return parent->get_offset(name) + 1; -} - -bool env_var::has_variable(const std::string& name) const { - if(name == this->name) return true; - if(parent) return parent->has_variable(name); - return false; -} - -int env_offset::get_offset(const std::string& name) const { - assert(parent != nullptr); - return parent->get_offset(name) + offset; -} - -bool env_offset::has_variable(const std::string& name) const { - if(parent) return parent->has_variable(name); - return false; -} diff --git a/code/compiler/13/env.hpp b/code/compiler/13/env.hpp deleted file mode 100644 index 5413bba..0000000 --- a/code/compiler/13/env.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include -#include - -class env { - public: - virtual ~env() = default; - - virtual int get_offset(const std::string& name) const = 0; - virtual bool has_variable(const std::string& name) const = 0; -}; - -using env_ptr = std::shared_ptr; - -class env_var : public env { - private: - std::string name; - env_ptr parent; - - public: - env_var(std::string n, env_ptr p) - : name(std::move(n)), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; - -class env_offset : public env { - private: - int offset; - env_ptr parent; - - public: - env_offset(int o, env_ptr p) - : offset(o), parent(std::move(p)) {} - - int get_offset(const std::string& name) const; - bool has_variable(const std::string& name) const; -}; diff --git a/code/compiler/13/error.cpp b/code/compiler/13/error.cpp deleted file mode 100644 index 7ed68c1..0000000 --- a/code/compiler/13/error.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "error.hpp" - -const char* compiler_error::what() const noexcept { - return "an error occured while compiling the program"; -} - -void compiler_error::print_about(std::ostream& to) { - to << what() << ": "; - to << description << std::endl; -} - -void compiler_error::print_location(std::ostream& to, file_mgr& fm, bool highlight) { - if(!loc) return; - to << "occuring on line " << loc->begin.line << ":" << std::endl; - fm.print_location(to, *loc, highlight); -} - -void compiler_error::pretty_print(std::ostream& to, file_mgr& fm) { - print_about(to); - print_location(to, fm); -} - -const char* type_error::what() const noexcept { - return "an error occured while checking the types of the program"; -} - -void type_error::pretty_print(std::ostream& to, file_mgr& fm) { - print_about(to); - print_location(to, fm, true); -} - -void unification_error::pretty_print(std::ostream& to, file_mgr& fm, type_mgr& mgr) { - type_error::pretty_print(to, fm); - to << "the expected type was:" << std::endl; - to << " \033[34m"; - left->print(mgr, to); - to << std::endl << "\033[0mwhile the actual type was:" << std::endl; - to << " \033[32m"; - right->print(mgr, to); - to << "\033[0m" << std::endl; -} diff --git a/code/compiler/13/error.hpp b/code/compiler/13/error.hpp deleted file mode 100644 index af5d705..0000000 --- a/code/compiler/13/error.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once -#include -#include -#include "type.hpp" -#include "location.hh" -#include "parse_driver.hpp" - -using maybe_location = std::optional; - -class compiler_error : std::exception { - private: - std::string description; - maybe_location loc; - - public: - compiler_error(std::string d, maybe_location l = std::nullopt) - : description(std::move(d)), loc(std::move(l)) {} - - const char* what() const noexcept override; - - void print_about(std::ostream& to); - void print_location(std::ostream& to, file_mgr& fm, bool highlight = false); - - void pretty_print(std::ostream& to, file_mgr& fm); -}; - -class type_error : compiler_error { - private: - - public: - type_error(std::string d, maybe_location l = std::nullopt) - : compiler_error(std::move(d), std::move(l)) {} - - const char* what() const noexcept override; - void pretty_print(std::ostream& to, file_mgr& fm); -}; - -class unification_error : public type_error { - private: - type_ptr left; - type_ptr right; - - public: - unification_error(type_ptr l, type_ptr r, maybe_location loc = std::nullopt) - : left(std::move(l)), right(std::move(r)), - type_error("failed to unify types", std::move(loc)) {} - - void pretty_print(std::ostream& to, file_mgr& fm, type_mgr& mgr); -}; diff --git a/code/compiler/13/examples/bad1.txt b/code/compiler/13/examples/bad1.txt deleted file mode 100644 index 86d4bc4..0000000 --- a/code/compiler/13/examples/bad1.txt +++ /dev/null @@ -1,2 +0,0 @@ -data Bool = { True, False } -defn main = { 3 + True } diff --git a/code/compiler/13/examples/bad2.txt b/code/compiler/13/examples/bad2.txt deleted file mode 100644 index def8785..0000000 --- a/code/compiler/13/examples/bad2.txt +++ /dev/null @@ -1 +0,0 @@ -defn main = { 1 2 3 4 5 } diff --git a/code/compiler/13/examples/bad3.txt b/code/compiler/13/examples/bad3.txt deleted file mode 100644 index 6f82b3d..0000000 --- a/code/compiler/13/examples/bad3.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } - -defn head l = { - case l of { - Nil -> { 0 } - Cons x y z -> { x } - } -} diff --git a/code/compiler/13/examples/errors/double_catchall.txt b/code/compiler/13/examples/errors/double_catchall.txt deleted file mode 100644 index a8842ac..0000000 --- a/code/compiler/13/examples/errors/double_catchall.txt +++ /dev/null @@ -1,6 +0,0 @@ -defn main = { - case True of { - n -> { 2 } - n -> { 1 } - } -} diff --git a/code/compiler/13/examples/errors/duplicate_type_param.txt b/code/compiler/13/examples/errors/duplicate_type_param.txt deleted file mode 100644 index a89b59d..0000000 --- a/code/compiler/13/examples/errors/duplicate_type_param.txt +++ /dev/null @@ -1 +0,0 @@ -data Pair a a = { MkPair a a } diff --git a/code/compiler/13/examples/errors/exhausted_patterns.txt b/code/compiler/13/examples/errors/exhausted_patterns.txt deleted file mode 100644 index 8ed206a..0000000 --- a/code/compiler/13/examples/errors/exhausted_patterns.txt +++ /dev/null @@ -1,7 +0,0 @@ -defn main = { - case True of { - True -> { 1 } - False -> { 0 } - n -> { 2 } - } -} diff --git a/code/compiler/13/examples/errors/incomplete_patterns.txt b/code/compiler/13/examples/errors/incomplete_patterns.txt deleted file mode 100644 index 84f15d2..0000000 --- a/code/compiler/13/examples/errors/incomplete_patterns.txt +++ /dev/null @@ -1,5 +0,0 @@ -defn main = { - case True of { - True -> { 1 } - } -} diff --git a/code/compiler/13/examples/errors/invalid_case_analysis.txt b/code/compiler/13/examples/errors/invalid_case_analysis.txt deleted file mode 100644 index 1a330bf..0000000 --- a/code/compiler/13/examples/errors/invalid_case_analysis.txt +++ /dev/null @@ -1,7 +0,0 @@ -defn add x y = { x + y } - -defn main = { - case add of { - n -> { 1 } - } -} diff --git a/code/compiler/13/examples/errors/match_after_catchall.txt b/code/compiler/13/examples/errors/match_after_catchall.txt deleted file mode 100644 index 588f213..0000000 --- a/code/compiler/13/examples/errors/match_after_catchall.txt +++ /dev/null @@ -1,7 +0,0 @@ -defn main = { - case True of { - n -> { 2 } - True -> { 1 } - False -> { 0 } - } -} diff --git a/code/compiler/13/examples/errors/pattern_too_few_args.txt b/code/compiler/13/examples/errors/pattern_too_few_args.txt deleted file mode 100644 index 229ff62..0000000 --- a/code/compiler/13/examples/errors/pattern_too_few_args.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } - -defn head l = { - case l of { - Nil -> { 0 } - Cons x -> { x } - } -} diff --git a/code/compiler/13/examples/errors/pattern_too_many_args.txt b/code/compiler/13/examples/errors/pattern_too_many_args.txt deleted file mode 100644 index 6f82b3d..0000000 --- a/code/compiler/13/examples/errors/pattern_too_many_args.txt +++ /dev/null @@ -1,8 +0,0 @@ -data List = { Nil, Cons Int List } - -defn head l = { - case l of { - Nil -> { 0 } - Cons x y z -> { x } - } -} diff --git a/code/compiler/13/examples/errors/pattern_unknown_constructor.txt b/code/compiler/13/examples/errors/pattern_unknown_constructor.txt deleted file mode 100644 index ea79da8..0000000 --- a/code/compiler/13/examples/errors/pattern_unknown_constructor.txt +++ /dev/null @@ -1,6 +0,0 @@ -defn main = { - case True of { - NotBool -> { 1 } - True -> { 2 } - } -} diff --git a/code/compiler/13/examples/errors/type_redefinition.txt b/code/compiler/13/examples/errors/type_redefinition.txt deleted file mode 100644 index da359ed..0000000 --- a/code/compiler/13/examples/errors/type_redefinition.txt +++ /dev/null @@ -1 +0,0 @@ -data Bool = { True, False } diff --git a/code/compiler/13/examples/errors/unknown_lid.txt b/code/compiler/13/examples/errors/unknown_lid.txt deleted file mode 100644 index 8b735f4..0000000 --- a/code/compiler/13/examples/errors/unknown_lid.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn main = { - weird 1 -} diff --git a/code/compiler/13/examples/errors/unknown_type.txt b/code/compiler/13/examples/errors/unknown_type.txt deleted file mode 100644 index b17668f..0000000 --- a/code/compiler/13/examples/errors/unknown_type.txt +++ /dev/null @@ -1 +0,0 @@ -data Wrapper = { Wrap Weird } diff --git a/code/compiler/13/examples/errors/unknown_type_param.txt b/code/compiler/13/examples/errors/unknown_type_param.txt deleted file mode 100644 index 98fbd88..0000000 --- a/code/compiler/13/examples/errors/unknown_type_param.txt +++ /dev/null @@ -1 +0,0 @@ -data Wrapper = { Wrap a } diff --git a/code/compiler/13/examples/errors/unknown_uid.txt b/code/compiler/13/examples/errors/unknown_uid.txt deleted file mode 100644 index 0bbf2a3..0000000 --- a/code/compiler/13/examples/errors/unknown_uid.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn main = { - Weird 1 -} diff --git a/code/compiler/13/examples/errors/wrong_type_kind.txt b/code/compiler/13/examples/errors/wrong_type_kind.txt deleted file mode 100644 index 5e14674..0000000 --- a/code/compiler/13/examples/errors/wrong_type_kind.txt +++ /dev/null @@ -1 +0,0 @@ -data Wrapper = { Wrap (Int Bool) } diff --git a/code/compiler/13/examples/fixpoint.txt b/code/compiler/13/examples/fixpoint.txt deleted file mode 100644 index aba81e8..0000000 --- a/code/compiler/13/examples/fixpoint.txt +++ /dev/null @@ -1,17 +0,0 @@ -data List a = { Nil, Cons a (List a) } - -defn fix f = { let { defn x = { f x } } in { x } } -defn fixpointOnes fo = { Cons 1 fo } -defn sumTwo l = { - case l of { - Nil -> { 0 } - Cons x xs -> { - x + case xs of { - Nil -> { 0 } - Cons y ys -> { y } - } - } - } -} - -defn main = { sumTwo (fix fixpointOnes) } diff --git a/code/compiler/13/examples/if.txt b/code/compiler/13/examples/if.txt deleted file mode 100644 index c00df35..0000000 --- a/code/compiler/13/examples/if.txt +++ /dev/null @@ -1,8 +0,0 @@ -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/code/compiler/13/examples/lambda.txt b/code/compiler/13/examples/lambda.txt deleted file mode 100644 index 35deace..0000000 --- a/code/compiler/13/examples/lambda.txt +++ /dev/null @@ -1,19 +0,0 @@ -data List a = { Nil, Cons a (List a) } - -defn sum l = { - case l of { - Nil -> { 0 } - Cons x xs -> { x + sum xs} - } -} - -defn map f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { Cons (f x) (map f xs) } - } -} - -defn main = { - sum (map \x -> { x * x } (map (\x -> { x + x }) (Cons 1 (Cons 2 (Cons 3 Nil))))) -} diff --git a/code/compiler/13/examples/letin.txt b/code/compiler/13/examples/letin.txt deleted file mode 100644 index 9e163b2..0000000 --- a/code/compiler/13/examples/letin.txt +++ /dev/null @@ -1,47 +0,0 @@ -data Bool = { True, False } - -data List a = { Nil, Cons a (List a) } - -defn if c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn mergeUntil l r p = { - let { - defn mergeLeft nl nr = { - case nl of { - Nil -> { Nil } - Cons x xs -> { if (p x) (Cons x (mergeRight xs nr)) Nil } - } - } - defn mergeRight nl nr = { - case nr of { - Nil -> { Nil } - Cons x xs -> { if (p x) (Cons x (mergeLeft nl xs)) Nil } - } - } - } in { - mergeLeft l r - } -} - -defn const x y = { x } - -defn sum l = { - case l of { - Nil -> { 0 } - Cons x xs -> { x + sum xs } - } -} - -defn main = { - let { - defn firstList = { Cons 1 (Cons 3 (Cons 5 Nil)) } - defn secondList = { Cons 2 (Cons 4 (Cons 6 Nil)) } - } in { - sum (mergeUntil firstList secondList (const True)) - } -} diff --git a/code/compiler/13/examples/list.txt b/code/compiler/13/examples/list.txt deleted file mode 100644 index 159bd1c..0000000 --- a/code/compiler/13/examples/list.txt +++ /dev/null @@ -1,32 +0,0 @@ -data List a = { Nil, Cons a (List a) } - -defn map f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { Cons (f x) (map f xs) } - } -} - -defn foldl f b l = { - case l of { - Nil -> { b } - Cons x xs -> { foldl f (f b x) xs } - } -} - -defn foldr f b l = { - case l of { - Nil -> { b } - Cons x xs -> { f x (foldr f b xs) } - } -} - -defn list = { Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil))) } - -defn add x y = { x + y } -defn sum l = { foldr add 0 l } - -defn skipAdd x y = { y + 1 } -defn length l = { foldr skipAdd 0 l } - -defn main = { sum list + length list } diff --git a/code/compiler/13/examples/mutual_recursion.txt b/code/compiler/13/examples/mutual_recursion.txt deleted file mode 100644 index 7fabf43..0000000 --- a/code/compiler/13/examples/mutual_recursion.txt +++ /dev/null @@ -1,25 +0,0 @@ -data Bool = { True, False } -data List = { Nil, Cons Int List } - -defn if c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn oddEven l e = { - case l of { - Nil -> { e } - Cons x xs -> { evenOdd xs e } - } -} - -defn evenOdd l e = { - case l of { - Nil -> { e } - Cons x xs -> { oddEven xs e } - } -} - -defn main = { if (oddEven (Cons 1 (Cons 2 (Cons 3 Nil))) True) (oddEven (Cons 1 (Cons 2 (Cons 3 Nil))) 1) 3 } diff --git a/code/compiler/13/examples/packed.txt b/code/compiler/13/examples/packed.txt deleted file mode 100644 index 8f25f71..0000000 --- a/code/compiler/13/examples/packed.txt +++ /dev/null @@ -1,23 +0,0 @@ -data Pair a b = { Pair a b } - -defn packer = { - let { - data Packed a = { Packed a } - defn pack a = { Packed a } - defn unpack p = { - case p of { - Packed a -> { a } - } - } - } in { - Pair pack unpack - } -} - -defn main = { - case packer of { - Pair pack unpack -> { - unpack (pack 3) - } - } -} diff --git a/code/compiler/13/examples/pair.txt b/code/compiler/13/examples/pair.txt deleted file mode 100644 index 3ed8362..0000000 --- a/code/compiler/13/examples/pair.txt +++ /dev/null @@ -1,17 +0,0 @@ -data Pair a b = { MkPair a b } - -defn fst p = { - case p of { - MkPair a b -> { a } - } -} - -defn snd p = { - case p of { - MkPair a b -> { b } - } -} - -defn pair = { MkPair 1 (MkPair 2 3) } - -defn main = { fst pair + snd (snd pair) } diff --git a/code/compiler/13/examples/primes.txt b/code/compiler/13/examples/primes.txt deleted file mode 100644 index 8421849..0000000 --- a/code/compiler/13/examples/primes.txt +++ /dev/null @@ -1,122 +0,0 @@ -data List = { Nil, Cons Nat List } -data Bool = { True, False } -data Nat = { O, S Nat } - -defn if c t e = { - case c of { - True -> { t } - False -> { e } - } -} - -defn toInt n = { - case n of { - O -> { 0 } - S np -> { 1 + toInt np } - } -} - -defn lte n m = { - case m of { - O -> { - case n of { - O -> { True } - S np -> { False } - } - } - S mp -> { - case n of { - O -> { True } - S np -> { lte np mp } - } - } - } -} - -defn minus n m = { - case m of { - O -> { n } - S mp -> { - case n of { - O -> { O } - S np -> { - minus np mp - } - } - } - } -} - -defn mod n m = { - if (lte m n) (mod (minus n m) m) n -} - -defn notDivisibleBy n m = { - case (mod m n) of { - O -> { False } - S mp -> { True } - } -} - -defn filter f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { if (f x) (Cons x (filter f xs)) (filter f xs) } - } -} - -defn map f l = { - case l of { - Nil -> { Nil } - Cons x xs -> { Cons (f x) (map f xs) } - } -} - -defn nats = { - Cons (S (S O)) (map S nats) -} - -defn primesRec l = { - case l of { - Nil -> { Nil } - Cons p xs -> { Cons p (primesRec (filter (notDivisibleBy p) xs)) } - } -} - -defn primes = { - primesRec nats -} - -defn take n l = { - case l of { - Nil -> { Nil } - Cons x xs -> { - case n of { - O -> { Nil } - S np -> { Cons x (take np xs) } - } - } - } -} - -defn head l = { - case l of { - Nil -> { O } - Cons x xs -> { x } - } -} - -defn reverseAcc a l = { - case l of { - Nil -> { a } - Cons x xs -> { reverseAcc (Cons x a) xs } - } -} - -defn reverse l = { - reverseAcc Nil l -} - -defn main = { - toInt (head (reverse (take ((S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S (S O))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) primes))) -} diff --git a/code/compiler/13/examples/runtime1.c b/code/compiler/13/examples/runtime1.c deleted file mode 100644 index 0157051..0000000 --- a/code/compiler/13/examples/runtime1.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "../runtime.h" - -void f_add(struct stack* s) { - struct node_num* left = (struct node_num*) eval(stack_peek(s, 0)); - struct node_num* right = (struct node_num*) eval(stack_peek(s, 1)); - stack_push(s, (struct node_base*) alloc_num(left->value + right->value)); -} - -void f_main(struct stack* s) { - // PushInt 320 - stack_push(s, (struct node_base*) alloc_num(320)); - - // PushInt 6 - stack_push(s, (struct node_base*) alloc_num(6)); - - // PushGlobal f_add (the function for +) - stack_push(s, (struct node_base*) alloc_global(f_add, 2)); - - struct node_base* left; - struct node_base* right; - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); - - // MkApp - left = stack_pop(s); - right = stack_pop(s); - stack_push(s, (struct node_base*) alloc_app(left, right)); -} diff --git a/code/compiler/13/examples/works1.txt b/code/compiler/13/examples/works1.txt deleted file mode 100644 index a2d647f..0000000 --- a/code/compiler/13/examples/works1.txt +++ /dev/null @@ -1,2 +0,0 @@ -defn main = { sum 320 6 } -defn sum x y = { x + y } diff --git a/code/compiler/13/examples/works2.txt b/code/compiler/13/examples/works2.txt deleted file mode 100644 index 8332fde..0000000 --- a/code/compiler/13/examples/works2.txt +++ /dev/null @@ -1,3 +0,0 @@ -defn add x y = { x + y } -defn double x = { add x x } -defn main = { double 163 } diff --git a/code/compiler/13/examples/works3.txt b/code/compiler/13/examples/works3.txt deleted file mode 100644 index cfd2ef3..0000000 --- a/code/compiler/13/examples/works3.txt +++ /dev/null @@ -1,9 +0,0 @@ -data List a = { Nil, Cons a (List a) } -data Bool = { True, False } -defn length l = { - case l of { - Nil -> { 0 } - Cons x xs -> { 1 + length xs } - } -} -defn main = { length (Cons 1 (Cons 2 (Cons 3 Nil))) + length (Cons True (Cons False (Cons True Nil))) } diff --git a/code/compiler/13/examples/works4.txt b/code/compiler/13/examples/works4.txt deleted file mode 100644 index 7674691..0000000 --- a/code/compiler/13/examples/works4.txt +++ /dev/null @@ -1,16 +0,0 @@ -data List = { Nil, Cons Int List } - -defn add x y = { x + y } -defn mul x y = { x * y } - -defn foldr f b l = { - case l of { - Nil -> { b } - Cons x xs -> { f x (foldr f b xs) } - } -} - -defn main = { - foldr add 0 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) + - foldr mul 1 (Cons 1 (Cons 2 (Cons 3 (Cons 4 Nil)))) -} diff --git a/code/compiler/13/examples/works5.txt b/code/compiler/13/examples/works5.txt deleted file mode 100644 index 3a8aff5..0000000 --- a/code/compiler/13/examples/works5.txt +++ /dev/null @@ -1,17 +0,0 @@ -data List = { Nil, Cons Int List } - -defn sumZip l m = { - case l of { - Nil -> { 0 } - Cons x xs -> { - case m of { - Nil -> { 0 } - Cons y ys -> { x + y + sumZip xs ys } - } - } - } -} - -defn ones = { Cons 1 ones } - -defn main = { sumZip ones (Cons 1 (Cons 2 (Cons 3 Nil))) } diff --git a/code/compiler/13/global_scope.cpp b/code/compiler/13/global_scope.cpp deleted file mode 100644 index 9ffc4cb..0000000 --- a/code/compiler/13/global_scope.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "global_scope.hpp" -#include "ast.hpp" - -void global_function::compile() { - env_ptr new_env = env_ptr(new env_offset(0, nullptr)); - for(auto it = params.rbegin(); it != params.rend(); it++) { - new_env = env_ptr(new env_var(*it, new_env)); - } - body->compile(new_env, instructions); - instructions.push_back(instruction_ptr(new instruction_update(params.size()))); - instructions.push_back(instruction_ptr(new instruction_pop(params.size()))); -} - -void global_function::declare_llvm(llvm_context& ctx) { - generated_function = ctx.create_custom_function(name, params.size()); -} - -void global_function::generate_llvm(llvm_context& ctx) { - ctx.get_builder().SetInsertPoint(&generated_function->getEntryBlock()); - for(auto& instruction : instructions) { - instruction->gen_llvm(ctx, generated_function); - } - ctx.get_builder().CreateRetVoid(); -} - -void global_constructor::generate_llvm(llvm_context& ctx) { - auto new_function = - ctx.create_custom_function(name, arity); - std::vector instructions; - instructions.push_back(instruction_ptr(new instruction_pack(tag, arity))); - instructions.push_back(instruction_ptr(new instruction_update(0))); - ctx.get_builder().SetInsertPoint(&new_function->getEntryBlock()); - for (auto& instruction : instructions) { - instruction->gen_llvm(ctx, new_function); - } - ctx.get_builder().CreateRetVoid(); -} - -global_function& global_scope::add_function( - const std::string& n, - std::vector ps, - ast_ptr b) { - auto name = mng->new_mangled_name(n); - global_function* new_function = - new global_function(std::move(name), std::move(ps), std::move(b)); - functions.push_back(global_function_ptr(new_function)); - return *new_function; -} - -global_constructor& global_scope::add_constructor( - const std::string& n, - int8_t t, - size_t a) { - auto name = mng->new_mangled_name(n); - global_constructor* new_constructor = new global_constructor(name, t, a); - constructors.push_back(global_constructor_ptr(new_constructor)); - return *new_constructor; -} - -void global_scope::compile() { - for(auto& function : functions) { - function->compile(); - } -} - -void global_scope::generate_llvm(llvm_context& ctx) { - for(auto& constructor : constructors) { - constructor->generate_llvm(ctx); - } - for(auto& function : functions) { - function->declare_llvm(ctx); - } - for(auto& function : functions) { - function->generate_llvm(ctx); - } -} diff --git a/code/compiler/13/global_scope.hpp b/code/compiler/13/global_scope.hpp deleted file mode 100644 index 872bda6..0000000 --- a/code/compiler/13/global_scope.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include "instruction.hpp" -#include "mangler.hpp" - -struct ast; -using ast_ptr = std::unique_ptr; - -struct global_function { - std::string name; - std::vector params; - ast_ptr body; - - std::vector instructions; - llvm::Function* generated_function; - - global_function(std::string n, std::vector ps, ast_ptr b) - : name(std::move(n)), params(std::move(ps)), body(std::move(b)) {} - - void compile(); - void declare_llvm(llvm_context& ctx); - void generate_llvm(llvm_context& ctx); -}; - -using global_function_ptr = std::unique_ptr; - -struct global_constructor { - std::string name; - int8_t tag; - size_t arity; - - global_constructor(std::string n, int8_t t, size_t a) - : name(std::move(n)), tag(t), arity(a) {} - - void generate_llvm(llvm_context& ctx); -}; - -using global_constructor_ptr = std::unique_ptr; - -class global_scope { - private: - std::vector functions; - std::vector constructors; - mangler* mng; - - public: - global_scope(mangler& m) : mng(&m) {} - - global_function& add_function( - const std::string& n, - std::vector ps, - ast_ptr b); - global_constructor& add_constructor(const std::string& n, int8_t t, size_t a); - - void compile(); - void generate_llvm(llvm_context& ctx); -}; diff --git a/code/compiler/13/graph.cpp b/code/compiler/13/graph.cpp deleted file mode 100644 index c648acd..0000000 --- a/code/compiler/13/graph.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "graph.hpp" - -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/code/compiler/13/graph.hpp b/code/compiler/13/graph.hpp deleted file mode 100644 index 072e085..0000000 --- a/code/compiler/13/graph.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -using function = std::string; - -struct group { - std::set members; -}; - -using group_ptr = std::unique_ptr; - -class function_graph { - private: - using group_id = size_t; - - struct group_data { - std::set functions; - std::set adjacency_list; - size_t indegree; - - group_data() : indegree(0) {} - }; - - using data_ptr = std::shared_ptr; - using edge = std::pair; - using group_edge = std::pair; - - std::map> adjacency_lists; - std::set edges; - - std::set compute_transitive_edges(); - void create_groups( - const std::set&, - std::map&, - std::map&); - void create_edges( - std::map&, - std::map&); - std::vector generate_order( - std::map&, - std::map&); - - public: - std::set& add_function(const function& f); - void add_edge(const function& from, const function& to); - std::vector compute_order(); -}; diff --git a/code/compiler/13/instruction.cpp b/code/compiler/13/instruction.cpp deleted file mode 100644 index b3fff15..0000000 --- a/code/compiler/13/instruction.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include "instruction.hpp" -#include "llvm_context.hpp" -#include -#include - -using namespace llvm; - -static void print_indent(int n, std::ostream& to) { - while(n--) to << " "; -} - -void instruction_pushint::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushInt(" << value << ")" << std::endl; -} - -void instruction_pushint::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_num(f, ctx.create_i32(value))); -} - -void instruction_pushglobal::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "PushGlobal(" << name << ")" << std::endl; -} - -void instruction_pushglobal::gen_llvm(llvm_context& ctx, Function* f) const { - auto& global_f = ctx.get_custom_function(name); - auto arity = ctx.create_i32(global_f.arity); - ctx.create_push(f, ctx.create_global(f, global_f.function, arity)); -} - -void instruction_push::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Push(" << offset << ")" << std::endl; -} - -void instruction_push::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_push(f, ctx.create_peek(f, ctx.create_size(offset))); -} - -void instruction_pop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pop(" << count << ")" << std::endl; -} - -void instruction_pop::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_popn(f, ctx.create_size(count)); -} - -void instruction_mkapp::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "MkApp()" << std::endl; -} - -void instruction_mkapp::gen_llvm(llvm_context& ctx, Function* f) const { - auto left = ctx.create_pop(f); - auto right = ctx.create_pop(f); - ctx.create_push(f, ctx.create_app(f, left, right)); -} - -void instruction_update::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Update(" << offset << ")" << std::endl; -} - -void instruction_update::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_update(f, ctx.create_size(offset)); -} - -void instruction_pack::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Pack(" << tag << ", " << size << ")" << std::endl; -} - -void instruction_pack::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_pack(f, ctx.create_size(size), ctx.create_i8(tag)); -} - -void instruction_split::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Split()" << std::endl; -} - -void instruction_split::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_split(f, ctx.create_size(size)); -} - -void instruction_jump::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Jump(" << std::endl; - for(auto& instruction_set : branches) { - for(auto& instruction : instruction_set) { - instruction->print(indent + 2, to); - } - to << std::endl; - } - print_indent(indent, to); - to << ")" << std::endl; -} - -void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const { - auto top_node = ctx.create_peek(f, ctx.create_size(0)); - auto tag = ctx.unwrap_data_tag(top_node); - auto safety_block = ctx.create_basic_block("safety", f); - auto switch_op = ctx.get_builder().CreateSwitch(tag, safety_block, tag_mappings.size()); - std::vector blocks; - - for(auto& branch : branches) { - auto branch_block = ctx.create_basic_block("branch", f); - ctx.get_builder().SetInsertPoint(branch_block); - for(auto& instruction : branch) { - instruction->gen_llvm(ctx, f); - } - ctx.get_builder().CreateBr(safety_block); - blocks.push_back(branch_block); - } - - for(auto& mapping : tag_mappings) { - switch_op->addCase(ctx.create_i8(mapping.first), blocks[mapping.second]); - } - - ctx.get_builder().SetInsertPoint(safety_block); -} - -void instruction_slide::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Slide(" << offset << ")" << std::endl; -} - -void instruction_slide::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_slide(f, ctx.create_size(offset)); -} - -void instruction_binop::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "BinOp(" << op_action(op) << ")" << std::endl; -} - -void instruction_binop::gen_llvm(llvm_context& ctx, Function* f) const { - auto left_int = ctx.unwrap_num(ctx.create_pop(f)); - auto right_int = ctx.unwrap_num(ctx.create_pop(f)); - llvm::Value* result; - switch(op) { - case PLUS: result = ctx.get_builder().CreateAdd(left_int, right_int); break; - case MINUS: result = ctx.get_builder().CreateSub(left_int, right_int); break; - case TIMES: result = ctx.get_builder().CreateMul(left_int, right_int); break; - case DIVIDE: result = ctx.get_builder().CreateSDiv(left_int, right_int); break; - } - ctx.create_push(f, ctx.create_num(f, result)); -} - -void instruction_eval::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Eval()" << std::endl; -} - -void instruction_eval::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_unwind(f); -} - -void instruction_alloc::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Alloc(" << amount << ")" << std::endl; -} - -void instruction_alloc::gen_llvm(llvm_context& ctx, Function* f) const { - ctx.create_alloc(f, ctx.create_size(amount)); -} - -void instruction_unwind::print(int indent, std::ostream& to) const { - print_indent(indent, to); - to << "Unwind()" << std::endl; -} - -void instruction_unwind::gen_llvm(llvm_context& ctx, Function* f) const { - // Nothing -} diff --git a/code/compiler/13/instruction.hpp b/code/compiler/13/instruction.hpp deleted file mode 100644 index abe2409..0000000 --- a/code/compiler/13/instruction.hpp +++ /dev/null @@ -1,142 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include "binop.hpp" -#include "llvm_context.hpp" - -struct instruction { - virtual ~instruction() = default; - - virtual void print(int indent, std::ostream& to) const = 0; - virtual void gen_llvm(llvm_context& ctx, llvm::Function* f) const = 0; -}; - -using instruction_ptr = std::unique_ptr; - -struct instruction_pushint : public instruction { - int value; - - instruction_pushint(int v) - : value(v) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pushglobal : public instruction { - std::string name; - - instruction_pushglobal(std::string n) - : name(std::move(n)) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_push : public instruction { - int offset; - - instruction_push(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pop : public instruction { - int count; - - instruction_pop(int c) - : count(c) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_mkapp : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_update : public instruction { - int offset; - - instruction_update(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_pack : public instruction { - int tag; - int size; - - instruction_pack(int t, int s) - : tag(t), size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_split : public instruction { - int size; - - instruction_split(int s) - : size(s) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_jump : public instruction { - std::vector> branches; - std::map tag_mappings; - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_slide : public instruction { - int offset; - - instruction_slide(int o) - : offset(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_binop : public instruction { - binop op; - - instruction_binop(binop o) - : op(o) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_eval : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_alloc : public instruction { - int amount; - - instruction_alloc(int a) - : amount(a) {} - - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; - -struct instruction_unwind : public instruction { - void print(int indent, std::ostream& to) const; - void gen_llvm(llvm_context& ctx, llvm::Function* f) const; -}; diff --git a/code/compiler/13/llvm_context.cpp b/code/compiler/13/llvm_context.cpp deleted file mode 100644 index 8d9fb1f..0000000 --- a/code/compiler/13/llvm_context.cpp +++ /dev/null @@ -1,294 +0,0 @@ -#include "llvm_context.hpp" -#include - -using namespace llvm; - -void llvm_context::create_types() { - stack_type = StructType::create(ctx, "stack"); - gmachine_type = StructType::create(ctx, "gmachine"); - stack_ptr_type = PointerType::getUnqual(stack_type); - gmachine_ptr_type = PointerType::getUnqual(gmachine_type); - tag_type = IntegerType::getInt8Ty(ctx); - struct_types["node_base"] = StructType::create(ctx, "node_base"); - struct_types["node_app"] = StructType::create(ctx, "node_app"); - struct_types["node_num"] = StructType::create(ctx, "node_num"); - struct_types["node_global"] = StructType::create(ctx, "node_global"); - struct_types["node_ind"] = StructType::create(ctx, "node_ind"); - struct_types["node_data"] = StructType::create(ctx, "node_data"); - node_ptr_type = PointerType::getUnqual(struct_types.at("node_base")); - function_type = FunctionType::get(Type::getVoidTy(ctx), { gmachine_ptr_type }, false); - - gmachine_type->setBody( - stack_ptr_type, - node_ptr_type, - IntegerType::getInt64Ty(ctx), - IntegerType::getInt64Ty(ctx) - ); - struct_types.at("node_base")->setBody( - IntegerType::getInt32Ty(ctx), - IntegerType::getInt8Ty(ctx), - node_ptr_type - ); - struct_types.at("node_app")->setBody( - struct_types.at("node_base"), - node_ptr_type, - node_ptr_type - ); - struct_types.at("node_num")->setBody( - struct_types.at("node_base"), - IntegerType::getInt32Ty(ctx) - ); - struct_types.at("node_global")->setBody( - struct_types.at("node_base"), - FunctionType::get(Type::getVoidTy(ctx), { stack_ptr_type }, false) - ); - struct_types.at("node_ind")->setBody( - struct_types.at("node_base"), - node_ptr_type - ); - struct_types.at("node_data")->setBody( - struct_types.at("node_base"), - IntegerType::getInt8Ty(ctx), - PointerType::getUnqual(node_ptr_type) - ); -} - -void llvm_context::create_functions() { - auto void_type = Type::getVoidTy(ctx); - auto sizet_type = IntegerType::get(ctx, sizeof(size_t) * 8); - functions["stack_init"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_init", - &module - ); - functions["stack_free"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_free", - &module - ); - functions["stack_push"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_push", - &module - ); - functions["stack_pop"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_pop", - &module - ); - functions["stack_peek"] = Function::Create( - FunctionType::get(node_ptr_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_peek", - &module - ); - functions["stack_popn"] = Function::Create( - FunctionType::get(void_type, { stack_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "stack_popn", - &module - ); - functions["gmachine_slide"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_slide", - &module - ); - functions["gmachine_update"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_update", - &module - ); - functions["gmachine_alloc"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_alloc", - &module - ); - functions["gmachine_pack"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type, tag_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_pack", - &module - ); - functions["gmachine_split"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type, sizet_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_split", - &module - ); - functions["gmachine_track"] = Function::Create( - FunctionType::get(node_ptr_type, { gmachine_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "gmachine_track", - &module - ); - - auto int32_type = IntegerType::getInt32Ty(ctx); - functions["alloc_app"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type, node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_app", - &module - ); - functions["alloc_num"] = Function::Create( - FunctionType::get(node_ptr_type, { int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_num", - &module - ); - functions["alloc_global"] = Function::Create( - FunctionType::get(node_ptr_type, { function_type, int32_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_global", - &module - ); - functions["alloc_ind"] = Function::Create( - FunctionType::get(node_ptr_type, { node_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "alloc_ind", - &module - ); - - functions["unwind"] = Function::Create( - FunctionType::get(void_type, { gmachine_ptr_type }, false), - Function::LinkageTypes::ExternalLinkage, - "unwind", - &module - ); -} - -IRBuilder<>& llvm_context::get_builder() { - return builder; -} - -Module& llvm_context::get_module() { - return module; -} - -BasicBlock* llvm_context::create_basic_block(const std::string& name, llvm::Function* f) { - return BasicBlock::Create(ctx, name, f); -} - -ConstantInt* llvm_context::create_i8(int8_t i) { - return ConstantInt::get(ctx, APInt(8, i)); -} -ConstantInt* llvm_context::create_i32(int32_t i) { - return ConstantInt::get(ctx, APInt(32, i)); -} -ConstantInt* llvm_context::create_size(size_t i) { - return ConstantInt::get(ctx, APInt(sizeof(size_t) * 8, i)); -} - -Value* llvm_context::create_pop(Function* f) { - auto pop_f = functions.at("stack_pop"); - return builder.CreateCall(pop_f, { unwrap_gmachine_stack_ptr(f->arg_begin()) }); -} -Value* llvm_context::create_peek(Function* f, Value* off) { - auto peek_f = functions.at("stack_peek"); - return builder.CreateCall(peek_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off }); -} -void llvm_context::create_push(Function* f, Value* v) { - auto push_f = functions.at("stack_push"); - builder.CreateCall(push_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), v }); -} -void llvm_context::create_popn(Function* f, Value* off) { - auto popn_f = functions.at("stack_popn"); - builder.CreateCall(popn_f, { unwrap_gmachine_stack_ptr(f->arg_begin()), off }); -} -void llvm_context::create_update(Function* f, Value* off) { - auto update_f = functions.at("gmachine_update"); - builder.CreateCall(update_f, { f->arg_begin(), off }); -} -void llvm_context::create_pack(Function* f, Value* c, Value* t) { - auto pack_f = functions.at("gmachine_pack"); - builder.CreateCall(pack_f, { f->arg_begin(), c, t }); -} -void llvm_context::create_split(Function* f, Value* c) { - auto split_f = functions.at("gmachine_split"); - builder.CreateCall(split_f, { f->arg_begin(), c }); -} -void llvm_context::create_slide(Function* f, Value* off) { - auto slide_f = functions.at("gmachine_slide"); - builder.CreateCall(slide_f, { f->arg_begin(), off }); -} -void llvm_context::create_alloc(Function* f, Value* n) { - auto alloc_f = functions.at("gmachine_alloc"); - builder.CreateCall(alloc_f, { f->arg_begin(), n }); -} -Value* llvm_context::create_track(Function* f, Value* v) { - auto track_f = functions.at("gmachine_track"); - return builder.CreateCall(track_f, { f->arg_begin(), v }); -} - -void llvm_context::create_unwind(Function* f) { - auto unwind_f = functions.at("unwind"); - builder.CreateCall(unwind_f, { f->args().begin() }); -} - -Value* llvm_context::unwrap_gmachine_stack_ptr(Value* g) { - auto offset_0 = create_i32(0); - return builder.CreateGEP(g, { offset_0, offset_0 }); -} - -Value* llvm_context::unwrap_num(Value* v) { - auto num_ptr_type = PointerType::getUnqual(struct_types.at("node_num")); - auto cast = builder.CreatePointerCast(v, num_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto int_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(int_ptr); -} -Value* llvm_context::create_num(Function* f, Value* v) { - auto alloc_num_f = functions.at("alloc_num"); - auto alloc_num_call = builder.CreateCall(alloc_num_f, { v }); - return create_track(f, alloc_num_call); -} - -Value* llvm_context::unwrap_data_tag(Value* v) { - auto data_ptr_type = PointerType::getUnqual(struct_types.at("node_data")); - auto cast = builder.CreatePointerCast(v, data_ptr_type); - auto offset_0 = create_i32(0); - auto offset_1 = create_i32(1); - auto tag_ptr = builder.CreateGEP(cast, { offset_0, offset_1 }); - return builder.CreateLoad(tag_ptr); -} - -Value* llvm_context::create_global(Function* f, Value* gf, Value* a) { - auto alloc_global_f = functions.at("alloc_global"); - auto alloc_global_call = builder.CreateCall(alloc_global_f, { gf, a }); - return create_track(f, alloc_global_call); -} - -Value* llvm_context::create_app(Function* f, Value* l, Value* r) { - auto alloc_app_f = functions.at("alloc_app"); - auto alloc_app_call = builder.CreateCall(alloc_app_f, { l, r }); - return create_track(f, alloc_app_call); -} - -llvm::Function* llvm_context::create_custom_function(const std::string& name, int32_t arity) { - auto void_type = llvm::Type::getVoidTy(ctx); - auto new_function = llvm::Function::Create( - function_type, - llvm::Function::LinkageTypes::ExternalLinkage, - "f_" + name, - &module - ); - auto start_block = llvm::BasicBlock::Create(ctx, "entry", new_function); - - auto new_custom_f = custom_function_ptr(new custom_function()); - new_custom_f->arity = arity; - new_custom_f->function = new_function; - custom_functions["f_" + name] = std::move(new_custom_f); - - return new_function; -} - -llvm_context::custom_function& llvm_context::get_custom_function(const std::string& name) { - return *custom_functions.at("f_" + name); -} diff --git a/code/compiler/13/llvm_context.hpp b/code/compiler/13/llvm_context.hpp deleted file mode 100644 index e1bdc7c..0000000 --- a/code/compiler/13/llvm_context.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -class llvm_context { - public: - struct custom_function { - llvm::Function* function; - int32_t arity; - }; - - using custom_function_ptr = std::unique_ptr; - - private: - llvm::LLVMContext ctx; - llvm::IRBuilder<> builder; - llvm::Module module; - - std::map custom_functions; - std::map functions; - std::map struct_types; - - llvm::StructType* stack_type; - llvm::StructType* gmachine_type; - llvm::PointerType* stack_ptr_type; - llvm::PointerType* gmachine_ptr_type; - llvm::PointerType* node_ptr_type; - llvm::IntegerType* tag_type; - llvm::FunctionType* function_type; - - void create_types(); - void create_functions(); - - public: - llvm_context() - : builder(ctx), module("bloglang", ctx) { - create_types(); - create_functions(); - } - - llvm::IRBuilder<>& get_builder(); - llvm::Module& get_module(); - - llvm::BasicBlock* create_basic_block(const std::string& name, llvm::Function* f); - - llvm::ConstantInt* create_i8(int8_t); - llvm::ConstantInt* create_i32(int32_t); - llvm::ConstantInt* create_size(size_t); - - llvm::Value* create_pop(llvm::Function*); - llvm::Value* create_peek(llvm::Function*, llvm::Value*); - void create_push(llvm::Function*, llvm::Value*); - void create_popn(llvm::Function*, llvm::Value*); - void create_update(llvm::Function*, llvm::Value*); - void create_pack(llvm::Function*, llvm::Value*, llvm::Value*); - void create_split(llvm::Function*, llvm::Value*); - void create_slide(llvm::Function*, llvm::Value*); - void create_alloc(llvm::Function*, llvm::Value*); - llvm::Value* create_track(llvm::Function*, llvm::Value*); - - void create_unwind(llvm::Function*); - - llvm::Value* unwrap_gmachine_stack_ptr(llvm::Value*); - - llvm::Value* unwrap_num(llvm::Value*); - llvm::Value* create_num(llvm::Function*, llvm::Value*); - - llvm::Value* unwrap_data_tag(llvm::Value*); - - llvm::Value* create_global(llvm::Function*, llvm::Value*, llvm::Value*); - - llvm::Value* create_app(llvm::Function*, llvm::Value*, llvm::Value*); - - llvm::Function* create_custom_function(const std::string& name, int32_t arity); - custom_function& get_custom_function(const std::string& name); -}; diff --git a/code/compiler/13/main.cpp b/code/compiler/13/main.cpp deleted file mode 100644 index 4607e5b..0000000 --- a/code/compiler/13/main.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "ast.hpp" -#include -#include "parser.hpp" -#include "compiler.hpp" -#include "error.hpp" - -void yy::parser::error(const yy::location& loc, const std::string& msg) { - std::cerr << "An error occured: " << msg << std::endl; -} - -int main(int argc, char** argv) { - if(argc != 2) { - std::cerr << "please enter a file to compile." << std::endl; - exit(1); - } - compiler cmp(argv[1]); - - try { - cmp("program.o"); - } catch(unification_error& err) { - err.pretty_print(std::cerr, cmp.get_file_manager(), cmp.get_type_manager()); - } catch(type_error& err) { - err.pretty_print(std::cerr, cmp.get_file_manager()); - } catch (compiler_error& err) { - err.pretty_print(std::cerr, cmp.get_file_manager()); - } -} diff --git a/code/compiler/13/mangler.cpp b/code/compiler/13/mangler.cpp deleted file mode 100644 index 3beb052..0000000 --- a/code/compiler/13/mangler.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "mangler.hpp" - -std::string mangler::new_mangled_name(const std::string& n) { - auto occurence_it = occurence_count.find(n); - int occurence = 0; - if(occurence_it != occurence_count.end()) { - occurence = occurence_it->second + 1; - } - occurence_count[n] = occurence; - - std::string final_name = n; - if (occurence != 0) { - final_name += "_"; - final_name += std::to_string(occurence); - } - return final_name; -} diff --git a/code/compiler/13/mangler.hpp b/code/compiler/13/mangler.hpp deleted file mode 100644 index 0df8efd..0000000 --- a/code/compiler/13/mangler.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include -#include - -class mangler { - private: - std::map occurence_count; - - public: - std::string new_mangled_name(const std::string& str); -}; diff --git a/code/compiler/13/parse_driver.cpp b/code/compiler/13/parse_driver.cpp deleted file mode 100644 index f353e45..0000000 --- a/code/compiler/13/parse_driver.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "parse_driver.hpp" -#include "scanner.hpp" -#include - -file_mgr::file_mgr() : file_offset(0) { - line_offsets.push_back(0); -} - -void file_mgr::write(const char* buf, size_t len) { - string_stream.write(buf, len); - file_offset += len; -} - -void file_mgr::mark_line() { - line_offsets.push_back(file_offset); -} - -void file_mgr::finalize() { - file_contents = string_stream.str(); -} - -size_t file_mgr::get_index(int line, int column) const { - assert(line > 0 && line <= line_offsets.size()); - return line_offsets.at(line-1) + column - 1; -} - -size_t file_mgr::get_line_end(int line) const { - if(line == line_offsets.size()) return file_contents.size(); - return get_index(line+1, 1); -} - -void file_mgr::print_location( - std::ostream& stream, - const yy::location& loc, - bool highlight) const { - size_t print_start = get_index(loc.begin.line, 1); - size_t highlight_start = get_index(loc.begin.line, loc.begin.column); - size_t highlight_end = get_index(loc.end.line, loc.end.column); - size_t print_end = get_line_end(loc.end.line); - const char* content = file_contents.c_str(); - stream.write(content + print_start, highlight_start - print_start); - if(highlight) stream << "\033[4;31m"; - stream.write(content + highlight_start, highlight_end - highlight_start); - if(highlight) stream << "\033[0m"; - stream.write(content + highlight_end, print_end - highlight_end); -} - -bool parse_driver::operator()() { - FILE* stream = fopen(file_name.c_str(), "r"); - if(!stream) return false; - yyscan_t scanner; - yylex_init(&scanner); - yyset_in(stream, scanner); - yy::parser parser(scanner, *this); - parser(); - yylex_destroy(scanner); - fclose(stream); - file_m->finalize(); - return true; -} - -yy::location& parse_driver::get_current_location() { - return location; -} - -file_mgr& parse_driver::get_file_manager() const { - return *file_m; -} - -definition_group& parse_driver::get_global_defs() const { - return *global_defs; -} diff --git a/code/compiler/13/parse_driver.hpp b/code/compiler/13/parse_driver.hpp deleted file mode 100644 index bf1a492..0000000 --- a/code/compiler/13/parse_driver.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once -#include -#include -#include -#include "definition.hpp" -#include "location.hh" -#include "parser.hpp" - -struct parse_driver; - -void scanner_init(parse_driver* d, yyscan_t* scanner); -void scanner_destroy(yyscan_t* scanner); - -class file_mgr { - private: - std::ostringstream string_stream; - std::string file_contents; - - size_t file_offset; - std::vector line_offsets; - public: - file_mgr(); - - void write(const char* buffer, size_t len); - void mark_line(); - void finalize(); - - size_t get_index(int line, int column) const; - size_t get_line_end(int line) const; - void print_location( - std::ostream& stream, - const yy::location& loc, - bool highlight = true) const; -}; - -class parse_driver { - private: - std::string file_name; - yy::location location; - definition_group* global_defs; - file_mgr* file_m; - - public: - parse_driver( - file_mgr& mgr, - definition_group& defs, - const std::string& file) - : file_name(file), file_m(&mgr), global_defs(&defs) {} - - bool operator()(); - yy::location& get_current_location(); - file_mgr& get_file_manager() const; - definition_group& get_global_defs() const; -}; - -#define YY_DECL yy::parser::symbol_type yylex(yyscan_t yyscanner, parse_driver& drv) - -YY_DECL; diff --git a/code/compiler/13/parsed_type.cpp b/code/compiler/13/parsed_type.cpp deleted file mode 100644 index 2fa31ee..0000000 --- a/code/compiler/13/parsed_type.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "parsed_type.hpp" -#include -#include "type.hpp" -#include "type_env.hpp" -#include "error.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 type_error("no such type or type constructor " + name); - type_base* base_type; - if(!(base_type = dynamic_cast(parent_type.get()))) - throw type_error("invalid type " + name); - if(base_type->arity != arguments.size()) { - std::ostringstream error_stream; - error_stream << "invalid application of type "; - error_stream << name; - error_stream << " (" << base_type->arity << " argument(s) expected, "; - error_stream << "but " << arguments.size() << " provided)"; - throw type_error(error_stream.str()); - } - - 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 type_error("the type variable " + var + " was not explicitly declared."); - 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/13/parsed_type.hpp b/code/compiler/13/parsed_type.hpp deleted file mode 100644 index 96c0fcc..0000000 --- a/code/compiler/13/parsed_type.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#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/13/parser.y b/code/compiler/13/parser.y deleted file mode 100644 index 86740cd..0000000 --- a/code/compiler/13/parser.y +++ /dev/null @@ -1,180 +0,0 @@ -%code requires { -#include -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parser.hpp" -#include "parsed_type.hpp" - -class parse_driver; -using yyscan_t = void*; -} - -%param { yyscan_t scanner } -%param { parse_driver& drv } - -%code { -#include "parse_driver.hpp" -} - -%token BACKSLASH -%token PLUS -%token TIMES -%token MINUS -%token DIVIDE -%token INT -%token DEFN -%token DATA -%token CASE -%token OF -%token LET -%token IN -%token OCURLY -%token CCURLY -%token OPAREN -%token CPAREN -%token COMMA -%token ARROW -%token EQUAL -%token LID -%token UID - -%language "c++" -%define api.value.type variant -%define api.token.constructor - -%locations - -%type > lowercaseParams -%type > branches -%type > constructors -%type > typeList -%type definitions -%type type nonArrowType typeListElement -%type aAdd aMul case let lambda app appBase -%type data -%type defn -%type branch -%type pattern -%type constructor - -%start program - -%% - -program - : definitions { $1.vis = visibility::global; std::swap(drv.get_global_defs(), $1); } - ; - -definitions - : definitions defn { $$ = std::move($1); auto name = $2->name; $$.defs_defn[name] = std::move($2); } - | definitions data { $$ = std::move($1); auto name = $2->name; $$.defs_data[name] = std::move($2); } - | %empty { $$ = definition_group(); } - ; - -defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY - { $$ = definition_defn_ptr( - new definition_defn(std::move($2), std::move($3), std::move($6), @$)); } - ; - -lowercaseParams - : %empty { $$ = std::vector(); } - | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } - ; - -aAdd - : aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3), @$)); } - | aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3), @$)); } - | aMul { $$ = std::move($1); } - ; - -aMul - : aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3), @$)); } - | aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3), @$)); } - | app { $$ = std::move($1); } - ; - -app - : app appBase { $$ = ast_ptr(new ast_app(std::move($1), std::move($2), @$)); } - | appBase { $$ = std::move($1); } - ; - -appBase - : INT { $$ = ast_ptr(new ast_int($1, @$)); } - | LID { $$ = ast_ptr(new ast_lid(std::move($1), @$)); } - | UID { $$ = ast_ptr(new ast_uid(std::move($1), @$)); } - | OPAREN aAdd CPAREN { $$ = std::move($2); } - | case { $$ = std::move($1); } - | let { $$ = std::move($1); } - | lambda { $$ = std::move($1); } - ; - -let - : LET OCURLY definitions CCURLY IN OCURLY aAdd CCURLY - { $$ = ast_ptr(new ast_let(std::move($3), std::move($7), @$)); } - ; - -lambda - : BACKSLASH lowercaseParams ARROW OCURLY aAdd CCURLY - { $$ = ast_ptr(new ast_lambda(std::move($2), std::move($5), @$)); } - ; - -case - : CASE aAdd OF OCURLY branches CCURLY - { $$ = ast_ptr(new ast_case(std::move($2), std::move($5), @$)); } - ; - -branches - : branches branch { $$ = std::move($1); $$.push_back(std::move($2)); } - | branch { $$ = std::vector(); $$.push_back(std::move($1));} - ; - -branch - : pattern ARROW OCURLY aAdd CCURLY - { $$ = branch_ptr(new branch(std::move($1), std::move($4))); } - ; - -pattern - : LID { $$ = pattern_ptr(new pattern_var(std::move($1), @$)); } - | UID lowercaseParams - { $$ = pattern_ptr(new pattern_constr(std::move($1), std::move($2), @$)); } - ; - -data - : DATA UID lowercaseParams EQUAL OCURLY constructors CCURLY - { $$ = definition_data_ptr(new definition_data(std::move($2), std::move($3), std::move($6), @$)); } - ; - -constructors - : constructors COMMA constructor { $$ = std::move($1); $$.push_back(std::move($3)); } - | constructor - { $$ = std::vector(); $$.push_back(std::move($1)); } - ; - -constructor - : UID typeList - { $$ = constructor_ptr(new constructor(std::move($1), std::move($2))); } - ; - -type - : nonArrowType ARROW type { $$ = parsed_type_ptr(new parsed_type_arr(std::move($1), std::move($3))); } - | nonArrowType { $$ = std::move($1); } - ; - -nonArrowType - : UID typeList { $$ = parsed_type_ptr(new parsed_type_app(std::move($1), std::move($2))); } - | LID { $$ = parsed_type_ptr(new parsed_type_var(std::move($1))); } - | OPAREN type CPAREN { $$ = std::move($2); } - ; - -typeListElement - : OPAREN type CPAREN { $$ = std::move($2); } - | UID { $$ = parsed_type_ptr(new parsed_type_app(std::move($1), {})); } - | LID { $$ = parsed_type_ptr(new parsed_type_var(std::move($1))); } - ; - -typeList - : %empty { $$ = std::vector(); } - | typeList typeListElement { $$ = std::move($1); $$.push_back(std::move($2)); } - ; diff --git a/code/compiler/13/runtime.c b/code/compiler/13/runtime.c deleted file mode 100644 index 7b8a7c3..0000000 --- a/code/compiler/13/runtime.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include -#include -#include -#include "runtime.h" - -struct node_base* alloc_node() { - struct node_base* new_node = malloc(sizeof(struct node_app)); - new_node->gc_next = NULL; - new_node->gc_reachable = 0; - assert(new_node != NULL); - return new_node; -} - -struct node_app* alloc_app(struct node_base* l, struct node_base* r) { - struct node_app* node = (struct node_app*) alloc_node(); - node->base.tag = NODE_APP; - node->left = l; - node->right = r; - return node; -} - -struct node_num* alloc_num(int32_t n) { - struct node_num* node = (struct node_num*) alloc_node(); - node->base.tag = NODE_NUM; - node->value = n; - return node; -} - -struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a) { - struct node_global* node = (struct node_global*) alloc_node(); - node->base.tag = NODE_GLOBAL; - node->arity = a; - node->function = f; - return node; -} - -struct node_ind* alloc_ind(struct node_base* n) { - struct node_ind* node = (struct node_ind*) alloc_node(); - node->base.tag = NODE_IND; - node->next = n; - return node; -} - -void free_node_direct(struct node_base* n) { - if(n->tag == NODE_DATA) { - free(((struct node_data*) n)->array); - } -} - -void gc_visit_node(struct node_base* n) { - if(n->gc_reachable) return; - n->gc_reachable = 1; - - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - gc_visit_node(app->left); - gc_visit_node(app->right); - } if(n->tag == NODE_IND) { - struct node_ind* ind = (struct node_ind*) n; - gc_visit_node(ind->next); - } if(n->tag == NODE_DATA) { - struct node_data* data = (struct node_data*) n; - struct node_base** to_visit = data->array; - while(*to_visit) { - gc_visit_node(*to_visit); - to_visit++; - } - } -} - -void stack_init(struct stack* s) { - s->size = 4; - s->count = 0; - s->data = malloc(sizeof(*s->data) * s->size); - assert(s->data != NULL); -} - -void stack_free(struct stack* s) { - free(s->data); -} - -void stack_push(struct stack* s, struct node_base* n) { - while(s->count >= s->size) { - s->data = realloc(s->data, sizeof(*s->data) * (s->size *= 2)); - assert(s->data != NULL); - } - s->data[s->count++] = n; -} - -struct node_base* stack_pop(struct stack* s) { - assert(s->count > 0); - return s->data[--s->count]; -} - -struct node_base* stack_peek(struct stack* s, size_t o) { - assert(s->count > o); - return s->data[s->count - o - 1]; -} - -void stack_popn(struct stack* s, size_t n) { - assert(s->count >= n); - s->count -= n; -} - -void gmachine_init(struct gmachine* g) { - stack_init(&g->stack); - g->gc_nodes = NULL; - g->gc_node_count = 0; - g->gc_node_threshold = 128; -} - -void gmachine_free(struct gmachine* g) { - stack_free(&g->stack); - struct node_base* to_free = g->gc_nodes; - struct node_base* next; - - while(to_free) { - next = to_free->gc_next; - free_node_direct(to_free); - free(to_free); - to_free = next; - } -} - -void gmachine_slide(struct gmachine* g, size_t n) { - assert(g->stack.count > n); - g->stack.data[g->stack.count - n - 1] = g->stack.data[g->stack.count - 1]; - g->stack.count -= n; -} - -void gmachine_update(struct gmachine* g, size_t o) { - assert(g->stack.count > o + 1); - struct node_ind* ind = - (struct node_ind*) g->stack.data[g->stack.count - o - 2]; - ind->base.tag = NODE_IND; - ind->next = g->stack.data[g->stack.count -= 1]; -} - -void gmachine_alloc(struct gmachine* g, size_t o) { - while(o--) { - stack_push(&g->stack, - gmachine_track(g, (struct node_base*) alloc_ind(NULL))); - } -} - -void gmachine_pack(struct gmachine* g, size_t n, int8_t t) { - assert(g->stack.count >= n); - - struct node_base** data = malloc(sizeof(*data) * (n + 1)); - assert(data != NULL); - memcpy(data, &g->stack.data[g->stack.count - n], n * sizeof(*data)); - data[n] = NULL; - - struct node_data* new_node = (struct node_data*) alloc_node(); - new_node->array = data; - new_node->base.tag = NODE_DATA; - new_node->tag = t; - - stack_popn(&g->stack, n); - stack_push(&g->stack, gmachine_track(g, (struct node_base*) new_node)); -} - -void gmachine_split(struct gmachine* g, size_t n) { - struct node_data* node = (struct node_data*) stack_pop(&g->stack); - for(size_t i = 0; i < n; i++) { - stack_push(&g->stack, node->array[i]); - } -} - -struct node_base* gmachine_track(struct gmachine* g, struct node_base* b) { - g->gc_node_count++; - b->gc_next = g->gc_nodes; - g->gc_nodes = b; - - if(g->gc_node_count >= g->gc_node_threshold) { - uint64_t nodes_before = g->gc_node_count; - gc_visit_node(b); - gmachine_gc(g); - g->gc_node_threshold = g->gc_node_count * 2; - } - - return b; -} - -void gmachine_gc(struct gmachine* g) { - for(size_t i = 0; i < g->stack.count; i++) { - gc_visit_node(g->stack.data[i]); - } - - struct node_base** head_ptr = &g->gc_nodes; - while(*head_ptr) { - if((*head_ptr)->gc_reachable) { - (*head_ptr)->gc_reachable = 0; - head_ptr = &(*head_ptr)->gc_next; - } else { - struct node_base* to_free = *head_ptr; - *head_ptr = to_free->gc_next; - free_node_direct(to_free); - free(to_free); - g->gc_node_count--; - } - } -} - -void unwind(struct gmachine* g) { - struct stack* s = &g->stack; - - while(1) { - struct node_base* peek = stack_peek(s, 0); - if(peek->tag == NODE_APP) { - struct node_app* n = (struct node_app*) peek; - stack_push(s, n->left); - } else if(peek->tag == NODE_GLOBAL) { - struct node_global* n = (struct node_global*) peek; - assert(s->count > n->arity); - - for(size_t i = 1; i <= n->arity; i++) { - s->data[s->count - i] - = ((struct node_app*) s->data[s->count - i - 1])->right; - } - - n->function(g); - } else if(peek->tag == NODE_IND) { - struct node_ind* n = (struct node_ind*) peek; - stack_pop(s); - stack_push(s, n->next); - } else { - break; - } - } -} - -extern void f_main(struct gmachine* s); - -void print_node(struct node_base* n) { - if(n->tag == NODE_APP) { - struct node_app* app = (struct node_app*) n; - print_node(app->left); - putchar(' '); - print_node(app->right); - } else if(n->tag == NODE_DATA) { - printf("(Packed)"); - } else if(n->tag == NODE_GLOBAL) { - struct node_global* global = (struct node_global*) n; - printf("(Global: %p)", global->function); - } else if(n->tag == NODE_IND) { - print_node(((struct node_ind*) n)->next); - } else if(n->tag == NODE_NUM) { - struct node_num* num = (struct node_num*) n; - printf("%d", num->value); - } -} - -int main(int argc, char** argv) { - struct gmachine gmachine; - struct node_global* first_node = alloc_global(f_main, 0); - struct node_base* result; - - gmachine_init(&gmachine); - gmachine_track(&gmachine, (struct node_base*) first_node); - stack_push(&gmachine.stack, (struct node_base*) first_node); - unwind(&gmachine); - result = stack_pop(&gmachine.stack); - printf("Result: "); - print_node(result); - putchar('\n'); - gmachine_free(&gmachine); -} diff --git a/code/compiler/13/runtime.h b/code/compiler/13/runtime.h deleted file mode 100644 index 030a27c..0000000 --- a/code/compiler/13/runtime.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once -#include - -struct gmachine; - -enum node_tag { - NODE_APP, - NODE_NUM, - NODE_GLOBAL, - NODE_IND, - NODE_DATA -}; - -struct node_base { - enum node_tag tag; - int8_t gc_reachable; - struct node_base* gc_next; -}; - -struct node_app { - struct node_base base; - struct node_base* left; - struct node_base* right; -}; - -struct node_num { - struct node_base base; - int32_t value; -}; - -struct node_global { - struct node_base base; - int32_t arity; - void (*function)(struct gmachine*); -}; - -struct node_ind { - struct node_base base; - struct node_base* next; -}; - -struct node_data { - struct node_base base; - int8_t tag; - struct node_base** array; -}; - -struct node_base* alloc_node(); -struct node_app* alloc_app(struct node_base* l, struct node_base* r); -struct node_num* alloc_num(int32_t n); -struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a); -struct node_ind* alloc_ind(struct node_base* n); -void free_node_direct(struct node_base*); -void gc_visit_node(struct node_base*); - -struct stack { - size_t size; - size_t count; - struct node_base** data; -}; - -void stack_init(struct stack* s); -void stack_free(struct stack* s); -void stack_push(struct stack* s, struct node_base* n); -struct node_base* stack_pop(struct stack* s); -struct node_base* stack_peek(struct stack* s, size_t o); -void stack_popn(struct stack* s, size_t n); - -struct gmachine { - struct stack stack; - struct node_base* gc_nodes; - int64_t gc_node_count; - int64_t gc_node_threshold; -}; - -void gmachine_init(struct gmachine* g); -void gmachine_free(struct gmachine* g); -void gmachine_slide(struct gmachine* g, size_t n); -void gmachine_update(struct gmachine* g, size_t o); -void gmachine_alloc(struct gmachine* g, size_t o); -void gmachine_pack(struct gmachine* g, size_t n, int8_t t); -void gmachine_split(struct gmachine* g, size_t n); -struct node_base* gmachine_track(struct gmachine* g, struct node_base* b); -void gmachine_gc(struct gmachine* g); diff --git a/code/compiler/13/scanner.l b/code/compiler/13/scanner.l deleted file mode 100644 index b29987e..0000000 --- a/code/compiler/13/scanner.l +++ /dev/null @@ -1,45 +0,0 @@ -%option noyywrap -%option reentrant -%option header-file="scanner.hpp" - -%{ -#include -#include "ast.hpp" -#include "definition.hpp" -#include "parse_driver.hpp" -#include "parser.hpp" - -#define YY_USER_ACTION \ - drv.get_file_manager().write(yytext, yyleng); \ - LOC.step(); LOC.columns(yyleng); -#define LOC drv.get_current_location() -%} - -%% - -\n { drv.get_current_location().lines(); drv.get_file_manager().mark_line(); } -[ ]+ {} -\\ { return yy::parser::make_BACKSLASH(LOC); } -\+ { return yy::parser::make_PLUS(LOC); } -\* { return yy::parser::make_TIMES(LOC); } -- { return yy::parser::make_MINUS(LOC); } -\/ { return yy::parser::make_DIVIDE(LOC); } -[0-9]+ { return yy::parser::make_INT(atoi(yytext), LOC); } -defn { return yy::parser::make_DEFN(LOC); } -data { return yy::parser::make_DATA(LOC); } -case { return yy::parser::make_CASE(LOC); } -of { return yy::parser::make_OF(LOC); } -let { return yy::parser::make_LET(LOC); } -in { return yy::parser::make_IN(LOC); } -\{ { return yy::parser::make_OCURLY(LOC); } -\} { return yy::parser::make_CCURLY(LOC); } -\( { return yy::parser::make_OPAREN(LOC); } -\) { return yy::parser::make_CPAREN(LOC); } -, { return yy::parser::make_COMMA(LOC); } --> { return yy::parser::make_ARROW(LOC); } -= { return yy::parser::make_EQUAL(LOC); } -[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext), LOC); } -[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext), LOC); } -<> { return yy::parser::make_YYEOF(LOC); } - -%% diff --git a/code/compiler/13/test.cpp b/code/compiler/13/test.cpp deleted file mode 100644 index 7972fa3..0000000 --- a/code/compiler/13/test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "graph.hpp" - -int main() { - function_graph graph; - graph.add_edge("f", "g"); - graph.add_edge("g", "h"); - graph.add_edge("h", "f"); - - graph.add_edge("i", "j"); - graph.add_edge("j", "i"); - - graph.add_edge("j", "f"); - - graph.add_edge("x", "f"); - graph.add_edge("x", "i"); - - for(auto& group : graph.compute_order()) { - std::cout << "Group: " << std::endl; - for(auto& member : group->members) { - std::cout << member << std::endl; - } - } -} diff --git a/code/compiler/13/type.cpp b/code/compiler/13/type.cpp deleted file mode 100644 index c604580..0000000 --- a/code/compiler/13/type.cpp +++ /dev/null @@ -1,213 +0,0 @@ -#include "type.hpp" -#include -#include -#include -#include -#include "error.hpp" - -void type_scheme::print(const type_mgr& mgr, std::ostream& to) const { - if(forall.size() != 0) { - to << "forall "; - for(auto& var : forall) { - to << var << " "; - } - to << ". "; - } - monotype->print(mgr, to); -} - -type_ptr type_scheme::instantiate(type_mgr& mgr) const { - if(forall.size() == 0) return monotype; - std::map subst; - for(auto& var : forall) { - subst[var] = mgr.new_type(); - } - return mgr.substitute(subst, monotype); -} - -void type_var::print(const type_mgr& mgr, std::ostream& to) const { - auto type = mgr.lookup(name); - if(type) { - type->print(mgr, to); - } else { - to << name; - } -} - -void type_base::print(const type_mgr& mgr, std::ostream& to) const { - to << name; -} - -void type_arr::print(const type_mgr& mgr, std::ostream& to) const { - type_var* var; - bool print_parenths = dynamic_cast(mgr.resolve(left, var).get()) != nullptr; - if(print_parenths) to << "("; - left->print(mgr, to); - if(print_parenths) to << ")"; - to << " -> "; - right->print(mgr, 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 = ""; - - while(temp != -1) { - str += (char) ('a' + (temp % 26)); - temp = temp / 26 - 1; - } - - std::reverse(str.begin(), str.end()); - return str; -} - -type_ptr type_mgr::new_type() { - return type_ptr(new type_var(new_type_name())); -} - -type_ptr type_mgr::new_arrow_type() { - return type_ptr(new type_arr(new_type(), new_type())); -} - -type_ptr type_mgr::lookup(const std::string& var) const { - auto types_it = types.find(var); - if(types_it != types.end()) return types_it->second; - return nullptr; -} - -type_ptr type_mgr::resolve(type_ptr t, type_var*& var) const { - type_var* cast; - - var = nullptr; - while((cast = dynamic_cast(t.get()))) { - auto it = types.find(cast->name); - - if(it == types.end()) { - var = cast; - break; - } - t = it->second; - } - - return t; -} - -void type_mgr::unify(type_ptr l, type_ptr r, const std::optional& loc) { - type_var *lvar, *rvar; - type_arr *larr, *rarr; - type_base *lid, *rid; - type_app *lapp, *rapp; - - l = resolve(l, lvar); - r = resolve(r, rvar); - - if(lvar) { - bind(lvar->name, r); - return; - } else if(rvar) { - bind(rvar->name, l); - return; - } else if((larr = dynamic_cast(l.get())) && - (rarr = dynamic_cast(r.get()))) { - unify(larr->left, rarr->left, loc); - unify(larr->right, rarr->right, loc); - return; - } else if((lid = dynamic_cast(l.get())) && - (rid = dynamic_cast(r.get()))) { - if(lid->name == rid->name && - lid->arity == rid->arity) - return; - } else if((lapp = dynamic_cast(l.get())) && - (rapp = dynamic_cast(r.get()))) { - unify(lapp->constructor, rapp->constructor, loc); - 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, loc); - left_it++, right_it++; - } - return; - } - - throw unification_error(l, r, loc); -} - -type_ptr type_mgr::substitute(const std::map& subst, const type_ptr& t) const { - type_ptr temp = t; - while(type_var* var = dynamic_cast(temp.get())) { - auto subst_it = subst.find(var->name); - if(subst_it != subst.end()) return subst_it->second; - auto var_it = types.find(var->name); - if(var_it == types.end()) return t; - temp = var_it->second; - } - - if(type_arr* arr = dynamic_cast(temp.get())) { - auto left_result = substitute(subst, arr->left); - auto right_result = substitute(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(temp.get())) { - auto constructor_result = substitute(subst, app->constructor); - bool arg_changed = false; - std::vector new_args; - for(auto& arg : app->arguments) { - auto arg_result = substitute(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; -} - -void type_mgr::bind(const std::string& s, type_ptr t) { - type_var* other = dynamic_cast(t.get()); - - if(other && other->name == s) return; - types[s] = t; -} - -void type_mgr::find_free(const type_ptr& t, std::set& into) const { - type_var* var; - type_ptr resolved = resolve(t, var); - - if(var) { - into.insert(var->name); - } 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); - } -} - -void type_mgr::find_free(const type_scheme_ptr& t, std::set& into) const { - std::set monotype_free; - type_mgr limited_mgr; - for(auto& binding : types) { - auto existing_position = std::find(t->forall.begin(), t->forall.end(), binding.first); - if(existing_position != t->forall.end()) continue; - limited_mgr.types[binding.first] = binding.second; - } - limited_mgr.find_free(t->monotype, monotype_free); - for(auto& not_free : t->forall) { - monotype_free.erase(not_free); - } - into.insert(monotype_free.begin(), monotype_free.end()); -} diff --git a/code/compiler/13/type.hpp b/code/compiler/13/type.hpp deleted file mode 100644 index ada3405..0000000 --- a/code/compiler/13/type.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include "location.hh" - -class type_mgr; - -struct type { - virtual ~type() = default; - - virtual void print(const type_mgr& mgr, std::ostream& to) const = 0; -}; - -using type_ptr = std::shared_ptr; - -struct type_scheme { - std::vector forall; - type_ptr monotype; - - type_scheme(type_ptr type) : forall(), monotype(std::move(type)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; - type_ptr instantiate(type_mgr& mgr) const; -}; - -using type_scheme_ptr = std::shared_ptr; - -struct type_var : public type { - std::string name; - - type_var(std::string n) - : name(std::move(n)) {} - - void print(const type_mgr& mgr, std::ostream& to) const; -}; - -struct type_base : public type { - std::string name; - int32_t arity; - - 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; -}; - -struct type_data : public type_base { - struct constructor { - int tag; - }; - - std::map constructors; - - type_data(std::string n, int32_t a = 0) - : type_base(std::move(n), a) {} -}; - -struct type_arr : public type { - type_ptr left; - type_ptr right; - - type_arr(type_ptr l, type_ptr r) - : left(std::move(l)), right(std::move(r)) {} - - 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; -}; - -class type_mgr { - private: - int last_id = 0; - std::map types; - - public: - std::string new_type_name(); - type_ptr new_type(); - type_ptr new_arrow_type(); - - void unify(type_ptr l, type_ptr r, const std::optional& loc = std::nullopt); - type_ptr substitute( - const std::map& subst, - const type_ptr& t) const; - type_ptr lookup(const std::string& var) const; - type_ptr resolve(type_ptr t, type_var*& var) const; - void bind(const std::string& s, type_ptr t); - void find_free(const type_ptr& t, std::set& into) const; - void find_free(const type_scheme_ptr& t, std::set& into) const; -}; diff --git a/code/compiler/13/type_env.cpp b/code/compiler/13/type_env.cpp deleted file mode 100644 index 47a5212..0000000 --- a/code/compiler/13/type_env.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "type_env.hpp" -#include "type.hpp" -#include "error.hpp" -#include - -void type_env::find_free(const type_mgr& mgr, std::set& into) const { - if(parent != nullptr) parent->find_free(mgr, into); - for(auto& binding : names) { - mgr.find_free(binding.second.type, into); - } -} - -void type_env::find_free_except(const type_mgr& mgr, const group& avoid, - std::set& into) const { - if(parent != nullptr) parent->find_free(mgr, into); - for(auto& binding : names) { - if(avoid.members.find(binding.first) != avoid.members.end()) continue; - mgr.find_free(binding.second.type, into); - } -} - -type_scheme_ptr type_env::lookup(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second.type; - if(parent) return parent->lookup(name); - return nullptr; -} - -bool type_env::is_global(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) return it->second.vis == visibility::global; - if(parent) return parent->is_global(name); - return false; -} - -void type_env::set_mangled_name(const std::string& name, const std::string& mangled) { - auto it = names.find(name); - - // Can't set mangled name for non-existent variable. - assert(it != names.end()); - // Local names shouldn't need mangling. - assert(it->second.vis == visibility::global); - - it->second.mangled_name = mangled; -} - -const std::string& type_env::get_mangled_name(const std::string& name) const { - auto it = names.find(name); - if(it != names.end()) { - assert(it->second.mangled_name); - return *it->second.mangled_name; - } - assert(parent != nullptr); - return parent->get_mangled_name(name); -} - -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, visibility v) { - type_scheme_ptr new_scheme(new type_scheme(std::move(t))); - names[name] = variable_data(std::move(new_scheme), v, std::nullopt); -} - -void type_env::bind(const std::string& name, type_scheme_ptr t, visibility v) { - names[name] = variable_data(std::move(t), v, ""); -} - -void type_env::bind_type(const std::string& type_name, type_ptr t) { - if(lookup_type(type_name) != nullptr) - throw type_error("redefinition of type"); - type_names[type_name] = t; -} - -void type_env::generalize(const std::string& name, const group& grp, type_mgr& mgr) { - auto names_it = names.find(name); - assert(names_it != names.end()); - assert(names_it->second.type->forall.size() == 0); - - std::set free_in_type; - std::set free_in_env; - mgr.find_free(names_it->second.type->monotype, free_in_type); - find_free_except(mgr, grp, free_in_env); - for(auto& free : free_in_type) { - if(free_in_env.find(free) != free_in_env.end()) continue; - names_it->second.type->forall.push_back(free); - } -} - -type_env_ptr type_scope(type_env_ptr parent) { - return type_env_ptr(new type_env(std::move(parent))); -} diff --git a/code/compiler/13/type_env.hpp b/code/compiler/13/type_env.hpp deleted file mode 100644 index 2bc3450..0000000 --- a/code/compiler/13/type_env.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include "graph.hpp" -#include "type.hpp" - -struct type_env; -using type_env_ptr = std::shared_ptr; - -enum class visibility { global,local }; - -class type_env { - private: - struct variable_data { - type_scheme_ptr type; - visibility vis; - std::optional mangled_name; - - variable_data() - : variable_data(nullptr, visibility::local, std::nullopt) {} - variable_data(type_scheme_ptr t, visibility v, std::optional n) - : type(std::move(t)), vis(v), mangled_name(std::move(n)) {} - }; - - type_env_ptr parent; - std::map names; - std::map type_names; - - public: - type_env(type_env_ptr p) : parent(std::move(p)) {} - type_env() : type_env(nullptr) {} - - void find_free(const type_mgr& mgr, std::set& into) const; - void find_free_except(const type_mgr& mgr, const group& avoid, - std::set& into) const; - type_scheme_ptr lookup(const std::string& name) const; - bool is_global(const std::string& name) const; - void set_mangled_name(const std::string& name, const std::string& mangled); - const std::string& get_mangled_name(const std::string& name) const; - type_ptr lookup_type(const std::string& name) const; - void bind(const std::string& name, type_ptr t, - visibility v = visibility::local); - void bind(const std::string& name, type_scheme_ptr t, - visibility v = visibility::local); - void bind_type(const std::string& type_name, type_ptr t); - void generalize(const std::string& name, const group& grp, type_mgr& mgr); -}; - - -type_env_ptr type_scope(type_env_ptr parent); diff --git a/code/compiler/test.sh b/code/compiler/test.sh deleted file mode 100755 index dca252f..0000000 --- a/code/compiler/test.sh +++ /dev/null @@ -1,4 +0,0 @@ -cd 11 -mkdir -p build && cd build -cmake .. -make -j8 diff --git a/config-gen.toml b/config-gen.toml index 57e9959..eecac96 100644 --- a/config-gen.toml +++ b/config-gen.toml @@ -6,6 +6,9 @@ [params.submoduleLinks.blogstaticflake] url = "https://dev.danilafe.com/Nix-Configs/blog-static-flake/src/commit/67b47d9c298e7476c2ca211aac5c5fd961637b7b" path = "blog-static-flake" + [params.submoduleLinks.compiler] + url = "https://dev.danilafe.com/DanilaFe/bloglang/src/commit/137455b0f4365ba3fd11c45ce49781cdbe829ec3" + path = "compiler" [params.submoduleLinks.serverconfig] url = "https://dev.danilafe.com/Nix-Configs/server-config/src/commit/98cffe09546aee1678f7baebdea5eb5fef288935" path = "server-config"