* add &&
* allow int in cond/loop
This commit is contained in:
parent
a8dfaa4fec
commit
3614712f6f
11 changed files with 50 additions and 19 deletions
|
@ -16,6 +16,7 @@ let _types_ =
|
||||||
; "%sle", Func_t (Bool_t, [ Int_t; Int_t ])
|
; "%sle", Func_t (Bool_t, [ Int_t; Int_t ])
|
||||||
; "%slt", 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 ])
|
; "%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 ])
|
; "puti", Func_t (Void_t, [ Int_t ])
|
||||||
; "puts", Func_t (Void_t, [ Str_t ])
|
; "puts", Func_t (Void_t, [ Str_t ])
|
||||||
; "geti", Func_t (Int_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) ]
|
; "%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) ]
|
; "%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) ]
|
; "%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 ]
|
; "puti", [ Lw (A0, Mem (SP, 0)); Li (V0, Syscall.print_int); Syscall ]
|
||||||
; "puts", [ Lw (A0, Mem (SP, 0)); Li (V0, Syscall.print_str); 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 ]
|
; "geti", [ Lw (A0, Mem (SP, 0)); Li (V0, Syscall.read_int); Syscall ]
|
||||||
|
|
|
@ -33,8 +33,8 @@ let errt expected given pos =
|
||||||
(SemanticsError
|
(SemanticsError
|
||||||
( Printf.sprintf
|
( Printf.sprintf
|
||||||
"Expected %s but given %s"
|
"Expected %s but given %s"
|
||||||
(string_of_type_t expected)
|
(String.concat ", " (List.map string_of_type_t expected))
|
||||||
(string_of_type_t given)
|
(String.concat ", " (List.map string_of_type_t given))
|
||||||
, pos ))
|
, pos ))
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ rule token = parse
|
||||||
| "<=" { Lsle }
|
| "<=" { Lsle }
|
||||||
| "<" { Lslt }
|
| "<" { Lslt }
|
||||||
| "!=" { Lsne }
|
| "!=" { Lsne }
|
||||||
|
| '&' { Land }
|
||||||
| '"' { read_string (Buffer.create 16) lexbuf }
|
| '"' { read_string (Buffer.create 16) lexbuf }
|
||||||
| ident as i { Lvar i }
|
| ident as i { Lvar i }
|
||||||
| '#' { comment lexbuf }
|
| '#' { comment lexbuf }
|
||||||
|
|
3
mips.ml
3
mips.ml
|
@ -55,6 +55,7 @@ type instr =
|
||||||
| Sle of reg * reg * reg
|
| Sle of reg * reg * reg
|
||||||
| Slt of reg * reg * reg
|
| Slt of reg * reg * reg
|
||||||
| Sne of reg * reg * reg
|
| Sne of reg * reg * reg
|
||||||
|
| And of reg * reg * reg
|
||||||
| Syscall
|
| Syscall
|
||||||
| B of label
|
| B of label
|
||||||
| Beq of reg * reg * 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)
|
Printf.sprintf "%sslt %s, %s, %s" indent (fmt_reg rd) (fmt_reg rs) (fmt_reg rt)
|
||||||
| Sne (rd, rs, rt) ->
|
| Sne (rd, rs, rt) ->
|
||||||
Printf.sprintf "%ssne %s, %s, %s" indent (fmt_reg rd) (fmt_reg rs) (fmt_reg 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
|
| Syscall -> Printf.sprintf "%ssyscall" indent
|
||||||
| B l -> Printf.sprintf "%sb %s" indent l
|
| B l -> Printf.sprintf "%sb %s" indent l
|
||||||
| Beq (rs, rt, l) ->
|
| Beq (rs, rt, l) ->
|
||||||
|
|
|
@ -12,9 +12,11 @@
|
||||||
%token Lbracedeb Lbracefin
|
%token Lbracedeb Lbracefin
|
||||||
%token Lpardeb Lparfin Lcomma
|
%token Lpardeb Lparfin Lcomma
|
||||||
%token Ladd Lsub Lmul Ldiv Lrem Lseq Lsge Lsgt Lsle Lslt Lsne
|
%token Ladd Lsub Lmul Ldiv Lrem Lseq Lsge Lsgt Lsle Lslt Lsne
|
||||||
|
%token Land
|
||||||
%token Lif Lelse Lwhile
|
%token Lif Lelse Lwhile
|
||||||
|
|
||||||
%left Ladd Lsub Lmul Ldiv Lrem Lseq Lsge Lsgt Lsle Lslt Lsne
|
%left Ladd Lsub Lmul Ldiv Lrem Lseq Lsge Lsgt Lsle Lslt Lsne
|
||||||
|
%left Land
|
||||||
|
|
||||||
%left Lbracedeb Lparfin Lbracefin Lreturn
|
%left Lbracedeb Lparfin Lbracefin Lreturn
|
||||||
%left Ltype Lbool Lint Lvar Lstr
|
%left Ltype Lbool Lint Lvar Lstr
|
||||||
|
@ -211,6 +213,11 @@ expr:
|
||||||
Call { func = "%sne" ; args = [ a ; b ] ; pos = $startpos($2) }
|
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 */
|
/* function(a */
|
||||||
| f = Lvar ; Lpardeb ; a = args_expr {
|
| f = Lvar ; Lpardeb ; a = args_expr {
|
||||||
Call { func = f ; args = a ; pos = $startpos(a) }
|
Call { func = f ; args = a ; pos = $startpos(a) }
|
||||||
|
|
26
semantics.ml
26
semantics.ml
|
@ -14,21 +14,21 @@ let analyze_value = function
|
||||||
let rec analyze_expr env ua t = function
|
let rec analyze_expr env ua t = function
|
||||||
| Syntax.Val v ->
|
| Syntax.Val v ->
|
||||||
let v2, new_t = analyze_value v.value in
|
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
|
Val v2, new_t
|
||||||
| Syntax.Var v ->
|
| Syntax.Var v ->
|
||||||
if not (Env.mem v.name env)
|
if not (Env.mem v.name env)
|
||||||
then raise (SemanticsError ("Unbound variable \"" ^ v.name ^ "\"", v.pos));
|
then raise (SemanticsError ("Unbound variable \"" ^ v.name ^ "\"", v.pos));
|
||||||
if List.mem v.name ua then warn ("Unassigned 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
|
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
|
Var v.name, new_t
|
||||||
| Syntax.Call c ->
|
| Syntax.Call c ->
|
||||||
if not (Env.mem c.func env)
|
if not (Env.mem c.func env)
|
||||||
then raise (SemanticsError ("Unbound function \"" ^ c.func ^ "\"", c.pos));
|
then raise (SemanticsError ("Unbound function \"" ^ c.func ^ "\"", c.pos));
|
||||||
(match Env.find c.func env with
|
(match Env.find c.func env with
|
||||||
| Func_t (ret_t, tl) ->
|
| 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
|
if List.length tl != List.length c.args
|
||||||
then
|
then
|
||||||
raise
|
raise
|
||||||
|
@ -41,14 +41,14 @@ let rec analyze_expr env ua t = function
|
||||||
, c.pos ));
|
, c.pos ));
|
||||||
let args =
|
let args =
|
||||||
List.map2
|
List.map2
|
||||||
(fun t e ->
|
(fun tt e ->
|
||||||
let e2, t2 = analyze_expr env ua t e in
|
let e2, t2 = analyze_expr env ua [ tt ] e in
|
||||||
if t2 = t
|
if t2 = tt
|
||||||
then e2
|
then e2
|
||||||
else
|
else
|
||||||
errt
|
errt
|
||||||
t
|
[ tt ]
|
||||||
t2
|
[ t2 ]
|
||||||
(match e with
|
(match e with
|
||||||
| Syntax.Val v -> v.pos
|
| Syntax.Val v -> v.pos
|
||||||
| Syntax.Var v -> v.pos
|
| Syntax.Var v -> v.pos
|
||||||
|
@ -65,22 +65,22 @@ let rec analyze_instr env ua ret_t = function
|
||||||
| Syntax.Assign a ->
|
| Syntax.Assign a ->
|
||||||
if not (Env.mem a.var env)
|
if not (Env.mem a.var env)
|
||||||
then raise (SemanticsError ("Unbound variable \"" ^ a.var ^ "\"", a.pos));
|
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
|
Assign (a.var, ae), env, List.filter (fun x -> x <> a.var) ua
|
||||||
| Syntax.Do d ->
|
| 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, []
|
Do ae, env, []
|
||||||
| Syntax.Cond c ->
|
| 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 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
|
let else_b, _ = analyze_block env ua Magic_t c.pos c.else_b in
|
||||||
Cond (cond, if_b, else_b), env, []
|
Cond (cond, if_b, else_b), env, []
|
||||||
| Syntax.Loop l ->
|
| 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
|
let block, _ = analyze_block env ua Magic_t l.pos l.block in
|
||||||
Loop (cond, block), env, []
|
Loop (cond, block), env, []
|
||||||
| Syntax.Return r ->
|
| 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, []
|
Return ae, env, []
|
||||||
|
|
||||||
and analyze_block env ua ret_t pos = function
|
and analyze_block env ua ret_t pos = function
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
void main () {
|
void main () {
|
||||||
if (1) { # Error on line 2 col 8: Expected bool but given int.
|
if (1) { # Même les int peuvent fonctionner dans les conditions
|
||||||
# Requiert le type bool, pas de convertion implicite
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
void main () {
|
void main () {
|
||||||
while (1) { # Error on line 2 col 11: Expected bool but given int.
|
while (1) { # Comme les conditions, les int sont autorisés
|
||||||
# Requiert le type bool, pas de convertion implicite
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
7
tests/35_op.test
Normal file
7
tests/35_op.test
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
void main () {
|
||||||
|
if (1 && 3 < 4) {
|
||||||
|
puti(1);
|
||||||
|
} else {
|
||||||
|
puti(0);
|
||||||
|
}
|
||||||
|
}
|
6
tests/36_if-str.test
Normal file
6
tests/36_if-str.test
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
7
tests/37_while-str.test
Normal file
7
tests/37_while-str.test
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue