summaryrefslogtreecommitdiff
path: root/Jennisys/Resolver.fs
diff options
context:
space:
mode:
Diffstat (limited to 'Jennisys/Resolver.fs')
-rw-r--r--Jennisys/Resolver.fs106
1 files changed, 59 insertions, 47 deletions
diff --git a/Jennisys/Resolver.fs b/Jennisys/Resolver.fs
index f1a1f67f..59c6904d 100644
--- a/Jennisys/Resolver.fs
+++ b/Jennisys/Resolver.fs
@@ -1,18 +1,33 @@
-module Resolver
+// ####################################################################
+/// Utilities for resolving the "Unresolved" constants with respect to
+/// a given context (heap/env/ctx)
+///
+/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+// ####################################################################
+
+module Resolver
open Ast
+open AstUtils
open Printer
open EnvUtils
// resolving values
+exception ConstResolveFailed of string
-let rec Resolve cst (env,ctx) =
+// ================================================================
+/// Resolves a given Const (cst) with respect to a given env/ctx.
+///
+/// If unable to resolve, it just delegates the task to the
+/// failResolver function
+// ================================================================
+let rec ResolveCont (env,ctx) failResolver cst =
match cst with
| Unresolved(_) as u ->
// see if it is in the env map first
let envVal = Map.tryFind cst env
match envVal with
- | Some(c) -> Resolve c (env,ctx)
+ | Some(c) -> ResolveCont (env,ctx) failResolver c
| None ->
// not found in the env map --> check the equality sets
let eq = ctx |> Set.filter (fun eqSet -> Set.contains u eqSet)
@@ -23,56 +38,53 @@ let rec Resolve cst (env,ctx) =
|> Utils.SetToOption
match cOpt with
| Some(c) -> c
- | _ -> failwith ("failed to resolve " + cst.ToString())
- | _ -> failwith ("failed to resolve " + cst.ToString())
+ | _ -> failResolver cst (env,ctx)
+ | _ -> failResolver cst (env,ctx)
| SeqConst(cseq) ->
- let resolvedLst = cseq |> List.rev |> List.fold (fun acc cOpt ->
- match cOpt with
- | Some(c) -> Some(Resolve c (env,ctx)) :: acc
- | None -> cOpt :: acc
- ) []
+ let resolvedLst = cseq |> List.rev |> List.fold (fun acc c -> ResolveCont (env,ctx) failResolver c :: acc) []
SeqConst(resolvedLst)
| SetConst(cset) ->
- let resolvedSet = cset |> Set.fold (fun acc cOpt ->
- match cOpt with
- | Some(c) -> acc |> Set.add (Some(Resolve c (env,ctx)))
- | None -> acc |> Set.add(cOpt)
- ) Set.empty
+ let resolvedSet = cset |> Set.fold (fun acc c -> acc |> Set.add (ResolveCont (env,ctx) failResolver c)) Set.empty
SetConst(resolvedSet)
| _ -> cst
-let rec EvalUnresolved expr (heap,env,ctx) =
- match expr with
- | IntLiteral(n) -> IntConst(n)
- | IdLiteral(id) when id = "this" -> GetThisLoc env
- | IdLiteral(id) -> EvalUnresolved (Dot(IdLiteral("this"), id)) (heap,env,ctx)
- | Dot(e, str) ->
- let discr = EvalUnresolved e (heap,env,ctx)
- let h2 = Map.filter (fun (loc,Var(fldName,_)) v -> loc = discr && fldName = str) heap |> Map.toList
- match h2 with
- | ((_,_),x) :: [] -> x
- | _ :: _ -> failwithf "can't evaluate expression deterministically: %s.%s resolves to multiple locations." (PrintConst discr) str
- | [] -> failwithf "can't find value for %s.%s" (PrintConst discr) str
- | SelectExpr(lst, idx) ->
- let lstC = Resolve (EvalUnresolved lst (heap,env,ctx)) (env,ctx)
- let idxC = EvalUnresolved idx (heap,env,ctx)
- match lstC, idxC with
- | SeqConst(clist), IntConst(n) -> clist.[n] |> Utils.ExtractOption
- | _ -> failwith "can't eval SelectExpr"
- | _ -> failwith "NOT IMPLEMENTED YET" //TODO finish this!
-// | Star
-// | SelectExpr(_)
-// | UpdateExpr(_)
-// | SequenceExpr(_)
-// | SeqLength(_)
-// | ForallExpr(_)
-// | UnaryExpr(_)
-// | BinaryExpr(_)
-
-// TODO: can this be implemented on top of the existing AstUtils.EvalSym?? We must!
-let Eval expr (heap,env,ctx) =
+// =====================================================================
+/// Tries to resolve a given Const (cst) with respect to a given env/ctx.
+///
+/// If unable to resolve, just returns the original Unresolved const.
+// =====================================================================
+let TryResolve (env,ctx) cst =
+ ResolveCont (env,ctx) (fun c (e,x) -> c) cst
+
+// ==============================================================
+/// Resolves a given Const (cst) with respect to a given env/ctx.
+///
+/// If unable to resolve, raises a ConstResolveFailed exception
+// ==============================================================
+let Resolve (env,ctx) cst =
+ ResolveCont (env,ctx) (fun c (e,x) -> raise (ConstResolveFailed("failed to resolve " + c.ToString()))) cst
+
+// =================================================================
+/// Evaluates a given expression with respect to a given heap/env/ctx
+// =================================================================
+let Eval (heap,env,ctx) expr =
+ let rec __EvalResolver expr =
+ match expr with
+ | IdLiteral(id) when id = "this" -> GetThisLoc env
+ | IdLiteral(id) ->
+ match TryResolve (env,ctx) (Unresolved(id)) with
+ | Unresolved(_) -> __EvalResolver (Dot(IdLiteral("this"), id))
+ | _ as c -> c
+ | Dot(e, str) ->
+ let discr = __EvalResolver e
+ let h2 = Map.filter (fun (loc,Var(fldName,_)) v -> loc = discr && fldName = str) heap |> Map.toList
+ match h2 with
+ | ((_,_),x) :: [] -> x
+ | _ :: _ -> failwithf "can't evaluate expression deterministically: %s.%s resolves to multiple locations." (PrintConst discr) str
+ | [] -> failwithf "can't find value for %s.%s" (PrintConst discr) str
+ | _ -> failwith "NOT IMPLEMENTED YET"
try
- let unresolvedConst = EvalUnresolved expr (heap,env,ctx)
- Some(Resolve unresolvedConst (env,ctx))
+ let unresolvedConst = EvalSym (fun e -> __EvalResolver e |> Resolve (env,ctx)) expr
+ Some(TryResolve (env,ctx) unresolvedConst)
with
ex -> None \ No newline at end of file