@@ -34,12 +34,14 @@ type dvalue =
3434 | DBool of bool
3535 | DString of string
3636 | DArray of dvalue array
37+ | DList of dvalue list ref (* Dynamic list with mutable reference *)
3738 | DStruct of dvalue array
3839
3940(* Expression with resolved indices *)
4041type iexp =
4142 | IEUnit
4243 | IEEmptyValue
44+ | IEEmptyList of type_ (* Empty list of the given element type *)
4345 | IEBool of bool
4446 | IEInt of int
4547 | IEReal of float
@@ -105,6 +107,16 @@ type iexp =
105107 (* Array/string functions *)
106108 | IEBuiltinSize of iexp
107109 | IEBuiltinLength of iexp
110+ (* List functions *)
111+ | IEBuiltinListSize of iexp
112+ | IEBuiltinListCapacity of iexp
113+ | IEBuiltinListAppend of iexp * iexp
114+ | IEBuiltinListInsert of iexp * iexp * iexp
115+ | IEBuiltinListRemove of iexp * iexp
116+ | IEBuiltinListClear of iexp
117+ | IEBuiltinListReserve of iexp * iexp
118+ | IEBuiltinListGet of iexp * iexp
119+ | IEBuiltinListSet of iexp * iexp * iexp
108120 | IEIndex of iexp * iexp
109121 | IEArray of iexp list
110122 | IECall of int * iexp list (* Function index and args *)
@@ -302,6 +314,7 @@ let rec printDvalue (dv : dvalue) : string =
302314 | DBool b -> string_of_bool b
303315 | DString s -> " \" " ^ s ^ " \" "
304316 | DArray arr -> " [" ^ String. concat " ; " (Array. to_list (Array. map printDvalue arr)) ^ " ]"
317+ | DList list_ref -> " list[" ^ String. concat " ; " (CCList. map printDvalue ! list_ref) ^ " ]"
305318 | DStruct arr ->
306319 " {" ^ String. concat " ; " (Array. to_list (Array. mapi (fun i v -> string_of_int i ^ " :" ^ printDvalue v) arr)) ^ " }"
307320
@@ -341,6 +354,7 @@ let rec printIexp (ie : iexp) : string =
341354 match ie with
342355 | IEUnit -> " ()"
343356 | IEEmptyValue -> " empty"
357+ | IEEmptyList _ -> " empty_list"
344358 | IEBool b -> string_of_bool b
345359 | IEInt i -> string_of_int i
346360 | IEReal f -> string_of_float f
@@ -408,6 +422,16 @@ let rec printIexp (ie : iexp) : string =
408422 (* Array/string functions *)
409423 | IEBuiltinSize e -> " size(" ^ printIexp e ^ " )"
410424 | IEBuiltinLength e -> " length(" ^ printIexp e ^ " )"
425+ (* List functions *)
426+ | IEBuiltinListSize e -> " list_size(" ^ printIexp e ^ " )"
427+ | IEBuiltinListCapacity e -> " list_capacity(" ^ printIexp e ^ " )"
428+ | IEBuiltinListAppend (l , v ) -> " list_append(" ^ printIexp l ^ " , " ^ printIexp v ^ " )"
429+ | IEBuiltinListInsert (l , i , v ) -> " list_insert(" ^ printIexp l ^ " , " ^ printIexp i ^ " , " ^ printIexp v ^ " )"
430+ | IEBuiltinListRemove (l , i ) -> " list_remove(" ^ printIexp l ^ " , " ^ printIexp i ^ " )"
431+ | IEBuiltinListClear e -> " list_clear(" ^ printIexp e ^ " )"
432+ | IEBuiltinListReserve (l , n ) -> " list_reserve(" ^ printIexp l ^ " , " ^ printIexp n ^ " )"
433+ | IEBuiltinListGet (l , i ) -> " list_get(" ^ printIexp l ^ " , " ^ printIexp i ^ " )"
434+ | IEBuiltinListSet (l , i , v ) -> " list_set(" ^ printIexp l ^ " , " ^ printIexp i ^ " , " ^ printIexp v ^ " )"
411435 | IEIndex (arr , idx ) -> printIexp arr ^ " [" ^ printIexp idx ^ " ]"
412436 | IEArray exprs -> " [" ^ String. concat " ; " (CCList. map printIexp exprs) ^ " ]"
413437 | IECall (func_idx , args ) ->
@@ -498,7 +522,11 @@ let isInt16Type (typ : type_) : bool =
498522let rec transformExp (ctx : transform_ctx ) (exp : exp ) : iexp =
499523 match exp.e with
500524 | EUnit -> IEUnit
501- | EEmptyValue -> IEEmptyValue
525+ | EEmptyValue -> (
526+ (* Check if the empty value is for a list type *)
527+ match exp.t.t with
528+ | TList _ -> IEEmptyList exp.t
529+ | _ -> IEEmptyValue )
502530 | EBool b -> IEBool b
503531 | EInt i -> IEInt i
504532 | EReal f -> IEReal f
@@ -579,6 +607,16 @@ let rec transformExp (ctx : transform_ctx) (exp : exp) : iexp =
579607 (* Array/string functions *)
580608 | "size" , [ arg ] -> IEBuiltinSize arg
581609 | "length" , [ arg ] -> IEBuiltinLength arg
610+ (* List functions *)
611+ | "list_size" , [ arg ] -> IEBuiltinListSize arg
612+ | "list_capacity" , [ arg ] -> IEBuiltinListCapacity arg
613+ | "list_append" , [ l; v ] -> IEBuiltinListAppend (l, v)
614+ | "list_insert" , [ l; i; v ] -> IEBuiltinListInsert (l, i, v)
615+ | "list_remove" , [ l; i ] -> IEBuiltinListRemove (l, i)
616+ | "list_clear" , [ arg ] -> IEBuiltinListClear arg
617+ | "list_reserve" , [ l; n ] -> IEBuiltinListReserve (l, n)
618+ | "list_get" , [ l; i ] -> IEBuiltinListGet (l, i)
619+ | "list_set" , [ l; i; v ] -> IEBuiltinListSet (l, i, v)
582620 (* External runtime functions *)
583621 | "push_block_header" , args -> IECallExt (" push_block_header" , args)
584622 | "push_int" , args -> IECallExt (" push_int" , args)
@@ -594,6 +632,7 @@ let rec transformExp (ctx : transform_ctx) (exp : exp) : iexp =
594632 | "deserialize_string" , args -> IECallExt (" deserialize_string" , args)
595633 | "search_type_description" , args -> IECallExt (" search_type_description" , args)
596634 | "first_array_element" , args -> IECallExt (" first_array_element" , args)
635+ | "get_array_count" , args -> IECallExt (" get_array_count" , args)
597636 | "next_object" , args -> IECallExt (" next_object" , args)
598637 (* Fall back to regular call for non-builtins *)
599638 | _ -> (
@@ -706,6 +745,7 @@ let rec evalConstantExpression (constants : dvalue array) (exp : iexp) : dvalue
706745 match exp with
707746 | IEUnit -> DVoid
708747 | IEEmptyValue -> DVoid
748+ | IEEmptyList _ -> DList (ref [] )
709749 | IEBool b -> DBool b
710750 | IEInt i -> DInt i
711751 | IEReal f -> DReal f
@@ -844,8 +884,11 @@ let rec defaultValue (typ : type_) : dvalue =
844884 | TTuple types -> DArray (Array. of_list (CCList. map defaultValue types))
845885 | TEmptyType -> DVoid
846886 | TArray (None, _ ) -> error " Cannot create default value for unsized array"
887+ | TList _ -> DList (ref [] )
847888
848889
890+ (* Empty mutable list *)
891+
849892(* Sets up a function call on the runtime stack and returns the frame start offset *)
850893let setupFunctionCall (stack : runtime_stack ) (ifunc : ifunc_def ) (args : dvalue list ) : int =
851894 let frame_start = stack.sp in
@@ -877,7 +920,17 @@ let getArrayElement (ctx : call_context) (arr : dvalue) (idx : dvalue) : dvalue
877920 ^ string_of_int (Array. length elems)
878921 ^ " index = "
879922 ^ string_of_int i)
880- | _ -> error_with_context ctx " getArrayElement: Invalid array access. This is not an array"
923+ | DList list_ref , DInt i -> (
924+ match CCList. nth_opt ! list_ref i with
925+ | Some v -> v
926+ | None ->
927+ error_with_context
928+ ctx
929+ (" getArrayElement: List index out of bounds. size = "
930+ ^ string_of_int (CCList. length ! list_ref)
931+ ^ " index = "
932+ ^ string_of_int i))
933+ | _ -> error_with_context ctx " getArrayElement: Invalid array access. This is not an array or list"
881934
882935
883936(* Retrieves a member from a struct using a member index *)
@@ -1084,7 +1137,17 @@ and assignIlvalue : call_context -> iprog -> runtime_stack -> int -> ilexp -> dv
10841137 let array_val = evalIlexpAsRvalue ctx prog stack frame_start e in
10851138 match array_val, idx_val with
10861139 | DArray arr , DInt i when i > = 0 && i < Array. length arr -> arr.(i) < - val_
1087- | _ -> error_with_context ctx " Invalid array assignment" )
1140+ | DList list_ref , DInt i ->
1141+ let old_list = ! list_ref in
1142+ let len = CCList. length old_list in
1143+ if i > = 0 && i < len then
1144+ let before, after = CCList. take_drop i old_list in
1145+ match after with
1146+ | _ :: rest -> list_ref := before @ [ val_ ] @ rest
1147+ | [] -> error_with_context ctx " List index out of bounds for assignment"
1148+ else
1149+ error_with_context ctx (" List index out of bounds: index = " ^ string_of_int i ^ " size = " ^ string_of_int len)
1150+ | _ -> error_with_context ctx " Invalid array or list assignment" )
10881151 | ILTuple lexps -> (
10891152 match val_ with
10901153 | DArray vals when Array. length vals = CCList. length lexps ->
@@ -1123,6 +1186,7 @@ and evalIexp (ctx : call_context) (prog : iprog) (stack : runtime_stack) (frame_
11231186 match exp with
11241187 | IEUnit -> DVoid
11251188 | IEEmptyValue -> DVoid
1189+ | IEEmptyList _ -> DList (ref [] )
11261190 | IEBool b -> DBool b
11271191 | IEInt i -> DInt i
11281192 | IEReal f -> DReal f
@@ -1390,6 +1454,89 @@ and evalIexp (ctx : call_context) (prog : iprog) (stack : runtime_stack) (frame_
13901454 match evalIexp ctx prog stack frame_start e with
13911455 | DString s -> DInt (String. length s)
13921456 | _ -> error_with_context ctx " Type mismatch in length - expected string" )
1457+ (* List functions *)
1458+ | IEBuiltinListSize e -> (
1459+ match evalIexp ctx prog stack frame_start e with
1460+ | DArray arr -> DInt (Array. length arr)
1461+ | DList list_ref -> DInt (CCList. length ! list_ref)
1462+ | _ -> error_with_context ctx " Type mismatch in list_size - expected list" )
1463+ | IEBuiltinListCapacity e -> (
1464+ (* Lists in the interpreter don't have a separate capacity, return size *)
1465+ match evalIexp ctx prog stack frame_start e with
1466+ | DArray arr -> DInt (Array. length arr)
1467+ | DList list_ref -> DInt (CCList. length ! list_ref)
1468+ | _ -> error_with_context ctx " Type mismatch in list_capacity - expected list" )
1469+ | IEBuiltinListAppend (l , v ) -> (
1470+ let list_val = evalIexp ctx prog stack frame_start l in
1471+ let new_val = evalIexp ctx prog stack frame_start v in
1472+ match list_val with
1473+ | DList list_ref ->
1474+ list_ref := ! list_ref @ [ new_val ];
1475+ DVoid
1476+ | _ -> error_with_context ctx " list_append requires list type" )
1477+ | IEBuiltinListInsert (l , i , v ) -> (
1478+ let list_val = evalIexp ctx prog stack frame_start l in
1479+ let idx = evalIexp ctx prog stack frame_start i in
1480+ let new_val = evalIexp ctx prog stack frame_start v in
1481+ match list_val, idx with
1482+ | DList list_ref , DInt index ->
1483+ let before, after = CCList. take_drop index ! list_ref in
1484+ list_ref := before @ [ new_val ] @ after;
1485+ DVoid
1486+ | _ -> error_with_context ctx " list_insert: invalid arguments" )
1487+ | IEBuiltinListRemove (l , i ) -> (
1488+ let list_val = evalIexp ctx prog stack frame_start l in
1489+ let idx = evalIexp ctx prog stack frame_start i in
1490+ match list_val, idx with
1491+ | DList list_ref , DInt index ->
1492+ let before, after = CCList. take_drop index ! list_ref in
1493+ list_ref := before @ CCList. drop 1 after;
1494+ DVoid
1495+ | _ -> error_with_context ctx " list_remove: invalid arguments" )
1496+ | IEBuiltinListClear l -> (
1497+ match evalIexp ctx prog stack frame_start l with
1498+ | DList list_ref ->
1499+ list_ref := [] ;
1500+ DVoid
1501+ | _ -> error_with_context ctx " list_clear requires list type" )
1502+ | IEBuiltinListReserve _ ->
1503+ (* Reserve is a hint, we can safely ignore it and return unit *)
1504+ DVoid
1505+ | IEBuiltinListGet (l , i ) -> (
1506+ let list_val = evalIexp ctx prog stack frame_start l in
1507+ let idx = evalIexp ctx prog stack frame_start i in
1508+ match list_val, idx with
1509+ | DList list_ref , DInt index -> (
1510+ match CCList. nth_opt ! list_ref index with
1511+ | Some v -> v
1512+ | None ->
1513+ error_with_context
1514+ ctx
1515+ (" list_get: index out of bounds. size = "
1516+ ^ string_of_int (CCList. length ! list_ref)
1517+ ^ " index = "
1518+ ^ string_of_int index))
1519+ | _ -> error_with_context ctx " list_get: invalid arguments" )
1520+ | IEBuiltinListSet (l , i , v ) -> (
1521+ let list_val = evalIexp ctx prog stack frame_start l in
1522+ let idx = evalIexp ctx prog stack frame_start i in
1523+ let new_val = evalIexp ctx prog stack frame_start v in
1524+ match list_val, idx with
1525+ | DList list_ref , DInt index ->
1526+ let old_list = ! list_ref in
1527+ let len = CCList. length old_list in
1528+ if index > = 0 && index < len then
1529+ let before, after = CCList. take_drop index old_list in
1530+ match after with
1531+ | _ :: rest ->
1532+ list_ref := before @ [ new_val ] @ rest;
1533+ DVoid
1534+ | [] -> error_with_context ctx " list_set: index out of bounds"
1535+ else
1536+ error_with_context
1537+ ctx
1538+ (" list_set: index out of bounds. size = " ^ string_of_int len ^ " index = " ^ string_of_int index)
1539+ | _ -> error_with_context ctx " list_set: invalid arguments" )
13931540 | IEIndex (e , index ) ->
13941541 let arr_val = evalIexp ctx prog stack frame_start e in
13951542 let idx_val = evalIexp ctx prog stack frame_start index in
0 commit comments