Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ type op =
| Mult
| Div
| Mod
| Exp
| Pow
| Preincr
| Postincr
| Predecr
Expand Down
134 changes: 87 additions & 47 deletions lib/irgen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -220,73 +220,113 @@ let rec build_expr expr (vars : variable StringMap.t) var_types the_module build
let se1 = build_expr e1 vars var_types the_module builder in
let se2 = build_expr e2 vars var_types the_module builder in
let lval =
match typ with
| RInt ->
(match op with
| A.Add -> L.build_add
| A.Sub -> L.build_sub
| A.Mult -> L.build_mul
| A.Div -> L.build_sdiv
| A.Mod -> L.build_srem
| A.Equal -> L.build_icmp L.Icmp.Eq
| A.Neq -> L.build_icmp L.Icmp.Ne
| A.Less -> L.build_icmp L.Icmp.Slt
| A.Leq -> L.build_icmp L.Icmp.Sle
| A.Greater -> L.build_icmp L.Icmp.Sgt
| A.Geq -> L.build_icmp L.Icmp.Sge
| _ ->
failwith
(Printf.sprintf
"Integer binary operator %s not yet implemented"
(Utils.string_of_op op)))
| RFloat ->
(match op with
| A.Add -> L.build_fadd
| A.Sub -> L.build_fsub
| A.Mult -> L.build_fmul
| A.Div -> L.build_fdiv
| A.Mod -> L.build_frem
| A.Equal -> L.build_fcmp L.Fcmp.Oeq
| A.Neq -> L.build_fcmp L.Fcmp.One
| A.Less -> L.build_fcmp L.Fcmp.Olt
| A.Leq -> L.build_fcmp L.Fcmp.Ole
| A.Greater -> L.build_fcmp L.Fcmp.Ogt
| A.Geq -> L.build_fcmp L.Fcmp.Oge
| _ ->
failwith
(Printf.sprintf
"Float binary operator %s not yet implemented"
(Utils.string_of_op op)))
| RBool ->
match typ, op with
| RInt, A.Pow ->
(* se1 = base, se2 = exponent *)
let parent_func = L.block_parent (L.insertion_block builder) in

let result = L.build_alloca l_int "pow_result" builder in
ignore (L.build_store (L.const_int l_int 1) result builder);

let i = L.build_alloca l_int "pow_i" builder in
ignore (L.build_store (L.const_int l_int 0) i builder);

let loop_bb = L.append_block context "pow_loop" parent_func in
let after_bb = L.append_block context "pow_after" parent_func in

ignore (L.build_br loop_bb builder);

(* Loop condition *)
L.position_at_end loop_bb builder;
let i_val = L.build_load i "i_val" builder in
let cond = L.build_icmp L.Icmp.Slt i_val se2 "pow_cond" builder in
let body_bb = L.append_block context "pow_body" parent_func in
ignore (L.build_cond_br cond body_bb after_bb builder);

(* Loop body: result *= base; i++ *)
L.position_at_end body_bb builder;
let res_val = L.build_load result "res_val" builder in
let new_res = L.build_mul res_val se1 "new_res" builder in
ignore (L.build_store new_res result builder);
let i_next = L.build_add i_val (L.const_int l_int 1) "i_next" builder in
ignore (L.build_store i_next i builder);
ignore (L.build_br loop_bb builder);

(* After loop *)
L.position_at_end after_bb builder;
L.build_load result "pow_result" builder
| RInt, _ ->
let op_fn =
match op with
| A.Add -> L.build_add se1 se2 "tmp_int" builder
| A.Sub -> L.build_sub se1 se2 "tmp_int" builder
| A.Mult -> L.build_mul se1 se2 "tmp_int" builder
| A.Div -> L.build_sdiv se1 se2 "tmp_int" builder
| A.Mod -> L.build_srem se1 se2 "tmp_int" builder
| A.Equal -> L.build_icmp L.Icmp.Eq se1 se2 "tmp_bool" builder
| A.Neq -> L.build_icmp L.Icmp.Ne se1 se2 "tmp_bool" builder
| A.Less -> L.build_icmp L.Icmp.Slt se1 se2 "tmp_bool" builder
| A.Leq -> L.build_icmp L.Icmp.Sle se1 se2 "tmp_bool" builder
| A.Greater -> L.build_icmp L.Icmp.Sgt se1 se2 "tmp_bool" builder
| A.Geq -> L.build_icmp L.Icmp.Sge se1 se2 "tmp_bool" builder
| _ ->
failwith
(Printf.sprintf
"Integer binary operator %s not yet implemented"
(Utils.string_of_op op))
in
op_fn
| RFloat, _ ->
let op_fn =
match op with
| A.Add -> L.build_fadd se1 se2 "tmp_float" builder
| A.Sub -> L.build_fsub se1 se2 "tmp_float" builder
| A.Mult -> L.build_fmul se1 se2 "tmp_float" builder
| A.Div -> L.build_fdiv se1 se2 "tmp_float" builder
| A.Mod -> L.build_frem se1 se2 "tmp_float" builder
| A.Equal -> L.build_fcmp L.Fcmp.Oeq se1 se2 "tmp_bool" builder
| A.Neq -> L.build_fcmp L.Fcmp.One se1 se2 "tmp_bool" builder
| A.Less -> L.build_fcmp L.Fcmp.Olt se1 se2 "tmp_bool" builder
| A.Leq -> L.build_fcmp L.Fcmp.Ole se1 se2 "tmp_bool" builder
| A.Greater -> L.build_fcmp L.Fcmp.Ogt se1 se2 "tmp_bool" builder
| A.Geq -> L.build_fcmp L.Fcmp.Oge se1 se2 "tmp_bool" builder
| _ ->
failwith
(Printf.sprintf
"Float binary operator %s not yet implemented"
(Utils.string_of_op op))
in
op_fn
| RBool, _ ->
(match op with
| A.And -> L.build_and
| A.Or -> L.build_or
| A.Equal -> L.build_icmp L.Icmp.Eq
| A.Neq -> L.build_icmp L.Icmp.Ne
| A.And -> L.build_and se1 se2 "tmp_bool" builder
| A.Or -> L.build_or se1 se2 "tmp_bool" builder
| A.Equal -> L.build_icmp L.Icmp.Eq se1 se2 "tmp_bool" builder
| A.Neq -> L.build_icmp L.Icmp.Ne se1 se2 "tmp_bool" builder
| _ ->
failwith
(Printf.sprintf
"Boolean binary operator %s not yet implemented"
(Utils.string_of_op op)))
| REnumType _ ->
| REnumType _, _ ->
(match op with
| A.Equal -> L.build_icmp L.Icmp.Eq
| A.Neq -> L.build_icmp L.Icmp.Ne
| A.Equal -> L.build_icmp L.Icmp.Eq se1 se2 "tmp_enum" builder
| A.Neq -> L.build_icmp L.Icmp.Ne se1 se2 "tmp_enum" builder
| _ ->
failwith
(Printf.sprintf
"Internal Compiler Error: Operator %s on EnumType %s reached IRgen."
(Utils.string_of_op op)
(Utils.string_of_resolved_type typ)))
| RString -> failwith "GOT A STRING\n"
| RString, _ -> failwith "GOT A STRING\n"
| _ ->
failwith
(Printf.sprintf
"Binary operator %s not yet implemented for type %s"
(Utils.string_of_op op)
(Utils.string_of_resolved_type typ))
in
lval se1 se2 ("tmp_" ^ Utils.string_of_resolved_type typ) builder
lval
| SUDTInstance (typename, fields) ->
let struct_type = Hashtbl.find udt_structs typename in
let field_indices = Hashtbl.find udt_field_indices typename in
Expand Down
4 changes: 2 additions & 2 deletions lib/parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ open Ast
%}

%token SEMI COLON DCOLON DOT COMMA LPAREN RPAREN LBRACE RBRACE LBRACKET RBRACKET
%token PLUS MINUS DIVIDE MODULO TIMES INCR DECR EXPONENT
%token PLUS MINUS DIVIDE MODULO TIMES INCR DECR POW
%token EQUAL WALRUS PLUS_ASSIGN MINUS_ASSIGN MULT_ASSIGN DIV_ASSIGN
%token BEQ NEQ LT LEQ GT GEQ AND OR NOT

Expand Down Expand Up @@ -86,7 +86,7 @@ expr:
| expr TIMES expr { Binop($1, Mult, $3) }
| expr DIVIDE expr { Binop($1, Div, $3) }
| expr MODULO expr { Binop($1, Mod, $3) }
| expr EXPONENT expr { Binop($1, Exp, $3) }
| expr POW expr { Binop($1, Pow, $3) }
| expr OR expr { Binop($1, Or, $3) }
| expr AND expr { Binop($1, And, $3) }
| expr BEQ expr { Binop($1, Equal, $3) }
Expand Down
2 changes: 1 addition & 1 deletion lib/scanner.mll
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ rule tokenize = parse
| '+' { PLUS }
| '-' { MINUS }
| '*' { TIMES }
| "**" { EXPONENT }
| "**" { POW }
| '/' { DIVIDE }
| '%' { MODULO }
| '=' { EQUAL }
Expand Down
2 changes: 1 addition & 1 deletion lib/semant.ml
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ and format_binop_error expr t1 t2 =

and get_binop_return_type expr t1 binop t2 =
match binop with
| Add | Sub | Mult | Div | Mod | Exp ->
| Add | Sub | Mult | Div | Mod | Pow ->
(match t1, t2 with
| RInt, RInt -> RInt
| RFloat, RFloat -> RFloat
Expand Down
4 changes: 2 additions & 2 deletions lib/utils/prints.ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ let string_of_token = function
| MINUS -> "MINUS"
| TIMES -> "TIMES"
| DIVIDE -> "DIVIDE"
| EXPONENT -> "EXPONENT"
| POW -> "POW"
| MODULO -> "MODULO"
| AND -> "AND" (* Logical operators *)
| OR -> "OR"
Expand Down Expand Up @@ -116,7 +116,7 @@ let string_of_op = function
| Sub -> "-"
| Mult -> "*"
| Div -> "/"
| Exp -> "**"
| Pow -> "**"
| Mod -> "%"
| Preincr -> "++"
| Predecr -> "--"
Expand Down
28 changes: 14 additions & 14 deletions test/scanner/test_exp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a1) WALRUS LITERAL(2) SEMI LET ID(b1) WALRUS LITERAL(3) SEMI LET \
ID(result1) WALRUS ID(a1) EXPONENT ID(b1) SEMI"
ID(result1) WALRUS ID(a1) POW ID(b1) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test2"
Expand All @@ -30,7 +30,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a2) WALRUS FLIT(2.500000) SEMI LET ID(b2) WALRUS LITERAL(2) SEMI LET \
ID(result2) WALRUS ID(a2) EXPONENT ID(b2) SEMI"
ID(result2) WALRUS ID(a2) POW ID(b2) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test3"
Expand All @@ -41,7 +41,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a3) WALRUS LITERAL(2) SEMI LET ID(b3) WALRUS FLIT(3.500000) SEMI LET \
ID(result3) WALRUS ID(a3) EXPONENT ID(b3) SEMI"
ID(result3) WALRUS ID(a3) POW ID(b3) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test4"
Expand All @@ -53,7 +53,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a4) WALRUS LITERAL(2) SEMI LET ID(b4) WALRUS SLIT(3) SEMI LET \
ID(result4) WALRUS ID(a4) EXPONENT ID(b4) SEMI"
ID(result4) WALRUS ID(a4) POW ID(b4) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test5"
Expand All @@ -64,7 +64,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a5) WALRUS LITERAL(2) SEMI LET ID(b5) WALRUS BLIT(true) SEMI LET \
ID(result5) WALRUS ID(a5) EXPONENT ID(b5) SEMI"
ID(result5) WALRUS ID(a5) POW ID(b5) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test6"
Expand All @@ -76,7 +76,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a6) WALRUS LPAREN LITERAL(1) COMMA LITERAL(2) RPAREN SEMI LET ID(b6) \
WALRUS LITERAL(2) SEMI LET ID(result6) WALRUS ID(a6) EXPONENT ID(b6) SEMI"
WALRUS LITERAL(2) SEMI LET ID(result6) WALRUS ID(a6) POW ID(b6) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test7"
Expand All @@ -89,7 +89,7 @@ let tests =
let expected =
"LET ID(a7) WALRUS LBRACKET LITERAL(1) COMMA LITERAL(2) COMMA LITERAL(3) \
RBRACKET SEMI LET ID(b7) WALRUS LITERAL(3) SEMI LET ID(result7) WALRUS \
ID(a7) EXPONENT ID(b7) SEMI"
ID(a7) POW ID(b7) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test8"
Expand All @@ -102,7 +102,7 @@ let tests =
let expected =
"LET ID(a8) WALRUS LBRACE LITERAL(1) COMMA LITERAL(2) COMMA LITERAL(3) \
RBRACE SEMI LET ID(b8) WALRUS LITERAL(2) SEMI LET ID(result8) WALRUS ID(a8) \
EXPONENT ID(b8) SEMI"
POW ID(b8) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test9"
Expand All @@ -113,7 +113,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a9) WALRUS LITERAL(0) SEMI LET ID(b9) WALRUS LITERAL(5) SEMI LET \
ID(result9) WALRUS ID(a9) EXPONENT ID(b9) SEMI"
ID(result9) WALRUS ID(a9) POW ID(b9) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test10"
Expand All @@ -125,7 +125,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a10) WALRUS LITERAL(4) SEMI LET ID(b10) WALRUS LITERAL(-2) SEMI LET \
ID(result10) WALRUS ID(a10) EXPONENT ID(b10) SEMI"
ID(result10) WALRUS ID(a10) POW ID(b10) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test11"
Expand All @@ -137,7 +137,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a11) WALRUS FLIT(5.000000) SEMI LET ID(b11) WALRUS LITERAL(-3) SEMI \
LET ID(result11) WALRUS ID(a11) EXPONENT ID(b11) SEMI"
LET ID(result11) WALRUS ID(a11) POW ID(b11) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test12"
Expand All @@ -149,7 +149,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a12) WALRUS LITERAL(1) SEMI LET ID(b12) WALRUS LITERAL(1000) SEMI \
LET ID(result12) WALRUS ID(a12) EXPONENT ID(b12) SEMI"
LET ID(result12) WALRUS ID(a12) POW ID(b12) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test13"
Expand All @@ -161,7 +161,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a13) WALRUS LITERAL(-2) SEMI LET ID(b13) WALRUS LITERAL(3) SEMI LET \
ID(result13) WALRUS ID(a13) EXPONENT ID(b13) SEMI"
ID(result13) WALRUS ID(a13) POW ID(b13) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
; ("test14"
Expand All @@ -173,7 +173,7 @@ let tests =
let actual = string_of_tokens (to_list lexbuf) in
let expected =
"LET ID(a14) WALRUS FLIT(-2.500000) SEMI LET ID(b14) WALRUS LITERAL(2) SEMI \
LET ID(result14) WALRUS ID(a14) EXPONENT ID(b14) SEMI"
LET ID(result14) WALRUS ID(a14) POW ID(b14) SEMI"
in
assert_equal expected actual ~printer:(fun s -> "\"" ^ s ^ "\""))
]
Expand Down