add baselib support

This commit is contained in:
Mylloon 2022-12-09 14:45:59 +01:00
parent d433aafc4f
commit cf14c64adc
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
9 changed files with 80 additions and 18 deletions

View file

@ -29,7 +29,7 @@ $ make test
- [x] Type `bool`
- [ ] Type `string`
- [x] Déclaration / assignation de variables
- [ ] Librairie standard (multiplication, addition, comparateur, ...)
- [x] Librairie standard (multiplication, addition, comparateur, ...)
- [ ] Conditions
- [ ] Boucles
- [ ] Fonctions utilisateurs

7
ast.ml
View file

@ -1,6 +1,7 @@
type type_t =
| Int_t
| Bool_t
| Func_t of type_t * type_t list
module Syntax = struct
type ident = string
@ -18,6 +19,11 @@ module Syntax = struct
{ name : ident
; pos : Lexing.position
}
| Call of
{ func : ident
; args : expr list
; pos : Lexing.position
}
type instr =
| Decl of
@ -48,6 +54,7 @@ module IR = struct
type expr =
| Val of value
| Var of ident
| Call of ident * expr list
type instr =
| Decl of ident

View file

@ -1,5 +1,12 @@
open Ast
open Mips
module Env = Map.Make (String)
let _types_ = Env.empty
let builtins = []
let _types_ = Env.of_seq (List.to_seq [ "%add", Func_t (Int_t, [ Int_t; Int_t ]) ])
let builtins =
List.fold_left
(fun env (fn, impl) -> Env.add fn impl env)
Env.empty
[ "%add", [ Lw (T0, Mem (SP, 0)); Lw (T1, Mem (SP, 4)); Add (V0, T0, T1) ] ]
;;

View file

@ -15,9 +15,16 @@ let compile_value = function
| Bool b -> [ Li (V0, if b then 1 else 0) ]
;;
let compile_expr env = function
let rec compile_expr env = function
| Val v -> compile_value v
| Var v -> [ Lw (V0, Env.find v env) ]
| Call (f, args) ->
let ca =
List.map
(fun a -> compile_expr env a @ [ Addi (SP, SP, -4); Sw (V0, Mem (SP, 0)) ])
args
in
List.flatten ca @ Env.find f Baselib.builtins
;;
let compile_instr info = function
@ -62,5 +69,5 @@ let compile_body body counter =
let compile ir =
let asm = compile_body ir 0 in
{ text = Baselib.builtins @ asm; data = [] }
{ text = asm; data = [] }
;;

View file

@ -21,6 +21,7 @@ rule token = parse
| bool as b { Lbool (bool_of_string b) }
| '=' { Lassign }
| ';' { Lsc }
| '+' { Ladd}
| ident as i { Lvar i }
| '#' { comment lexbuf }
| _ as c { raise (Error c) }

View file

@ -8,6 +8,9 @@
%token <Ast.type_t> Ltype
%token <string> Lvar
%token Lend Lassign Lsc Lreturn
%token Ladd
%left Ladd
%start prog
@ -17,20 +20,20 @@
prog:
| Lend { [] }
| i = instr; Lsc; b = prog { i @ b }
| i = instr ; Lsc ; b = prog { i @ b }
;
instr:
| Lreturn; e = expr { [ Return { expr = e ; pos = $startpos } ] }
| t = Ltype; v = Lvar {
[ Decl { name = v; type_t = t; pos = $startpos(t) } ]
| Lreturn ; e = expr { [ Return { expr = e ; pos = $startpos } ] }
| t = Ltype ; v = Lvar {
[ Decl { name = v ; type_t = t ; pos = $startpos(t) } ]
}
| t = Ltype; v = Lvar; Lassign; e = expr
{ [ Decl { name = v; type_t = t; pos = $startpos(t) }
; Assign { var = v; expr = e; pos = $startpos(v) } ]
| t = Ltype ; v = Lvar ; Lassign ; e = expr
{ [ Decl { name = v ; type_t = t ; pos = $startpos(t) }
; Assign { var = v ; expr = e ; pos = $startpos(v) } ]
}
| v = Lvar; Lassign; e = expr
{ [ Assign { var = v; expr = e; pos = $startpos($2) } ]
| v = Lvar ; Lassign ; e = expr
{ [ Assign { var = v ; expr = e ; pos = $startpos($2) } ]
}
expr:
@ -43,4 +46,7 @@ expr:
| v = Lvar {
Var { name = v ; pos = $startpos(v) }
}
| a = expr ; Ladd ; b = expr {
Call { func = "%add" ; args = [ a ; b ] ; pos = $startpos($2) }
}
;

View file

@ -7,16 +7,22 @@ open Baselib
exception Error of string * Lexing.position
let errt expected given pos =
let str_of_type_t = function
let rec string_of_type_t = function
| Int_t -> "int"
| Bool_t -> "bool"
| Func_t (r, a) ->
(if List.length a > 1 then "(" else "")
^ String.concat ", " (List.map string_of_type_t a)
^ (if List.length a > 1 then ")" else "")
^ " -> "
^ string_of_type_t r
in
raise
(Error
( Printf.sprintf
"Expected %s but given %s"
(str_of_type_t expected)
(str_of_type_t given)
(string_of_type_t expected)
(string_of_type_t given)
, pos ))
;;
@ -35,7 +41,7 @@ let analyze_value = function
| Syntax.Bool b -> Bool b, Bool_t
;;
let analyze_expr env ua t = 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 then errt t new_t v.pos;
@ -47,6 +53,29 @@ let analyze_expr env ua t = function
let new_t = Env.find v.name env in
if new_t != t then errt t new_t v.pos;
Var v.name, new_t
| Syntax.Call c ->
(match Env.find c.func env with
| Func_t (ret_t, tl) ->
if ret_t != t then errt t ret_t c.pos;
( Call
( c.func
, List.map2
(fun t e ->
let e2, t2 = analyze_expr env ua t e in
if t2 = t
then e2
else
errt
t
t2
(match e with
| Syntax.Val v -> v.pos
| Syntax.Var v -> v.pos
| Syntax.Call c -> c.pos))
tl
c.args )
, ret_t )
| _ -> raise (Error ("\"" ^ c.func ^ "\" isn't a function", c.pos)))
;;
let analyze_instr env ua = function
@ -77,6 +106,8 @@ let emit oc ast =
and fmt_e = function
| Val v -> "Val (" ^ fmt_v v ^ ")"
| Var v -> "Var \"" ^ v ^ "\""
| Call (f, a) ->
"Call (\"" ^ f ^ "\", [ " ^ String.concat " ; " (List.map fmt_e a) ^ " ])"
and fmt_i = function
| Decl v -> "Decl \"" ^ v ^ "\""
| Assign (v, e) -> "Assign (\"" ^ v ^ "\", " ^ fmt_e e ^ ")"

2
tests/09_return.test Normal file
View file

@ -0,0 +1,2 @@
int vie = 42;
return vie;

1
tests/10_add.test Normal file
View file

@ -0,0 +1 @@
int res = 1 + 1;