This repository has been archived on 2022-12-27. You can view files and clone it, but cannot push or open issues or pull requests.
compilateurMIPS/semantics.ml

118 lines
3.3 KiB
OCaml
Raw Normal View History

2022-12-06 20:39:15 +01:00
open Ast
open Ast.IR
open Baselib
2022-12-08 19:55:22 +01:00
(* Erreurs *)
2022-12-06 20:39:15 +01:00
exception Error of string * Lexing.position
2022-12-08 19:55:22 +01:00
let errt expected given pos =
2022-12-09 14:45:59 +01:00
let rec string_of_type_t = function
2022-12-08 19:55:22 +01:00
| Int_t -> "int"
2022-12-08 21:30:39 +01:00
| Bool_t -> "bool"
2022-12-09 14:45:59 +01:00
| 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
2022-12-08 19:55:22 +01:00
in
raise
(Error
( Printf.sprintf
2022-12-08 21:30:39 +01:00
"Expected %s but given %s"
2022-12-09 14:45:59 +01:00
(string_of_type_t expected)
(string_of_type_t given)
2022-12-08 19:55:22 +01:00
, pos ))
;;
let warn msg (pos : Lexing.position) =
Printf.eprintf
"Warning on line %d col %d: %s.\n"
pos.pos_lnum
(pos.pos_cnum - pos.pos_bol)
msg
;;
(* Sémantique *)
let analyze_value = function
| Syntax.Int n -> Int n, Int_t
2022-12-08 21:30:39 +01:00
| Syntax.Bool b -> Bool b, Bool_t
2022-12-08 19:55:22 +01:00
;;
2022-12-09 14:45:59 +01:00
let rec analyze_expr env ua t = function
2022-12-08 19:55:22 +01:00
| Syntax.Val v ->
2022-12-09 14:14:33 +01:00
let v2, new_t = analyze_value v.value in
if new_t != t then errt t new_t v.pos;
Val v2, new_t
2022-12-08 19:55:22 +01:00
| Syntax.Var v ->
if not (Env.mem v.name env)
then raise (Error ("Unbound variable \"" ^ v.name ^ "\"", v.pos));
if List.mem v.name ua then warn ("Unassigned variable \"" ^ v.name ^ "\"") v.pos;
2022-12-09 14:14:33 +01:00
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
2022-12-09 14:45:59 +01:00
| 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)))
2022-12-08 19:55:22 +01:00
;;
let analyze_instr env ua = function
| Syntax.Decl d -> Decl d.name, Env.add d.name d.type_t env, [ d.name ] @ ua
| Syntax.Assign a ->
if not (Env.mem a.var env)
then raise (Error ("Unbound variable \"" ^ a.var ^ "\"", a.pos));
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
2022-12-09 14:14:33 +01:00
| Syntax.Return r ->
let ae, _ = analyze_expr env ua Int_t r.expr in
Return ae, env, []
2022-12-06 22:22:48 +01:00
;;
2022-12-06 20:39:15 +01:00
2022-12-08 19:55:22 +01:00
let rec analyze_block env ua = function
| [] -> []
| instr :: new_block ->
let new_instr, new_env, new_ua = analyze_instr env ua instr in
new_instr :: analyze_block new_env new_ua new_block
;;
let analyze parsed = analyze_block _types_ [] parsed
let emit oc ast =
let rec fmt_v = function
| Int n -> "Int " ^ string_of_int n
2022-12-08 21:30:39 +01:00
| Bool b -> "Bool " ^ string_of_bool b
2022-12-08 19:55:22 +01:00
and fmt_e = function
| Val v -> "Val (" ^ fmt_v v ^ ")"
| Var v -> "Var \"" ^ v ^ "\""
2022-12-09 14:45:59 +01:00
| Call (f, a) ->
"Call (\"" ^ f ^ "\", [ " ^ String.concat " ; " (List.map fmt_e a) ^ " ])"
2022-12-08 19:55:22 +01:00
and fmt_i = function
| Decl v -> "Decl \"" ^ v ^ "\""
| Assign (v, e) -> "Assign (\"" ^ v ^ "\", " ^ fmt_e e ^ ")"
2022-12-09 14:14:33 +01:00
| Return e -> "Return (" ^ fmt_e e ^ ")"
2022-12-08 19:55:22 +01:00
and fmt_b b = "[ " ^ String.concat "\n; " (List.map fmt_i b) ^ " ]" in
Printf.fprintf oc "%s\n" (fmt_b ast)
;;