Compare commits
	
		
			1 Commits
		
	
	
		
			franknoiro
			...
			achalmers/
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7711bf768c | 
| @ -918,165 +918,193 @@ impl Node<MemberExpression> { | |||||||
| impl Node<BinaryExpression> { | impl Node<BinaryExpression> { | ||||||
|     #[async_recursion] |     #[async_recursion] | ||||||
|     pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> { |     pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> { | ||||||
|         let left_value = self.left.get_result(exec_state, ctx).await?; |         let mut partial = self.right.get_result(exec_state, ctx).await?; | ||||||
|         let right_value = self.right.get_result(exec_state, ctx).await?; |         let mut next = &self.left; | ||||||
|         let mut meta = left_value.metadata(); |         let source_range = self.into(); | ||||||
|         meta.extend(right_value.metadata()); |         // Don't recurse through a big chain of binary operations, iterate instead. | ||||||
|  |         while let BinaryPart::BinaryExpression(next_binary_expr) = next { | ||||||
|         // First check if we are doing string concatenation. |             let metadata = partial.metadata(); | ||||||
|         if self.operator == BinaryOperator::Add { |             partial = do_binary_op( | ||||||
|             if let (KclValue::String { value: left, meta: _ }, KclValue::String { value: right, meta: _ }) = |                 partial, | ||||||
|                 (&left_value, &right_value) |                 next_binary_expr.right.get_result(exec_state, ctx).await?, | ||||||
|             { |                 next_binary_expr.operator, | ||||||
|                 return Ok(KclValue::String { |                 metadata, | ||||||
|                     value: format!("{}{}", left, right), |                 source_range, | ||||||
|                     meta, |                 exec_state, | ||||||
|                 }); |                 ctx, | ||||||
|             } |             ) | ||||||
|  |             .await?; | ||||||
|  |             next = &next_binary_expr.left; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Then check if we have solids. |         let next_value = next.get_result(exec_state, ctx).await?; | ||||||
|         if self.operator == BinaryOperator::Add || self.operator == BinaryOperator::Or { |         let mut meta = partial.metadata(); | ||||||
|             if let (KclValue::Solid { value: left }, KclValue::Solid { value: right }) = (&left_value, &right_value) { |         meta.extend(next_value.metadata()); | ||||||
|                 let args = crate::std::Args::new(Default::default(), self.into(), ctx.clone(), None); |  | ||||||
|                 let result = |  | ||||||
|                     crate::std::csg::inner_union(vec![*left.clone(), *right.clone()], exec_state, args).await?; |  | ||||||
|                 return Ok(result.into()); |  | ||||||
|             } |  | ||||||
|         } else if self.operator == BinaryOperator::Sub { |  | ||||||
|             // Check if we have solids. |  | ||||||
|             if let (KclValue::Solid { value: left }, KclValue::Solid { value: right }) = (&left_value, &right_value) { |  | ||||||
|                 let args = crate::std::Args::new(Default::default(), self.into(), ctx.clone(), None); |  | ||||||
|                 let result = |  | ||||||
|                     crate::std::csg::inner_subtract(vec![*left.clone()], vec![*right.clone()], exec_state, args) |  | ||||||
|                         .await?; |  | ||||||
|                 return Ok(result.into()); |  | ||||||
|             } |  | ||||||
|         } else if self.operator == BinaryOperator::And { |  | ||||||
|             // Check if we have solids. |  | ||||||
|             if let (KclValue::Solid { value: left }, KclValue::Solid { value: right }) = (&left_value, &right_value) { |  | ||||||
|                 let args = crate::std::Args::new(Default::default(), self.into(), ctx.clone(), None); |  | ||||||
|                 let result = |  | ||||||
|                     crate::std::csg::inner_intersect(vec![*left.clone(), *right.clone()], exec_state, args).await?; |  | ||||||
|                 return Ok(result.into()); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // Check if we are doing logical operations on booleans. |  | ||||||
|         if self.operator == BinaryOperator::Or || self.operator == BinaryOperator::And { |  | ||||||
|             let KclValue::Bool { |  | ||||||
|                 value: left_value, |  | ||||||
|                 meta: _, |  | ||||||
|             } = left_value |  | ||||||
|             else { |  | ||||||
|                 return Err(KclError::Semantic(KclErrorDetails { |  | ||||||
|                     message: format!( |  | ||||||
|                         "Cannot apply logical operator to non-boolean value: {}", |  | ||||||
|                         left_value.human_friendly_type() |  | ||||||
|                     ), |  | ||||||
|                     source_ranges: vec![self.left.clone().into()], |  | ||||||
|                 })); |  | ||||||
|             }; |  | ||||||
|             let KclValue::Bool { |  | ||||||
|                 value: right_value, |  | ||||||
|                 meta: _, |  | ||||||
|             } = right_value |  | ||||||
|             else { |  | ||||||
|                 return Err(KclError::Semantic(KclErrorDetails { |  | ||||||
|                     message: format!( |  | ||||||
|                         "Cannot apply logical operator to non-boolean value: {}", |  | ||||||
|                         right_value.human_friendly_type() |  | ||||||
|                     ), |  | ||||||
|                     source_ranges: vec![self.right.clone().into()], |  | ||||||
|                 })); |  | ||||||
|             }; |  | ||||||
|             let raw_value = match self.operator { |  | ||||||
|                 BinaryOperator::Or => left_value || right_value, |  | ||||||
|                 BinaryOperator::And => left_value && right_value, |  | ||||||
|                 _ => unreachable!(), |  | ||||||
|             }; |  | ||||||
|             return Ok(KclValue::Bool { value: raw_value, meta }); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         let left = number_as_f64(&left_value, self.left.clone().into())?; |  | ||||||
|         let right = number_as_f64(&right_value, self.right.clone().into())?; |  | ||||||
|  |  | ||||||
|         let value = match self.operator { |  | ||||||
|             BinaryOperator::Add => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_eq(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Adding", exec_state); |  | ||||||
|                 KclValue::Number { value: l + r, meta, ty } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::Sub => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_eq(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Subtracting", exec_state); |  | ||||||
|                 KclValue::Number { value: l - r, meta, ty } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::Mul => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_mul(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Multiplying", exec_state); |  | ||||||
|                 KclValue::Number { value: l * r, meta, ty } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::Div => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_div(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Dividing", exec_state); |  | ||||||
|                 KclValue::Number { value: l / r, meta, ty } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::Mod => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_div(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Modulo of", exec_state); |  | ||||||
|                 KclValue::Number { value: l % r, meta, ty } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::Pow => KclValue::Number { |  | ||||||
|                 value: left.n.powf(right.n), |  | ||||||
|                 meta, |  | ||||||
|                 ty: NumericType::Unknown, |  | ||||||
|             }, |  | ||||||
|             BinaryOperator::Neq => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_eq(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Comparing", exec_state); |  | ||||||
|                 KclValue::Bool { value: l != r, meta } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::Gt => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_eq(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Comparing", exec_state); |  | ||||||
|                 KclValue::Bool { value: l > r, meta } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::Gte => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_eq(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Comparing", exec_state); |  | ||||||
|                 KclValue::Bool { value: l >= r, meta } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::Lt => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_eq(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Comparing", exec_state); |  | ||||||
|                 KclValue::Bool { value: l < r, meta } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::Lte => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_eq(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Comparing", exec_state); |  | ||||||
|                 KclValue::Bool { value: l <= r, meta } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::Eq => { |  | ||||||
|                 let (l, r, ty) = NumericType::combine_eq(left, right); |  | ||||||
|                 self.warn_on_unknown(&ty, "Comparing", exec_state); |  | ||||||
|                 KclValue::Bool { value: l == r, meta } |  | ||||||
|             } |  | ||||||
|             BinaryOperator::And | BinaryOperator::Or => unreachable!(), |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|  |         let value = do_binary_op(partial, next_value, self.operator, meta, self.into(), exec_state, ctx).await?; | ||||||
|         Ok(value) |         Ok(value) | ||||||
|     } |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|     fn warn_on_unknown(&self, ty: &NumericType, verb: &str, exec_state: &mut ExecState) { | fn warn_on_unknown(source_range: SourceRange, ty: &NumericType, verb: &str, exec_state: &mut ExecState) { | ||||||
|         if *CHECK_NUMERIC_TYPES && ty == &NumericType::Unknown { |     if *CHECK_NUMERIC_TYPES && ty == &NumericType::Unknown { | ||||||
|             // TODO suggest how to fix this |         // TODO suggest how to fix this | ||||||
|             exec_state.warn(CompilationError::err( |         exec_state.warn(CompilationError::err( | ||||||
|                 self.as_source_range(), |             source_range, | ||||||
|                 format!("{} numbers which have unknown or incompatible units.", verb), |             format!("{} numbers which have unknown or incompatible units.", verb), | ||||||
|             )); |         )); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async fn do_binary_op( | ||||||
|  |     left_value: KclValue, | ||||||
|  |     right_value: KclValue, | ||||||
|  |     operator: BinaryOperator, | ||||||
|  |     meta: Vec<Metadata>, | ||||||
|  |     source_range: SourceRange, | ||||||
|  |     exec_state: &mut ExecState, | ||||||
|  |     ctx: &ExecutorContext, | ||||||
|  | ) -> Result<KclValue, KclError> { | ||||||
|  |     // First check if we are doing string concatenation. | ||||||
|  |     if operator == BinaryOperator::Add { | ||||||
|  |         if let (KclValue::String { value: left, meta: _ }, KclValue::String { value: right, meta: _ }) = | ||||||
|  |             (&left_value, &right_value) | ||||||
|  |         { | ||||||
|  |             return Ok(KclValue::String { | ||||||
|  |                 value: format!("{}{}", left, right), | ||||||
|  |                 meta, | ||||||
|  |             }); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Then check if we have solids. | ||||||
|  |     if operator == BinaryOperator::Add || operator == BinaryOperator::Or { | ||||||
|  |         if let (KclValue::Solid { value: left }, KclValue::Solid { value: right }) = (&left_value, &right_value) { | ||||||
|  |             let args = crate::std::Args::new(Default::default(), source_range, ctx.clone(), None); | ||||||
|  |             let result = crate::std::csg::inner_union(vec![*left.clone(), *right.clone()], exec_state, args).await?; | ||||||
|  |             return Ok(result.into()); | ||||||
|  |         } | ||||||
|  |     } else if operator == BinaryOperator::Sub { | ||||||
|  |         // Check if we have solids. | ||||||
|  |         if let (KclValue::Solid { value: left }, KclValue::Solid { value: right }) = (&left_value, &right_value) { | ||||||
|  |             let args = crate::std::Args::new(Default::default(), source_range, ctx.clone(), None); | ||||||
|  |             let result = | ||||||
|  |                 crate::std::csg::inner_subtract(vec![*left.clone()], vec![*right.clone()], exec_state, args).await?; | ||||||
|  |             return Ok(result.into()); | ||||||
|  |         } | ||||||
|  |     } else if operator == BinaryOperator::And { | ||||||
|  |         // Check if we have solids. | ||||||
|  |         if let (KclValue::Solid { value: left }, KclValue::Solid { value: right }) = (&left_value, &right_value) { | ||||||
|  |             let args = crate::std::Args::new(Default::default(), source_range, ctx.clone(), None); | ||||||
|  |             let result = | ||||||
|  |                 crate::std::csg::inner_intersect(vec![*left.clone(), *right.clone()], exec_state, args).await?; | ||||||
|  |             return Ok(result.into()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Check if we are doing logical operations on booleans. | ||||||
|  |     if operator == BinaryOperator::Or || operator == BinaryOperator::And { | ||||||
|  |         let KclValue::Bool { | ||||||
|  |             value: left_value, | ||||||
|  |             meta: _, | ||||||
|  |         } = left_value | ||||||
|  |         else { | ||||||
|  |             return Err(KclError::Semantic(KclErrorDetails { | ||||||
|  |                 message: format!( | ||||||
|  |                     "Cannot apply logical operator to non-boolean value: {}", | ||||||
|  |                     left_value.human_friendly_type() | ||||||
|  |                 ), | ||||||
|  |                 source_ranges: left_value.into(), | ||||||
|  |             })); | ||||||
|  |         }; | ||||||
|  |         let KclValue::Bool { | ||||||
|  |             value: right_value, | ||||||
|  |             meta: _, | ||||||
|  |         } = right_value | ||||||
|  |         else { | ||||||
|  |             return Err(KclError::Semantic(KclErrorDetails { | ||||||
|  |                 message: format!( | ||||||
|  |                     "Cannot apply logical operator to non-boolean value: {}", | ||||||
|  |                     right_value.human_friendly_type() | ||||||
|  |                 ), | ||||||
|  |                 source_ranges: right_value.into(), | ||||||
|  |             })); | ||||||
|  |         }; | ||||||
|  |         let raw_value = match operator { | ||||||
|  |             BinaryOperator::Or => left_value || right_value, | ||||||
|  |             BinaryOperator::And => left_value && right_value, | ||||||
|  |             _ => unreachable!(), | ||||||
|  |         }; | ||||||
|  |         return Ok(KclValue::Bool { value: raw_value, meta }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     let left = number_as_f64(&left_value, (&left_value).into())?; | ||||||
|  |     let right = number_as_f64(&right_value, (&left_value).into())?; | ||||||
|  |  | ||||||
|  |     let value = match operator { | ||||||
|  |         BinaryOperator::Add => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_eq(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Adding", exec_state); | ||||||
|  |             KclValue::Number { value: l + r, meta, ty } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::Sub => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_eq(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Subtracting", exec_state); | ||||||
|  |             KclValue::Number { value: l - r, meta, ty } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::Mul => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_mul(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Multiplying", exec_state); | ||||||
|  |             KclValue::Number { value: l * r, meta, ty } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::Div => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_div(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Dividing", exec_state); | ||||||
|  |             KclValue::Number { value: l / r, meta, ty } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::Mod => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_div(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Modulo of", exec_state); | ||||||
|  |             KclValue::Number { value: l % r, meta, ty } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::Pow => KclValue::Number { | ||||||
|  |             value: left.n.powf(right.n), | ||||||
|  |             meta, | ||||||
|  |             ty: NumericType::Unknown, | ||||||
|  |         }, | ||||||
|  |         BinaryOperator::Neq => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_eq(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Comparing", exec_state); | ||||||
|  |             KclValue::Bool { value: l != r, meta } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::Gt => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_eq(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Comparing", exec_state); | ||||||
|  |             KclValue::Bool { value: l > r, meta } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::Gte => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_eq(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Comparing", exec_state); | ||||||
|  |             KclValue::Bool { value: l >= r, meta } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::Lt => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_eq(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Comparing", exec_state); | ||||||
|  |             KclValue::Bool { value: l < r, meta } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::Lte => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_eq(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Comparing", exec_state); | ||||||
|  |             KclValue::Bool { value: l <= r, meta } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::Eq => { | ||||||
|  |             let (l, r, ty) = NumericType::combine_eq(left, right); | ||||||
|  |             warn_on_unknown(source_range, &ty, "Comparing", exec_state); | ||||||
|  |             KclValue::Bool { value: l == r, meta } | ||||||
|  |         } | ||||||
|  |         BinaryOperator::And | BinaryOperator::Or => unreachable!(), | ||||||
|  |     }; | ||||||
|  |     Ok(value) | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Node<UnaryExpression> { | impl Node<UnaryExpression> { | ||||||
|  | |||||||
| @ -2832,7 +2832,7 @@ impl BinaryExpression { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, FromStr, Display)] | #[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS, JsonSchema, FromStr, Display)] | ||||||
| #[ts(export)] | #[ts(export)] | ||||||
| #[serde(rename_all = "snake_case")] | #[serde(rename_all = "snake_case")] | ||||||
| #[display(style = "snake_case")] | #[display(style = "snake_case")] | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -2,6 +2,6 @@ fn f(i) { | |||||||
|   return i * 2 |   return i * 2 | ||||||
| } | } | ||||||
|  |  | ||||||
| x = f(0) + f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) + f(8) + f(9) + f(10) + f(11) + f(12) + f(13) + f(14) + f(15) + f(16) + f(17) + f(18) + f(19) + f(20) + f(21) + f(22) + f(23) + f(24) + f(25) + f(26) + f(27) + f(28) + f(29) + f(30) + f(31) + f(32) + f(33) + f(34) + f(35) + f(36) + f(37) + f(38) + f(39) + f(40) + f(41) + f(42) + f(43) + f(44) + f(45) + f(46) + f(47) + f(48) + f(49) + f(50) + f(51) + f(52) + f(53) + f(54) + f(55) + f(56) + f(57) + f(58) + f(59) + f(60) + f(61) + f(62) + f(63) + f(64) + f(65) + f(66) + f(67) + f(68) + f(69) + f(70) | x = f(0) + f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) + f(8) + f(9) + f(10) + f(11) + f(12) + f(13) + f(14) + f(15) + f(16) + f(17) + f(18) + f(19) + f(20) + f(21) + f(22) + f(23) + f(24) + f(25) + f(26) + f(27) + f(28) + f(29) + f(30) + f(31) + f(32) + f(33) + f(34) + f(35) + f(36) + f(37) + f(38) + f(39) + f(40) + f(41) + f(42) + f(43) + f(44) + f(45) + f(46) + f(47) + f(48) + f(49) + f(50) + f(51) + f(52) + f(53) + f(54) + f(55) + f(56) + f(57) + f(58) + f(59) + f(60) + f(61) + f(62) + f(63) + f(64) + f(65) + f(66) + f(67) + f(68) + f(69) + f(70) + f(71) + f(72) + f(73) + f(74) + f(75) + f(76) + f(77) + f(78) + f(79) + f(80) + f(81) + f(82) + f(83) + f(84) + f(85) + f(86) + f(87) + f(88) + f(89) + f(90) + f(91) + f(92) + f(93) + f(94) + f(95) + f(96) + f(97) + f(98) + f(99) + f(100) | ||||||
|  |  | ||||||
| assertEqual(x, 4970, 0.1, "Big sum") | assertEqual(x, 10100, 0.1, "Big sum") | ||||||
|  | |||||||
| @ -1278,6 +1278,546 @@ description: Operations executed add_lots.kcl | |||||||
|     }, |     }, | ||||||
|     "sourceRange": [] |     "sourceRange": [] | ||||||
|   }, |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupEnd" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     "type": "GroupBegin", | ||||||
|  |     "group": { | ||||||
|  |       "type": "FunctionCall", | ||||||
|  |       "name": "f", | ||||||
|  |       "functionSourceRange": [ | ||||||
|  |         4, | ||||||
|  |         26, | ||||||
|  |         0 | ||||||
|  |       ], | ||||||
|  |       "unlabeledArg": null, | ||||||
|  |       "labeledArgs": {} | ||||||
|  |     }, | ||||||
|  |     "sourceRange": [] | ||||||
|  |   }, | ||||||
|   { |   { | ||||||
|     "type": "GroupEnd" |     "type": "GroupEnd" | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ description: Variables in memory after executing add_lots.kcl | |||||||
|   }, |   }, | ||||||
|   "x": { |   "x": { | ||||||
|     "type": "Number", |     "type": "Number", | ||||||
|     "value": 4970.0, |     "value": 10100.0, | ||||||
|     "ty": { |     "ty": { | ||||||
|       "type": "Default", |       "type": "Default", | ||||||
|       "len": { |       "len": { | ||||||
|  | |||||||
| @ -6,6 +6,6 @@ fn f(i) { | |||||||
|   return i * 2 |   return i * 2 | ||||||
| } | } | ||||||
|  |  | ||||||
| x = f(0) + f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) + f(8) + f(9) + f(10) + f(11) + f(12) + f(13) + f(14) + f(15) + f(16) + f(17) + f(18) + f(19) + f(20) + f(21) + f(22) + f(23) + f(24) + f(25) + f(26) + f(27) + f(28) + f(29) + f(30) + f(31) + f(32) + f(33) + f(34) + f(35) + f(36) + f(37) + f(38) + f(39) + f(40) + f(41) + f(42) + f(43) + f(44) + f(45) + f(46) + f(47) + f(48) + f(49) + f(50) + f(51) + f(52) + f(53) + f(54) + f(55) + f(56) + f(57) + f(58) + f(59) + f(60) + f(61) + f(62) + f(63) + f(64) + f(65) + f(66) + f(67) + f(68) + f(69) + f(70) | x = f(0) + f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) + f(8) + f(9) + f(10) + f(11) + f(12) + f(13) + f(14) + f(15) + f(16) + f(17) + f(18) + f(19) + f(20) + f(21) + f(22) + f(23) + f(24) + f(25) + f(26) + f(27) + f(28) + f(29) + f(30) + f(31) + f(32) + f(33) + f(34) + f(35) + f(36) + f(37) + f(38) + f(39) + f(40) + f(41) + f(42) + f(43) + f(44) + f(45) + f(46) + f(47) + f(48) + f(49) + f(50) + f(51) + f(52) + f(53) + f(54) + f(55) + f(56) + f(57) + f(58) + f(59) + f(60) + f(61) + f(62) + f(63) + f(64) + f(65) + f(66) + f(67) + f(68) + f(69) + f(70) + f(71) + f(72) + f(73) + f(74) + f(75) + f(76) + f(77) + f(78) + f(79) + f(80) + f(81) + f(82) + f(83) + f(84) + f(85) + f(86) + f(87) + f(88) + f(89) + f(90) + f(91) + f(92) + f(93) + f(94) + f(95) + f(96) + f(97) + f(98) + f(99) + f(100) | ||||||
|  |  | ||||||
| assertEqual(x, 4970, 0.1, "Big sum") | assertEqual(x, 10100, 0.1, "Big sum") | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	