diff --git a/code/compiler/13/ast.cpp b/code/compiler/13/ast.cpp index d66ee4e..693cafd 100644 --- a/code/compiler/13/ast.cpp +++ b/code/compiler/13/ast.cpp @@ -287,6 +287,7 @@ struct case_strategy_bool { repr_type repr, std::vector& into) { branch->expr->compile(env_ptr(new env_offset(1, env)), into); + into.push_back(instruction_ptr(new instruction_slide(1))); } size_t case_count(const type* type) { diff --git a/code/compiler/13/binop.cpp b/code/compiler/13/binop.cpp index 3a5f0ca..f311007 100644 --- a/code/compiler/13/binop.cpp +++ b/code/compiler/13/binop.cpp @@ -6,6 +6,9 @@ std::string op_name(binop op) { case MINUS: return "-"; case TIMES: return "*"; case DIVIDE: return "/"; + case MODULO: return "%"; + case EQUALS: return "=="; + case LESS_EQUALS: return "<="; } return "??"; } @@ -16,6 +19,9 @@ std::string op_action(binop op) { case MINUS: return "minus"; case TIMES: return "times"; case DIVIDE: return "divide"; + case MODULO: return "modulo"; + case EQUALS: return "equals"; + case LESS_EQUALS: return "less_equals"; } return "??"; } diff --git a/code/compiler/13/binop.hpp b/code/compiler/13/binop.hpp index 8d07858..90b4c89 100644 --- a/code/compiler/13/binop.hpp +++ b/code/compiler/13/binop.hpp @@ -5,7 +5,10 @@ enum binop { PLUS, MINUS, TIMES, - DIVIDE + DIVIDE, + MODULO, + EQUALS, + LESS_EQUALS, }; std::string op_name(binop op); diff --git a/code/compiler/13/instruction.cpp b/code/compiler/13/instruction.cpp index 80ae40c..afe80aa 100644 --- a/code/compiler/13/instruction.cpp +++ b/code/compiler/13/instruction.cpp @@ -153,7 +153,7 @@ void instruction_if::gen_llvm(llvm_context& ctx, llvm::Function* f) const { ctx.builder.CreateBr(resume_block); ctx.builder.SetInsertPoint(zero_block); - for(auto& instruction : on_true) { + for(auto& instruction : on_false) { instruction->gen_llvm(ctx, f); } ctx.builder.CreateBr(resume_block); @@ -184,6 +184,9 @@ void instruction_binop::gen_llvm(llvm_context& ctx, Function* f) const { 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; + case MODULO: result = ctx.builder.CreateSRem(left_int, right_int); break; + case EQUALS: result = ctx.builder.CreateICmpEQ(left_int, right_int); break; + case LESS_EQUALS: result = ctx.builder.CreateICmpSLE(left_int, right_int); break; } ctx.create_push(f, ctx.create_num(f, result)); } diff --git a/code/compiler/13/main.cpp b/code/compiler/13/main.cpp index aa3bcef..7ad06c0 100644 --- a/code/compiler/13/main.cpp +++ b/code/compiler/13/main.cpp @@ -34,10 +34,16 @@ void prelude_types(definition_group& defs, type_env_ptr env) { type_ptr binop_type = type_ptr(new type_arr( int_type_app, type_ptr(new type_arr(int_type_app, int_type_app)))); + type_ptr cmp_type = type_ptr(new type_arr( + int_type_app, + type_ptr(new type_arr(int_type_app, bool_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); + env->bind("%", binop_type, visibility::global); + env->bind("==", cmp_type, visibility::global); + env->bind("<=", cmp_type, visibility::global); env->bind("True", bool_type_app, visibility::global); env->bind("False", bool_type_app, visibility::global); @@ -146,6 +152,9 @@ void gen_llvm(global_scope& scope) { gen_llvm_internal_op(ctx, MINUS); gen_llvm_internal_op(ctx, TIMES); gen_llvm_internal_op(ctx, DIVIDE); + gen_llvm_internal_op(ctx, MODULO); + gen_llvm_internal_op(ctx, EQUALS); + gen_llvm_internal_op(ctx, LESS_EQUALS); gen_llvm_boolean_constructor(ctx, "True", true); gen_llvm_boolean_constructor(ctx, "False", false); diff --git a/code/compiler/13/parser.y b/code/compiler/13/parser.y index 1bf8c48..44c4215 100644 --- a/code/compiler/13/parser.y +++ b/code/compiler/13/parser.y @@ -22,6 +22,9 @@ using yyscan_t = void*; %token TIMES %token MINUS %token DIVIDE +%token MODULO +%token EQUALS +%token LESS_EQUALS %token INT %token DEFN %token DATA @@ -51,7 +54,7 @@ using yyscan_t = void*; %type > typeList %type definitions %type type nonArrowType typeListElement -%type aAdd aMul case let lambda app appBase +%type aEq aAdd aMul case let lambda app appBase %type data %type defn %type branch @@ -73,7 +76,7 @@ definitions ; defn - : DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY + : DEFN LID lowercaseParams EQUAL OCURLY aEq CCURLY { $$ = definition_defn_ptr( new definition_defn(std::move($2), std::move($3), std::move($6), @$)); } ; @@ -83,6 +86,12 @@ lowercaseParams | lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); } ; +aEq + : aAdd EQUALS aAdd { $$ = ast_ptr(new ast_binop(EQUALS, std::move($1), std::move($3), @$)); } + | aAdd LESS_EQUALS aAdd { $$ = ast_ptr(new ast_binop(LESS_EQUALS, std::move($1), std::move($3), @$)); } + | aAdd { $$ = std::move($1); } + ; + 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), @$)); } @@ -92,6 +101,7 @@ aAdd 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), @$)); } + | aMul MODULO app { $$ = ast_ptr(new ast_binop(MODULO, std::move($1), std::move($3), @$)); } | app { $$ = std::move($1); } ; @@ -104,7 +114,7 @@ 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); } + | OPAREN aEq CPAREN { $$ = std::move($2); } | case { $$ = std::move($1); } | let { $$ = std::move($1); } | lambda { $$ = std::move($1); } diff --git a/code/compiler/13/scanner.l b/code/compiler/13/scanner.l index 6f201c5..162643d 100644 --- a/code/compiler/13/scanner.l +++ b/code/compiler/13/scanner.l @@ -26,6 +26,9 @@ \* { return yy::parser::make_TIMES(drv.location); } - { return yy::parser::make_MINUS(drv.location); } \/ { return yy::parser::make_DIVIDE(drv.location); } +% { return yy::parser::make_MODULO(drv.location); } +== { return yy::parser::make_EQUALS(drv.location); } +\<= { return yy::parser::make_LESS_EQUALS(drv.location); } [0-9]+ { return yy::parser::make_INT(atoi(yytext), drv.location); } defn { return yy::parser::make_DEFN(drv.location); } data { return yy::parser::make_DATA(drv.location); }