structures: semantics fixes, part of analyzer

This commit is contained in:
ProgramSnail 2026-04-28 14:37:54 +00:00
parent 967d213f54
commit 0be430a59b
2 changed files with 206 additions and 39 deletions

View file

@ -1,50 +1,212 @@
module Functional = module Functional =
struct struct
(* --- types --- *)
type data = int type data = int
type memid = int
(* --- syntax --- *)
type read_cap = Rd | NRd type read_cap = Rd | NRd
type write_cap = AlwaysWr | MayWr | NeverWr type write_cap = AlwaysWr | MayWr | NeverWr
type copy_cap = Cp | NCp type copy_cap = Cp | Rf
type in_cap = In | NIn type in_cap = In | NIn
type out_cap = Out | NOut type out_cap = Out | NOut
type tag = read_cap * write_cap * copy_cap * in_cap * out_cap type mode = in_cap * out_cap
type path = VarP of data | DerefP of path | AccessP of path * data type path = VarP of data | DerefP of path | AccessP of path * data
type argtype = UnitT | RefT of tag * argtype | TupleT of argtype list | FunT of data
type argmem = VarM of data | RefM of argmem | TupleM of argmem list | FunM
type stmt = Call of data * path list | CallLam of path * path list | Read of path | Write of path | Choice of stmt list * stmt list type atype = UnitT of read_cap * write_cap
type body = stmt list | RefT of copy_cap * atype
| TupleT of atype list
| FunT of data (* declaration id for ease of impl (?) *)
type fun_decl = argtype list * body type mtype = mode * atype
type prog = fun_decl list * fun_decl
type expr = UnitE
| PathE of path
(* | RefE *)
| TupleE of expr list
type stmt = CallS of path * expr list
| WriteS of path
| ReadS of path
| SeqS of stmt * stmt
| ChoiceS of stmt * stmt
type decl = VarD of (* data * *) atype * expr
| FunD of (* data * *) (* (data * *) mtype (* ) *) list * stmt
type prog = decl list * stmt
(* --- exceptions --- *) (* --- exceptions --- *)
exception Incorrect_memory_access of int (* exception Incorrect_memory_access of int *)
exception Ref_rvalue_argument of int (* exception Ref_rvalue_argument of int *)
exception Incorrect_const_cast of int (* exception Incorrect_const_cast of int *)
exception Invalid_argument_tag of int (* exception Invalid_argument_tag of int *)
exception Incompatible_states (* exception Incompatible_states *)
exception Incompatible_path_and_type (* exception Incompatible_path_and_type *)
exception Incompatible_path_and_mem (* exception Incompatible_path_and_mem *)
exception Incompatible_path_and_type_for_tag (* exception Incompatible_path_and_type_for_tag *)
exception Typing_error of string
(* --- static interpreter (no rec) --- *) (* value model & memory model *)
(* TODO: allow data (rvalue) in calls ?? *) type deepvalue = ZeroDV
type arg = RValue | LValue of path | SmthDV
type value = UnitV | UndefV | BotV | BotDV
| FunDV of (* data list * *) stmt
| RefDV of deepvalue
| TupleDV of deepvalue list
type env = (int * (argmem * argtype)) list type value = ZeroV
| SmthV
| BotV
| FunV of (* data list * *) stmt
| RefV of memid
| TupleV of value list
(* env * memory * last unused memory * visited functions *) (* TODO: any additional difference between rvalue and lvalue now ?? *)
type state = env * value list * int * int list
(* --- *)
type mem = (memid * value) list * memid (* NOTE: memory and first free elem *)
type types = (data * atype) list
type vals = (data * memid) list
type state = mem * types * vals
(* --- *)
(* TODO: FIXME: use list_replace for memory instead ?? *)
let mem_get (mem : mem) (id : memid) : value = List.assoc id (fst mem)
let mem_add (mem : mem) (v : value) : mem * memid =
(((snd mem, v) :: fst mem, snd mem + 1), snd mem)
let mem_set (mem : mem) (id : memid) (v : value) : mem =
((id, v) :: fst mem, snd mem)
let rec v_to_deepv (mem : mem) (v : value) : deepvalue = match v with
| ZeroV -> ZeroDV
| SmthV -> SmthDV
| BotV -> BotDV
| FunV s -> FunDV s
| RefV id -> RefDV (v_to_deepv mem @@ mem_get mem id)
| TupleV vs -> TupleDV (List.map (v_to_deepv mem) vs)
let is_trivial_v (v : value) : bool =
v == ZeroV || v == SmthV || v == BotV
(* --- path accessors --- *)
let rec pathvar (p : path) : data = match p with
| VarP x -> x
| DerefP p -> pathvar p
| AccessP (p, _) -> pathvar p
let rec pathtype (types : types) (p : path) : atype = match p with
| VarP x -> List.assoc x types
| DerefP p -> (match pathtype types p with
| RefT (_, t) -> t
| _ -> raise @@ Typing_error "pathtype: deref")
| AccessP (p, id) -> match pathtype types p with
| TupleT ts -> (List.nth ts id)
| _ -> raise @@ Typing_error "pathtype: access"
let rec pathval (mem : mem) (vals : vals) (p : path) : value = match p with
| VarP x -> mem_get mem @@ List.assoc x vals
| DerefP p -> (match pathval mem vals p with
| RefV id -> mem_get mem id
| _ -> raise @@ Typing_error "pathval: deref")
| AccessP (p, id) -> match pathval mem vals p with
| TupleV vs -> (List.nth vs id)
| _ -> raise @@ Typing_error "pathval: access"
(* --- eval rules --- *)
(* - utils *)
let rec list_replace (xs : 'a list) (id : int) (y : 'a) : 'a list = match xs, id with
| _ :: xs, 0 -> y :: xs
| x :: xs, _ -> x :: list_replace xs (id - 1) y
| [], _ -> raise Not_found
(* - value construction *)
let rec valcopy (mem : mem) (v : value) (t : atype) : mem * value = match t, v with
| UnitT (Rd, w), ZeroV -> (mem, v)
| UnitT (Rd, w), SmthV -> (mem, v)
| UnitT (Rd, w), BotV -> (mem, v)
| UnitT (NRd, w), ZeroV -> (mem, BotV)
| UnitT (NRd, w), SmthV -> (mem, BotV)
| UnitT (NRd, w), BotV -> (mem, BotV)
| FunT _, FunV _ -> (mem, v)
| RefT (Rf, _), RefV _ -> (mem, v)
| RefT (Cp, t), RefV id -> let (mem', v') = valcopy mem (mem_get mem id) t in
let (mem'', id'') = mem_add mem' v' in
(mem'', RefV id'')
| TupleT ts, TupleV vs -> let folder = fun (mem, vs') v t -> let (mem', v') = valcopy mem v t in
mem, v' :: vs' in
let mem', vs' = List.fold_left2 folder (mem, []) vs ts in
(mem', TupleV vs')
| _, _ -> raise @@ Typing_error "valcopy"
(* - value update *)
let rec valupd (mem : mem) (v : value) (p : path) (b : value) : mem * value = match p, v with
| VarP x, _ -> (mem, b)
| DerefP p, RefV id -> let (mem', v') = valupd mem (mem_get mem id) p b in
(mem_set mem' id v', RefV id)
| AccessP (p, id), TupleV vs -> let (mem', v') = valupd mem (List.nth vs id) p b in
(mem', TupleV (list_replace vs id v'))
| _, _ -> raise @@ Typing_error "valupd"
(* - value combination *)
let rec valcomb (u : value) (v : value) : value =
if is_trivial_v u && is_trivial_v v
then (if u == v then u else BotV)
else match u, v with
(* TODO: FIXME: combining semanticsfor funcitons statements *)
| FunV s, FunV t -> if s == t then u else raise @@ Typing_error "valcomb: fun"
| RefV a, RefV b -> if a == b then u else raise @@ Typing_error "valcomb: ref"
| TupleV us, TupleV vs -> TupleV (List.map2 valcomb us vs)
| _, _ -> raise @@ Typing_error "valcomb"
(* TODO: func for list memory, not assoc list *)
(* let rec memcomb (m : mem) (n : mem) : mem = *)
(* if snd m != snd n *)
(* then raise @@ Typing_error "memcomb" *)
(* else (List.map2 valcomb (fst m) (fst n), snd m) *)
(* - call values spoil *)
(* TODO: check all cases *)
let is_correct_tags (v : value) (r : read_cap) (w : write_cap)
(r' : read_cap) (w' : write_cap) (m : mode)
(c : copy_cap) : bool =
(r != Rd || v == ZeroV) &&
(r != Rd || fst m == In) &&
(o != Out || w == AlwaysWr) &&
(* TODO: check *)
((not @@ (w == AlwaysWr || w == MayWr) && (snd m == Out || c == Rf)) || w' == AlwaysWr) &&
is_trivial_v v
let rec valspoil (mem : mem) (v : value) (t : atype)
(u : atype) (m : mode) (c : copy_cap)
: mem * value = match t, u, v with
| UnitT (r, w), UnitT (r', w'), _ -> (* TODO FIXME *) raise Not_found
| FunT ts, FunT us, FunV _ -> if ts == us then (mem, v) else raise @@ Typing_error "valspoil: fun"
| RefT (ct, t), RefT (cu, u), RefV id ->
let (mem', v') = valspoil mem (mem_get mem id) t u m ct in
(mem_set mem id v', RefV id)
| TupleT ts, TupleT us, TupleV vs -> (* TODO FIXME *) raise Not_found
| _, _, _ -> raise @@ Typing_error "valspoil"
(* --- FIXME --- CURRENT REWRITE POINT --- FIXME --- *)
(* let rec argsspoil (* full spoil *) *)
(* --- *) (* --- *)
@ -277,12 +439,12 @@ struct
let wi_value : tag = (NRd, AlwaysWr, Cp, In, NOut) let wi_value : tag = (NRd, AlwaysWr, Cp, In, NOut)
let mwi_value : tag = (NRd, MayWr, Cp, In, NOut) let mwi_value : tag = (NRd, MayWr, Cp, In, NOut)
let i_value : tag = (NRd, NeverWr, Cp, In, NOut) let i_value : tag = (NRd, NeverWr, Cp, In, NOut)
let rwi_ref : tag = (Rd, AlwaysWr, NCp, In, NOut) let rwi_ref : tag = (Rd, AlwaysWr, Rf, In, NOut)
let rmwi_ref : tag = (Rd, MayWr, NCp, In, NOut) let rmwi_ref : tag = (Rd, MayWr, Rf, In, NOut)
let ri_ref : tag = (Rd, NeverWr, NCp, In, NOut) let ri_ref : tag = (Rd, NeverWr, Rf, In, NOut)
let wi_ref : tag = (NRd, AlwaysWr, NCp, In, NOut) let wi_ref : tag = (NRd, AlwaysWr, Rf, In, NOut)
let mwi_ref : tag = (NRd, MayWr, NCp, In, NOut) let mwi_ref : tag = (NRd, MayWr, Rf, In, NOut)
let i_ref : tag = (NRd, NeverWr, NCp, In, NOut) let i_ref : tag = (NRd, NeverWr, Rf, In, NOut)
(* >> tests without functions *) (* >> tests without functions *)

View file

@ -138,7 +138,7 @@
Prod( Prod(
`prog`, `prog`,
{ {
Or[$decl stmt$][declarations and executet statement] Or[$decl+ space stmt$][declarations and executed statement]
} }
), ),
) )
@ -155,7 +155,7 @@
Or[$0$][valid value of simple type] // `Unit` Or[$0$][valid value of simple type] // `Unit`
Or[$\#$][valid or spoiled value of simple type] // `Unit` Or[$\#$][valid or spoiled value of simple type] // `Unit`
Or[$bot$][spoiled value of simple type] // `Unit` Or[$bot$][spoiled value of simple type] // `Unit`
Or[$lambda overline(x) space stmt$][function pointer value] // `Fun` Or[$lambda space overline(x) stmt$][function pointer value] // `Fun`
Or[$rf deepValue$][reference value, contains label of the value in the memory] // `Ref` Or[$rf deepValue$][reference value, contains label of the value in the memory] // `Ref`
Or[$[deepValue+]$][tuple value] // `Prod` Or[$[deepValue+]$][tuple value] // `Prod`
} }
@ -166,7 +166,7 @@
Or[$0$][valid value of simple type] // `Unit` Or[$0$][valid value of simple type] // `Unit`
Or[$\#$][valid or spoiled value of simple type] // `Unit` Or[$\#$][valid or spoiled value of simple type] // `Unit`
Or[$bot$][spoiled value of simple type] // `Unit` Or[$bot$][spoiled value of simple type] // `Unit`
Or[$lambda overline(x) space stmt$][function pointer value] // `Fun` Or[$lambda space overline(x) stmt$][function pointer value] // `Fun`
Or[$rf LL$][reference value, contains label of the value in the memory] // `Ref` Or[$rf LL$][reference value, contains label of the value in the memory] // `Ref`
Or[$[value+]$][tuple value] // `Prod` Or[$[value+]$][tuple value] // `Prod`
} }
@ -585,7 +585,11 @@ $s in stmt, f in X, x in X, a in X$
rule( rule(
name: [ combine lambda values], name: [ combine lambda values],
$lambda plus.o lambda = lambda$ // TODO: FIXME: how to combine statments in the right way? should check both
[*TODO: combining semantics for lambda values (sets?)*],
$overline(x_1) = overline(x_2)$,
$s_1 = s_2$,
$lambda space overline(x_1) space s_2 plus.o lambda space overline(x_2) space s_2 = lambda$
) )
)) ))
@ -711,7 +715,8 @@ $s in stmt, f in X, x in X, a in X$
rule( rule(
name: [ lambda step], name: [ lambda step],
$cl lambda, mu cr xarrowSquiggly(lambda overline(t) \, lambda overline(t) \, m \, c)_spoil cl lambda, mu cr$, $overline(t) = overline(t')$,
$cl lambda, mu cr xarrowSquiggly(lambda overline(t) \, lambda overline(t') \, m \, c)_spoil cl lambda, mu cr$,
) )
)) ))
@ -736,10 +741,10 @@ $s in stmt, f in X, x in X, a in X$
rule( rule(
name: [ tuple step], name: [ tuple step],
$cl v_1, mu cr xarrowSquiggly(t_1 \, t'_1 \, m \, c)_spoil cl v'_1, mu cr$, $cl v_1, mu_0 cr xarrowSquiggly(t_1 \, t'_1 \, m \, c)_spoil cl v'_1, mu_1 cr$,
$...$, $...$,
$cl v_n, mu cr xarrowSquiggly(t_n \, t'_n \, m \, c)_spoil cl v'_n, mu cr$, $cl v_n, mu_(n - 1) cr xarrowSquiggly(t_n \, t'_n \, m \, c)_spoil cl v'_n, mu_n cr$,
$cl [v_1, ... v_n], mu cr xarrowSquiggly([t_1, ... t_n] \, [t'_1, ... t'_n] \, m \, c)_spoil cl [v'_1, ... v'_n], mu' cr$, $cl [v_1, ... v_n], mu_0 cr xarrowSquiggly([t_1, ... t_n] \, [t'_1, ... t'_n] \, m \, c)_spoil cl [v'_1, ... v'_n], mu_n cr$,
) )
)) ))