@@ -42,33 +42,41 @@ type rule =
| RuleSetB


(*
(* Double arrow reduction relations (cf Fig 3) *)

(*
let rule_Exp : state -> state option =
fun state -> match stack_pop state.stack with
| None -> None
| _ -> None
*)

(* Promise Evaluation *)
let rule_ForceP : state -> state option =
fun state -> match stack_pop_expr state.stack with
| Some (MemRef mem, env, stack2) -> (match heap_find mem state.heap with
| Some (PromiseObj (p_expr, p_env)) ->
let top_slot = EvalSlot (p_expr, p_env) in
let bot_slot = UpdateSlot mem in
Some { state with stack = stack_push top_slot
(stack_push bot_slot stack2) }
| _ -> None)
| _ -> None
fun state -> match stack_pop_slot state.state_stack with
| Some (EvalSlot (MemRef mem), c_frame2, c_stack2) ->
(match heap_find mem state.state_heap with
| Some (PromiseObj (p_expr, p_env)) ->
let p_slot = EvalSlot p_expr in
let p_frame = { frame_empty with frame_env = p_env;
slot_list = [p_slot] } in
let c_slot = UpdateSlot mem in
let c_frame3 = frame_push c_slot c_frame2 in
Some { state with
state_stack = stack_push p_frame
(stack_push c_frame3 c_stack2) }
| _ -> None)
| _ -> None

(* Force function *)
let rule_ForceF : state -> state option =
fun state -> match stack_pop_expr state.stack with
| Some (LambdaApp (f_expr, args), env, stack2) ->
let top_slot = EvalSlot (f_expr, env) in
let bot_slot = ArgsSlot (args, env) in
Some { state with stack = stack_push top_slot
(stack_push bot_slot stack2) }
fun state -> match stack_pop_slot state.state_stack with
| Some (EvalSlot (LambdaApp (f_expr, args)), c_frame2, c_stack2) ->
let f_slot = EvalSlot f_expr in
let c_slot = ArgsSlot args in
let c_frame3 = frame_push f_slot (frame_push c_slot c_frame2) in
Some { state with
state_stack = stack_push c_frame3 c_stack2 }
| _ -> None

(* Technically this rule doesn't even ... matter???
@@ -78,59 +86,66 @@ let rule_GetF : state -> state option =
None

let rule_InvF : state -> state option =
fun state -> match stack_pop_2 state.stack with
fun state -> match stack_pop_slot state.state_stack with
| Some _ -> None
| _ -> None


(* Single arrow expression manipulations (cf Fig 5) *)
let rule_Const : state -> state option =
(* pop the stack frame *)
fun state -> match stack_pop_expr state.stack with
(* if it's a constant *)
| Some ((Const c), env, stack2) ->
(* allocate space for it on the heap *)
(let (mem, heap2) = heap_alloc_const c state.heap in
(* create a new slot on the stack with the pointer to where it now
lives on the heap *)
let slot = ReturnSlot (mem, env) in
(* push that slot onto the stack *)
Some { state with heap = heap2;
stack = stack_push slot stack2 })

let rule_const : state -> state option =
fun state -> match stack_pop_slot state.state_stack with
| Some (EvalSlot (Const const), c_frame2, c_stack2) ->
let (mem, heap2) = heap_alloc_const const state.state_heap in
let c_slot = ReturnSlot mem in
let c_frame3 = frame_push c_slot c_frame2 in
Some { state with
state_heap = heap2;
state_stack = stack_push c_frame3 c_stack2 }
| _ -> None


(* Function Definition *)
let rule_Fun : state -> state option =
fun state -> match stack_pop_expr state.stack with
| Some ((LambdaAbs (params, expr)), env, stack2) ->
(let obj = DataObj (FuncVal (params, expr, env), []) in
let (mem, heap2) = heap_alloc obj state.heap in
let slot = ReturnSlot (mem, env) in
Some { state with heap = heap2;
stack = stack_push slot stack2 })
fun state -> match stack_pop_slot state.state_stack with
| Some (EvalSlot (LambdaAbs (params, expr)), c_frame2, c_stack2) ->
let obj = DataObj (FuncVal (params, expr, c_frame2.frame_env), []) in
let (mem, heap2) = heap_alloc obj state.state_heap in
let c_slot = ReturnSlot mem in
let c_frame3 = frame_push c_slot c_frame2 in
Some { state with
state_heap = heap2;
state_stack = stack_push c_frame3 c_stack2 }
| _ -> None

(* Symbol. Actual search code in language/support.ml *)
let rule_Find : state -> state option =
fun state -> match stack_pop_expr state.stack with
| Some (Ident id, env, stack2) -> (match env_find id env state.heap with
(* search for the symbol in the current environment *)
| Some mem -> (* push its address to the stack *)
let slot = EvalSlot (MemRef mem, env) in
Some { state with stack = stack_push slot stack2 }
| _ -> None)
|_ -> None
fun state -> match stack_pop_slot state.state_stack with
| Some (EvalSlot (Ident id), c_frame2, c_stack2) ->
(match env_find id c_frame2.frame_env with
| None -> None
| Some mem ->
let c_slot = EvalSlot (MemRef mem) in
let c_frame3 = frame_push c_slot c_frame2 in
Some { state with
state_stack = stack_push c_frame3 c_stack2 })
| _ -> None


(* Promise Indirection: a shortcut when a promise pointer points to a pointer *)
let rule_GetP : state -> state option =
fun state -> match stack_pop_expr state.stack with
| Some (MemRef mem, env, stack2) -> (match heap_find mem state.heap with
| Some (PromiseObj (MemRef p_mem, p_env)) ->
let slot = EvalSlot (MemRef p_mem, p_env) in (* TODO: verify *)
Some { state with stack = stack_push slot stack2 }
| _ -> None)
let rule_GetP : state -> state option =
fun state -> match stack_pop_slot state.state_stack with
| Some (EvalSlot (MemRef mem), c_frame2, c_stack2) ->
(match heap_find mem state.state_heap with
| Some (PromiseObj (MemRef p_mem, _)) ->
let c_slot = EvalSlot (MemRef p_mem) in
let c_frame3 = frame_push c_slot c_frame2 in
Some { state with
state_stack = stack_push c_frame3 c_stack2 }
| _ -> None)
| _ -> None

(*
(* Assignment *)
let rule_AssId : state -> state option =
fun state -> match stack_pop_expr state.stack with
@@ -147,8 +162,8 @@ let rule_AssId : state -> state option =
let rule_AssStr : state -> state option =
fun state -> match stack_pop_expr state.stack with
| Some (Assign (Const (Str str), expr), env, stack2) ->
let slot = EvalSlot (Ident { default_id with name = str }, env) in
| Some (Assign (Const (Str (Some str)), expr), env, stack2) ->
let slot = ExprSlot (Ident { default_id with name = str }, env) in
Some { state with stack = stack_push slot stack2 }
| _ -> None
@@ -0,0 +1,91 @@
module S = Syntax

(* TODO: better error messaging *)

int_of_bool = function
| true -> 1
| false -> 0

let int_to_bool: S.expr -> S.expr =
function
| S.Const (S.Num (S.Int None)) -> S.Const (S.Bool None)
| S.Const (S.Num (S.Int (Some x))) -> let b = S.Bool (x<>0) in
S.Const(b)
| _ -> failwith "Integer expected"

let float_to_bool: S.expr -> S.expr =
function
| S.Const (S.Num (S.Float None)) -> S.Const (S.Bool None)
| S.Const (S.Num (S.Float (Some x))) -> let b = if x<>x then S.Bool None (* x<>x means x is NaN *)
else S.Bool (x<>0) in S.Const(b)
| _ -> failwith "Float expected"

let complex_to_bool: S.expr -> S.expr =
function
| S.Const (S.Num (S.Complex None)) -> S.Const (S.Bool None)
| S.Const (S.Num (S.Complex (Some x)) -> let b = if (x.re <> x.re) || (x.im <> x.im) then S.Bool None
else S.Bool (x.re <> 0) || (x.im <> 0) in S.Const(b)
| _ -> failwith "Complex expected"

let str_to_bool_help: string -> bool option =
function
| "T" -> Some true
| "TRUE" -> Some true
| "True" -> Some true
| "true" -> Some true
| "F" -> Some false
| "FALSE" -> Some false
| "False" -> Some false
| "false" -> Some false
| _ -> None

let string_to_bool: S.expr -> S.expr =
function
| S.Const (S.String None) -> S.Const (S.Bool None)
| S.Const (S.String (Some s)) -> S.Const (S.Bool (str_to_bool_help s))
|
| _ -> failwith "String expected"

let bool_to_int: S.expr -> S.expr =
function
| S.Const (S.Bool None) -> S.Const (S.Num (S.Int None))
| S.Const (S.Bool (Some b)) -> S.Const (S.Num (S.Int (Some b)))
| _ -> failwith "Bool expected"

let float_to_int_help: float option -> int option = function
| Some x when x > max_int || x < min_int -> let _ = Printf.printf
"Float conversion exceeds integer bounds" in None
| Some x -> Some (int_of_float x)
| None -> None

(* TODO: is there a separate float NA? *)
let float_to_int: S.expr -> S.expr =
function
| S.Const (S.Num (S.Float x) ) -> S.Const (S.Num (S.Int (float_to_int_help x)))
| _ -> failwith "Float expected"

let complex_to_int_help: Complex.complex option -> int option = function
| Some x when x.re > max_int -> None
| Some x when x.im > max_int -> None
| Some x when x.im <> 0 -> let _ = Printf.printf "Implicit conversion of complex" in
Some (int_of_float x.re)
| Some x -> Some (int_of_float x.re)
| None -> None

let complex_to_int: S.expr -> S.expr =
function
| S.Const (S.Num (S.Complex x) -> S.Const (S.Num (S.Int (complex_to_int_help x)))
| _ -> failwith "Complex expected"

(* TODO: R's conversion may be slightly different *)
let string_to_int: S.expr -> S.expr =
function
| S.Const (S.String None) -> S.Const (S.Num (S.Int None))
| S.Const (S.String s) -> S.Const (S.Num (S.Int (Some (int_of_string x))))
| _ -> failwith "String expected"

let bool_to_real: S.expr -> S.expr =
function
| S.Const (S.Bool None) -> S.Const (S.Num (S.Float None))
| S.Const (S.Bool (Some b)) -> S.Const (S.Num (S.Float (Some (float_of_int b))))
| _ -> failwith "Bool expected"
@@ -25,16 +25,21 @@ and string_of_memref : memref -> string =

and string_of_numeric : numeric -> string =
fun num -> match num with
| Na -> "Na"
| Int i -> "Int (" ^ string_of_int i ^ ")"
| Float f -> "Float (" ^ string_of_float f ^ ")"
| Complex c -> "Complex (" ^ string_of_float (c.Complex.re) ^ "," ^
| Int (Some i) -> "Int (" ^ string_of_int i ^ ")"
| Int None -> "Int (Na)"
| Float (Some f) -> "Float (" ^ string_of_float f ^ ")"
| Float None -> "Float (Na)"
| Complex (Some c) -> "Complex (" ^ string_of_float (c.Complex.re) ^ "," ^
string_of_float (c.Complex.im) ^ ")"
| Complex None -> "Complex (Na)"

and string_of_const : const -> string =
fun const -> match const with
| Num n -> "Num (" ^ string_of_numeric n ^ ")"
| Str s -> "Str (" ^ s ^ ")"
| Num n -> "Num (" ^ string_of_numeric n ^ ")"
| Str (Some s) -> "Str (" ^ s ^ ")"
| Str None -> "Str (Na)"
| Bool (Some b) -> "Bool (" ^ string_of_int b ^ ")"
| Bool None -> "Bool (Na)"

and string_of_param : param -> string =
fun param -> match param with
@@ -36,12 +36,13 @@ end
module Ident_Map = Map.Make (Ident)

(* Environment *)
type env = { env_list : memref list }
type env = { env_map : memref Ident_Map.t }

(* Values *)
type value =
NumArray of numeric list
| StrArray of string list
| StrArray of (string option) list
| BoolArray of (int option) list
| RefArray of memref list
| FuncVal of param list * expr * env

@@ -63,18 +64,14 @@ type slot =

type frame =
{ frame_env : env;
frame_slots : slot list }
slot_list : slot list }

type stack = { stack_list : slot list }
type stack = { frame_list : frame list }


(* Frame *)
type mapping = { mapping_map: memref Ident_Map.t }

(* Heap *)
type heapobj =
FrameObj of mapping
| PromiseObj of expr * env
PromiseObj of expr * env
| DataObj of value * attribute list

type heap =
@@ -83,8 +80,9 @@ type heap =

(* Execution state *)
type state =
{ stack : stack;
heap : heap;
{ state_stack : stack;
state_heap : heap;
state_env : env;
ident_count : int }


@@ -105,66 +103,96 @@ let mem_of_int : int -> memref =
fun addr ->
{ R.addr = addr }

let incr_mem : memref -> memref =
let mem_incr : memref -> memref =
fun mem ->
{ mem with R.addr = mem.R.addr + 1 }


(* Fresh identifier *)
let default_id : ident =
let id_default : ident =
{ R.pkg = None;
R.name = "";
R.ident_tag = None }

let fresh_id : state -> ident * state =
let id_of_string : string -> ident =
fun name ->
{ id_default with R.name = name }

let id_fresh : state -> ident * state =
fun state ->
let count2 = state.ident_count + 1 in
let name2 = "fs$" ^ string_of_int count2 in
({ default_id with R.name = name2 },
{ state with ident_count = count2 })
(id_of_string name2, { state with ident_count = count2 })


(* Frame lookup *)

let mapping_empty : mapping =
{ mapping_map = Ident_Map.empty }
(* Environment lookup *)
let env_empty : env =
{ env_map = Ident_Map.empty }

let mapping_find : ident -> mapping -> memref option =
fun id mapping ->
let env_find : ident -> env -> memref option =
fun id env ->
try
Some (Ident_Map.find id mapping.mapping_map)
Some (Ident_Map.find id env.env_map)
with
Not_found -> None

let mapping_add : ident -> memref -> mapping -> mapping =
fun id mem mapping ->
{ mapping with mapping_map = Ident_Map.add id mem mapping.mapping_map }
let env_add : ident -> memref -> env -> env =
fun id mem env ->
{ env with env_map = Ident_Map.add id mem env.env_map }


(* Stack operations *)
(* Frame operations *)
let frame_empty : frame =
{ frame_env = env_empty;
slot_list = [] }

let frame_pop : frame -> (slot * frame) option =
fun frame -> match frame.slot_list with
| [] -> None
| (slot :: tail) -> Some (slot, { frame with slot_list = tail })

let frame_pop_2 : frame -> (slot * slot * frame) option =
fun frame -> match frame_pop frame with
| None -> None
| Some (slot1, frame2) -> match frame_pop frame2 with
| None -> None
| Some (slot2, frame3) -> Some (slot1, slot2, frame3)

let frame_push : slot -> frame -> frame =
fun slot frame ->
{ frame with slot_list = slot :: frame.slot_list }

let frame_push_2 : slot -> slot -> frame -> frame =
fun slot1 slot2 frame ->
frame_push slot1 (frame_push slot2 frame)


(* Stack operations *)
let stack_empty : stack =
{ stack_list = [] }
{ frame_list = [] }

let stack_pop : stack -> (slot * stack) option =
fun stack -> match stack.stack_list with
let stack_pop : stack -> (frame * stack) option =
fun stack -> match stack.frame_list with
| [] -> None
| (slot :: tail) -> Some (slot, { stack with stack_list = tail })
| (frame :: tail) -> Some (frame, { stack with frame_list = tail })

let stack_pop_2 : stack -> (slot * slot * stack) option =
fun stack -> match stack.stack_list with
| (slot1 :: slot2 :: tail) ->
Some (slot1, slot2, { stack with stack_list = tail })
| _ -> None
let stack_pop_slot : stack -> (slot * frame * stack) option =
fun stack -> match stack_pop stack with
| None -> None
| Some (frame, stack2) -> match frame_pop frame with
| None -> None
| Some (slot, frame2) -> Some (slot, frame2, stack2)

let stack_pop_expr : stack -> (expr * env * stack) option =
let stack_pop_slot_2 : stack -> (slot * slot * frame * stack) option =
fun stack -> match stack_pop stack with
| Some (EvalSlot (expr, env), stack2) -> Some (expr, env, stack2)
| _ -> None
| None -> None
| Some (frame, stack2) -> match frame_pop_2 frame with
| None -> None
| Some (slot1, slot2, frame2) -> Some (slot1, slot2, frame2, stack2)

let stack_push : slot -> stack -> stack =
fun slot stack ->
{ stack with stack_list = slot :: stack.stack_list }
let stack_push : frame -> stack -> stack =
fun frame stack ->
{ stack with frame_list = frame :: stack.frame_list }


(* Heap operations *)
@@ -195,60 +223,13 @@ let heap_alloc : heapobj -> heap -> memref * heap =
let used_mem = heap.next_mem in
(used_mem,
{ heap with heap_map = MemRef_Map.add used_mem obj heap.heap_map;
next_mem = incr_mem used_mem })
next_mem = mem_incr used_mem })

let heap_alloc_const : R.const -> heap -> (memref * heap) =
fun const heap -> match const with
| R.Num n -> heap_alloc (DataObj (NumArray [n], [])) heap
| R.Str s -> heap_alloc (DataObj (StrArray [s], [])) heap
| R.Bool b -> heap_alloc (DataObj (BoolArray [b], [])) heap


(* Environment operations *)

let env_empty : env =
{ env_list = [] }

let env_pop : env -> (memref * env) option =
fun env -> match env.env_list with
| [] -> None
| (f_mem :: tail) -> Some (f_mem, { env with env_list = tail })

let env_push : memref -> env -> env =
fun f_mem env ->
{ env with env_list = f_mem :: env.env_list }

(* Pop the top-level mapping and its memory reference on the heap *)
let env_pop_mapping : env -> heap -> (memref * mapping * env) option =
fun env heap -> match env_pop env with
| None -> None
| Some (f_mem, env2) -> match heap_find f_mem heap with
| Some (FrameObj mapping) -> Some (f_mem, mapping, env2)
| _ -> None

(* Add a mapping to the mapping at the top level.
Do not push new mappings if the memory reference is wrong. *)
let env_add_map : ident -> memref -> env -> heap -> (env * heap) option =
fun id mem env heap -> match env_pop_mapping env heap with
| None -> None
| Some (f_mem, mapping, _) ->
let f_obj = FrameObj (mapping_add id mem mapping) in
let heap2 = heap_add f_mem f_obj heap in
Some (env, heap2)

let rec env_find : ident -> env -> heap -> memref option =
fun id env heap -> match env_pop_mapping env heap with
| None -> None
| Some (f_mem, mapping, env2) -> match mapping_find id mapping with
| None -> env_find id env2 heap
| Some mem -> Some mem

let rec env_find_deep : ident -> env -> heap -> memref option =
fun id env heap -> match env_pop_mapping env heap with
| None -> None
| Some (f_mem, mapping, env2) -> match mapping_find id mapping with
| None -> env_find_deep id env2 heap
| Some mem -> match heap_find_deep mem heap with
| None -> None
| Some (mem2, _) -> Some mem2


@@ -7,14 +7,14 @@ type 'a ident =
type 'b tick = { tick_tag : 'b }

type numeric =
Int of int
| Float of float
| Complex of Complex.t
| Na
Int of int option
| Float of float option
| Complex of Complex.t option

type const =
Num of numeric
| Str of string
| Str of string option
| Bool of int option (* bools are stored as 0,1 *)

type memref = { addr : int }

@@ -13,27 +13,27 @@ let convert_ident: 'a R.ident -> 'a L.ident =

let convert_numeric: R.numeric -> L.numeric =
function
| R.Int n -> L.Int n
| R.Float f -> L.Float f
| R.Complex (f1, f2) -> L.Complex {re = f1; im = f2}
| R.Na -> L.Na
| R.Int n -> L.Int (Some n)
| R.Float f -> L.Float (Some f)
| R.Complex (f1, f2) -> L.Complex (Some {re = f1; im = f2})
| R.Na -> L.Int (None) (* TODO *)

let rec convert_expr: 'a R.expr -> ('a, 'b) L.expr =
function
| R.NumericConst n -> L.Const (L.Num (convert_numeric n))
| R.StringConst s -> L.Const (L.Str s)
| R.BoolConst b -> let b_num = if b then 1 else 0 in
L.Const (L.Num (L.Int b_num))
| R.Null -> L.Const (L.Num (L.Int 0)) (* TODO *)
| R.StringConst s -> L.Const (L.Str (Some s))
| R.BoolConst b -> let b_num = if b then Some 1 else Some 0 in
L.Const (L.Bool b_num)
| R.Null -> L.Const (L.Num (L.Int (Some 0))) (* TODO *)
| R.Ident i -> L.Ident (convert_ident i)
| R.Uop (u, e) -> let u_ident = uop_to_ident u in
let c_expr = convert_expr e in
begin match u with
| R.UMinus -> L.LambdaApp (L.Ident u_ident,
[L.Arg (L.Const (L.Num (L.Int 0)));
[L.Arg (L.Const (L.Num (L.Int (Some 0))));
L.Arg c_expr])
| R.UPlus -> L.LambdaApp (L.Ident u_ident,
[L.Arg (L.Const (L.Num (L.Int 0)));
[L.Arg (L.Const (L.Num (L.Int (Some 0))));
L.Arg c_expr])
| R.Not -> L.LambdaApp (L.Ident u_ident,
[L.Arg c_expr])