Statistics: |
|
|
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
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))
000270| (*[0]*)raise ( ETypeMismatchInAssignment(index, string_of_value_type oldvalue, string_of_value_type value)))
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")
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
000291| match Hashtbl.find h name with
000292| | RFunctionValue(_, _, _, _, _, _, _) | RLibraryFunction(_) as v -> (*[2478]*)v
000293| | _ -> (*[0]*)raise Not_found
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")
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")
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
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
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
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)
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]*)()
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)
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]*)()
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))
000445| (*[0]*)try
000446| (*[0]*)let _ = Hashtbl.find h index in ((*[0]*)h, index)
000448| | Not_found -> (*[0]*)raise (EArrayIndexOutOfBounds index)
000451| | _ -> (*[0]*)raise (ELeftSideIsNotAMap(string_of_value_type left, string_of_value left))
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