@@ -429,7 +429,7 @@ where
429
429
else {
430
430
panic ! ( )
431
431
} ;
432
- let buffer_size = buffer_size. as_integer ( ) ?;
432
+ let buffer_size = buffer_size. clone ( ) . unwrap_reference ( ) . as_integer ( ) ?;
433
433
434
434
let buffer_len = pkg_length - ( context. current_block . pc - start_pc) ;
435
435
let mut buffer = vec ! [ 0 ; buffer_size as usize ] ;
@@ -441,7 +441,7 @@ where
441
441
442
442
context. contribute_arg ( Argument :: Object ( Arc :: new ( Object :: Buffer ( buffer) ) ) ) ;
443
443
}
444
- Opcode :: Package => {
444
+ Opcode :: Package | Opcode :: VarPackage => {
445
445
let mut elements = Vec :: with_capacity ( op. expected_arguments ) ;
446
446
for arg in & op. arguments {
447
447
let Argument :: Object ( object) = arg else { panic ! ( ) } ;
@@ -766,13 +766,28 @@ where
766
766
*/
767
767
assert ! ( context. block_stack. len( ) > 0 ) ;
768
768
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...
772
769
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 )
774
771
{
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
+
776
791
for _ in 0 ..num_elements_left {
777
792
package_op. arguments . push ( Argument :: Object ( Arc :: new ( Object :: Uninitialized ) ) ) ;
778
793
}
@@ -908,7 +923,20 @@ where
908
923
context. start_in_flight_op ( OpInFlight :: new ( Opcode :: Package , num_elements as usize ) ) ;
909
924
context. start_new_block ( BlockKind :: Package , remaining_length) ;
910
925
}
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
+ }
912
940
Opcode :: Method => {
913
941
let start_pc = context. current_block . pc ;
914
942
let pkg_length = context. pkglength ( ) ?;
0 commit comments