@@ -429,7 +429,7 @@ where
429429 else {
430430 panic ! ( )
431431 } ;
432- let buffer_size = buffer_size. as_integer ( ) ?;
432+ let buffer_size = buffer_size. clone ( ) . unwrap_reference ( ) . as_integer ( ) ?;
433433
434434 let buffer_len = pkg_length - ( context. current_block . pc - start_pc) ;
435435 let mut buffer = vec ! [ 0 ; buffer_size as usize ] ;
@@ -441,7 +441,7 @@ where
441441
442442 context. contribute_arg ( Argument :: Object ( Arc :: new ( Object :: Buffer ( buffer) ) ) ) ;
443443 }
444- Opcode :: Package => {
444+ Opcode :: Package | Opcode :: VarPackage => {
445445 let mut elements = Vec :: with_capacity ( op. expected_arguments ) ;
446446 for arg in & op. arguments {
447447 let Argument :: Object ( object) = arg else { panic ! ( ) } ;
@@ -766,13 +766,28 @@ where
766766 */
767767 assert ! ( context. block_stack. len( ) > 0 ) ;
768768
769- // TODO: I think we can handle VarPackage here as well because by the
770- // time the block finishes, the first arg should be resolvable (the var
771- // length) and so can be updated here...
772769 if let Some ( package_op) = context. in_flight . last_mut ( )
773- && package_op. op == Opcode :: Package
770+ && ( package_op. op == Opcode :: Package || package_op . op == Opcode :: VarPackage )
774771 {
775- let num_elements_left = package_op. expected_arguments - package_op. arguments . len ( ) ;
772+ let num_elements_left = match package_op. op {
773+ Opcode :: Package => package_op. expected_arguments - package_op. arguments . len ( ) ,
774+ Opcode :: VarPackage => {
775+ let Argument :: Object ( total_elements) = & package_op. arguments [ 0 ] else {
776+ panic ! ( )
777+ } ;
778+ let total_elements =
779+ total_elements. clone ( ) . unwrap_reference ( ) . as_integer ( ) ? as usize ;
780+
781+ // Update the expected number of arguments to terminate the in-flight op
782+ package_op. expected_arguments = total_elements;
783+
784+ total_elements - package_op. arguments . len ( )
785+ }
786+ _ => panic ! (
787+ "Current in-flight op is not a `Package` or `VarPackage` when finished parsing package block"
788+ ) ,
789+ } ;
790+
776791 for _ in 0 ..num_elements_left {
777792 package_op. arguments . push ( Argument :: Object ( Arc :: new ( Object :: Uninitialized ) ) ) ;
778793 }
@@ -908,7 +923,20 @@ where
908923 context. start_in_flight_op ( OpInFlight :: new ( Opcode :: Package , num_elements as usize ) ) ;
909924 context. start_new_block ( BlockKind :: Package , remaining_length) ;
910925 }
911- Opcode :: VarPackage => todo ! ( ) ,
926+ Opcode :: VarPackage => {
927+ let start_pc = context. current_block . pc ;
928+ let pkg_length = context. pkglength ( ) ?;
929+ let remaining_length = pkg_length - ( context. current_block . pc - start_pc) ;
930+
931+ /*
932+ * For variable packages, we're first going to parse a `TermArg` that encodes,
933+ * dynamically, how many elements the package will have. We then accept as many
934+ * elements as remain in the block, and we'll sort out how many are supposed to
935+ * be in the package later.
936+ */
937+ context. start_in_flight_op ( OpInFlight :: new ( Opcode :: VarPackage , usize:: MAX ) ) ;
938+ context. start_new_block ( BlockKind :: Package , remaining_length) ;
939+ }
912940 Opcode :: Method => {
913941 let start_pc = context. current_block . pc ;
914942 let pkg_length = context. pkglength ( ) ?;
0 commit comments