Compare commits
	
		
			6 Commits
		
	
	
		
			nightly-v2
			...
			achalmers/
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 09dc17f994 | |||
| 4fa9eb4a0e | |||
| c2d3808f7c | |||
| e77c83a7b8 | |||
| 189099bce5 | |||
| 628310952f | 
| @ -17,7 +17,12 @@ pub enum EpBinding { | |||||||
|     /// A KCL value which gets stored in a particular address in KCEP memory. |     /// A KCL value which gets stored in a particular address in KCEP memory. | ||||||
|     Single(Address), |     Single(Address), | ||||||
|     /// A sequence of KCL values, indexed by their position in the sequence. |     /// A sequence of KCL values, indexed by their position in the sequence. | ||||||
|     Sequence(Vec<EpBinding>), |     Sequence { | ||||||
|  |         /// Address where the length of the array is stored. | ||||||
|  |         length_at: Address, | ||||||
|  |         /// Where is each element in the array bound? | ||||||
|  |         elements: Vec<EpBinding>, | ||||||
|  |     }, | ||||||
|     /// A sequence of KCL values, indexed by their identifier. |     /// A sequence of KCL values, indexed by their identifier. | ||||||
|     Map(HashMap<String, EpBinding>), |     Map(HashMap<String, EpBinding>), | ||||||
|     /// Not associated with a KCEP address. |     /// Not associated with a KCEP address. | ||||||
| @ -38,9 +43,11 @@ impl EpBinding { | |||||||
|             LiteralIdentifier::Literal(litval) => match litval.value { |             LiteralIdentifier::Literal(litval) => match litval.value { | ||||||
|                 // Arrays can be indexed by integers. |                 // Arrays can be indexed by integers. | ||||||
|                 LiteralValue::IInteger(i) => match self { |                 LiteralValue::IInteger(i) => match self { | ||||||
|                     EpBinding::Sequence(seq) => { |                     EpBinding::Sequence { length_at: _, elements } => { | ||||||
|                         let i = usize::try_from(i).map_err(|_| CompileError::InvalidIndex(i.to_string()))?; |                         let i = usize::try_from(i).map_err(|_| CompileError::InvalidIndex(i.to_string()))?; | ||||||
|                         seq.get(i).ok_or(CompileError::IndexOutOfBounds { i, len: seq.len() }) |                         elements | ||||||
|  |                             .get(i) | ||||||
|  |                             .ok_or(CompileError::IndexOutOfBounds { i, len: elements.len() }) | ||||||
|                     } |                     } | ||||||
|                     EpBinding::Map(_) => Err(CompileError::CannotIndex), |                     EpBinding::Map(_) => Err(CompileError::CannotIndex), | ||||||
|                     EpBinding::Single(_) => Err(CompileError::CannotIndex), |                     EpBinding::Single(_) => Err(CompileError::CannotIndex), | ||||||
| @ -50,7 +57,7 @@ impl EpBinding { | |||||||
|                 LiteralValue::String(property) => match self { |                 LiteralValue::String(property) => match self { | ||||||
|                     EpBinding::Single(_) => Err(CompileError::NoProperties), |                     EpBinding::Single(_) => Err(CompileError::NoProperties), | ||||||
|                     EpBinding::Function(_) => Err(CompileError::NoProperties), |                     EpBinding::Function(_) => Err(CompileError::NoProperties), | ||||||
|                     EpBinding::Sequence(_) => Err(CompileError::ArrayDoesNotHaveProperties), |                     EpBinding::Sequence { .. } => Err(CompileError::ArrayDoesNotHaveProperties), | ||||||
|                     EpBinding::Map(map) => map.get(&property).ok_or(CompileError::UndefinedProperty { property }), |                     EpBinding::Map(map) => map.get(&property).ok_or(CompileError::UndefinedProperty { property }), | ||||||
|                 }, |                 }, | ||||||
|                 // It's never valid to index by a fractional number. |                 // It's never valid to index by a fractional number. | ||||||
|  | |||||||
| @ -231,7 +231,7 @@ impl Planner { | |||||||
|                             binding: arg, |                             binding: arg, | ||||||
|                         } = match KclValueGroup::from(argument) { |                         } = match KclValueGroup::from(argument) { | ||||||
|                             KclValueGroup::Single(value) => self.plan_to_compute_single(ctx, value)?, |                             KclValueGroup::Single(value) => self.plan_to_compute_single(ctx, value)?, | ||||||
|                             KclValueGroup::ArrayExpression(_) => todo!(), |                             KclValueGroup::ArrayExpression(expr) => self.plan_to_bind_array(ctx, *expr)?, | ||||||
|                             KclValueGroup::ObjectExpression(_) => todo!(), |                             KclValueGroup::ObjectExpression(_) => todo!(), | ||||||
|                         }; |                         }; | ||||||
|                         acc_instrs.extend(new_instructions); |                         acc_instrs.extend(new_instructions); | ||||||
| @ -411,9 +411,9 @@ impl Planner { | |||||||
|             .declarations |             .declarations | ||||||
|             .into_iter() |             .into_iter() | ||||||
|             .try_fold(Vec::new(), |mut acc, declaration| { |             .try_fold(Vec::new(), |mut acc, declaration| { | ||||||
|                 let (instrs, binding) = self.plan_to_bind_one(&mut ctx, declaration.init)?; |                 let EvalPlan { instructions, binding } = self.plan_to_bind_one(&mut ctx, declaration.init)?; | ||||||
|                 self.binding_scope.bind(declaration.id.name, binding); |                 self.binding_scope.bind(declaration.id.name, binding); | ||||||
|                 acc.extend(instrs); |                 acc.extend(instructions); | ||||||
|                 Ok(acc) |                 Ok(acc) | ||||||
|             }) |             }) | ||||||
|     } |     } | ||||||
| @ -422,69 +422,14 @@ impl Planner { | |||||||
|         &mut self, |         &mut self, | ||||||
|         ctx: &mut Context, |         ctx: &mut Context, | ||||||
|         value_being_bound: ast::types::Value, |         value_being_bound: ast::types::Value, | ||||||
|     ) -> Result<(Vec<Instruction>, EpBinding), CompileError> { |     ) -> Result<EvalPlan, CompileError> { | ||||||
|         match KclValueGroup::from(value_being_bound) { |         match KclValueGroup::from(value_being_bound) { | ||||||
|             KclValueGroup::Single(init_value) => { |             KclValueGroup::Single(init_value) => { | ||||||
|                 // Simple! Just evaluate it, note where the final value will be stored in KCEP memory, |                 // Simple! Just evaluate it, note where the final value will be stored in KCEP memory, | ||||||
|                 // and bind it to the KCL identifier. |                 // and bind it to the KCL identifier. | ||||||
|                 let EvalPlan { instructions, binding } = self.plan_to_compute_single(ctx, init_value)?; |                 self.plan_to_compute_single(ctx, init_value) | ||||||
|                 Ok((instructions, binding)) |  | ||||||
|             } |  | ||||||
|             KclValueGroup::ArrayExpression(expr) => { |  | ||||||
|                 // First, emit a plan to compute each element of the array. |  | ||||||
|                 // Collect all the bindings from each element too. |  | ||||||
|                 let (instructions, bindings) = expr.elements.into_iter().try_fold( |  | ||||||
|                     (Vec::new(), Vec::new()), |  | ||||||
|                     |(mut acc_instrs, mut acc_bindings), element| { |  | ||||||
|                         match KclValueGroup::from(element) { |  | ||||||
|                             KclValueGroup::Single(value) => { |  | ||||||
|                                 // If this element of the array is a single value, then binding it is |  | ||||||
|                                 // straightforward -- you got a single binding, no need to change anything. |  | ||||||
|                                 let EvalPlan { instructions, binding } = self.plan_to_compute_single(ctx, value)?; |  | ||||||
|                                 acc_instrs.extend(instructions); |  | ||||||
|                                 acc_bindings.push(binding); |  | ||||||
|                             } |  | ||||||
|                             KclValueGroup::ArrayExpression(expr) => { |  | ||||||
|                                 // If this element of the array is _itself_ an array, then we need to |  | ||||||
|                                 // emit a plan to calculate each element of this child array. |  | ||||||
|                                 // Then we collect the child array's bindings, and bind them to one |  | ||||||
|                                 // element of the parent array. |  | ||||||
|                                 let binding = expr |  | ||||||
|                                     .elements |  | ||||||
|                                     .into_iter() |  | ||||||
|                                     .try_fold(Vec::new(), |mut seq, child_element| { |  | ||||||
|                                         let (instructions, binding) = self.plan_to_bind_one(ctx, child_element)?; |  | ||||||
|                                         acc_instrs.extend(instructions); |  | ||||||
|                                         seq.push(binding); |  | ||||||
|                                         Ok(seq) |  | ||||||
|                                     }) |  | ||||||
|                                     .map(EpBinding::Sequence)?; |  | ||||||
|                                 acc_bindings.push(binding); |  | ||||||
|                             } |  | ||||||
|                             KclValueGroup::ObjectExpression(expr) => { |  | ||||||
|                                 // If this element of the array is an object, then we need to |  | ||||||
|                                 // emit a plan to calculate each value of each property of the object. |  | ||||||
|                                 // Then we collect the bindings for each child value, and bind them to one |  | ||||||
|                                 // element of the parent array. |  | ||||||
|                                 let map = HashMap::with_capacity(expr.properties.len()); |  | ||||||
|                                 let binding = expr |  | ||||||
|                                     .properties |  | ||||||
|                                     .into_iter() |  | ||||||
|                                     .try_fold(map, |mut map, property| { |  | ||||||
|                                         let (instructions, binding) = self.plan_to_bind_one(ctx, property.value)?; |  | ||||||
|                                         map.insert(property.key.name, binding); |  | ||||||
|                                         acc_instrs.extend(instructions); |  | ||||||
|                                         Ok(map) |  | ||||||
|                                     }) |  | ||||||
|                                     .map(EpBinding::Map)?; |  | ||||||
|                                 acc_bindings.push(binding); |  | ||||||
|                             } |  | ||||||
|                         }; |  | ||||||
|                         Ok((acc_instrs, acc_bindings)) |  | ||||||
|                     }, |  | ||||||
|                 )?; |  | ||||||
|                 Ok((instructions, EpBinding::Sequence(bindings))) |  | ||||||
|             } |             } | ||||||
|  |             KclValueGroup::ArrayExpression(expr) => self.plan_to_bind_array(ctx, *expr), | ||||||
|             KclValueGroup::ObjectExpression(expr) => { |             KclValueGroup::ObjectExpression(expr) => { | ||||||
|                 // Convert the object to a sequence of key-value pairs. |                 // Convert the object to a sequence of key-value pairs. | ||||||
|                 let mut kvs = expr.properties.into_iter().map(|prop| (prop.key, prop.value)); |                 let mut kvs = expr.properties.into_iter().map(|prop| (prop.key, prop.value)); | ||||||
| @ -502,16 +447,22 @@ impl Planner { | |||||||
|                                 // each element of that array. Collect their bindings, and bind them all |                                 // each element of that array. Collect their bindings, and bind them all | ||||||
|                                 // under one property of the parent object. |                                 // under one property of the parent object. | ||||||
|                                 let n = expr.elements.len(); |                                 let n = expr.elements.len(); | ||||||
|  |                                 let length_at = self.next_addr.offset_by(1); | ||||||
|  |                                 acc_instrs.push(Instruction::SetPrimitive { | ||||||
|  |                                     address: length_at, | ||||||
|  |                                     value: n.into(), | ||||||
|  |                                 }); | ||||||
|                                 let binding = expr |                                 let binding = expr | ||||||
|                                     .elements |                                     .elements | ||||||
|                                     .into_iter() |                                     .into_iter() | ||||||
|                                     .try_fold(Vec::with_capacity(n), |mut seq, child_element| { |                                     .try_fold(Vec::with_capacity(n), |mut seq, child_element| { | ||||||
|                                         let (instructions, binding) = self.plan_to_bind_one(ctx, child_element)?; |                                         let EvalPlan { instructions, binding } = | ||||||
|  |                                             self.plan_to_bind_one(ctx, child_element)?; | ||||||
|                                         seq.push(binding); |                                         seq.push(binding); | ||||||
|                                         acc_instrs.extend(instructions); |                                         acc_instrs.extend(instructions); | ||||||
|                                         Ok(seq) |                                         Ok(seq) | ||||||
|                                     }) |                                     }) | ||||||
|                                     .map(EpBinding::Sequence)?; |                                     .map(|elements| EpBinding::Sequence { length_at, elements })?; | ||||||
|                                 acc_bindings.insert(key.name, binding); |                                 acc_bindings.insert(key.name, binding); | ||||||
|                             } |                             } | ||||||
|                             KclValueGroup::ObjectExpression(expr) => { |                             KclValueGroup::ObjectExpression(expr) => { | ||||||
| @ -524,7 +475,8 @@ impl Planner { | |||||||
|                                     .properties |                                     .properties | ||||||
|                                     .into_iter() |                                     .into_iter() | ||||||
|                                     .try_fold(HashMap::with_capacity(n), |mut map, property| { |                                     .try_fold(HashMap::with_capacity(n), |mut map, property| { | ||||||
|                                         let (instructions, binding) = self.plan_to_bind_one(ctx, property.value)?; |                                         let EvalPlan { instructions, binding } = | ||||||
|  |                                             self.plan_to_bind_one(ctx, property.value)?; | ||||||
|                                         map.insert(property.key.name, binding); |                                         map.insert(property.key.name, binding); | ||||||
|                                         acc_instrs.extend(instructions); |                                         acc_instrs.extend(instructions); | ||||||
|                                         Ok(map) |                                         Ok(map) | ||||||
| @ -536,10 +488,90 @@ impl Planner { | |||||||
|                         Ok((acc_instrs, acc_bindings)) |                         Ok((acc_instrs, acc_bindings)) | ||||||
|                     }, |                     }, | ||||||
|                 )?; |                 )?; | ||||||
|                 Ok((instructions, EpBinding::Map(each_property_binding))) |                 Ok(EvalPlan { | ||||||
|  |                     instructions, | ||||||
|  |                     binding: EpBinding::Map(each_property_binding), | ||||||
|  |                 }) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fn plan_to_bind_array( | ||||||
|  |         &mut self, | ||||||
|  |         ctx: &mut Context, | ||||||
|  |         expr: ast::types::ArrayExpression, | ||||||
|  |     ) -> Result<EvalPlan, CompileError> { | ||||||
|  |         let length_at = self.next_addr.offset_by(1); | ||||||
|  |         let mut instructions = vec![Instruction::SetPrimitive { | ||||||
|  |             address: length_at, | ||||||
|  |             value: expr.elements.len().into(), | ||||||
|  |         }]; | ||||||
|  |         // First, emit a plan to compute each element of the array. | ||||||
|  |         // Collect all the bindings from each element too. | ||||||
|  |         let (instrs, bindings) = expr.elements.into_iter().try_fold( | ||||||
|  |             (Vec::new(), Vec::new()), | ||||||
|  |             |(mut acc_instrs, mut acc_bindings), element| { | ||||||
|  |                 match KclValueGroup::from(element) { | ||||||
|  |                     KclValueGroup::Single(value) => { | ||||||
|  |                         // If this element of the array is a single value, then binding it is | ||||||
|  |                         // straightforward -- you got a single binding, no need to change anything. | ||||||
|  |                         let EvalPlan { instructions, binding } = self.plan_to_compute_single(ctx, value)?; | ||||||
|  |                         acc_instrs.extend(instructions); | ||||||
|  |                         acc_bindings.push(binding); | ||||||
|  |                     } | ||||||
|  |                     KclValueGroup::ArrayExpression(expr) => { | ||||||
|  |                         // If this element of the array is _itself_ an array, then we need to | ||||||
|  |                         // emit a plan to calculate each element of this child array. | ||||||
|  |                         // Then we collect the child array's bindings, and bind them to one | ||||||
|  |                         // element of the parent array. | ||||||
|  |                         let length_at = self.next_addr.offset_by(1); | ||||||
|  |                         acc_instrs.push(Instruction::SetPrimitive { | ||||||
|  |                             address: length_at, | ||||||
|  |                             value: expr.elements.len().into(), | ||||||
|  |                         }); | ||||||
|  |                         let binding = expr | ||||||
|  |                             .elements | ||||||
|  |                             .into_iter() | ||||||
|  |                             .try_fold(Vec::new(), |mut seq, child_element| { | ||||||
|  |                                 let EvalPlan { instructions, binding } = self.plan_to_bind_one(ctx, child_element)?; | ||||||
|  |                                 acc_instrs.extend(instructions); | ||||||
|  |                                 seq.push(binding); | ||||||
|  |                                 Ok(seq) | ||||||
|  |                             }) | ||||||
|  |                             .map(|elements| EpBinding::Sequence { length_at, elements })?; | ||||||
|  |                         acc_bindings.push(binding); | ||||||
|  |                     } | ||||||
|  |                     KclValueGroup::ObjectExpression(expr) => { | ||||||
|  |                         // If this element of the array is an object, then we need to | ||||||
|  |                         // emit a plan to calculate each value of each property of the object. | ||||||
|  |                         // Then we collect the bindings for each child value, and bind them to one | ||||||
|  |                         // element of the parent array. | ||||||
|  |                         let map = HashMap::with_capacity(expr.properties.len()); | ||||||
|  |                         let binding = expr | ||||||
|  |                             .properties | ||||||
|  |                             .into_iter() | ||||||
|  |                             .try_fold(map, |mut map, property| { | ||||||
|  |                                 let EvalPlan { instructions, binding } = self.plan_to_bind_one(ctx, property.value)?; | ||||||
|  |                                 map.insert(property.key.name, binding); | ||||||
|  |                                 acc_instrs.extend(instructions); | ||||||
|  |                                 Ok(map) | ||||||
|  |                             }) | ||||||
|  |                             .map(EpBinding::Map)?; | ||||||
|  |                         acc_bindings.push(binding); | ||||||
|  |                     } | ||||||
|  |                 }; | ||||||
|  |                 Ok((acc_instrs, acc_bindings)) | ||||||
|  |             }, | ||||||
|  |         )?; | ||||||
|  |         instructions.extend(instrs); | ||||||
|  |         Ok(EvalPlan { | ||||||
|  |             instructions, | ||||||
|  |             binding: EpBinding::Sequence { | ||||||
|  |                 length_at, | ||||||
|  |                 elements: bindings, | ||||||
|  |             }, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Every KCL literal value is equivalent to an Execution Plan value, and therefore can be | /// Every KCL literal value is equivalent to an Execution Plan value, and therefore can be | ||||||
|  | |||||||
| @ -48,16 +48,22 @@ fn bind_array() { | |||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         plan, |         plan, | ||||||
|         vec![ |         vec![ | ||||||
|  |             // Arrays start with the length. | ||||||
|             Instruction::SetPrimitive { |             Instruction::SetPrimitive { | ||||||
|                 address: Address::ZERO, |                 address: Address::ZERO, | ||||||
|  |                 value: 3usize.into(), | ||||||
|  |             }, | ||||||
|  |             // Then the elements follow. | ||||||
|  |             Instruction::SetPrimitive { | ||||||
|  |                 address: Address::ZERO + 1, | ||||||
|                 value: 44i64.into(), |                 value: 44i64.into(), | ||||||
|             }, |             }, | ||||||
|             Instruction::SetPrimitive { |             Instruction::SetPrimitive { | ||||||
|                 address: Address::ZERO.offset(1), |                 address: Address::ZERO + 2, | ||||||
|                 value: 55i64.into(), |                 value: 55i64.into(), | ||||||
|             }, |             }, | ||||||
|             Instruction::SetPrimitive { |             Instruction::SetPrimitive { | ||||||
|                 address: Address::ZERO.offset(2), |                 address: Address::ZERO + 3, | ||||||
|                 value: "sixty-six".to_owned().into(), |                 value: "sixty-six".to_owned().into(), | ||||||
|             } |             } | ||||||
|         ] |         ] | ||||||
| @ -73,14 +79,22 @@ fn bind_nested_array() { | |||||||
|         vec![ |         vec![ | ||||||
|             Instruction::SetPrimitive { |             Instruction::SetPrimitive { | ||||||
|                 address: Address::ZERO, |                 address: Address::ZERO, | ||||||
|  |                 value: 2usize.into(), | ||||||
|  |             }, | ||||||
|  |             Instruction::SetPrimitive { | ||||||
|  |                 address: Address::ZERO + 1, | ||||||
|                 value: 44i64.into(), |                 value: 44i64.into(), | ||||||
|             }, |             }, | ||||||
|             Instruction::SetPrimitive { |             Instruction::SetPrimitive { | ||||||
|                 address: Address::ZERO.offset(1), |                 address: Address::ZERO + 2, | ||||||
|  |                 value: 2usize.into(), | ||||||
|  |             }, | ||||||
|  |             Instruction::SetPrimitive { | ||||||
|  |                 address: Address::ZERO + 3, | ||||||
|                 value: 55i64.into(), |                 value: 55i64.into(), | ||||||
|             }, |             }, | ||||||
|             Instruction::SetPrimitive { |             Instruction::SetPrimitive { | ||||||
|                 address: Address::ZERO.offset(2), |                 address: Address::ZERO + 4, | ||||||
|                 value: "sixty-six".to_owned().into(), |                 value: "sixty-six".to_owned().into(), | ||||||
|             } |             } | ||||||
|         ] |         ] | ||||||
| @ -96,14 +110,18 @@ fn bind_arrays_with_objects_elements() { | |||||||
|         vec![ |         vec![ | ||||||
|             Instruction::SetPrimitive { |             Instruction::SetPrimitive { | ||||||
|                 address: Address::ZERO, |                 address: Address::ZERO, | ||||||
|  |                 value: 2usize.into() | ||||||
|  |             }, | ||||||
|  |             Instruction::SetPrimitive { | ||||||
|  |                 address: Address::ZERO + 1, | ||||||
|                 value: 44i64.into(), |                 value: 44i64.into(), | ||||||
|             }, |             }, | ||||||
|             Instruction::SetPrimitive { |             Instruction::SetPrimitive { | ||||||
|                 address: Address::ZERO.offset(1), |                 address: Address::ZERO + 2, | ||||||
|                 value: 55i64.into(), |                 value: 55i64.into(), | ||||||
|             }, |             }, | ||||||
|             Instruction::SetPrimitive { |             Instruction::SetPrimitive { | ||||||
|                 address: Address::ZERO.offset(2), |                 address: Address::ZERO + 3, | ||||||
|                 value: "sixty-six".to_owned().into(), |                 value: "sixty-six".to_owned().into(), | ||||||
|             } |             } | ||||||
|         ] |         ] | ||||||
| @ -187,6 +205,45 @@ fn use_native_function_add() { | |||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[test] | ||||||
|  | fn arrays_as_parameters() { | ||||||
|  |     let program = "fn identity = (x) => { return x } | ||||||
|  |     let array = identity([1,2,3])"; | ||||||
|  |     let (plan, scope) = must_plan(program); | ||||||
|  |     let expected_plan = vec![ | ||||||
|  |         // Array length | ||||||
|  |         Instruction::SetPrimitive { | ||||||
|  |             address: Address::ZERO, | ||||||
|  |             value: 3usize.into(), | ||||||
|  |         }, | ||||||
|  |         // Array contents | ||||||
|  |         Instruction::SetPrimitive { | ||||||
|  |             address: Address::ZERO + 1, | ||||||
|  |             value: 1i64.into(), | ||||||
|  |         }, | ||||||
|  |         Instruction::SetPrimitive { | ||||||
|  |             address: Address::ZERO + 2, | ||||||
|  |             value: 2i64.into(), | ||||||
|  |         }, | ||||||
|  |         Instruction::SetPrimitive { | ||||||
|  |             address: Address::ZERO + 3, | ||||||
|  |             value: 3i64.into(), | ||||||
|  |         }, | ||||||
|  |     ]; | ||||||
|  |     assert_eq!(plan, expected_plan); | ||||||
|  |     assert_eq!( | ||||||
|  |         scope.get("array").unwrap(), | ||||||
|  |         &EpBinding::Sequence { | ||||||
|  |             length_at: Address::ZERO, | ||||||
|  |             elements: vec![ | ||||||
|  |                 EpBinding::Single(Address::ZERO + 1), | ||||||
|  |                 EpBinding::Single(Address::ZERO + 2), | ||||||
|  |                 EpBinding::Single(Address::ZERO + 3), | ||||||
|  |             ] | ||||||
|  |         } | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  |  | ||||||
| #[test] | #[test] | ||||||
| fn use_native_function_id() { | fn use_native_function_id() { | ||||||
|     let program = "let x = id(2)"; |     let program = "let x = id(2)"; | ||||||
| @ -265,7 +322,7 @@ fn member_expressions_array() { | |||||||
|     let (_plan, scope) = must_plan(program); |     let (_plan, scope) = must_plan(program); | ||||||
|     match scope.get("first").unwrap() { |     match scope.get("first").unwrap() { | ||||||
|         EpBinding::Single(addr) => { |         EpBinding::Single(addr) => { | ||||||
|             assert_eq!(*addr, Address::ZERO); |             assert_eq!(*addr, Address::ZERO + 2); | ||||||
|         } |         } | ||||||
|         other => { |         other => { | ||||||
|             panic!("expected 'number' bound to 0x0 but it was bound to {other:?}"); |             panic!("expected 'number' bound to 0x0 but it was bound to {other:?}"); | ||||||
| @ -273,7 +330,7 @@ fn member_expressions_array() { | |||||||
|     } |     } | ||||||
|     match scope.get("last").unwrap() { |     match scope.get("last").unwrap() { | ||||||
|         EpBinding::Single(addr) => { |         EpBinding::Single(addr) => { | ||||||
|             assert_eq!(*addr, Address::ZERO + 3); |             assert_eq!(*addr, Address::ZERO + 6); | ||||||
|         } |         } | ||||||
|         other => { |         other => { | ||||||
|             panic!("expected 'number' bound to 0x3 but it was bound to {other:?}"); |             panic!("expected 'number' bound to 0x3 but it was bound to {other:?}"); | ||||||
| @ -682,14 +739,11 @@ fn store_object() { | |||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         bindings.get("x0").unwrap(), |         bindings.get("x0").unwrap(), | ||||||
|         &EpBinding::Map(HashMap::from([ |         &EpBinding::Map(HashMap::from([ | ||||||
|             ("a".to_owned(), EpBinding::Single(Address::ZERO),), |             ("a".to_owned(), EpBinding::Single(Address::ZERO)), | ||||||
|             ("b".to_owned(), EpBinding::Single(Address::ZERO.offset(1))), |             ("b".to_owned(), EpBinding::Single(Address::ZERO + 1)), | ||||||
|             ( |             ( | ||||||
|                 "c".to_owned(), |                 "c".to_owned(), | ||||||
|                 EpBinding::Map(HashMap::from([( |                 EpBinding::Map(HashMap::from([("d".to_owned(), EpBinding::Single(Address::ZERO + 2))])) | ||||||
|                     "d".to_owned(), |  | ||||||
|                     EpBinding::Single(Address::ZERO.offset(2)) |  | ||||||
|                 )])) |  | ||||||
|             ), |             ), | ||||||
|         ])) |         ])) | ||||||
|     ) |     ) | ||||||
| @ -697,7 +751,7 @@ fn store_object() { | |||||||
|  |  | ||||||
| #[test] | #[test] | ||||||
| fn store_object_with_array_property() { | fn store_object_with_array_property() { | ||||||
|     let program = "const x0 = {a: 1, b: [2, 3]}"; |     let program = "const x0 = {a: 1, b: [22, 33]}"; | ||||||
|     let (actual, bindings) = must_plan(program); |     let (actual, bindings) = must_plan(program); | ||||||
|     let expected = vec![ |     let expected = vec![ | ||||||
|         Instruction::SetPrimitive { |         Instruction::SetPrimitive { | ||||||
| @ -705,12 +759,16 @@ fn store_object_with_array_property() { | |||||||
|             value: 1i64.into(), |             value: 1i64.into(), | ||||||
|         }, |         }, | ||||||
|         Instruction::SetPrimitive { |         Instruction::SetPrimitive { | ||||||
|             address: Address::ZERO.offset(1), |             address: Address::ZERO + 1, | ||||||
|             value: 2i64.into(), |             value: 2usize.into(), | ||||||
|         }, |         }, | ||||||
|         Instruction::SetPrimitive { |         Instruction::SetPrimitive { | ||||||
|             address: Address::ZERO.offset(2), |             address: Address::ZERO + 2, | ||||||
|             value: 3i64.into(), |             value: 22i64.into(), | ||||||
|  |         }, | ||||||
|  |         Instruction::SetPrimitive { | ||||||
|  |             address: Address::ZERO + 3, | ||||||
|  |             value: 33i64.into(), | ||||||
|         }, |         }, | ||||||
|     ]; |     ]; | ||||||
|     assert_eq!(actual, expected); |     assert_eq!(actual, expected); | ||||||
| @ -721,10 +779,13 @@ fn store_object_with_array_property() { | |||||||
|             ("a".to_owned(), EpBinding::Single(Address::ZERO),), |             ("a".to_owned(), EpBinding::Single(Address::ZERO),), | ||||||
|             ( |             ( | ||||||
|                 "b".to_owned(), |                 "b".to_owned(), | ||||||
|                 EpBinding::Sequence(vec![ |                 EpBinding::Sequence { | ||||||
|                     EpBinding::Single(Address::ZERO.offset(1)), |                     length_at: Address::ZERO.offset(1), | ||||||
|                     EpBinding::Single(Address::ZERO.offset(2)), |                     elements: vec![ | ||||||
|                 ]) |                         EpBinding::Single(Address::ZERO.offset(2)), | ||||||
|  |                         EpBinding::Single(Address::ZERO.offset(3)), | ||||||
|  |                     ] | ||||||
|  |                 } | ||||||
|             ), |             ), | ||||||
|         ])) |         ])) | ||||||
|     ) |     ) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	