82 lines
2.2 KiB
OCaml
82 lines
2.2 KiB
OCaml
open Ast
|
|
open Ast.IR
|
|
open Baselib
|
|
|
|
(* Erreurs *)
|
|
|
|
exception Error of string * Lexing.position
|
|
|
|
let errt expected given pos =
|
|
let str_of_type_t = function
|
|
| Int_t -> "int"
|
|
| Bool_t -> "bool"
|
|
in
|
|
raise
|
|
(Error
|
|
( Printf.sprintf
|
|
"Expected %s but given %s"
|
|
(str_of_type_t expected)
|
|
(str_of_type_t given)
|
|
, 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
|
|
| Syntax.Bool b -> Bool b, Bool_t
|
|
;;
|
|
|
|
let analyze_expr env ua x = function
|
|
| Syntax.Val v ->
|
|
let v2, t = analyze_value v.value in
|
|
if t != x then errt x t v.pos;
|
|
Val v2, t
|
|
| 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;
|
|
let t = Env.find v.name env in
|
|
if t != x then errt x t v.pos;
|
|
Var v.name, t
|
|
;;
|
|
|
|
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
|
|
;;
|
|
|
|
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
|
|
| Bool b -> "Bool " ^ string_of_bool b
|
|
and fmt_e = function
|
|
| Val v -> "Val (" ^ fmt_v v ^ ")"
|
|
| Var v -> "Var \"" ^ v ^ "\""
|
|
and fmt_i = function
|
|
| Decl v -> "Decl \"" ^ v ^ "\""
|
|
| Assign (v, e) -> "Assign (\"" ^ v ^ "\", " ^ fmt_e e ^ ")"
|
|
and fmt_b b = "[ " ^ String.concat "\n; " (List.map fmt_i b) ^ " ]" in
|
|
Printf.fprintf oc "%s\n" (fmt_b ast)
|
|
;;
|