summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gen_lib/sail_operators_mwords.lem10
-rw-r--r--src/initial_check.ml1
-rw-r--r--src/monomorphise.ml322
-rw-r--r--src/ocaml_backend.ml71
-rw-r--r--src/pretty_print_lem.ml44
-rw-r--r--src/process_file.ml2
-rw-r--r--src/rewriter.mli12
-rw-r--r--src/sail.ml61
-rw-r--r--src/trace_viewer/.gitignore6
-rw-r--r--src/trace_viewer/List-add.svg56
-rw-r--r--src/trace_viewer/List-remove.svg117
-rw-r--r--src/trace_viewer/README11
-rw-r--r--src/trace_viewer/index.css86
-rw-r--r--src/trace_viewer/index.html19
-rw-r--r--src/trace_viewer/index.ts287
-rw-r--r--src/trace_viewer/main.ts12
-rw-r--r--src/trace_viewer/package.json15
-rw-r--r--src/trace_viewer/tsconfig.json18
-rw-r--r--src/type_check.ml26
19 files changed, 1088 insertions, 88 deletions
diff --git a/src/gen_lib/sail_operators_mwords.lem b/src/gen_lib/sail_operators_mwords.lem
index d4dca80c..8fb55137 100644
--- a/src/gen_lib/sail_operators_mwords.lem
+++ b/src/gen_lib/sail_operators_mwords.lem
@@ -3,6 +3,16 @@ open import Machine_word
open import Sail_impl_base
open import Sail_values
+(* Translating between a type level number (itself 'n) and an integer *)
+
+let size_itself_int x = integerFromNat (size_itself x)
+
+(* NB: the corresponding sail type is forall 'n. atom('n) -> itself('n),
+ the actual integer is ignored. *)
+
+val make_the_value : forall 'n. integer -> itself 'n
+let inline make_the_value x = the_value
+
(*** Bit vector operations *)
let bitvector_length bs = integerFromNat (word_length bs)
diff --git a/src/initial_check.ml b/src/initial_check.ml
index 61e352f5..b33d90f5 100644
--- a/src/initial_check.ml
+++ b/src/initial_check.ml
@@ -913,6 +913,7 @@ let initial_kind_env =
("atom", {k = K_Lam( [ {k=K_Nat} ], {k=K_Typ})});
("option", { k = K_Lam( [{k=K_Typ}], {k=K_Typ}) });
("implicit", {k = K_Lam( [{k = K_Nat}], {k=K_Typ})} );
+ ("itself", {k = K_Lam( [ {k=K_Nat} ], {k=K_Typ})});
]
let typschm_of_string order str =
diff --git a/src/monomorphise.ml b/src/monomorphise.ml
index f00cfd44..f79c1dc3 100644
--- a/src/monomorphise.ml
+++ b/src/monomorphise.ml
@@ -264,24 +264,24 @@ and contains_exist_arg (Typ_arg_aux (arg,_)) =
-> false
| Typ_arg_typ typ -> contains_exist typ
+let rec size_nvars_nexp (Nexp_aux (ne,_)) =
+ match ne with
+ | Nexp_var v -> [v]
+ | Nexp_id _
+ | Nexp_constant _
+ -> []
+ | Nexp_times (n1,n2)
+ | Nexp_sum (n1,n2)
+ | Nexp_minus (n1,n2)
+ -> size_nvars_nexp n1 @ size_nvars_nexp n2
+ | Nexp_exp n
+ | Nexp_neg n
+ -> size_nvars_nexp n
+
(* Given a type for a constructor, work out which refinements we ought to produce *)
(* TODO collision avoidance *)
let split_src_type id ty (TypQ_aux (q,ql)) =
let i = string_of_id id in
- let rec size_nvars_nexp (Nexp_aux (ne,_)) =
- match ne with
- | Nexp_var v -> [v]
- | Nexp_id _
- | Nexp_constant _
- -> []
- | Nexp_times (n1,n2)
- | Nexp_sum (n1,n2)
- | Nexp_minus (n1,n2)
- -> size_nvars_nexp n1 @ size_nvars_nexp n2
- | Nexp_exp n
- | Nexp_neg n
- -> size_nvars_nexp n
- in
(* This was originally written for the general case, but I cut it down to the
more manageable prenex-form below *)
let rec size_nvars_ty (Typ_aux (ty,l) as typ) =
@@ -575,6 +575,32 @@ let lit_match = function
| (L_one | L_true ), (L_one | L_true ) -> true
| l1,l2 -> l1 = l2
+(* There's no undefined nexp, so replace undefined sizes with a plausible size.
+ 32 is used as a sensible default. *)
+let fabricate_nexp l = function
+ | None -> Nexp_aux (Nexp_constant 32,Unknown)
+ | Some (env,typ,_) ->
+ match Type_check.destruct_exist env typ with
+ | None -> Nexp_aux (Nexp_constant 32,Unknown)
+ | Some (kids,nc,typ') ->
+ match kids,nc,Env.expand_synonyms env typ' with
+ | ([kid],NC_aux (NC_set (kid',i::_),_),
+ Typ_aux (Typ_app (Id_aux (Id "range",_),
+ [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_var kid'',_)),_);
+ Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_var kid''',_)),_)]),_))
+ when Kid.compare kid kid' = 0 && Kid.compare kid kid'' = 0 &&
+ Kid.compare kid kid''' = 0 ->
+ Nexp_aux (Nexp_constant i,Unknown)
+ | ([kid],NC_aux (NC_true,_),
+ Typ_aux (Typ_app (Id_aux (Id "range",_),
+ [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_var kid'',_)),_);
+ Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_var kid''',_)),_)]),_))
+ when Kid.compare kid kid'' = 0 &&
+ Kid.compare kid kid''' = 0 ->
+ Nexp_aux (Nexp_constant 32,Unknown)
+ | _ -> raise (Reporting_basic.err_general l
+ ("Undefined value at unsupported type " ^ string_of_typ typ))
+
type 'a matchresult =
| DoesMatch of 'a
| DoesNotMatch
@@ -614,12 +640,20 @@ let can_match_with_env env (E_aux (e,(l,annot)) as exp0) cases =
let checkpat = function
| P_aux (P_lit (L_aux (lit_p, _)),_) ->
if lit_match (lit_e,lit_p) then DoesMatch ([],[]) else DoesNotMatch
- | P_aux (P_var (P_aux (P_id id,_), kid),_) ->
+ | P_aux (P_var (P_aux (P_id id,p_id_annot), kid),_) ->
begin
match lit_e with
| L_num i ->
DoesMatch ([id, E_aux (e,(l,annot))],
[kid,Nexp_aux (Nexp_constant i,Unknown)])
+ (* For undefined we fix the type-level size (because there's no good
+ way to construct an undefined size), but leave the term as undefined
+ to make the meaning clear. *)
+ | L_undef ->
+ let nexp = fabricate_nexp l annot in
+ let typ = subst_src_typ (KBindings.singleton kid nexp) (typ_of_annot p_id_annot) in
+ DoesMatch ([id, E_aux (E_cast (typ,E_aux (e,(l,None))),(l,None))],
+ [kid,nexp])
| _ ->
(Reporting_basic.print_err false true lit_l "Monomorphisation"
"Unexpected kind of literal for var match"; GiveUp)
@@ -692,7 +726,7 @@ let try_app (l,ann) (Id_aux (id,_),args) =
| _ -> None
else if id = Id "ex_int" then
match args with
- | [E_aux (E_lit (L_aux (L_num _,_)),_) as exp] -> Some exp
+ | [E_aux (E_lit lit,(l,_))] -> Some (E_aux (E_lit lit,(l,ann)))
| _ -> None
else if id = Id "vector_access" || id = Id "bitvector_access" then
match args with
@@ -1444,8 +1478,262 @@ let split_defs splits defs =
| DEF_fundef fd -> [DEF_fundef (map_fundef fd)]
| DEF_val lb -> [DEF_val (map_letbind lb)]
| DEF_scattered sd -> List.map (fun x -> DEF_scattered x) (map_scattered_def sd)
-
in
Defs (List.concat (List.map map_def defs))
in
map_locs splits defs'
+
+
+
+(* The next section of code turns atom('n) types into itself('n) types, which
+ survive into the Lem output, so can be used to parametrise functions over
+ internal bitvector lengths (such as datasize and regsize in ARM specs *)
+
+module AtomToItself =
+struct
+
+let findi f =
+ let rec aux n = function
+ | [] -> None
+ | h::t -> match f h with Some x -> Some (n,x) | _ -> aux (n+1) t
+ in aux 0
+
+let mapat f is xs =
+ let rec aux n = function
+ | _, [] -> []
+ | (i,_)::is, h::t when i = n ->
+ let h' = f h in
+ let t' = aux (n+1) (is, t) in
+ h'::t'
+ | is, h::t ->
+ let t' = aux (n+1) (is, t) in
+ h::t'
+ in aux 0 (is, xs)
+
+let mapat_extra f is xs =
+ let rec aux n = function
+ | _, [] -> [], []
+ | (i,v)::is, h::t when i = n ->
+ let h',x = f v h in
+ let t',xs = aux (n+1) (is, t) in
+ h'::t',x::xs
+ | is, h::t ->
+ let t',xs = aux (n+1) (is, t) in
+ h::t',xs
+ in aux 0 (is, xs)
+
+let tyvars_bound_in_pat pat =
+ let open Rewriter in
+ fst (fold_pat
+ { (compute_pat_alg KidSet.empty KidSet.union) with
+ p_var = (fun ((s,pat),kid) -> KidSet.add kid s, P_var (pat,kid)) }
+ pat)
+let tyvars_bound_in_lb (LB_aux (LB_val (pat,_),_)) = tyvars_bound_in_pat pat
+
+let rec sizes_of_typ (Typ_aux (t,l)) =
+ match t with
+ Typ_wild
+ | Typ_id _
+ | Typ_var _
+ -> KidSet.empty
+ | Typ_fn _ -> raise (Reporting_basic.err_general l
+ "Function type on expressinon")
+ | Typ_tup typs -> kidset_bigunion (List.map sizes_of_typ typs)
+ | Typ_exist (kids,_,typ) ->
+ List.fold_left (fun s k -> KidSet.remove k s) (sizes_of_typ typ) kids
+ | Typ_app (Id_aux (Id "vector",_),
+ [_;Typ_arg_aux (Typ_arg_nexp size,_);
+ _;Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id (Id_aux (Id "bit",_)),_)),_)]) ->
+ KidSet.of_list (size_nvars_nexp size)
+ | Typ_app (_,tas) ->
+ kidset_bigunion (List.map sizes_of_typarg tas)
+and sizes_of_typarg (Typ_arg_aux (ta,_)) =
+ match ta with
+ Typ_arg_nexp _
+ | Typ_arg_order _
+ -> KidSet.empty
+ | Typ_arg_typ typ -> sizes_of_typ typ
+
+let sizes_of_annot = function
+ | _,None -> KidSet.empty
+ | _,Some (_,typ,_) -> sizes_of_typ typ
+
+let change_parameter_pat kid = function
+ | P_aux (P_id var, (l,_))
+ | P_aux (P_typ (_,P_aux (P_id var, (l,_))),_)
+ -> P_aux (P_id var, (l,None)), (var,kid)
+ | P_aux (_,(l,_)) -> raise (Reporting_basic.err_unreachable l
+ "Expected variable pattern")
+
+(* We add code to change the itself('n) parameter into the corresponding
+ integer. *)
+let add_var_rebind exp (var,kid) =
+ let l = Generated Unknown in
+ let annot = (l,None) in
+ E_aux (E_let (LB_aux (LB_val (P_aux (P_id var,annot),
+ E_aux (E_app (mk_id "size_itself_int",[E_aux (E_id var,annot)]),annot)),annot),exp),annot)
+
+(* atom('n) arguments to function calls need to be rewritten *)
+let replace_with_the_value (E_aux (_,(l,_)) as exp) =
+ let env = env_of exp in
+ let typ, wrap = match typ_of exp with
+ | Typ_aux (Typ_exist (kids,nc,typ),l) -> typ, fun t -> Typ_aux (Typ_exist (kids,nc,t),l)
+ | typ -> typ, fun x -> x
+ in
+ let typ = Env.expand_synonyms env typ in
+ let mk_exp nexp l l' =
+ E_aux (E_cast (wrap (Typ_aux (Typ_app (Id_aux (Id "itself",Generated Unknown),
+ [Typ_arg_aux (Typ_arg_nexp nexp,l')]),Generated Unknown)),
+ E_aux (E_app (Id_aux (Id "make_the_value",Generated Unknown),[exp]),(Generated l,None))),
+ (Generated l,None))
+ in
+ match typ with
+ | Typ_aux (Typ_app (Id_aux (Id "range",_),
+ [Typ_arg_aux (Typ_arg_nexp nexp,l');Typ_arg_aux (Typ_arg_nexp nexp',_)]),_)
+ when nexp = nexp' ->
+ mk_exp nexp l l'
+ | _ -> raise (Reporting_basic.err_unreachable l
+ "atom stopped being an atom?")
+
+let replace_type env typ =
+ let Typ_aux (t,l) = Env.expand_synonyms env typ in
+ match t with
+ | Typ_app (Id_aux (Id "range",_),
+ [Typ_arg_aux (Typ_arg_nexp nexp,l');Typ_arg_aux (Typ_arg_nexp _,_)]) ->
+ Typ_aux (Typ_app (Id_aux (Id "itself",Generated Unknown),
+ [Typ_arg_aux (Typ_arg_nexp nexp,l')]),Generated l)
+ | _ -> raise (Reporting_basic.err_unreachable l
+ "atom stopped being an atom?")
+
+
+let rewrite_size_parameters env (Defs defs) =
+ let open Rewriter in
+ let size_vars exp =
+ fst (fold_exp
+ { (compute_exp_alg KidSet.empty KidSet.union) with
+ e_aux = (fun ((s,e),annot) -> KidSet.union s (sizes_of_annot annot), E_aux (e,annot));
+ e_let = (fun ((sl,lb),(s2,e2)) -> KidSet.union sl (KidSet.diff s2 (tyvars_bound_in_lb lb)), E_let (lb,e2));
+ pat_exp = (fun ((sp,pat),(s,e)) -> KidSet.diff s (tyvars_bound_in_pat pat), Pat_exp (pat,e))}
+ exp)
+ in
+ let sizes_funcl fsizes (FCL_aux (FCL_Funcl (id,pat,exp),(l,_))) =
+ let sizes = size_vars exp in
+ (* TODO: what, if anything, should sequential be? *)
+ let visible_tyvars =
+ KidSet.union (Pretty_print_lem.lem_tyvars_of_typ false true (pat_typ_of pat))
+ (Pretty_print_lem.lem_tyvars_of_typ false true (typ_of exp))
+ in
+ let expose_tyvars = KidSet.diff sizes visible_tyvars in
+ let parameters = match pat with
+ | P_aux (P_tup ps,_) -> ps
+ | _ -> [pat]
+ in
+ let to_change = List.map
+ (fun kid ->
+ let check (P_aux (_,(_,Some (env,typ,_)))) =
+ match Env.expand_synonyms env typ with
+ Typ_aux (Typ_app(Id_aux (Id "range",_),
+ [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_var kid',_)),_);
+ Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_var kid'',_)),_)]),_) ->
+ if Kid.compare kid kid' = 0 && Kid.compare kid kid'' = 0 then Some kid else None
+ | _ -> None
+ in match findi check parameters with
+ | None -> raise (Reporting_basic.err_general l
+ ("Unable to find an argument for " ^ string_of_kid kid))
+ | Some i -> i)
+ (KidSet.elements expose_tyvars)
+ in
+ let to_change = List.sort compare to_change in
+ match Bindings.find id fsizes with
+ | old -> if old = to_change then fsizes else
+ raise (Reporting_basic.err_general l
+ ("Different size type variables in different clauses of " ^ string_of_id id))
+ | exception Not_found -> Bindings.add id to_change fsizes
+ in
+ let sizes_def fsizes = function
+ | DEF_fundef (FD_aux (FD_function (_,_,_,funcls),_)) ->
+ List.fold_left sizes_funcl fsizes funcls
+ | _ -> fsizes
+ in
+ let fn_sizes = List.fold_left sizes_def Bindings.empty defs in
+
+ let rewrite_e_app (id,args) =
+ match Bindings.find id fn_sizes with
+ | [] -> E_app (id,args)
+ | to_change ->
+ let args' = mapat replace_with_the_value to_change args in
+ E_app (id,args')
+ | exception Not_found -> E_app (id,args)
+ in
+ let rewrite_funcl (FCL_aux (FCL_Funcl (id,pat,body),(l,annot))) =
+ let pat,body =
+ (* Update pattern and add itself -> nat wrapper to body *)
+ match Bindings.find id fn_sizes with
+ | [] -> pat,body
+ | to_change ->
+ let pat, vars =
+ match pat with
+ P_aux (P_tup pats,(l,_)) ->
+ let pats, vars = mapat_extra change_parameter_pat to_change pats in
+ P_aux (P_tup pats,(l,None)), vars
+ | P_aux (_,(l,_)) ->
+ begin
+ match to_change with
+ | [0,kid] ->
+ let pat, var = change_parameter_pat kid pat in
+ pat, [var]
+ | _ ->
+ raise (Reporting_basic.err_unreachable l
+ "Expected multiple parameters at single parameter")
+ end
+ in
+ let body = List.fold_left add_var_rebind body vars in
+ pat,body
+ | exception Not_found -> pat,body
+ in
+ (* Update function applications *)
+ let body = fold_exp { id_exp_alg with e_app = rewrite_e_app } body in
+ FCL_aux (FCL_Funcl (id,pat,body),(l,None))
+ in
+ let rewrite_def = function
+ | DEF_fundef (FD_aux (FD_function (recopt,tannopt,effopt,funcls),(l,_))) ->
+ (* TODO rewrite tannopt? *)
+ DEF_fundef (FD_aux (FD_function (recopt,tannopt,effopt,List.map rewrite_funcl funcls),(l,None)))
+ | DEF_spec (VS_aux (VS_val_spec (typschm,id,extern,cast),(l,annot))) as spec ->
+ begin
+ match Bindings.find id fn_sizes with
+ | [] -> spec
+ | to_change ->
+ let typschm = match typschm with
+ | TypSchm_aux (TypSchm_ts (tq,typ),l) ->
+ let typ = match typ with
+ | Typ_aux (Typ_fn (Typ_aux (Typ_tup ts,l),t2,eff),l2) ->
+ Typ_aux (Typ_fn (Typ_aux (Typ_tup (mapat (replace_type env) to_change ts),l),t2,eff),l2)
+ | _ -> replace_type env typ
+ in TypSchm_aux (TypSchm_ts (tq,typ),l)
+ in
+ DEF_spec (VS_aux (VS_val_spec (typschm,id,extern,cast),(l,None)))
+ | exception Not_found -> spec
+ end
+ | def -> def
+ in
+(*
+ Bindings.iter (fun id args ->
+ print_endline (string_of_id id ^ " needs " ^
+ String.concat ", " (List.map string_of_int args))) fn_sizes
+*)
+ Defs (List.map rewrite_def defs)
+
+end
+
+let monomorphise mwords splits defs =
+ let defs = split_defs splits defs in
+ (* TODO: currently doing this because constant propagation leaves numeric literals as
+ int, try to avoid this later; also use final env for DEF_spec case above, because the
+ type checker doesn't store the env at that point :( *)
+ if mwords then
+ let (defs,env) = Type_check.check (Type_check.Env.no_casts Type_check.initial_env) defs in
+ let defs = AtomToItself.rewrite_size_parameters env defs in
+ defs
+ else
+ defs
diff --git a/src/ocaml_backend.ml b/src/ocaml_backend.ml
index 384d8109..5a378fa6 100644
--- a/src/ocaml_backend.ml
+++ b/src/ocaml_backend.ml
@@ -3,6 +3,9 @@ open Ast_util
open PPrint
open Type_check
+(* Option to turn tracing features on or off *)
+let opt_trace_ocaml = ref false
+
type ctx =
{ register_inits : tannot exp list;
externs : id Bindings.t;
@@ -61,7 +64,10 @@ let rec ocaml_string_typ (Typ_aux (typ_aux, _)) arg =
match typ_aux with
| Typ_id id -> ocaml_string_of id ^^ space ^^ arg
| Typ_app (id, []) -> ocaml_string_of id ^^ space ^^ arg
- | Typ_app (id, typs) -> string ("\"APP" ^ string_of_id id ^ "\"")
+ | Typ_app (id, [Typ_arg_aux (Typ_arg_typ typ, _)]) ->
+ let farg = gensym () in
+ separate space [string "string_of_list \", \""; parens (separate space [string "fun"; farg; string "->"; ocaml_string_typ typ farg]); arg]
+ | Typ_app (_, _) -> assert false
| Typ_tup typs ->
let args = List.map (fun _ -> gensym ()) typs in
let body =
@@ -72,6 +78,7 @@ let rec ocaml_string_typ (Typ_aux (typ_aux, _)) arg =
| Typ_fn (typ1, typ2, _) -> string "\"FN\""
| Typ_var kid -> string "\"VAR\""
| Typ_exist _ | Typ_wild -> assert false
+
let ocaml_typ_id ctx = function
| id when Id.compare id (mk_id "string") = 0 -> string "string"
| id when Id.compare id (mk_id "list") = 0 -> string "list"
@@ -119,7 +126,7 @@ let ocaml_lit (L_aux (lit_aux, _)) =
| L_num n -> parens (string "big_int_of_int" ^^ space ^^ string (string_of_int n))
| L_undef -> failwith "undefined should have been re-written prior to ocaml backend"
| L_string str -> string_lit str
- | L_real str -> parens (string "Num.num_of_string" ^^ space ^^ dquotes (string (String.escaped str)))
+ | L_real str -> parens (string "real_of_string" ^^ space ^^ dquotes (string (String.escaped str)))
| _ -> string "LIT"
let rec ocaml_pat ctx (P_aux (pat_aux, _) as pat) =
@@ -199,11 +206,20 @@ let rec ocaml_exp ctx (E_aux (exp_aux, _) as exp) =
^/^ string "in"
^/^ string "loop ()"
| E_lit _ | E_list _ | E_id _ | E_tuple _ -> ocaml_atomic_exp ctx exp
- | E_for (id, exp_from, exp_to, exp_step, _, exp_body) ->
+ | E_for (id, exp_from, exp_to, exp_step, ord, exp_body) ->
let loop_var = separate space [string "let"; zencode ctx id; equals; string "ref"; ocaml_atomic_exp ctx exp_from; string "in"] in
- let loop_mod = string "add_big_int" ^^ space ^^ zencode ctx id ^^ space ^^ ocaml_atomic_exp ctx exp_step in
+ let loop_mod =
+ match ord with
+ | Ord_aux (Ord_inc, _) -> string "add_big_int" ^^ space ^^ zencode ctx id ^^ space ^^ ocaml_atomic_exp ctx exp_step
+ | Ord_aux (Ord_dec, _) -> string "sub_big_int" ^^ space ^^ zencode ctx id ^^ space ^^ ocaml_atomic_exp ctx exp_step
+ in
+ let loop_compare =
+ match ord with
+ | Ord_aux (Ord_inc, _) -> string "le_big_int"
+ | Ord_aux (Ord_dec, _) -> string "gt_big_int"
+ in
let loop_body =
- separate space [string "if"; zencode ctx id; string "<="; ocaml_atomic_exp ctx exp_to]
+ separate space [string "if"; loop_compare; zencode ctx id; ocaml_atomic_exp ctx exp_to]
^/^ separate space [string "then";
parens (ocaml_atomic_exp ctx exp_body ^^ semi ^^ space ^^ string "loop" ^^ space ^^ parens loop_mod)]
^/^ string "else ()"
@@ -240,7 +256,13 @@ and ocaml_atomic_exp ctx (E_aux (exp_aux, _) as exp) =
match Env.lookup_id id (env_of exp) with
| Local (Immutable, _) | Unbound -> zencode ctx id
| Enum _ | Union _ -> zencode_upper ctx id
- | Register _ -> parens (string ("trace \"Read: " ^ string_of_id id ^ "\";") ^^ space ^^ bang ^^ zencode ctx id)
+ | Register typ ->
+ if !opt_trace_ocaml then
+ let var = gensym () in
+ let str_typ = parens (ocaml_string_typ (Rewriter.simple_typ typ) var) in
+ parens (separate space [string "let"; var; equals; bang ^^ zencode ctx id; string "in";
+ string "trace_read" ^^ space ^^ string_lit (string_of_id id) ^^ space ^^ str_typ ^^ semi; var])
+ else bang ^^ zencode ctx id
| Local (Mutable, _) -> bang ^^ zencode ctx id
end
| E_list exps -> enclose lbracket rbracket (separate_map (semi ^^ space) (ocaml_exp ctx) exps)
@@ -254,8 +276,12 @@ and ocaml_assignment ctx (LEXP_aux (lexp_aux, _) as lexp) exp =
| Register typ ->
let var = gensym () in
let traced_exp =
- parens (separate space [string "let"; var; equals; ocaml_atomic_exp ctx exp; string "in";
- string "trace_write" ^^ space ^^ string_lit (string_of_id id) ^^ space ^^ parens (ocaml_string_typ (Rewriter.simple_typ typ) var) ^^ semi; var])
+ if !opt_trace_ocaml then
+ let var = gensym () in
+ let str_typ = parens (ocaml_string_typ (Rewriter.simple_typ typ) var) in
+ parens (separate space [string "let"; var; equals; ocaml_atomic_exp ctx exp; string "in";
+ string "trace_write" ^^ space ^^ string_lit (string_of_id id) ^^ space ^^ str_typ ^^ semi; var])
+ else ocaml_atomic_exp ctx exp
in
separate space [zencode ctx id; string ":="; traced_exp]
| _ -> separate space [zencode ctx id; string ":="; ocaml_exp ctx exp]
@@ -331,22 +357,36 @@ let ocaml_funcls ctx =
in
(arg_sym, string_of_arg, ret_sym, string_of_ret)
in
+ let sail_call id arg_sym pat_sym ret_sym =
+ if !opt_trace_ocaml
+ then separate space [string "sail_trace_call"; string_lit (string_of_id id); parens (arg_sym ^^ space ^^ pat_sym); ret_sym]
+ else separate space [string "sail_call"]
+ in
+ let ocaml_funcl call string_of_arg string_of_ret =
+ if !opt_trace_ocaml
+ then (call ^^ twice hardline ^^ string_of_arg ^^ twice hardline ^^ string_of_ret)
+ else call
+ in
function
| [] -> failwith "Ocaml: empty function"
| [FCL_aux (FCL_Funcl (id, pat, exp),_)] ->
let Typ_aux (Typ_fn (typ1, typ2, _), _) = Bindings.find id ctx.val_specs in
let pat_sym = gensym () in
- let annot_pat = parens (separate space [parens (ocaml_pat ctx pat ^^ space ^^ colon ^^ space ^^ ocaml_typ ctx typ1); string "as"; pat_sym]) in
+ let annot_pat =
+ let pat = parens (ocaml_pat ctx pat ^^ space ^^ colon ^^ space ^^ ocaml_typ ctx typ1) in
+ if !opt_trace_ocaml
+ then parens (separate space [pat; string "as"; pat_sym])
+ else pat
+ in
let call_header = function_header () in
let arg_sym, string_of_arg, ret_sym, string_of_ret = trace_info typ1 typ2 in
let call =
separate space [call_header; zencode ctx id; annot_pat; colon; ocaml_typ ctx typ2; equals;
- string "sail_trace_call"; string_lit (string_of_id id); parens (arg_sym ^^ space ^^ pat_sym); ret_sym;
- string "(fun r ->"]
+ sail_call id arg_sym pat_sym ret_sym; string "(fun r ->"]
^//^ ocaml_exp ctx exp
^^ rparen
in
- call ^^ twice hardline ^^ string_of_arg ^^ twice hardline ^^ string_of_ret
+ ocaml_funcl call string_of_arg string_of_ret
| funcls ->
let id = funcls_id funcls in
let Typ_aux (Typ_fn (typ1, typ2, _), _) = Bindings.find id ctx.val_specs in
@@ -355,12 +395,11 @@ let ocaml_funcls ctx =
let arg_sym, string_of_arg, ret_sym, string_of_ret = trace_info typ1 typ2 in
let call =
separate space [call_header; zencode ctx id; parens (pat_sym ^^ space ^^ colon ^^ space ^^ ocaml_typ ctx typ1); equals;
- string "sail_trace_call"; string_lit (string_of_id id); parens (arg_sym ^^ space ^^ pat_sym); ret_sym;
- string "(fun r ->"]
+ sail_call id arg_sym pat_sym ret_sym; string "(fun r ->"]
^//^ (separate space [string "match"; pat_sym; string "with"] ^^ hardline ^^ ocaml_funcl_matches ctx funcls)
^^ rparen
in
- call ^^ twice hardline ^^ string_of_arg ^^ twice hardline ^^ string_of_ret
+ ocaml_funcl call string_of_arg string_of_ret
let ocaml_fundef ctx (FD_aux (FD_function (_, _, _, funcls), _)) =
ocaml_funcls ctx funcls
@@ -391,7 +430,6 @@ let rec ocaml_enum ctx = function
(* We generate a string_of_X ocaml function for each type X, to be used for debugging purposes *)
-
let ocaml_def_end = string ";;" ^^ twice hardline
let ocaml_string_of_enum ctx id ids =
@@ -491,6 +529,7 @@ let ocaml_main spec =
separate space [string "let"; string "()"; equals]
^//^ (string "Random.self_init ();"
^/^ string "load_elf ();"
+ ^/^ string (if !opt_trace_ocaml then "Sail_lib.opt_trace := true;" else "Sail_lib.opt_trace := false;")
^/^ string "initialize_registers ();"
^/^ string "Printexc.record_backtrace true;"
^/^ string "zmain ()")
diff --git a/src/pretty_print_lem.ml b/src/pretty_print_lem.ml
index d6ec25dc..7a29579b 100644
--- a/src/pretty_print_lem.ml
+++ b/src/pretty_print_lem.ml
@@ -152,7 +152,9 @@ let is_regtyp (Typ_aux (typ, _)) env = match typ with
| Typ_id(id) when Env.is_regtyp id env -> true
| _ -> false
-let doc_nexp_lem (Nexp_aux (nexp, l) as full_nexp) = match nexp with
+let doc_nexp_lem nexp =
+ let (Nexp_aux (nexp, l) as full_nexp) = nexp_simp nexp in
+ match nexp with
| Nexp_constant i -> string ("ty" ^ string_of_int i)
| Nexp_var v -> string (string_of_kid (orig_kid v))
| _ ->
@@ -427,9 +429,12 @@ let rec typeclass_nexps (Typ_aux(t,_)) = match t with
| Typ_tup ts -> List.fold_left NexpSet.union NexpSet.empty (List.map typeclass_nexps ts)
| Typ_app (Id_aux (Id "vector",_),
[_;Typ_arg_aux (Typ_arg_nexp size_nexp,_);
- _;Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id (Id_aux (Id "bit",_)),_)),_)]) ->
- if is_nexp_constant (nexp_simp size_nexp) then NexpSet.empty else
- NexpSet.singleton (nexp_simp (orig_nexp size_nexp))
+ _;Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id (Id_aux (Id "bit",_)),_)),_)])
+| Typ_app (Id_aux (Id "itself",_),
+ [Typ_arg_aux (Typ_arg_nexp size_nexp,_)]) ->
+ let size_nexp = nexp_simp size_nexp in
+ if is_nexp_constant size_nexp then NexpSet.empty else
+ NexpSet.singleton (orig_nexp size_nexp)
| Typ_app _ -> NexpSet.empty
| Typ_exist (kids,_,t) -> NexpSet.empty (* todo *)
@@ -493,13 +498,14 @@ let rec doc_pat_lem sequential mwords apat_needed (P_aux (p,(l,annot)) as pa) =
| P_cons (p,p') -> doc_op (string "::") (doc_pat_lem sequential mwords true p) (doc_pat_lem sequential mwords true p')
| P_record (_,_) -> empty (* TODO *)
-let rec contains_bitvector_typ (Typ_aux (t,_) as typ) = match t with
- | Typ_tup ts -> List.exists contains_bitvector_typ ts
- | Typ_app (_, targs) -> is_bitvector_typ typ || List.exists contains_bitvector_typ_arg targs
- | Typ_fn (t1,t2,_) -> contains_bitvector_typ t1 || contains_bitvector_typ t2
+let rec typ_needs_printed (Typ_aux (t,_) as typ) = match t with
+ | Typ_tup ts -> List.exists typ_needs_printed ts
+ | Typ_app (Id_aux (Id "itself",_),_) -> true
+ | Typ_app (_, targs) -> is_bitvector_typ typ || List.exists typ_needs_printed_arg targs
+ | Typ_fn (t1,t2,_) -> typ_needs_printed t1 || typ_needs_printed t2
| _ -> false
-and contains_bitvector_typ_arg (Typ_arg_aux (targ, _)) = match targ with
- | Typ_arg_typ t -> contains_bitvector_typ t
+and typ_needs_printed_arg (Typ_arg_aux (targ, _)) = match targ with
+ | Typ_arg_typ t -> typ_needs_printed t
| _ -> false
let contains_early_return exp =
@@ -698,7 +704,7 @@ let doc_exp_lem, doc_let_lem =
let (taepp,aexp_needed) =
let t = Env.base_typ_of (env_of full_exp) (typ_of full_exp) in
let eff = effect_of full_exp in
- if contains_bitvector_typ t && not (contains_t_pp_var t)
+ if typ_needs_printed t && not (contains_t_pp_var t)
then (align epp ^^ (doc_tannot_lem sequential mwords (effectful eff) t), true)
else (epp, aexp_needed) in
if aexp_needed then parens (align taepp) else taepp*)
@@ -740,7 +746,7 @@ let doc_exp_lem, doc_let_lem =
let (taepp,aexp_needed) =
let t = (*Env.base_typ_of (env_of full_exp)*) (typ_of full_exp) in
let eff = effect_of full_exp in
- if contains_bitvector_typ (Env.base_typ_of (env_of full_exp) t)
+ if typ_needs_printed (Env.base_typ_of (env_of full_exp) t)
then (align epp ^^ (doc_tannot_lem sequential mwords (effectful eff) t), true)
else (epp, aexp_needed) in
liftR (if aexp_needed then parens (align taepp) else taepp)
@@ -798,7 +804,7 @@ let doc_exp_lem, doc_let_lem =
let (epp,aexp_needed) =
if has_effect eff BE_rreg then
let epp = align (string "read_reg_range" ^^ space ^^ expY v ^//^ expY e1 ^//^ expY e2) in
- if contains_bitvector_typ t && not (contains_t_pp_var t)
+ if typ_needs_printed t && not (contains_t_pp_var t)
then (epp ^^ doc_tannot_lem sequential mwords true t, true)
else (epp, aexp_needed)
else
@@ -819,7 +825,7 @@ let doc_exp_lem, doc_let_lem =
let eff = effect_of full_exp in
let field_f = doc_id_lem tid ^^ underscore ^^ doc_id_lem id ^^ dot ^^ string "get_field" in
let (ta,aexp_needed) =
- if contains_bitvector_typ t
+ if typ_needs_printed t
then (doc_tannot_lem sequential mwords (effectful eff) t, true)
else (empty, aexp_needed) in
let epp = field_f ^^ space ^^ (expY fexp) in
@@ -854,7 +860,7 @@ let doc_exp_lem, doc_let_lem =
| Tid "bit" | Tabbrev (_,{t=Tid "bit"}) -> "read_reg_bitfield"
| _ -> "read_reg_field" in
let ta =
- if contains_bitvector_typ t && not (contains_t_pp_var t)
+ if typ_needs_printed t && not (contains_t_pp_var t)
then doc_tannot_lem sequential mwords true t else empty in
let epp = separate space [string call;string reg;string_lit(string field)] ^^ ta in
if aexp_needed then parens (align epp) else epp
@@ -862,7 +868,7 @@ let doc_exp_lem, doc_let_lem =
let (call,ta) =
if has_effect eff BE_rreg then
let ta =
- if contains_bitvector_typ t && not (contains_t_pp_var t)
+ if typ_needs_printed t && not (contains_t_pp_var t)
then doc_tannot_lem sequential mwords true t else empty in
("read_two_regs", ta)
else
@@ -875,7 +881,7 @@ let doc_exp_lem, doc_let_lem =
separate space [string "read_reg_bit";string reg;doc_int start]
else
let ta =
- if contains_bitvector_typ t && not (contains_t_pp_var t)
+ if typ_needs_printed t && not (contains_t_pp_var t)
then doc_tannot_lem sequential mwords true t else empty in
separate space [string "read_reg_range";string reg;doc_int start;doc_int stop] ^^ ta in
if aexp_needed then parens (align epp) else epp
@@ -887,7 +893,7 @@ let doc_exp_lem, doc_let_lem =
| Base((_,t),External _,_,_,_,_) ->
(* TODO: Does this case still exist with the new type checker? *)
let epp = string "read_reg" ^^ space ^^ expY e in
- if contains_bitvector_typ t && not (contains_t_pp_var t)
+ if typ_needs_printed t && not (contains_t_pp_var t)
then parens (epp ^^ doc_tannot_lem sequential mwords true t) else epp
| Base((_,t),_,_,_,_,_) ->
(match typ with
@@ -1117,7 +1123,7 @@ let doc_exp_lem, doc_let_lem =
| _ ->
string name ^//^ parens (expN e1 ^^ comma ^/^ expN e2)) in
let (epp,aexp_needed) =
- if contains_bitvector_typ t && not (contains_t_pp_var t)
+ if typ_needs_printed t && not (contains_t_pp_var t)
then (parens epp ^^ doc_tannot_lem sequential mwords false t, true)
else (epp, aexp_needed) in
if aexp_needed then parens (align epp) else epp
diff --git a/src/process_file.ml b/src/process_file.ml
index 59518075..aea53ca7 100644
--- a/src/process_file.ml
+++ b/src/process_file.ml
@@ -121,7 +121,7 @@ let check_ast (defs : unit Ast.defs) : Type_check.tannot Ast.defs * Type_check.E
let opt_ddump_raw_mono_ast = ref false
let monomorphise_ast locs ast =
- let ast = Monomorphise.split_defs locs ast in
+ let ast = Monomorphise.monomorphise (!opt_lem_mwords) locs ast in
let () = if !opt_ddump_raw_mono_ast then Pretty_print.pp_defs stdout ast else () in
let ienv = Type_check.Env.no_casts Type_check.initial_env in
Type_check.check ienv ast
diff --git a/src/rewriter.mli b/src/rewriter.mli
index 3125c410..3f375e25 100644
--- a/src/rewriter.mli
+++ b/src/rewriter.mli
@@ -151,12 +151,24 @@ type ('a,'exp,'exp_aux,'lexp,'lexp_aux,'fexp,'fexp_aux,'fexps,'fexps_aux,
; pat_alg : ('a,'pat,'pat_aux,'fpat,'fpat_aux) pat_alg
}
+(* fold over patterns *)
+val fold_pat : ('a,'pat,'pat_aux,'fpat,'fpat_aux) pat_alg -> 'a pat -> 'pat
+
(* fold over expressions *)
val fold_exp : ('a,'exp,'exp_aux,'lexp,'lexp_aux,'fexp,'fexp_aux,'fexps,'fexps_aux,
'opt_default_aux,'opt_default,'pexp,'pexp_aux,'letbind_aux,'letbind,
'pat,'pat_aux,'fpat,'fpat_aux) exp_alg -> 'a exp -> 'exp
val id_pat_alg : ('a,'a pat, 'a pat_aux, 'a fpat, 'a fpat_aux) pat_alg
+val id_exp_alg :
+ ('a,'a exp,'a exp_aux,'a lexp,'a lexp_aux,'a fexp,
+ 'a fexp_aux,'a fexps,'a fexps_aux,
+ 'a opt_default_aux,'a opt_default,'a pexp,'a pexp_aux,
+ 'a letbind_aux,'a letbind,
+ 'a pat,'a pat_aux,'a fpat,'a fpat_aux) exp_alg
+
+val compute_pat_alg : 'b -> ('b -> 'b -> 'b) ->
+ ('a,('b * 'a pat),('b * 'a pat_aux),('b * 'a fpat),('b * 'a fpat_aux)) pat_alg
val compute_exp_alg : 'b -> ('b -> 'b -> 'b) ->
('a,('b * 'a exp),('b * 'a exp_aux),('b * 'a lexp),('b * 'a lexp_aux),('b * 'a fexp),
diff --git a/src/sail.ml b/src/sail.ml
index 9c447f36..8a70cb70 100644
--- a/src/sail.ml
+++ b/src/sail.ml
@@ -56,39 +56,35 @@ let opt_libs_lem = ref ([]:string list)
let opt_libs_ocaml = ref ([]:string list)
let opt_file_arguments = ref ([]:string list)
let opt_mono_split = ref ([]:((string * int) * string) list)
+
let options = Arg.align ([
( "-o",
Arg.String (fun f -> opt_file_out := Some f),
"<prefix> select output filename prefix");
+ ( "-ocaml",
+ Arg.Tuple [Arg.Set opt_print_ocaml; Arg.Set Initial_check.opt_undefined_gen],
+ " output an OCaml translated version of the input");
+ ( "-ocaml_trace",
+ Arg.Tuple [Arg.Set opt_print_ocaml; Arg.Set Initial_check.opt_undefined_gen; Arg.Set Ocaml_backend.opt_trace_ocaml],
+ " output an OCaml translated version of the input with tracing instrumentation, implies -ocaml");
+ ( "-ocaml_lib",
+ Arg.String (fun l -> opt_libs_ocaml := l::!opt_libs_ocaml),
+ "<filename> provide additional library to open in OCaml output");
( "-lem_ast",
Arg.Set opt_print_lem_ast,
" output a Lem AST representation of the input");
( "-lem",
Arg.Set opt_print_lem,
" output a Lem translated version of the input");
- ( "-ocaml",
- Arg.Tuple [Arg.Set opt_print_ocaml; Arg.Set Initial_check.opt_undefined_gen],
- " output an OCaml translated version of the input");
( "-lem_lib",
Arg.String (fun l -> opt_libs_lem := l::!opt_libs_lem),
"<filename> provide additional library to open in Lem output");
- ( "-ocaml_lib",
- Arg.String (fun l -> opt_libs_ocaml := l::!opt_libs_ocaml),
- "<filename> provide additional library to open in OCaml output");
( "-lem_sequential",
Arg.Set Process_file.opt_lem_sequential,
" use sequential state monad for Lem output");
( "-lem_mwords",
Arg.Set Process_file.opt_lem_mwords,
" use native machine word library for Lem output");
-(*
- ( "-i",
- Arg.String (fun l -> lib := l::!lib),
- "<library_filename> treat this file as input only and generate no output for it");
-*)
- ( "-verbose",
- Arg.Set opt_print_verbose,
- " (debug) pretty-print the input to standard output");
( "-mono-split",
Arg.String (fun s ->
let l = Util.split_on_char ':' s in
@@ -96,39 +92,42 @@ let options = Arg.align ([
| [fname;line;var] -> opt_mono_split := ((fname,int_of_string line),var)::!opt_mono_split
| _ -> raise (Arg.Bad (s ^ " not of form <filename>:<line>:<variable>"))),
"<filename>:<line>:<variable> to case split for monomorphisation");
- ( "-ddump_raw_mono_ast",
- Arg.Set opt_ddump_raw_mono_ast,
- " (debug) dump the monomorphised ast before type-checking");
+ ( "-memo_z3",
+ Arg.Set opt_memo_z3,
+ " memoize calls to z3, improving performance when typechecking repeatedly");
+ ( "-undefined_gen",
+ Arg.Set Initial_check.opt_undefined_gen,
+ " generate undefined_type functions for types in the specification");
+ ( "-no_effects",
+ Arg.Set Type_check.opt_no_effects,
+ " (experimental) turn off effect checking");
( "-new_parser",
Arg.Set Process_file.opt_new_parser,
" (experimental) use new parser");
+ ( "-convert",
+ Arg.Set opt_convert,
+ " (experimental) convert sail to new syntax for use with -new_parser");
( "-just_check",
Arg.Set opt_just_check,
" (experimental) terminate immediately after typechecking");
- ( "-convert",
- Arg.Set opt_convert,
- " Convert sail to new syntax");
- ( "-memo_z3",
- Arg.Set opt_memo_z3,
- " Memoize calls to z3");
+ ( "-ddump_raw_mono_ast",
+ Arg.Set opt_ddump_raw_mono_ast,
+ " (debug) dump the monomorphised ast before type-checking");
+ ( "-verbose",
+ Arg.Set opt_print_verbose,
+ " (debug) pretty-print the input to standard output");
( "-ddump_tc_ast",
Arg.Set opt_ddump_tc_ast,
" (debug) dump the typechecked ast to stdout");
( "-ddump_rewrite_ast",
Arg.String (fun l -> opt_ddump_rewrite_ast := Some (l, 0)),
- " <prefix> (debug) dump the ast after each rewriting step to <prefix>_<i>.lem");
+ "<prefix> (debug) dump the ast after each rewriting step to <prefix>_<i>.lem");
( "-dtc_verbose",
Arg.Int (fun verbosity -> Type_check.opt_tc_debug := verbosity),
- " (debug) verbose typechecker output: 0 is silent");
+ "<verbosity> (debug) verbose typechecker output: 0 is silent");
( "-dno_cast",
Arg.Set opt_dno_cast,
" (debug) typecheck without any implicit casting");
- ( "-no_effects",
- Arg.Set Type_check.opt_no_effects,
- " turn off effect checking");
- ( "-undefined_gen",
- Arg.Set Initial_check.opt_undefined_gen,
- " generate undefined_type functions for types in the specification");
( "-v",
Arg.Set opt_print_version,
" print version");
diff --git a/src/trace_viewer/.gitignore b/src/trace_viewer/.gitignore
new file mode 100644
index 00000000..c1f9aea6
--- /dev/null
+++ b/src/trace_viewer/.gitignore
@@ -0,0 +1,6 @@
+*~
+*.js
+*.js.map
+
+# Dependencies
+node_modules/
diff --git a/src/trace_viewer/List-add.svg b/src/trace_viewer/List-add.svg
new file mode 100644
index 00000000..f8031599
--- /dev/null
+++ b/src/trace_viewer/List-add.svg
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg id="svg6431" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" sodipodi:docname="list-add.svg" xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" height="48px" sodipodi:version="0.32" width="48px" xmlns:cc="http://web.resource.org/cc/" xmlns:xlink="http://www.w3.org/1999/xlink" sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <defs id="defs6433">
+ <linearGradient id="linearGradient4975" y2="48.548" gradientUnits="userSpaceOnUse" x2="45.919" gradientTransform="translate(-18.018 -13.571)" y1="36.423" x1="34.893">
+ <stop id="stop1324" stop-color="#729fcf" offset="0"/>
+ <stop id="stop1326" stop-color="#5187d6" offset="1"/>
+ </linearGradient>
+ <linearGradient id="linearGradient7922" y2="34.977" gradientUnits="userSpaceOnUse" x2="27.901" y1="22.852" x1="16.875">
+ <stop id="stop7918" stop-color="#fff" offset="0"/>
+ <stop id="stop7920" stop-color="#fff" stop-opacity=".34021" offset="1"/>
+ </linearGradient>
+ <radialGradient id="radialGradient2097" gradientUnits="userSpaceOnUse" cy="35.127" cx="23.071" gradientTransform="matrix(.91481 .012650 -.0082150 .21356 2.2539 27.189)" r="10.319">
+ <stop id="stop2093" offset="0"/>
+ <stop id="stop2095" stop-opacity="0" offset="1"/>
+ </radialGradient>
+ </defs>
+ <sodipodi:namedview id="base" bordercolor="#666666" pagecolor="#ffffff" showgrid="false" borderopacity="0.15686275" showguides="true"/>
+ <metadata id="metadata6436">
+ <rdf:RDF>
+ <cc:Work rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <dc:title>Add</dc:title>
+ <dc:date>2006-01-04</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Andreas Nilsson</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>http://tango-project.org</dc:source>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>add</rdf:li>
+ <rdf:li>plus</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/"/>
+ </cc:Work>
+ <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+ <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+ <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+ <cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
+ <cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
+ <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+ <cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g id="layer1">
+ <path id="path1361" sodipodi:rx="10.319340" sodipodi:ry="2.3201940" sodipodi:type="arc" d="m33.278 34.941a10.319 2.3202 0 1 1 -20.638 0 10.319 2.3202 0 1 1 20.638 0z" opacity=".2" transform="matrix(1.5505 0 0 1.293 -11.597 -8.1782)" sodipodi:cy="34.940620" sodipodi:cx="22.958872" fill="url(#radialGradient2097)"/>
+ <path id="text1314" d="m27.514 37.543v-9.027l9.979-0.04v-6.996h-9.97l-0.009-9.96-7.016 0.011 0.005 9.931-9.99 0.074-0.036 6.969 10.034-0.029 0.007 9.04 6.996 0.027z" sodipodi:nodetypes="ccccccccccccc" stroke="#3465a4" stroke-width="1px" fill="#75a1d0"/>
+ <path id="path7076" opacity=".40860" d="m26.499 36.534v-9.034h10.002l-0.006-5.025h-9.987v-9.995l-4.995 0.018 0.009 9.977-10.026 0.018-0.027 4.973 10.064 0.009-0.013 9.028 4.979 0.031z" sodipodi:nodetypes="ccccccccccccc" stroke="url(#linearGradient7922)" stroke-width="1px" fill="url(#linearGradient4975)"/>
+ <path id="path7914" opacity=".31183" d="m11 25c0 1.938 25.984-0.969 25.984-0.031v-3l-9.984 0.031v-9.965h-6v9.965h-10v3z" fill-rule="evenodd" sodipodi:nodetypes="ccccccccc" fill="#fff"/>
+ </g>
+</svg>
diff --git a/src/trace_viewer/List-remove.svg b/src/trace_viewer/List-remove.svg
new file mode 100644
index 00000000..18c9a135
--- /dev/null
+++ b/src/trace_viewer/List-remove.svg
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="48px" height="48px" id="svg6431" sodipodi:version="0.32" inkscape:version="0.43+devel" sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions" sodipodi:docname="list-remove.svg">
+ <defs id="defs6433">
+ <linearGradient inkscape:collect="always" id="linearGradient2091">
+ <stop style="stop-color:#000000;stop-opacity:1;" offset="0" id="stop2093"/>
+ <stop style="stop-color:#000000;stop-opacity:0;" offset="1" id="stop2095"/>
+ </linearGradient>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient2091" id="radialGradient2097" cx="23.070683" cy="35.127438" fx="23.070683" fy="35.127438" r="10.319340" gradientTransform="matrix(0.914812,1.265023e-2,-8.21502e-3,0.213562,2.253914,27.18889)" gradientUnits="userSpaceOnUse"/>
+ <linearGradient id="linearGradient7916">
+ <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop7918"/>
+ <stop style="stop-color:#ffffff;stop-opacity:0.34020618;" offset="1.0000000" id="stop7920"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" id="linearGradient8662">
+ <stop style="stop-color:#000000;stop-opacity:1;" offset="0" id="stop8664"/>
+ <stop style="stop-color:#000000;stop-opacity:0;" offset="1" id="stop8666"/>
+ </linearGradient>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient8662" id="radialGradient1503" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.000000,0.000000,0.000000,0.536723,-1.018989e-13,16.87306)" cx="24.837126" cy="36.421127" fx="24.837126" fy="36.421127" r="15.644737"/>
+ <linearGradient inkscape:collect="always" id="linearGradient2847">
+ <stop style="stop-color:#3465a4;stop-opacity:1;" offset="0" id="stop2849"/>
+ <stop style="stop-color:#3465a4;stop-opacity:0;" offset="1" id="stop2851"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2847" id="linearGradient1488" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,-1.242480,40.08170)" x1="37.128052" y1="29.729605" x2="37.065414" y2="26.194071"/>
+ <linearGradient id="linearGradient2831">
+ <stop style="stop-color:#3465a4;stop-opacity:1;" offset="0" id="stop2833"/>
+ <stop id="stop2855" offset="0.33333334" style="stop-color:#5b86be;stop-opacity:1;"/>
+ <stop style="stop-color:#83a8d8;stop-opacity:0;" offset="1" id="stop2835"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2831" id="linearGradient1486" gradientUnits="userSpaceOnUse" gradientTransform="translate(-48.30498,-6.043298)" x1="13.478554" y1="10.612206" x2="15.419417" y2="19.115122"/>
+ <linearGradient id="linearGradient2380">
+ <stop style="stop-color:#b9cfe7;stop-opacity:1" offset="0" id="stop2382"/>
+ <stop style="stop-color:#729fcf;stop-opacity:1" offset="1" id="stop2384"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2682">
+ <stop style="stop-color:#3977c3;stop-opacity:1;" offset="0" id="stop2684"/>
+ <stop style="stop-color:#89aedc;stop-opacity:0;" offset="1" id="stop2686"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2682" id="linearGradient2688" x1="36.713837" y1="31.455952" x2="37.124462" y2="24.842253" gradientUnits="userSpaceOnUse" gradientTransform="translate(-48.77039,-5.765705)"/>
+ <linearGradient inkscape:collect="always" id="linearGradient2690">
+ <stop style="stop-color:#c4d7eb;stop-opacity:1;" offset="0" id="stop2692"/>
+ <stop style="stop-color:#c4d7eb;stop-opacity:0;" offset="1" id="stop2694"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2690" id="linearGradient2696" x1="32.647972" y1="30.748846" x2="37.124462" y2="24.842253" gradientUnits="userSpaceOnUse" gradientTransform="translate(-48.77039,-5.765705)"/>
+ <linearGradient inkscape:collect="always" id="linearGradient2871">
+ <stop style="stop-color:#3465a4;stop-opacity:1;" offset="0" id="stop2873"/>
+ <stop style="stop-color:#3465a4;stop-opacity:1" offset="1" id="stop2875"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2402">
+ <stop style="stop-color:#729fcf;stop-opacity:1;" offset="0" id="stop2404"/>
+ <stop style="stop-color:#528ac5;stop-opacity:1;" offset="1" id="stop2406"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2797" id="linearGradient1493" gradientUnits="userSpaceOnUse" x1="5.9649176" y1="26.048164" x2="52.854097" y2="26.048164"/>
+ <linearGradient inkscape:collect="always" id="linearGradient2797">
+ <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop2799"/>
+ <stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop2801"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2797" id="linearGradient1491" gradientUnits="userSpaceOnUse" x1="5.9649176" y1="26.048164" x2="52.854097" y2="26.048164"/>
+ <linearGradient inkscape:collect="always" id="linearGradient7179">
+ <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop7181"/>
+ <stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop7183"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2316">
+ <stop style="stop-color:#000000;stop-opacity:1;" offset="0" id="stop2318"/>
+ <stop style="stop-color:#ffffff;stop-opacity:0.65979379;" offset="1" id="stop2320"/>
+ </linearGradient>
+ <linearGradient id="linearGradient1322">
+ <stop id="stop1324" offset="0.0000000" style="stop-color:#729fcf"/>
+ <stop id="stop1326" offset="1.0000000" style="stop-color:#5187d6;stop-opacity:1.0000000;"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient1322" id="linearGradient4975" x1="34.892849" y1="36.422989" x2="45.918697" y2="48.547989" gradientUnits="userSpaceOnUse" gradientTransform="translate(-18.01785,-13.57119)"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient7179" id="linearGradient7185" x1="13.435029" y1="13.604306" x2="22.374878" y2="23.554308" gradientUnits="userSpaceOnUse"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient7179" id="linearGradient7189" gradientUnits="userSpaceOnUse" x1="13.435029" y1="13.604306" x2="22.374878" y2="23.554308" gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,47.93934,50.02474)"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2380" id="linearGradient7180" gradientUnits="userSpaceOnUse" x1="62.513836" y1="36.061237" x2="15.984863" y2="20.60858"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2871" id="linearGradient7182" gradientUnits="userSpaceOnUse" x1="46.834816" y1="45.264122" x2="45.380436" y2="50.939667"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2402" id="linearGradient7184" gradientUnits="userSpaceOnUse" x1="18.935766" y1="23.667896" x2="53.588622" y2="26.649362"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2871" id="linearGradient7186" gradientUnits="userSpaceOnUse" x1="46.834816" y1="45.264122" x2="45.380436" y2="50.939667"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient7916" id="linearGradient7922" x1="16.874998" y1="22.851799" x2="27.900846" y2="34.976799" gradientUnits="userSpaceOnUse"/>
+ </defs>
+ <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="0.10980392" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1" inkscape:cx="38.727739" inkscape:cy="26.974252" inkscape:current-layer="layer1" showgrid="false" inkscape:grid-bbox="true" inkscape:document-units="px" inkscape:window-width="1280" inkscape:window-height="949" inkscape:window-x="380" inkscape:window-y="79" inkscape:showpageshadow="false"/>
+ <metadata id="metadata6436">
+ <rdf:RDF>
+ <cc:Work rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <dc:title>Remove</dc:title>
+ <dc:date>2006-01-04</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Andreas Nilsson</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>http://tango-project.org</dc:source>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>remove</rdf:li>
+ <rdf:li>delete</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/"/>
+ </cc:Work>
+ <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+ <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+ <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+ <cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
+ <cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
+ <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+ <cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer">
+ <path style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" d="M 27.514356,28.359472 L 39.633445,28.475543 L 39.633445,21.480219 L 27.523285,21.480219 L 20.502546,21.462362 L 8.5441705,21.489147 L 8.5084565,28.457686 L 20.511475,28.475543 L 27.514356,28.359472 z " id="text1314" sodipodi:nodetypes="ccccccccc"/>
+ <path style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" d="M 38.579429,27.484113 L 38.588357,22.475309 L 9.5267863,22.493166 L 9.5000003,27.466256 L 38.579429,27.484113 z " id="path7076" sodipodi:nodetypes="ccccc"/>
+ <path style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;opacity:0.31182796" d="M 9.0000000,25.000000 C 9.0000000,26.937500 39.125000,24.062500 39.125000,25.000000 L 39.125000,22.000000 L 9.0000000,22.000000 L 9.0000000,25.000000 z " id="path7914" sodipodi:nodetypes="ccccc"/>
+ <path sodipodi:type="arc" style="opacity:0.10439561;fill:url(#radialGradient2097);fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" id="path1361" sodipodi:cx="22.958872" sodipodi:cy="34.94062" sodipodi:rx="10.31934" sodipodi:ry="2.320194" d="M 33.278212 34.94062 A 10.31934 2.320194 0 1 1 12.639532,34.94062 A 10.31934 2.320194 0 1 1 33.278212 34.94062 z" transform="matrix(2.32573,0,0,1.293,-29.39613,-8.178198)" inkscape:r_cx="true" inkscape:r_cy="true"/>
+ </g>
+</svg> \ No newline at end of file
diff --git a/src/trace_viewer/README b/src/trace_viewer/README
new file mode 100644
index 00000000..547a1435
--- /dev/null
+++ b/src/trace_viewer/README
@@ -0,0 +1,11 @@
+
+To use, first make sure node.js and npm are installed (e.g. via the
+Ubuntu package manager), then run the following in this directory:
+
+> npm install
+
+> npm run tsc
+
+> ./node_modules/.bin/electron .
+
+and point the file selector at a trace produced by sail -ocaml_trace \ No newline at end of file
diff --git a/src/trace_viewer/index.css b/src/trace_viewer/index.css
new file mode 100644
index 00000000..35ebcb23
--- /dev/null
+++ b/src/trace_viewer/index.css
@@ -0,0 +1,86 @@
+
+body {
+ background-color: #202020;
+ color: #DCDCCC;
+ font-family: monospace;
+ font-size: 14pt;
+ font-weight: bold;
+}
+
+img {
+ height: 30px;
+}
+
+#control {
+ position: fixed;
+ bottom: 0px;
+ left:10%;
+ right:10%;
+ width:80%;
+}
+
+#command {
+ font-size: 16pt;
+ width: 100%;
+}
+
+.call {
+ background-color: #313131;
+ border: 1px;
+ border-left: 5px;
+ border-color: rgb(118, 173, 160);
+ border-style: solid;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ margin: 0px;
+ min-height: 32px;
+ display: flex;
+ align-items: center;
+}
+
+.write {
+ background-color: #313131;
+ border: 1px;
+ border-left: 5px;
+ border-color: rgb(255, 40, 40);
+ border-style: solid;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ margin: 0px;
+ min-height: 32px;
+ display: flex;
+ align-items: center;
+}
+
+.load {
+ background-color: #313131;
+ color: white;
+ border: 1px;
+ border-left: 5px;
+ border-color: #ff9100;
+ border-style: solid;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ margin: 0px;
+ min-height: 32px;
+ display: flex;
+ align-items: center;
+}
+
+.read {
+ background-color: #313131;
+ border: 1px;
+ border-left: 5px;
+ border-color: rgb(107, 199, 47);
+ border-style: solid;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ margin: 0px;
+ min-height: 32px;
+ display: flex;
+ align-items: center;
+}
+
+.tree {
+ padding-left: 20px;
+} \ No newline at end of file
diff --git a/src/trace_viewer/index.html b/src/trace_viewer/index.html
new file mode 100644
index 00000000..75c5e035
--- /dev/null
+++ b/src/trace_viewer/index.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>Sail Log Viewer</title>
+ <script type="text/javascript">
+ var exports = {}
+ </script>
+ <script type="text/javascript" src="index.js"></script>
+ <link rel="stylesheet" type="text/css" href="index.css">
+ </head>
+ <body>
+ <div id="container">
+ </div>
+ <div id="control">
+ <input type="text" id="command">
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/src/trace_viewer/index.ts b/src/trace_viewer/index.ts
new file mode 100644
index 00000000..f9b5041b
--- /dev/null
+++ b/src/trace_viewer/index.ts
@@ -0,0 +1,287 @@
+import {remote} from "electron"
+import fs = require("fs")
+const dialog = remote.dialog
+const app = remote.app
+
+let topCallDiv = document.createElement("div")
+
+const max_arg_length = 5000
+
+abstract class Event {
+ caller: Call
+
+ protected div: HTMLDivElement | null = null
+
+ public hide(): void {
+ if (this.div != null) {
+ this.div.remove()
+ this.div = null
+ }
+ }
+
+ protected abstract showText(text: HTMLParagraphElement): void
+
+ public show(): HTMLDivElement {
+ let callerDiv: HTMLDivElement = (this.caller != null) ? this.caller.show() : topCallDiv
+
+ if (this.div != null) {
+ return this.div
+ } else {
+ this.div = document.createElement("div")
+ this.div.className = "tree"
+ callerDiv.appendChild(this.div)
+ let text = document.createElement("p")
+ this.showText(text)
+ this.div.appendChild(text)
+ return this.div
+ }
+ }
+}
+
+class Load extends Event {
+ loc: string
+ val: string
+
+ constructor(loc: string, val: string) {
+ super()
+ this.loc = loc
+ this.val = val
+ }
+
+ protected showText(text: HTMLParagraphElement): void {
+ text.className = "load"
+ text.insertAdjacentText('beforeend', this.loc + " " + this.val)
+ }
+}
+
+class Read extends Event {
+ reg: string
+ value: string
+
+ constructor(reg: string, value: string) {
+ super()
+ this.reg = reg
+ this.value = value
+ }
+
+ public showText(text: HTMLParagraphElement): void {
+ text.className = "read"
+ text.insertAdjacentText('beforeend', this.reg + " " + this.value)
+ }
+}
+
+class Write extends Event {
+ reg: string
+ value: string
+
+ constructor(reg: string, value: string) {
+ super()
+ this.reg = reg
+ this.value = value
+ }
+
+ public showText(text: HTMLParagraphElement): void {
+ text.className = "write"
+ text.insertAdjacentText('beforeend', this.reg + " " + this.value)
+ }
+}
+
+class Call {
+ fn: string
+ arg: string
+ ret: string
+ callees: (Call | Event)[] = []
+ caller: Call
+
+ private div: HTMLDivElement | null = null
+
+ private toggle: boolean = false
+ private toggleImg: HTMLImageElement | null = null
+
+ constructor(fn: string, arg: string, ret: string) {
+ this.fn = fn
+ this.arg = arg
+ this.ret = ret
+ }
+
+ public expand() {
+ if (this.caller != undefined) {
+ this.caller.expand()
+ }
+ this.showChildren()
+ }
+
+ public iter(f: (call: Call) => void): void {
+ f(this)
+ this.callees.forEach((callee) => {
+ if (callee instanceof Call) { callee.iter(f) }
+ })
+
+ }
+
+ public show(): HTMLDivElement {
+ let callerDiv: HTMLDivElement = (this.caller != null) ? this.caller.show() : topCallDiv
+
+ if (this.div != null) {
+ return this.div
+ } else {
+ this.div = document.createElement("div")
+ this.div.className = "tree"
+ callerDiv.appendChild(this.div)
+ let text = document.createElement("p")
+ text.className = "call"
+ if (this.callees.length > 0) {
+ this.toggleImg = document.createElement("img")
+ this.toggleImg.src = "List-add.svg"
+ this.toggleImg.addEventListener('click', () => {
+ if (this.toggle) {
+ this.hideChildren()
+ } else {
+ this.showChildren()
+ }
+ })
+ text.appendChild(this.toggleImg)
+ }
+ this.toggle = false
+ let display_arg = this.arg
+ if (this.arg.length > max_arg_length) {
+ display_arg = this.arg.slice(0, max_arg_length)
+ }
+ let display_ret = this.ret
+ if (this.ret.length > max_arg_length) {
+ display_ret = this.ret.slice(0, max_arg_length)
+ }
+
+ text.insertAdjacentText('beforeend', this.fn + " " + display_arg + " -> " + display_ret)
+ this.div.appendChild(text)
+ return this.div
+ }
+ }
+
+ public hide(): void {
+ if (this.toggle == true) {
+ this.hideChildren()
+ }
+
+ if (this.div != null) {
+ this.div.remove()
+ this.div = null
+ }
+ if (this.toggleImg != null) {
+ this.toggleImg.remove()
+ this.toggleImg = null
+ }
+ }
+
+ public hideChildren(): void {
+ this.callees.forEach(call => {
+ call.hide()
+ })
+
+ if (this.toggleImg != null) {
+ this.toggleImg.src = "List-add.svg"
+ this.toggle = false
+ } else {
+ alert("this.toggleImg was null!")
+ }
+ }
+
+ public showChildren(): void {
+ this.callees.forEach(call => {
+ call.show()
+ });
+
+ if (this.toggleImg != null) {
+ this.toggleImg.src = "List-remove.svg"
+ this.toggle = true
+ } else {
+ alert("this.toggleImg was null!")
+ }
+ }
+
+ public appendChild(child: Call | Write | Read | Load): void {
+ child.caller = this
+
+ this.callees.push(child)
+ }
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ let rootCall = new Call("ROOT", "", "")
+ topCallDiv.id = "root"
+ document.getElementById("container")!.appendChild(topCallDiv)
+
+ let commandInput = document.getElementById("command") as HTMLInputElement
+
+ commandInput.addEventListener("keydown", (event) => {
+ if(event.keyCode == 13) {
+ let cmd = commandInput.value.split(" ")
+ commandInput.value = ""
+
+ if (cmd[0] == "function") {
+ rootCall.iter((call) => {
+ if (call.fn == cmd[1]) { call.caller.expand() }
+ })
+ }
+ }
+ })
+
+ let files = dialog.showOpenDialog(remote.getCurrentWindow(), {title: "Select log file", defaultPath: app.getAppPath()})
+
+ if (files == [] || files == undefined) {
+ dialog.showErrorBox("Error", "No file selected")
+ app.exit(1)
+ }
+
+ fs.readFile(files[0], 'utf-8', (err, data) => {
+ if (err) {
+ dialog.showErrorBox("Error", "An error occurred when reading the log: " + err.message)
+ app.exit(1)
+ }
+
+ let lines = data.split("\n")
+ // let indents = lines.map(line => line.search(/[^\s]/) / 2)
+ lines = lines.map(line => line.trim())
+
+ let stack : Call[] = [rootCall]
+
+ lines.forEach(line => {
+ if (line.match(/^Call:/)) {
+ let words = line.slice(6).split(" ")
+ let call = new Call(words[0], words.slice(1).join(" "), "")
+ if (stack.length > 0) {
+ stack[stack.length - 1].appendChild(call)
+ }
+ stack.push(call)
+ } else if (line.match(/^Return:/)) {
+ let call = stack.pop()
+ if (call == undefined) {
+ alert("Unbalanced return")
+ app.exit(1)
+ } else {
+ call.ret = line.slice(8)
+ }
+ } else if (line.match(/^Write:/)) {
+ let words = line.slice(7).split(" ")
+ let write = new Write(words[0], words.slice(1).join(" "))
+ if (stack.length > 0) {
+ stack[stack.length - 1].appendChild(write)
+ }
+ } else if (line.match(/^Read:/)) {
+ let words = line.slice(6).split(" ")
+ let read = new Read(words[0], words.slice(1).join(" "))
+ if (stack.length > 0) {
+ stack[stack.length - 1].appendChild(read)
+ }
+ } else if (line.match(/^Load:/)) {
+ let words = line.slice(6).split(" ")
+ let load = new Load(words[0], words[1])
+ if (stack.length > 0) {
+ stack[stack.length - 1].appendChild(load)
+ }
+ }
+ })
+
+ rootCall.show()
+ })
+}) \ No newline at end of file
diff --git a/src/trace_viewer/main.ts b/src/trace_viewer/main.ts
new file mode 100644
index 00000000..5cc33452
--- /dev/null
+++ b/src/trace_viewer/main.ts
@@ -0,0 +1,12 @@
+import {app, BrowserWindow} from 'electron'
+
+let win : BrowserWindow | null = null
+
+app.on('ready', () => {
+ win = new BrowserWindow({width: 1920, height: 1200})
+ win.loadURL('file://' + __dirname + '/index.html')
+ //win.webContents.openDevTools()
+ win.on('close', () => {
+ win = null
+ })
+}) \ No newline at end of file
diff --git a/src/trace_viewer/package.json b/src/trace_viewer/package.json
new file mode 100644
index 00000000..e3a88d30
--- /dev/null
+++ b/src/trace_viewer/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "trace_viewer",
+ "version": "1.0.0",
+ "description": "",
+ "main": "main.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "tsc": "./node_modules/typescript/bin/tsc"
+ },
+ "devDependencies": {
+ "@types/node": "^8.0.46",
+ "electron": "1.7.9",
+ "typescript": "^2.5.3"
+ }
+}
diff --git a/src/trace_viewer/tsconfig.json b/src/trace_viewer/tsconfig.json
new file mode 100644
index 00000000..e66156b3
--- /dev/null
+++ b/src/trace_viewer/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "compileOnSave": true,
+ "compilerOptions": {
+ "target": "es5",
+ "moduleResolution": "node",
+ "pretty": true,
+ "newLine": "LF",
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "sourceMap": true,
+ "strictNullChecks": true,
+ "skipLibCheck": true,
+ "allowJs": true,
+ "jsx": "preserve"
+ }
+} \ No newline at end of file
diff --git a/src/type_check.ml b/src/type_check.ml
index 816f6d04..6489195a 100644
--- a/src/type_check.ml
+++ b/src/type_check.ml
@@ -507,6 +507,7 @@ end = struct
|| Id.compare id (mk_id "real") = 0
|| Id.compare id (mk_id "list") = 0
|| Id.compare id (mk_id "string") = 0
+ || Id.compare id (mk_id "itself") = 0
(* Check if a type, order, or n-expression is well-formed. Throws a
type error if the type is badly formed. FIXME: Add arity to type
@@ -922,6 +923,21 @@ let initial_env =
Env.empty
|> Env.add_typ_synonym (mk_id "atom") (fun _ args -> mk_typ (Typ_app (mk_id "range", args @ args)))
+ (* Internal functions for Monomorphise.AtomToItself *)
+
+ |> Env.add_extern (mk_id "size_itself_int") "size_itself_int"
+ |> Env.add_val_spec (mk_id "size_itself_int")
+ (TypQ_aux (TypQ_tq [QI_aux (QI_id (KOpt_aux (KOpt_none (mk_kid "n"),Parse_ast.Unknown)),
+ Parse_ast.Unknown)],Parse_ast.Unknown),
+ function_typ (app_typ (mk_id "itself") [mk_typ_arg (Typ_arg_nexp (nvar (mk_kid "n")))])
+ (atom_typ (nvar (mk_kid "n"))) no_effect)
+ |> Env.add_extern (mk_id "make_the_value") "make_the_value"
+ |> Env.add_val_spec (mk_id "make_the_value")
+ (TypQ_aux (TypQ_tq [QI_aux (QI_id (KOpt_aux (KOpt_none (mk_kid "n"),Parse_ast.Unknown)),
+ Parse_ast.Unknown)],Parse_ast.Unknown),
+ function_typ (atom_typ (nvar (mk_kid "n")))
+ (app_typ (mk_id "itself") [mk_typ_arg (Typ_arg_nexp (nvar (mk_kid "n")))]) no_effect)
+
let ex_counter = ref 0
let fresh_existential ?name:(n="") () =
@@ -2644,9 +2660,9 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) =
annot_exp (E_loop (loop_type, checked_cond, checked_body)) unit_typ
| E_for (v, f, t, step, ord, body) ->
begin
- let f, t = match ord with
- | Ord_aux (Ord_inc, _) -> f, t
- | Ord_aux (Ord_dec, _) -> t, f (* reverse direction for downto loop *)
+ let f, t, is_dec = match ord with
+ | Ord_aux (Ord_inc, _) -> f, t, false
+ | Ord_aux (Ord_dec, _) -> t, f, true (* reverse direction to typechecking downto as upto loop *)
in
let inferred_f = irule infer_exp env f in
let inferred_t = irule infer_exp env t in
@@ -2668,7 +2684,9 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) =
let env = Env.add_constraint (nc_and (nc_lteq l1 (nvar kid)) (nc_lteq (nvar kid) u2)) env in
let loop_vtyp = atom_typ (nvar kid) in
let checked_body = crule check_exp (Env.add_local v (Immutable, loop_vtyp) env) body unit_typ in
- annot_exp (E_for (v, inferred_f, inferred_t, checked_step, ord, checked_body)) unit_typ
+ if not is_dec (* undo reverse direction in annoteded ast for downto loop *)
+ then annot_exp (E_for (v, inferred_f, inferred_t, checked_step, ord, checked_body)) unit_typ
+ else annot_exp (E_for (v, inferred_t, inferred_f, checked_step, ord, checked_body)) unit_typ
end
| _, _ -> typ_error l "Ranges in foreach overlap"
end