2022-12-06 20:39:15 +01:00
|
|
|
open Ast
|
|
|
|
open Ast.IR
|
|
|
|
open Baselib
|
2022-12-09 21:47:22 +01:00
|
|
|
open Errors
|
2022-12-08 19:55:22 +01:00
|
|
|
|
|
|
|
let analyze_value = function
|
2022-12-09 22:20:05 +01:00
|
|
|
| Syntax.Void -> Void, Void_t
|
2022-12-08 19:55:22 +01:00
|
|
|
| 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)
|
2022-12-09 21:47:22 +01:00
|
|
|
then raise (SemanticsError ("Unbound variable \"" ^ v.name ^ "\"", v.pos));
|
2022-12-08 19:55:22 +01:00
|
|
|
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 )
|
2022-12-09 21:47:22 +01:00
|
|
|
| _ -> raise (SemanticsError ("\"" ^ 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)
|
2022-12-09 21:47:22 +01:00
|
|
|
then raise (SemanticsError ("Unbound variable \"" ^ a.var ^ "\"", a.pos));
|
2022-12-08 19:55:22 +01:00
|
|
|
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-10 01:55:15 +01:00
|
|
|
| Syntax.Do d ->
|
|
|
|
let ae, _ = analyze_expr env ua Int_t d.expr in
|
|
|
|
Do ae, env, []
|
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
|
|
|
|
;;
|
|
|
|
|
2022-12-10 01:55:15 +01:00
|
|
|
let analyze_func env ua = function
|
|
|
|
| Syntax.Func f -> Func (f.func, f.args, analyze_block env ua f.code)
|
|
|
|
;;
|
2022-12-08 19:55:22 +01:00
|
|
|
|
2022-12-10 01:55:15 +01:00
|
|
|
let rec analyze_prog env ua = function
|
|
|
|
| [] -> []
|
|
|
|
| fn :: suite -> analyze_func env ua fn :: analyze_prog env ua suite
|
2022-12-08 19:55:22 +01:00
|
|
|
;;
|
2022-12-10 01:55:15 +01:00
|
|
|
|
|
|
|
let analyze parsed = analyze_prog _types_ [] parsed
|