Compare commits

..

1 Commits

Author SHA1 Message Date
7ca51be5bc Hook react-router-dom into XState in one location 2025-04-08 13:23:53 -04:00
12 changed files with 479 additions and 2229 deletions

View File

@ -19,14 +19,9 @@
(self: super: { (self: super: {
rustToolchain = super. rust-bin.stable.latest.default.override { rustToolchain = super. rust-bin.stable.latest.default.override {
targets = [ "wasm32-unknown-unknown" ]; targets = [ "wasm32-unknown-unknown" ];
extensions = [ "rustfmt" "llvm-tools-preview" "rust-src" ]; extensions = [ "rustfmt" "llvm-tools-preview" ];
}; };
}) })
(self: super: {
cargo-llvm-cov = super.cargo-llvm-cov.overrideAttrs(oa: {
doCheck = false; doInstallCheck = false;
});
})
]; ];
# Systems supported # Systems supported
@ -39,7 +34,7 @@
# Helper to provide system-specific attributes # Helper to provide system-specific attributes
forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f { forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f {
pkgs = import nixpkgs { inherit overlays system; config.allowBroken = true; }; pkgs = import nixpkgs { inherit overlays system; };
}); });
in in
@ -67,7 +62,7 @@
electron electron
playwright-driver.browsers playwright-driver.browsers
]) ++ pkgs.lib.optionals pkgs.stdenv.isDarwin (with pkgs; [ ]) ++ pkgs.lib.optionals pkgs.stdenv.isDarwin (with pkgs; [
libiconv libiconv
darwin.apple_sdk.frameworks.Security darwin.apple_sdk.frameworks.Security
]); ]);

View File

@ -918,193 +918,165 @@ 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 mut partial = self.right.get_result(exec_state, ctx).await?; let left_value = self.left.get_result(exec_state, ctx).await?;
let mut next = &self.left; let right_value = self.right.get_result(exec_state, ctx).await?;
let source_range = self.into(); let mut meta = left_value.metadata();
// Don't recurse through a big chain of binary operations, iterate instead. meta.extend(right_value.metadata());
while let BinaryPart::BinaryExpression(next_binary_expr) = next {
let metadata = partial.metadata(); // First check if we are doing string concatenation.
partial = do_binary_op( if self.operator == BinaryOperator::Add {
partial, if let (KclValue::String { value: left, meta: _ }, KclValue::String { value: right, meta: _ }) =
next_binary_expr.right.get_result(exec_state, ctx).await?, (&left_value, &right_value)
next_binary_expr.operator, {
metadata, return Ok(KclValue::String {
source_range, value: format!("{}{}", left, right),
exec_state, meta,
ctx, });
) }
.await?;
next = &next_binary_expr.left;
} }
let next_value = next.get_result(exec_state, ctx).await?; // Then check if we have solids.
let mut meta = partial.metadata(); if self.operator == BinaryOperator::Add || self.operator == BinaryOperator::Or {
meta.extend(next_value.metadata()); 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_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(source_range: SourceRange, ty: &NumericType, verb: &str, exec_state: &mut ExecState) { fn warn_on_unknown(&self, 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(
source_range, self.as_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> {

View File

@ -2832,7 +2832,7 @@ impl BinaryExpression {
} }
} }
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS, JsonSchema, FromStr, Display)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, 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

View File

@ -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) + 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) 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)
assertEqual(x, 10100, 0.1, "Big sum") assertEqual(x, 4970, 0.1, "Big sum")

View File

@ -1278,546 +1278,6 @@ 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"
} }

View File

@ -8,7 +8,7 @@ description: Variables in memory after executing add_lots.kcl
}, },
"x": { "x": {
"type": "Number", "type": "Number",
"value": 10100.0, "value": 4970.0,
"ty": { "ty": {
"type": "Default", "type": "Default",
"len": { "len": {

View File

@ -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) + 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) 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)
assertEqual(x, 10100, 0.1, "Big sum") assertEqual(x, 4970, 0.1, "Big sum")

View File

@ -18,7 +18,7 @@ import { markOnce } from '@src/lib/performance'
import { loadAndValidateSettings } from '@src/lib/settings/settingsUtils' import { loadAndValidateSettings } from '@src/lib/settings/settingsUtils'
import { trap } from '@src/lib/trap' import { trap } from '@src/lib/trap'
import type { IndexLoaderData } from '@src/lib/types' import type { IndexLoaderData } from '@src/lib/types'
import { settingsActor, useSettings } from '@src/machines/appMachine' import { appActor, settingsActor, useSettings } from '@src/machines/appMachine'
export const RouteProviderContext = createContext({}) export const RouteProviderContext = createContext({})
@ -34,6 +34,38 @@ export function RouteProvider({ children }: { children: ReactNode }) {
const location = useLocation() const location = useLocation()
const settings = useSettings() const settings = useSettings()
/**
* Spawn a router machine that we can interact with outside of React,
* but providing the react-router-dom methods and information we need.
*/
useEffect(() => {
appActor.send({
type: 'event:router_set_up',
data: {
location,
navigation,
navigate,
},
})
}, [])
/**
* "Subscribe" to the location and navigation from react-router-dom
* to keep the router actor up-to-date from here on out
*/
useEffect(() => {
appActor.getSnapshot().children.router?.send({
type: 'event:set_location',
data: location,
})
}, [location])
useEffect(() => {
appActor.getSnapshot().children.router?.send({
type: 'event:set_navigation',
data: navigation,
})
}, [navigation])
useEffect(() => { useEffect(() => {
// On initialization, the react-router-dom does not send a 'loading' state event. // On initialization, the react-router-dom does not send a 'loading' state event.
// it sends an idle event first. // it sends an idle event first.

View File

@ -1,5 +1,5 @@
import { useSelector } from '@xstate/react' import { useSelector } from '@xstate/react'
import { createActor, setup, spawnChild } from 'xstate' import { createActor, InputFrom, setup, spawnChild } from 'xstate'
import { createSettings } from '@src/lib/settings/initialSettings' import { createSettings } from '@src/lib/settings/initialSettings'
import { authMachine } from '@src/machines/authMachine' import { authMachine } from '@src/machines/authMachine'
@ -9,13 +9,15 @@ import {
engineStreamMachine, engineStreamMachine,
} from '@src/machines/engineStreamMachine' } from '@src/machines/engineStreamMachine'
import { ACTOR_IDS } from '@src/machines/machineConstants' import { ACTOR_IDS } from '@src/machines/machineConstants'
import { routerMachine } from '@src/machines/routerMachine'
import { settingsMachine } from '@src/machines/settingsMachine' import { settingsMachine } from '@src/machines/settingsMachine'
const { AUTH, SETTINGS, ENGINE_STREAM } = ACTOR_IDS const { AUTH, SETTINGS, ENGINE_STREAM, ROUTER } = ACTOR_IDS
const appMachineActors = { const appMachineActors = {
[AUTH]: authMachine, [AUTH]: authMachine,
[SETTINGS]: settingsMachine, [SETTINGS]: settingsMachine,
[ENGINE_STREAM]: engineStreamMachine, [ENGINE_STREAM]: engineStreamMachine,
[ROUTER]: routerMachine,
} as const } as const
const appMachine = setup({ const appMachine = setup({
@ -23,6 +25,12 @@ const appMachine = setup({
children: { children: {
auth: typeof AUTH auth: typeof AUTH
settings: typeof SETTINGS settings: typeof SETTINGS
engine_stream: typeof ENGINE_STREAM
router?: typeof ROUTER
}
events: {
type: 'event:router_set_up'
data: InputFrom<typeof routerMachine>
} }
}, },
actors: appMachineActors, actors: appMachineActors,
@ -41,9 +49,30 @@ const appMachine = setup({
input: engineStreamContextCreate(), input: engineStreamContextCreate(),
}), }),
], ],
on: {
'event:router_set_up': {
actions: spawnChild(ROUTER, {
id: ROUTER,
systemId: ROUTER,
input: ({ event, context }) => {
if (event.type !== 'event:router_set_up')
return {
location: {} as InputFrom<typeof routerMachine>['location'],
navigation: {} as InputFrom<typeof routerMachine>['navigation'],
navigate: (() => {}) as InputFrom<
typeof routerMachine
>['navigate'],
}
return event.data
},
}),
},
},
}) })
export const appActor = createActor(appMachine) export const appActor = createActor(appMachine)
// REMOVE THIS BEFORE MERGING
window.appActor = appActor
/** /**
* GOTCHA: the type coercion of this actor works because it is spawned for * GOTCHA: the type coercion of this actor works because it is spawned for
* the lifetime of {appActor}, but would not work if it were invoked * the lifetime of {appActor}, but would not work if it were invoked

View File

@ -2,4 +2,5 @@ export const ACTOR_IDS = {
AUTH: 'auth', AUTH: 'auth',
SETTINGS: 'settings', SETTINGS: 'settings',
ENGINE_STREAM: 'engine_stream', ENGINE_STREAM: 'engine_stream',
ROUTER: 'router',
} as const } as const

View File

@ -0,0 +1,81 @@
import { useLocation, useNavigate, useNavigation } from 'react-router-dom'
import { assign, setup } from 'xstate'
export const routerMachine = setup({
types: {} as {
context: {
location: ReturnType<typeof useLocation>
navigation: ReturnType<typeof useNavigation>
navigate: ReturnType<typeof useNavigate>
}
input: {
location: ReturnType<typeof useLocation>
navigation: ReturnType<typeof useNavigation>
navigate: ReturnType<typeof useNavigate>
}
events:
| {
type: 'event:navigate'
data: Parameters<ReturnType<typeof useNavigate>>
}
| { type: 'event:set_location'; data: ReturnType<typeof useLocation> }
| { type: 'event:set_navigation'; data: ReturnType<typeof useNavigation> }
},
actions: {
navigate: (
_,
params: {
navigate: ReturnType<typeof useNavigate>
args: Parameters<ReturnType<typeof useNavigate>>
}
) => {
console.log("FRANK let's try and navigate", {
params,
})
params.navigate(...params.args)
},
},
}).createMachine({
id: 'router',
context: ({ input }) => ({
...input,
}),
on: {
'event:navigate': {
actions: {
type: 'navigate',
params: ({ event, context }) => ({
navigate: context.navigate,
args: event.data,
}),
},
},
'event:set_location': {
actions: assign({
location: ({ event }) => event.data,
}),
},
'event:set_navigation': {
actions: assign({
navigation: ({ event }) => event.data,
}),
},
},
// states: {
// idle: {
// on: {
// 'event:navigate:start': {
// target: 'navigating',
// actions: ['navigate'],
// },
// },
// },
// navigating: {
// on: {
// 'event:navigate:end': {
// target: 'idle',
// },
// },
// },
// },
})