wip (fn): add return
This commit is contained in:
parent
a923bdb6b9
commit
d433aafc4f
5 changed files with 40 additions and 15 deletions
5
ast.ml
5
ast.ml
|
@ -30,6 +30,10 @@ module Syntax = struct
|
||||||
; expr : expr
|
; expr : expr
|
||||||
; pos : Lexing.position
|
; pos : Lexing.position
|
||||||
}
|
}
|
||||||
|
| Return of
|
||||||
|
{ expr : expr
|
||||||
|
; pos : Lexing.position
|
||||||
|
}
|
||||||
|
|
||||||
and block = instr list
|
and block = instr list
|
||||||
end
|
end
|
||||||
|
@ -48,6 +52,7 @@ module IR = struct
|
||||||
type instr =
|
type instr =
|
||||||
| Decl of ident
|
| Decl of ident
|
||||||
| Assign of ident * expr
|
| Assign of ident * expr
|
||||||
|
| Return of expr
|
||||||
|
|
||||||
and block = instr list
|
and block = instr list
|
||||||
end
|
end
|
||||||
|
|
25
compiler.ml
25
compiler.ml
|
@ -6,6 +6,8 @@ type info =
|
||||||
{ asm : instr list
|
{ asm : instr list
|
||||||
; env : loc Env.t
|
; env : loc Env.t
|
||||||
; fpo : int (* FP offset *)
|
; fpo : int (* FP offset *)
|
||||||
|
; cnt : int (* Counter *)
|
||||||
|
; ret : string (* Return *)
|
||||||
}
|
}
|
||||||
|
|
||||||
let compile_value = function
|
let compile_value = function
|
||||||
|
@ -25,6 +27,7 @@ let compile_instr info = function
|
||||||
{ info with
|
{ info with
|
||||||
asm = info.asm @ compile_expr info.env e @ [ Sw (V0, Env.find v info.env) ]
|
asm = info.asm @ compile_expr info.env e @ [ Sw (V0, Env.find v info.env) ]
|
||||||
}
|
}
|
||||||
|
| Return e -> { info with asm = info.asm @ compile_expr info.env e @ [ B info.ret ] }
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let rec compile_block info = function
|
let rec compile_block info = function
|
||||||
|
@ -32,18 +35,32 @@ let rec compile_block info = function
|
||||||
| i :: b -> compile_block (compile_instr info i) b
|
| i :: b -> compile_block (compile_instr info i) b
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let compile_body body =
|
let compile_body body counter =
|
||||||
let compiled = compile_block { asm = []; env = Env.empty; fpo = 8 } body in
|
let compiled =
|
||||||
|
compile_block
|
||||||
|
{ asm = []
|
||||||
|
; env = Env.empty
|
||||||
|
; fpo = 8
|
||||||
|
; cnt = counter + 1
|
||||||
|
; ret = "ret" ^ string_of_int counter
|
||||||
|
}
|
||||||
|
body
|
||||||
|
in
|
||||||
[ Addi (SP, SP, -compiled.fpo)
|
[ Addi (SP, SP, -compiled.fpo)
|
||||||
; Sw (RA, Mem (SP, compiled.fpo - 4))
|
; Sw (RA, Mem (SP, compiled.fpo - 4))
|
||||||
; Sw (FP, Mem (SP, compiled.fpo - 8))
|
; Sw (FP, Mem (SP, compiled.fpo - 8))
|
||||||
; Addi (FP, SP, compiled.fpo - 4)
|
; Addi (FP, SP, compiled.fpo - 4)
|
||||||
]
|
]
|
||||||
@ compiled.asm
|
@ compiled.asm
|
||||||
@ [ Addi (SP, SP, compiled.fpo); Lw (RA, Mem (FP, 0)); Lw (FP, Mem (FP, -4)); Jr RA ]
|
@ [ Label compiled.ret
|
||||||
|
; Addi (SP, SP, compiled.fpo)
|
||||||
|
; Lw (RA, Mem (FP, 0))
|
||||||
|
; Lw (FP, Mem (FP, -4))
|
||||||
|
; Jr RA
|
||||||
|
]
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let compile ir =
|
let compile ir =
|
||||||
let asm = compile_body ir in
|
let asm = compile_body ir 0 in
|
||||||
{ text = Baselib.builtins @ asm; data = [] }
|
{ text = Baselib.builtins @ asm; data = [] }
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -15,6 +15,7 @@ rule token = parse
|
||||||
| [ ' ' '\t' ] { token lexbuf }
|
| [ ' ' '\t' ] { token lexbuf }
|
||||||
| '\n' { Lexing.new_line lexbuf; token lexbuf }
|
| '\n' { Lexing.new_line lexbuf; token lexbuf }
|
||||||
| num+ as n { Lint (int_of_string n) }
|
| num+ as n { Lint (int_of_string n) }
|
||||||
|
| "return" { Lreturn }
|
||||||
| "int" { Ltype (Int_t) }
|
| "int" { Ltype (Int_t) }
|
||||||
| "bool" { Ltype (Bool_t) }
|
| "bool" { Ltype (Bool_t) }
|
||||||
| bool as b { Lbool (bool_of_string b) }
|
| bool as b { Lbool (bool_of_string b) }
|
||||||
|
|
|
@ -5,12 +5,9 @@
|
||||||
|
|
||||||
%token <int> Lint
|
%token <int> Lint
|
||||||
%token <bool> Lbool
|
%token <bool> Lbool
|
||||||
|
|
||||||
%token <Ast.type_t> Ltype
|
%token <Ast.type_t> Ltype
|
||||||
|
|
||||||
%token <string> Lvar
|
%token <string> Lvar
|
||||||
|
%token Lend Lassign Lsc Lreturn
|
||||||
%token Lend Lassign Lsc
|
|
||||||
|
|
||||||
%start prog
|
%start prog
|
||||||
|
|
||||||
|
@ -24,6 +21,7 @@ prog:
|
||||||
;
|
;
|
||||||
|
|
||||||
instr:
|
instr:
|
||||||
|
| Lreturn; e = expr { [ Return { expr = e ; pos = $startpos } ] }
|
||||||
| t = Ltype; v = Lvar {
|
| t = Ltype; v = Lvar {
|
||||||
[ Decl { name = v; type_t = t; pos = $startpos(t) } ]
|
[ Decl { name = v; type_t = t; pos = $startpos(t) } ]
|
||||||
}
|
}
|
||||||
|
|
18
semantics.ml
18
semantics.ml
|
@ -35,18 +35,18 @@ let analyze_value = function
|
||||||
| Syntax.Bool b -> Bool b, Bool_t
|
| Syntax.Bool b -> Bool b, Bool_t
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let analyze_expr env ua x = function
|
let analyze_expr env ua t = function
|
||||||
| Syntax.Val v ->
|
| Syntax.Val v ->
|
||||||
let v2, t = analyze_value v.value in
|
let v2, new_t = analyze_value v.value in
|
||||||
if t != x then errt x t v.pos;
|
if new_t != t then errt t new_t v.pos;
|
||||||
Val v2, 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 (Error ("Unbound variable \"" ^ v.name ^ "\"", v.pos));
|
then raise (Error ("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 t = Env.find v.name env in
|
let new_t = Env.find v.name env in
|
||||||
if t != x then errt x t v.pos;
|
if new_t != t then errt t new_t v.pos;
|
||||||
Var v.name, t
|
Var v.name, new_t
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let analyze_instr env ua = function
|
let analyze_instr env ua = function
|
||||||
|
@ -56,6 +56,9 @@ let analyze_instr env ua = function
|
||||||
then raise (Error ("Unbound variable \"" ^ a.var ^ "\"", a.pos));
|
then raise (Error ("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.Return r ->
|
||||||
|
let ae, _ = analyze_expr env ua Int_t r.expr in
|
||||||
|
Return ae, env, []
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let rec analyze_block env ua = function
|
let rec analyze_block env ua = function
|
||||||
|
@ -77,6 +80,7 @@ let emit oc ast =
|
||||||
and fmt_i = function
|
and fmt_i = function
|
||||||
| Decl v -> "Decl \"" ^ v ^ "\""
|
| Decl v -> "Decl \"" ^ v ^ "\""
|
||||||
| Assign (v, e) -> "Assign (\"" ^ v ^ "\", " ^ fmt_e e ^ ")"
|
| Assign (v, e) -> "Assign (\"" ^ v ^ "\", " ^ fmt_e e ^ ")"
|
||||||
|
| Return e -> "Return (" ^ fmt_e e ^ ")"
|
||||||
and fmt_b b = "[ " ^ String.concat "\n; " (List.map fmt_i b) ^ " ]" in
|
and fmt_b b = "[ " ^ String.concat "\n; " (List.map fmt_i b) ^ " ]" in
|
||||||
Printf.fprintf oc "%s\n" (fmt_b ast)
|
Printf.fprintf oc "%s\n" (fmt_b ast)
|
||||||
;;
|
;;
|
||||||
|
|
Reference in a new issue