File: build/interpreter.ml (return to index)



Statistics:  
kind coverage
binding 69 / 76 (90 %)
sequence 69 / 76 (90 %)
for 0 / 0 (- %)
if/then 21 / 28 (75 %)
try 17 / 18 (94 %)
while 0 / 0 (- %)
match/function 96 / 110 (87 %)
kind coverage
class expression 0 / 0 (- %)
class initializer 0 / 0 (- %)
class method 0 / 0 (- %)
class value 0 / 0 (- %)
toplevel expression 0 / 0 (- %)
lazy operator 4 / 4 (100 %)



Source:

fold all unfold all
000001| (**
000002| This program is free software; you can redistribute it and / or modify
000003| it under the terms of the GNU General Public License as published by
000004| the Free Software Foundation; version 3 of the License.
000005|  
000006| This program is distributed in the hope that it will be useful,
000007| but WITHOUT ANY WARRANTY; without even the implied warranty of
000008| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
000009| GNU General Public License for more details.
000010|  
000011| The Jtemplate interpreter
000012|  
000013| @author Tony BenBrahim < tony.benbrahim at gmail.com >
000014|  
000015| *)
000016|  
000017| open Ast
000018| open Expression
000019| open RuntimeError
000020|  
000021| (**
000022| Interpret a runtime AST
000023| @param env a runtime environment
000024| @param ast the runtime AST to interpret
000025| @return unit
000026| *)
000027| let rec interpret env = function
000028|         | RProgram(stmts) | RStatementBlock(stmts) ->
000029|                         (*[6118]*)List.iter (fun stmt -> (*[12384]*)interpret env stmt) stmts
000030|         | RExpressionStatement(expr, cloc) ->
000031|                         (*[9606]*)env.current_line <- cloc;
000032|                         (*[9606]*)let _ = evaluate env expr in (*[9530]*)()
000033|         | RReturn (expr, cloc) ->
000034|                         (*[452]*)env.current_line <- cloc;
000035|                         (*[452]*)let (_, value) = evaluate env expr
000036|                         in (*[452]*)raise (CFReturn value)
000037|         | RFor (preloop, condexpr, postloop, stmt, cloc) ->
000038|                         (*[16]*)env.current_line <- cloc;
000039|                         (*[16]*)let _ = evaluate env preloop
000040|                         in (*[16]*)let rec loop () =
000041|                                 (*[2476]*)let (env, value) = evaluate env condexpr
000042|                                 in match value with
000043|                                 | RBooleanValue(false) -> (*[12]*)()
000044|                                 | RBooleanValue(true) | RVoid ->
000045|                                                 ((*[2462]*)try
000046|                                                         (*[2462]*)interpret env stmt
000047|                                                 with
000048|                                                 | CFContinue -> (*[100]*)()
000049|                                                 );
000050|                                                 (*[2460]*)let _ = evaluate env postloop
000051|                                                 in (*[2460]*)loop ()
000052|                                 | value ->
000053|                                                 (*[2]*)raise (EInvalidCast(string_of_value value,"boolean"))
000054|                         in ((*[16]*)try
000055|                                 (*[16]*)loop ()
000056|                         with
000057|                         | CFBreak -> (*[2]*)())
000058|         | RFastIterator (vloc, start, max, inc, stmt, cloc) ->
000059|                         (*[20]*)env.current_line <- cloc;
000060|                         (*[20]*)let rec loop ind =
000061|                                 (*[560]*)let _ = Environment.set_value env (RIntegerValue(ind)) vloc
000062|                                 in (*[560]*)if ind < max then
000063|                                         (((*[544]*)try
000064|                                                         (*[544]*)interpret env stmt
000065|                                                 with
000066|                                                 | CFContinue -> (*[120]*)()
000067|                                                 );
000068|                                                 (*[540]*)loop (ind + inc))
000069|                                 else
000070|                                         (*[16]*)()
000071|                         in ((*[20]*)try
000072|                                 (*[20]*)loop start
000073|                         with
000074|                         | CFBreak -> (*[4]*)())
000075|         | RForEach (vloc, expr, stmt, cloc) ->
000076|                         (*[40]*)env.current_line <- cloc;
000077|                         (*[40]*)let list =
000078|                                 let (env, value) = evaluate env expr
000079|                                 in match value with
000080|                                 | RMapValue(h, MapSubtype) -> (*[2]*)Hashtbl.fold (fun k v lst -> (*[6]*)RStringValue(k):: lst) h []
000081|                                 | RMapValue(_, ArraySubtype) as v -> (*[36]*)list_of_array v
000082|                                 | _ as v -> (*[2]*)raise(ENotACollectionType("the second argument of forEach", string_of_value_type v))
000083|                         in (*[38]*)let rec loop = function
000084|                                 | [] -> (*[36]*)()
000085|                                 | hd:: tl ->
000086|                                                 (*[372]*)let _ = Environment.set_value env hd vloc
000087|                                                 in ((*[372]*)try (*[372]*)interpret env stmt with CFContinue -> (*[6]*)());
000088|                                                 (*[370]*)loop tl
000089|                         in
000090|                         ((*[38]*)try (*[38]*)loop list with CFBreak -> (*[2]*)() )
000091|         | RIf(condexpr, if_stmt, else_stmt, cloc) ->
000092|                         (*[3152]*)env.current_line <- cloc;
000093|                         (*[3152]*)let (env, value) = evaluate env condexpr
000094|                         in (match value with
000095|                                 | RBooleanValue(true) -> (*[2548]*)interpret env if_stmt
000096|                                 | RBooleanValue(false) -> (*[602]*)interpret env else_stmt
000097|                                 | value -> (*[2]*)raise (EInvalidCast(string_of_value value,"boolean"))
000098|                         )
000099|         | RSwitch(expr, stmtlist, cloc) ->
000100|                         (*[14]*)env.current_line <- cloc;
000101|                         (*[14]*)let rec find_cases caselist defaultfound = function
000102|                                 | []-> (*[8]*)caselist
000103|                                 | RCase(Some expr, _):: tl ->
000104|                                                 (*[30]*)if defaultfound then
000105|                                                         (*[4]*)raise EDefaultCaseShouldBeLast
000106|                                                 else(
000107|                                                         (*[26]*)let caselist = (Some expr, tl):: caselist in
000108|                                                         (*[26]*)find_cases caselist false tl)
000109|                                 | RCase(None, _):: tl ->
000110|                                                 (*[14]*)if defaultfound then
000111|                                                         (*[2]*)raise EDefaultCaseShouldBeLast
000112|                                                 else(
000113|                                                         (*[12]*)let caselist = (None, tl):: caselist in
000114|                                                         (*[12]*)find_cases caselist true tl)
000115|                                 | _:: tl -> (*[34]*)find_cases caselist defaultfound tl
000116|                         (* match a value with a case and return a statement list *)
000117|                         in (*[14]*)let rec match_case expr1 = function
000118|                                 | [] -> (*[2]*)[]
000119|                                 | (Some expr2, stmts):: tl ->
000120|                                                 (*[18]*)let (env, value) = evaluate env (RCompOp(expr1, Equal, expr2))
000121|                                                 in (*[18]*)if value = RBooleanValue(true) then
000122|                                                         (*[4]*)stmts
000123|                                                 else
000124|                                                         (*[14]*)match_case expr1 tl
000125|                                 | (None, stmts):: tl -> (*[2]*)stmts
000126|                         in (*[14]*)let caselist = List.rev (find_cases [] false stmtlist)
000127|                         in (*[8]*)let (env, value) = evaluate env expr
000128|                         in (*[8]*)let stmts = match_case (RValue(value)) caselist
000129|                         in ((*[8]*)try
000130|                                 (*[8]*)List.iter (fun stmt -> (*[12]*)interpret env stmt) stmts
000131|                         with
000132|                         | CFBreak -> (*[2]*)())
000133|         | RTryCatch(stmt1, vloc, stmt2, cloc) ->
000134|                         (*[410]*)env.current_line <- cloc;
000135|                         ((*[410]*)try
000136|                                 (*[410]*)interpret env stmt1;
000137|                         with
000138|                         | CFUserException(e, _) ->
000139|                                         (*[2]*)let _ = Environment.set_value env e vloc
000140|                                         in (*[2]*)interpret env stmt2
000141|                         | CFBreak | CFContinue as exn -> (*[22]*)raise exn
000142|                         | CFReturn(v) -> (*[2]*)raise (CFReturn v)
000143|                         | exn ->
000144|                                         (*[88]*)let _ = Environment.set_value env (RStringValue(RuntimeError.string_of_error exn)) vloc
000145|                                         in (*[88]*)interpret env stmt2
000146|                         )
000147|         | RTryFinally(stmt1, stmt2, cloc) ->
000148|                         (*[8]*)env.current_line <- cloc;
000149|                         ((*[8]*)try
000150|                                 (*[8]*)interpret env stmt1
000151|                         with
000152|                         | _ as e -> (*[8]*)interpret env stmt2; (*[6]*)raise e)
000153|         | RContinue(cloc) ->
000154|                         (*[226]*)env.current_line <- cloc;
000155|                         (*[226]*)raise CFContinue
000156|         | RBreak(cloc) ->
000157|                         (*[10]*)env.current_line <- cloc;
000158|                         (*[10]*)raise CFBreak;
000159|         | RThrow(expr, cloc) ->
000160|                         (*[2]*)env.current_line <- cloc;
000161|                         (*[2]*)let (_, value) = evaluate env expr
000162|                         in (*[2]*)raise (CFUserException(value, string_of_value value))
000163|         | RNoop | RCase(_, _) -> (*[420]*)()
000164|  
000165| (**
000166| Interprets a list of statements
000167| @param env runtime environments
000168| @param stmts list of statements
000169| *)
000170| and interpret_stmts env = function
000171|         | [] -> (*[4]*)()
000172|         | stmt:: tl ->
000173|                         (*[1052]*)interpret env stmt; (*[602]*)interpret_stmts env tl
000174| (**
000175| Evaluates an expression
000176| @param env runtime environment
000177| @param expr expression to be evaluated
000178| @return a value
000179| *)
000180| and evaluate env = function
000181|         | RVariable(loc) -> ((*[18606]*)env, Environment.get_value env loc)
000182|         | RValue(v) ->
000183|                         (match v with (* look for closure vars*)
000184|                                 | RFunctionValue(framesize, depth, argslen, has_varargs, statements, Some closure_vars, _) ->
000185|                                                 (*[36]*)let closure_vals = Hashtbl.create 10
000186|                                                 in (*[36]*)let _ = Hashtbl.fold(
000187|                                                                         fun k _ _ -> (*[36]*)let (d, i) = k
000188|                                                                                         in (*[36]*)let (_, value) = evaluate env (RVariable(LocalVar(0, d, i)))
000189|                                                                                         in (*[36]*)Hashtbl.replace closure_vals (d, i) value) closure_vars ()
000190|                                                 in ((*[36]*)env, RFunctionValue(framesize, depth, argslen, has_varargs, statements, Some closure_vals, None))
000191|                                 | _ -> ((*[20744]*)env, v))
000192|         | RPostFixSum(expr, inc) ->
000193|                         (*[4]*)let (env, v) = evaluate env expr
000194|                         in (*[4]*)let _ = evaluate env (RAssignment(expr, RBinaryOp(RValue(v), Plus, RValue(RIntegerValue(inc)))))
000195|                         in ((*[4]*)env, v)
000196|         | RArrayExpr(expr_list) ->
000197|                         (*[158]*)let value_list = List.map (fun e -> (*[608]*)let (_, v) = evaluate env e in (*[608]*)v) expr_list
000198|                         in (*[158]*)let len = (List.length value_list)
000199|                         in (*[158]*)let t = Hashtbl.create len
000200|                         in (*[158]*)let _ = List.fold_left (fun ind v -> (*[608]*)Hashtbl.add t (string_of_int ind) v; (*[608]*)ind + 1) 0 value_list
000201|                         in (*[158]*)let _ = Hashtbl.add t "length" (RIntegerValue(len))
000202|                         in ((*[158]*)env, RMapValue(t, ArraySubtype))
000203|         | RMapExpr(prop_list) ->
000204|                         (*[386]*)let t = Hashtbl.create (List.length prop_list)
000205|                         in (*[386]*)let _ = List.iter(fun prop -> (*[760]*)let (name, e) = prop in (*[760]*)Hashtbl.add t name (let (_, v) = evaluate env e in (*[760]*)v)) prop_list
000206|                         in ((*[386]*)env, RMapValue(t, MapSubtype))
000207|         | RBinaryOp(e1, op, e2) ->
000208|                         (*[6428]*)let (env, v1) = evaluate env e1
000209|                         in (*[6422]*)let (env, v2) = evaluate env e2
000210|                         in ((*[6422]*)env, evaluate_op v1 v2 op)
000211|         | RCompOp(e1, op, e2) ->
000212|                         (*[5696]*)let (env, v1) = evaluate env e1
000213|                         in (*[5694]*)let (env, v2) = evaluate env e2
000214|                         in ((*[5694]*)env, compare v1 op v2)
000215|         | RTernaryCond(e1, e2, e3) ->
000216|                         (*[38]*)let (env, value) = evaluate env e1
000217|                         in (match value with
000218|                                 | RBooleanValue(true) -> (*[12]*)evaluate env e2
000219|                                 | RBooleanValue(false) -> (*[22]*)evaluate env e3
000220|                                 | v -> (*[2]*)raise (EIncompatibleTypes ("boolean" , string_of_value_type v)))
000221|         | RMemberExpr(left, index) ->
000222|                         (*[1002]*)let (env, left_map) = evaluate env left
000223|                         in (*[1002]*)let (key, is_int) = evaluate_memb_expr_index env index
000224|                         in (match left_map with
000225|                                 | RMapValue(h, ArraySubtype) ->
000226|                                                 (*[32]*)if (not is_int) then
000227|                                                         (*[2]*)raise (EInvalidArrayIndex("string", key))
000228|                                                 else
000229|                                                         ((*[30]*)try
000230|                                                                 ((*[30]*)env, Hashtbl.find h key)
000231|                                                         with Not_found ->
000232|                                                                         (*[4]*)raise (EArrayIndexOutOfBounds key))
000233|                                 | RMapValue(h, MapSubtype) ->
000234|                                                 ((*[962]*)try
000235|                                                         ((*[962]*)env, Hashtbl.find h key)
000236|                                                 with Not_found ->
000237|                                                                 (*[2]*)raise (EUndefinedMapMember key))
000238|                                 | _ -> (*[8]*)raise (ELeftSideIsNotAMap(string_of_value_type left_map, string_of_value left_map)))
000239|         | RNot(expr) ->
000240|                         (*[66]*)let (env, v) = evaluate env expr in
000241|                         (match v with
000242|                                 | RBooleanValue(b) -> ((*[64]*)env, RBooleanValue(not b))
000243|                                 | _ -> (*[2]*)raise (EIncompatibleTypes(string_of_value_type v, "boolean"))
000244|                         )
000245|         | RDeclaration(left, right) ->
000246|                         (*[2694]*)let (env, value) = evaluate env right in
000247|                         (match left with
000248|                                 | RVariable(loc) -> ((*[2646]*)env, Environment.set_value env value loc)
000249|                                 | RMemberExpr(expr, key) ->
000250|                                                 (*[20]*)let (h, index) = get_member_expr_map env expr key
000251|                                                 in (*[20]*)Hashtbl.replace h index value; ((*[20]*)env, value)
000252|                                 | _ -> (*[0]*)raise ELeftSideCannotBeAssigned
000253|                         )
000254|         | RAssignment(left, right) ->
000255|                         (*[6128]*)let (env, value) = evaluate env right in
000256|                         (match left with
000257|                                 | RVariable(loc) ->
000258|                                                 (*[6122]*)let oldvalue = Environment.get_value env loc
000259|                                                 in ((*[6122]*)if value_type oldvalue = value_type value then
000260|                                                                 ((*[6120]*)env, (Environment.set_value env value loc))
000261|                                                         else
000262|                                                                 (*[2]*)raise ( ETypeMismatchInAssignment(Environment.get_loc_name env loc, string_of_value_type oldvalue, string_of_value_type value)))
000263|                                 
000264|                                 | RMemberExpr(expr, key) ->
000265|                                                 (*[4]*)let (h, index) = get_member_expr_map env expr key
000266|                                                 in (*[0]*)let oldvalue = Hashtbl.find h index
000267|                                                 in ((*[0]*)if value_type oldvalue = value_type value then
000268|                                                                 ((*[0]*)Hashtbl.replace h index value; ((*[0]*)env, value))
000269|                                                         else
000270|                                                                 (*[0]*)raise ( ETypeMismatchInAssignment(index, string_of_value_type oldvalue, string_of_value_type value)))
000271|                                 | _ -> (*[2]*)raise ELeftSideCannotBeAssigned
000272|                         )
000273|         | RFunctionCall(fexpr, args_expr) ->
000274|                         (*[3826]*)let (this, func) = resolve_func_this env fexpr
000275|                         in (*[3826]*)let value_list = (evaluate_expr_list env args_expr)
000276|                         in (*[3822]*)run_function env value_list this func
000277|         | RVarArg(_) ->
000278|                         (*[0]*)raise (RuntimeError.InternalError "unexpected expression in evaluate")
000279| (**
000280| Resolves a function call by an expression into a function and a this object
000281| @param env runtime environment
000282| @param fexpr the expression to analyze
000283| @return a tuple of the this object and the function
000284| *)
000285| and resolve_func_this env fexpr =
000286|         (*[3826]*)let find_prototype h =
000287|                 match Hashtbl.find h "prototype" with
000288|                 | RMapValue(h, MapSubtype) -> (*[46]*)h
000289|                 | _ -> (*[0]*)raise Not_found
000290|         in (*[3826]*)let find_func h name =
000291|                 match Hashtbl.find h name with
000292|                 | RFunctionValue(_, _, _, _, _, _, _) | RLibraryFunction(_) as v -> (*[2478]*)v
000293|                 | _ -> (*[0]*)raise Not_found
000294|         in (*[3826]*)let rec find_map_func h = function
000295|                 | "prototype":: tl -> (*[86]*)find_map_func (find_prototype h) tl
000296|                 | name:: tl -> (*[24]*)find_func h name
000297|                 | [] -> (*[0]*)raise (RuntimeError.InternalError "map function find")
000298|         in match fexpr with
000299|         | RMemberExpr(this_expr, funcname) ->
000300|                         (*[2670]*)let (env, this) = evaluate env this_expr
000301|                         in (*[2670]*)let f = match this with
000302|                                 | RUndefined -> (*[0]*)raise (RuntimeError.InternalError "unexpected undefined this in function resolution")
000303|                                 | RStringValue(_) ->
000304|                                                 (*[100]*)let (env, v) = evaluate env (RMemberExpr(RMemberExpr(RVariable(GlobalVar(1, 1)), RValue(RStringValue("prototype"))), funcname))
000305|                                                 in (*[100]*)v
000306|                                 | RIntegerValue(_) ->
000307|                                                 (*[0]*)let (env, v) = evaluate env (RMemberExpr(RMemberExpr(RVariable(GlobalVar(2, 2)), RValue(RStringValue("prototype"))), funcname))
000308|                                                 in (*[0]*)v
000309|                                 | RFloatValue(_) ->
000310|                                                 (*[4]*)let (env, v) = evaluate env (RMemberExpr(RMemberExpr(RVariable(GlobalVar(3, 3)), RValue(RStringValue("prototype"))), funcname))
000311|                                                 in (*[4]*)v
000312|                                 | RBooleanValue(_) ->
000313|                                                 (*[0]*)let (env, v) = evaluate env (RMemberExpr(RMemberExpr(RVariable(GlobalVar(4, 4)), RValue(RStringValue("prototype"))), funcname))
000314|                                                 in (*[0]*)v
000315|                                 | RFunctionValue(_, _, _, _, _, _, _) | RLibraryFunction(_) ->
000316|                                                 (*[22]*)let (env, v) = evaluate env (RMemberExpr(RMemberExpr(RVariable(GlobalVar(5, 5)), RValue(RStringValue("prototype"))), funcname))
000317|                                                 in (*[22]*)v
000318|                                 | RVoid ->
000319|                                                 (*[0]*)let (env, v) = evaluate env (RMemberExpr(RMemberExpr(RVariable(GlobalVar(6, 6)), RValue(RStringValue("prototype"))), funcname))
000320|                                                 in (*[0]*)v
000321|                                 | RMapValue(_, ArraySubtype) ->
000322|                                                 (*[36]*)let (env, v) = evaluate env (RMemberExpr(RMemberExpr(RVariable(GlobalVar(8, 8)), RValue(RStringValue("prototype"))), funcname))
000323|                                                 in (*[36]*)v
000324|                                 | RMapValue(h, MapSubtype) ->
000325|                                                 (*[2508]*)let (env, value) = evaluate env funcname
000326|                                                 in (*[2508]*)let name = string_of_value value
000327|                                                 in (*[2508]*)try (*[2508]*)find_func h name
000328|                                                 with | Not_found ->
000329|                                                                 (*[32]*)try (*[32]*)find_map_func h ["prototype"; name]
000330|                                                                 with | Not_found ->
000331|                                                                                 (*[32]*)try (*[32]*)find_map_func h ["prototype";"prototype"; name]
000332|                                                                                 with | Not_found ->
000333|                                                                                                 (*[30]*)try
000334|                                                                                                         (*[30]*)let (env, value) = evaluate env (RMemberExpr(RMemberExpr(RVariable(GlobalVar(9, 9)), RValue(RStringValue("prototype"))), funcname))
000335|                                                                                                         in (*[30]*)value
000336|                                                                                                 with EUndefinedMapMember _ -> (*[0]*)raise (EUndefinedMapMember name)
000337|                         in ((*[2670]*)this, f)
000338|         | _ ->
000339|                         (*[1156]*)let (env, v) = evaluate env fexpr
000340|                         in ((*[1156]*)RVoid, v)
000341| (**
000342| Runs a function
000343| @param env runtime environment
000344| @value_list list of values to pass as arguments
000345| @this this pointer
000346| @func function
000347| @return a tuple of the environemt and return value
000348| *)
000349| and run_function env value_list this func =
000350|         match func with
000351|         | RFunctionValue(framesize, depth, argslen, vararg, stmts, closure_vars, _) ->
000352|                         (*[458]*)let old_frame = env.stackframes.(depth)
000353|                         in (*[458]*)let _ = env.stackframes.(depth) <- make_stackframe framesize argslen vararg value_list this
000354|                         in (*[454]*)let old_closure_vars = env.closure_vars
000355|                         in (*[454]*)let old_skip_callstack_pop = env.skip_callstack_pop
000356|                         in (*[454]*)let _ = env.closure_vars <- closure_vars
000357|                         in ((*[454]*)try
000358|                                 ((*[454]*)if (*[454]*)Stack.is_empty env.callstack or (*[452]*)Stack.top env.callstack!= env.current_line then
000359|                                                 ((*[432]*)Stack.push env.current_line env.callstack;
000360|                                                         (*[432]*)env.skip_callstack_pop <- false)
000361|                                         else
000362|                                                 (*[22]*)env.skip_callstack_pop <- true
000363|                                 );
000364|                                 (*[454]*)interpret_stmts env stmts;
000365|                                 ((*[4]*)if env.skip_callstack_pop then (*[0]*)()
000366|                                         else (*[4]*)let _ = Stack.pop env.callstack in (*[4]*)());
000367|                                 (*[4]*)env.skip_callstack_pop <- old_skip_callstack_pop;
000368|                                 (*[4]*)env.stackframes.(depth) <- old_frame;
000369|                                 (*[4]*)env.closure_vars <- old_closure_vars;
000370|                                 ((*[4]*)env, RVoid)
000371|                         with
000372|                         | CFReturn value ->
000373|                                         ((*[450]*)if env.skip_callstack_pop then (*[22]*)()
000374|                                                 else (*[428]*)let _ = Stack.pop env.callstack in (*[428]*)());
000375|                                         (*[450]*)env.skip_callstack_pop <- old_skip_callstack_pop;
000376|                                         (*[450]*)env.stackframes.(depth) <- old_frame;
000377|                                         (*[450]*)env.closure_vars <- old_closure_vars;
000378|                                         ((*[450]*)env, value)
000379|                         | ex ->
000380|                                         ((*[0]*)if env.skip_callstack_pop then (*[0]*)()
000381|                                                 else (*[0]*)let _ = Stack.pop env.callstack in (*[0]*)());
000382|                                         (*[0]*)env.skip_callstack_pop <- old_skip_callstack_pop;
000383|                                         (*[0]*)env.stackframes.(depth) <- old_frame;
000384|                                         (*[0]*)env.closure_vars <- old_closure_vars;
000385|                                         (*[0]*)raise ex)
000386|         | RLibraryFunction(def) ->
000387|                         (*[3384]*)let old_frame = env.stackframes.(0)
000388|                         in (*[3384]*)let old_skip_callstack_pop = env.skip_callstack_pop
000389|                         in (*[3384]*)env.stackframes.(0) <- make_stackframe def.num_args def.num_args def.vararg value_list this;
000390|                         ((*[3382]*)try
000391|                                 ((*[3382]*)if (*[3382]*)Stack.is_empty env.callstack or (*[3382]*)Stack.top env.callstack!= env.current_line then
000392|                                                 ((*[3346]*)Stack.push env.current_line env.callstack;
000393|                                                         (*[3346]*)env.skip_callstack_pop <- false)
000394|                                         else
000395|                                                 (*[36]*)env.skip_callstack_pop <- true
000396|                                 );
000397|                                 (*[3382]*)def.code env;
000398|                                 ((*[744]*)if env.skip_callstack_pop then (*[0]*)()
000399|                                         else (*[744]*)let _ = Stack.pop env.callstack in (*[744]*)());
000400|                                 (*[744]*)env.skip_callstack_pop <- old_skip_callstack_pop;
000401|                                 (*[744]*)env.stackframes.(0) <- old_frame;
000402|                                 ((*[744]*)env, RVoid)
000403|                         with
000404|                         | CFReturn value ->
000405|                                         ((*[2592]*)if env.skip_callstack_pop then (*[22]*)()
000406|                                                 else (*[2570]*)let _ = Stack.pop env.callstack in (*[2570]*)());
000407|                                         (*[2592]*)env.skip_callstack_pop <- old_skip_callstack_pop;
000408|                                         (*[2592]*)env.stackframes.(0) <- old_frame;
000409|                                         ((*[2592]*)env, value)
000410|                         | ex ->
000411|                                         ((*[46]*)if env.skip_callstack_pop then (*[14]*)()
000412|                                                 else (*[32]*)let _ = Stack.pop env.callstack in (*[32]*)());
000413|                                         (*[46]*)env.skip_callstack_pop <- old_skip_callstack_pop;
000414|                                         (*[46]*)env.stackframes.(0) <- old_frame;
000415|                                         (*[46]*)raise ex)
000416|         | _ -> (*[2]*)raise ENotAFunction
000417|  
000418| (**
000419| Determines the value and type of expression for the last member of a member expression
000420| @param env the runtime environment
000421| @param index the expression to evaluate
000422| @return a tuple with the index of the expression and a boolean indicating
000423| whether it is an integer
000424| *)
000425| and evaluate_memb_expr_index env index =
000426|         (match evaluate env index with
000427|                 | (_, RStringValue(s)) -> ((*[968]*)s, false)
000428|                 | (_, RIntegerValue(i)) -> ((*[54]*)string_of_int i, true)
000429|                 | (_, v) -> (*[4]*)raise (EInvalidMember(string_of_value_type v, string_of_value v))
000430|         )
000431| (**
000432| Returns the hashmap that corresponds to the member expression
000433| @env the runtime environment
000434| @param expr the member expression (without the last member)
000435| @param index the index (the last member of the member expression)
000436| @return the hashmap that corresponds to the member expression
000437| *)
000438| and get_member_expr_map env expr index =
000439|         (*[24]*)let (env, left) = evaluate env expr
000440|         in (*[24]*)let (index, is_int) = evaluate_memb_expr_index env index
000441|         in (match left with
000442|                 | RMapValue(h, ArraySubtype) ->
000443|                                 ((*[0]*)if not is_int then (*[0]*)raise (EInvalidArrayIndex("string", index))
000444|                                         else
000445|                                                 (*[0]*)try
000446|                                                         (*[0]*)let _ = Hashtbl.find h index in ((*[0]*)h, index)
000447|                                                 with
000448|                                                 | Not_found -> (*[0]*)raise (EArrayIndexOutOfBounds index)
000449|                                 )
000450|                 | RMapValue(h, MapSubtype) -> ((*[20]*)h, index)
000451|                 | _ -> (*[0]*)raise (ELeftSideIsNotAMap(string_of_value_type left, string_of_value left))
000452|         )
000453| (**
000454| Evaluates a list of expressions
000455| @param env the runtime environment
000456| @param expr_list an expression list
000457| @param a list of the corresponding value for each expression
000458| *)
000459| and evaluate_expr_list env expr_list =
000460|         (*[3826]*)let rec loop result = function
000461|                 | [] -> (*[3822]*)List.rev result
000462|                 | RVarArg(loc):: tl ->
000463|                                 (*[2]*)loop (List.concat [
000464|                                                         (let (env, v) = evaluate env (RVariable(loc))
000465|                                                                 in match v with
000466|                                                                 | RMapValue(_, ArraySubtype) as arr -> (*[2]*)List.rev (list_of_array arr)
000467|                                                                 | _ -> (*[0]*)raise (RuntimeError.InternalError "expected array while expanding args")); result]) tl
000468|                 | expr:: tl -> (*[4390]*)let (env, v) = evaluate env expr in (*[4386]*)loop (v:: result) tl
000469|         in (*[3826]*)loop [] expr_list

Legend:
   some code - line containing no point
   some code - line containing only visited points
   some code - line containing only unvisited points
   some code - line containing both visited and unvisited points