From 3614712f6f34179b85391d1154a70ff0e8dca47b Mon Sep 17 00:00:00 2001 From: Mylloon Date: Thu, 22 Dec 2022 19:15:42 +0100 Subject: [PATCH] * add && * allow int in cond/loop --- baselib.ml | 2 ++ errors.ml | 4 ++-- lexer.mll | 1 + mips.ml | 3 +++ parser.mly | 7 +++++++ semantics.ml | 26 +++++++++++++------------- tests/29_if-int.test | 3 +-- tests/32_while-int.test | 3 +-- tests/35_op.test | 7 +++++++ tests/36_if-str.test | 6 ++++++ tests/37_while-str.test | 7 +++++++ 11 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 tests/35_op.test create mode 100644 tests/36_if-str.test create mode 100644 tests/37_while-str.test diff --git a/baselib.ml b/baselib.ml index c252b9f..145087c 100644 --- a/baselib.ml +++ b/baselib.ml @@ -16,6 +16,7 @@ let _types_ = ; "%sle", Func_t (Bool_t, [ Int_t; Int_t ]) ; "%slt", Func_t (Bool_t, [ Int_t; Int_t ]) ; "%sne", Func_t (Bool_t, [ Int_t; Int_t ]) + ; "%and", Func_t (Int_t, [ Int_t; Int_t ]) ; "puti", Func_t (Void_t, [ Int_t ]) ; "puts", Func_t (Void_t, [ Str_t ]) ; "geti", Func_t (Int_t, []) @@ -38,6 +39,7 @@ let builtins = ; "%sle", [ Lw (T0, Mem (SP, 4)); Lw (T1, Mem (SP, 0)); Sle (V0, T0, T1) ] ; "%slt", [ Lw (T0, Mem (SP, 4)); Lw (T1, Mem (SP, 0)); Slt (V0, T0, T1) ] ; "%sne", [ Lw (T0, Mem (SP, 4)); Lw (T1, Mem (SP, 0)); Sne (V0, T0, T1) ] + ; "%and", [ Lw (T0, Mem (SP, 4)); Lw (T1, Mem (SP, 0)); And (V0, T0, T1) ] ; "puti", [ Lw (A0, Mem (SP, 0)); Li (V0, Syscall.print_int); Syscall ] ; "puts", [ Lw (A0, Mem (SP, 0)); Li (V0, Syscall.print_str); Syscall ] ; "geti", [ Lw (A0, Mem (SP, 0)); Li (V0, Syscall.read_int); Syscall ] diff --git a/errors.ml b/errors.ml index 3d0d63a..979618f 100644 --- a/errors.ml +++ b/errors.ml @@ -33,8 +33,8 @@ let errt expected given pos = (SemanticsError ( Printf.sprintf "Expected %s but given %s" - (string_of_type_t expected) - (string_of_type_t given) + (String.concat ", " (List.map string_of_type_t expected)) + (String.concat ", " (List.map string_of_type_t given)) , pos )) ;; diff --git a/lexer.mll b/lexer.mll index ba048f8..f820e77 100644 --- a/lexer.mll +++ b/lexer.mll @@ -41,6 +41,7 @@ rule token = parse | "<=" { Lsle } | "<" { Lslt } | "!=" { Lsne } + | '&' { Land } | '"' { read_string (Buffer.create 16) lexbuf } | ident as i { Lvar i } | '#' { comment lexbuf } diff --git a/mips.ml b/mips.ml index 1e4fa35..5739056 100644 --- a/mips.ml +++ b/mips.ml @@ -55,6 +55,7 @@ type instr = | Sle of reg * reg * reg | Slt of reg * reg * reg | Sne of reg * reg * reg + | And of reg * reg * reg | Syscall | B of label | Beq of reg * reg * label @@ -148,6 +149,8 @@ let fmt_instr ?(indent = " ") = function Printf.sprintf "%sslt %s, %s, %s" indent (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Sne (rd, rs, rt) -> Printf.sprintf "%ssne %s, %s, %s" indent (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | And (rd, rs, rt) -> + Printf.sprintf "%sand %s, %s, %s" indent (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Syscall -> Printf.sprintf "%ssyscall" indent | B l -> Printf.sprintf "%sb %s" indent l | Beq (rs, rt, l) -> diff --git a/parser.mly b/parser.mly index 88d30a0..72e5501 100644 --- a/parser.mly +++ b/parser.mly @@ -12,9 +12,11 @@ %token Lbracedeb Lbracefin %token Lpardeb Lparfin Lcomma %token Ladd Lsub Lmul Ldiv Lrem Lseq Lsge Lsgt Lsle Lslt Lsne +%token Land %token Lif Lelse Lwhile %left Ladd Lsub Lmul Ldiv Lrem Lseq Lsge Lsgt Lsle Lslt Lsne +%left Land %left Lbracedeb Lparfin Lbracefin Lreturn %left Ltype Lbool Lint Lvar Lstr @@ -211,6 +213,11 @@ expr: Call { func = "%sne" ; args = [ a ; b ] ; pos = $startpos($2) } } + /* e && e */ + | a = expr ; Land ; Land ; b = expr { + Call { func = "%and" ; args = [ a ; b ] ; pos = $startpos($2) } + } + /* function(a */ | f = Lvar ; Lpardeb ; a = args_expr { Call { func = f ; args = a ; pos = $startpos(a) } diff --git a/semantics.ml b/semantics.ml index 45ad794..18504e5 100644 --- a/semantics.ml +++ b/semantics.ml @@ -14,21 +14,21 @@ let analyze_value = function let rec analyze_expr env ua t = function | Syntax.Val v -> let v2, new_t = analyze_value v.value in - if new_t != t && t != Magic_t then errt t new_t v.pos; + if (not (List.mem new_t t)) && not (List.mem Magic_t t) then errt t [ new_t ] v.pos; Val v2, new_t | Syntax.Var v -> if not (Env.mem v.name env) then raise (SemanticsError ("Unbound variable \"" ^ v.name ^ "\"", v.pos)); if List.mem v.name ua then warn ("Unassigned variable \"" ^ v.name ^ "\"") v.pos; let new_t = Env.find v.name env in - if new_t != t then errt t new_t v.pos; + if not (List.mem new_t t) then errt t [ new_t ] v.pos; Var v.name, new_t | Syntax.Call c -> if not (Env.mem c.func env) then raise (SemanticsError ("Unbound function \"" ^ c.func ^ "\"", c.pos)); (match Env.find c.func env with | Func_t (ret_t, tl) -> - if ret_t != t && t != Magic_t then errt ret_t t c.pos; + if (not (List.mem ret_t t)) && not (List.mem Magic_t t) then errt [ ret_t ] t c.pos; if List.length tl != List.length c.args then raise @@ -41,14 +41,14 @@ let rec analyze_expr env ua t = function , c.pos )); let args = List.map2 - (fun t e -> - let e2, t2 = analyze_expr env ua t e in - if t2 = t + (fun tt e -> + let e2, t2 = analyze_expr env ua [ tt ] e in + if t2 = tt then e2 else errt - t - t2 + [ tt ] + [ t2 ] (match e with | Syntax.Val v -> v.pos | Syntax.Var v -> v.pos @@ -65,22 +65,22 @@ let rec analyze_instr env ua ret_t = function | Syntax.Assign a -> if not (Env.mem a.var env) then raise (SemanticsError ("Unbound variable \"" ^ a.var ^ "\"", a.pos)); - let ae, et = analyze_expr env ua (Env.find a.var env) a.expr in + let ae, et = analyze_expr env ua [ Env.find a.var env ] a.expr in Assign (a.var, ae), env, List.filter (fun x -> x <> a.var) ua | Syntax.Do d -> - let ae, _ = analyze_expr env ua Magic_t d.expr in + let ae, _ = analyze_expr env ua [ Magic_t ] d.expr in Do ae, env, [] | Syntax.Cond c -> - let cond, _ = analyze_expr env ua Bool_t c.expr in + let cond, _ = analyze_expr env ua [ Bool_t; Int_t ] c.expr in let if_b, _ = analyze_block env ua Magic_t c.pos c.if_b in let else_b, _ = analyze_block env ua Magic_t c.pos c.else_b in Cond (cond, if_b, else_b), env, [] | Syntax.Loop l -> - let cond, _ = analyze_expr env ua Bool_t l.expr in + let cond, _ = analyze_expr env ua [ Bool_t; Int_t ] l.expr in let block, _ = analyze_block env ua Magic_t l.pos l.block in Loop (cond, block), env, [] | Syntax.Return r -> - let ae, _ = analyze_expr env ua ret_t r.expr in + let ae, _ = analyze_expr env ua [ ret_t ] r.expr in Return ae, env, [] and analyze_block env ua ret_t pos = function diff --git a/tests/29_if-int.test b/tests/29_if-int.test index a1ef6a3..81b5e2f 100644 --- a/tests/29_if-int.test +++ b/tests/29_if-int.test @@ -1,6 +1,5 @@ void main () { - if (1) { # Error on line 2 col 8: Expected bool but given int. - # Requiert le type bool, pas de convertion implicite + if (1) { # Même les int peuvent fonctionner dans les conditions return; } } diff --git a/tests/32_while-int.test b/tests/32_while-int.test index acde393..f02d555 100644 --- a/tests/32_while-int.test +++ b/tests/32_while-int.test @@ -1,6 +1,5 @@ void main () { - while (1) { # Error on line 2 col 11: Expected bool but given int. - # Requiert le type bool, pas de convertion implicite + while (1) { # Comme les conditions, les int sont autorisés return; } } diff --git a/tests/35_op.test b/tests/35_op.test new file mode 100644 index 0000000..5f739b4 --- /dev/null +++ b/tests/35_op.test @@ -0,0 +1,7 @@ +void main () { + if (1 && 3 < 4) { + puti(1); + } else { + puti(0); + } +} diff --git a/tests/36_if-str.test b/tests/36_if-str.test new file mode 100644 index 0000000..9960e70 --- /dev/null +++ b/tests/36_if-str.test @@ -0,0 +1,6 @@ +void main () { + if ("mettez20svp") { # Error on line 2 col 20: Expected bool, int but given str. + # les strings ne sont pas valides pour les conditions + return; + } +} diff --git a/tests/37_while-str.test b/tests/37_while-str.test new file mode 100644 index 0000000..81e6a24 --- /dev/null +++ b/tests/37_while-str.test @@ -0,0 +1,7 @@ +void main () { + while ("salut") { # Error on line 2 col 17: Expected bool, int but given str. + # Comme les conditions, les strings peuvent pas être + # des conditions + return; + } +}