breaking change: Add more KCL reserved words, part 1 (#4502)

This commit is contained in:
Jonathan Tran
2024-11-18 19:54:25 -05:00
committed by GitHub
parent 16b7544d69
commit f71fafdece
15 changed files with 482 additions and 433 deletions

View File

@ -36,15 +36,15 @@ fn add = (a, b) => {
// This function adds an array of numbers. // This function adds an array of numbers.
// It uses the `reduce` function, to call the `add` function on every // It uses the `reduce` function, to call the `add` function on every
// element of the `array` parameter. The starting value is 0. // element of the `arr` parameter. The starting value is 0.
fn sum = (array) => { fn sum = (arr) => {
return reduce(array, 0, add) return reduce(arr, 0, add)
} }
/* The above is basically like this pseudo-code: /* The above is basically like this pseudo-code:
fn sum(array): fn sum(arr):
let sumSoFar = 0 let sumSoFar = 0
for i in array: for i in arr:
sumSoFar = add(sumSoFar, i) sumSoFar = add(sumSoFar, i)
return sumSoFar */ return sumSoFar */
@ -60,8 +60,8 @@ assertEqual(sum([1, 2, 3]), 6, 0.00001, "1 + 2 + 3 summed is 6")
// This example works just like the previous example above, but it uses // This example works just like the previous example above, but it uses
// an anonymous `add` function as its parameter, instead of declaring a // an anonymous `add` function as its parameter, instead of declaring a
// named function outside. // named function outside.
array = [1, 2, 3] arr = [1, 2, 3]
sum = reduce(array, 0, (i, result_so_far) => { sum = reduce(arr, 0, (i, result_so_far) => {
return i + result_so_far return i + result_so_far
}) })

View File

@ -162561,8 +162561,8 @@
"unpublished": false, "unpublished": false,
"deprecated": false, "deprecated": false,
"examples": [ "examples": [
"// This function adds two numbers.\nfn add = (a, b) => {\n return a + b\n}\n\n// This function adds an array of numbers.\n// It uses the `reduce` function, to call the `add` function on every\n// element of the `array` parameter. The starting value is 0.\nfn sum = (array) => {\n return reduce(array, 0, add)\n}\n\n/* The above is basically like this pseudo-code:\nfn sum(array):\n let sumSoFar = 0\n for i in array:\n sumSoFar = add(sumSoFar, i)\n return sumSoFar */\n\n\n// We use `assertEqual` to check that our `sum` function gives the\n// expected result. It's good to check your work!\nassertEqual(sum([1, 2, 3]), 6, 0.00001, \"1 + 2 + 3 summed is 6\")", "// This function adds two numbers.\nfn add = (a, b) => {\n return a + b\n}\n\n// This function adds an array of numbers.\n// It uses the `reduce` function, to call the `add` function on every\n// element of the `arr` parameter. The starting value is 0.\nfn sum = (arr) => {\n return reduce(arr, 0, add)\n}\n\n/* The above is basically like this pseudo-code:\nfn sum(arr):\n let sumSoFar = 0\n for i in arr:\n sumSoFar = add(sumSoFar, i)\n return sumSoFar */\n\n\n// We use `assertEqual` to check that our `sum` function gives the\n// expected result. It's good to check your work!\nassertEqual(sum([1, 2, 3]), 6, 0.00001, \"1 + 2 + 3 summed is 6\")",
"// This example works just like the previous example above, but it uses\n// an anonymous `add` function as its parameter, instead of declaring a\n// named function outside.\narray = [1, 2, 3]\nsum = reduce(array, 0, (i, result_so_far) => {\n return i + result_so_far\n})\n\n// We use `assertEqual` to check that our `sum` function gives the\n// expected result. It's good to check your work!\nassertEqual(sum, 6, 0.00001, \"1 + 2 + 3 summed is 6\")", "// This example works just like the previous example above, but it uses\n// an anonymous `add` function as its parameter, instead of declaring a\n// named function outside.\narr = [1, 2, 3]\nsum = reduce(arr, 0, (i, result_so_far) => {\n return i + result_so_far\n})\n\n// We use `assertEqual` to check that our `sum` function gives the\n// expected result. It's good to check your work!\nassertEqual(sum, 6, 0.00001, \"1 + 2 + 3 summed is 6\")",
"// Declare a function that sketches a decagon.\nfn decagon = (radius) => {\n // Each side of the decagon is turned this many degrees from the previous angle.\n stepAngle = 1 / 10 * tau()\n\n // Start the decagon sketch at this point.\n startOfDecagonSketch = startSketchAt([cos(0) * radius, sin(0) * radius])\n\n // Use a `reduce` to draw the remaining decagon sides.\n // For each number in the array 1..10, run the given function,\n // which takes a partially-sketched decagon and adds one more edge to it.\n fullDecagon = reduce([1..10], startOfDecagonSketch, (i, partialDecagon) => {\n // Draw one edge of the decagon.\n x = cos(stepAngle * i) * radius\n y = sin(stepAngle * i) * radius\n return lineTo([x, y], partialDecagon)\n})\n\n return fullDecagon\n}\n\n/* The `decagon` above is basically like this pseudo-code:\nfn decagon(radius):\n let stepAngle = (1/10) * tau()\n let startOfDecagonSketch = startSketchAt([(cos(0)*radius), (sin(0) * radius)])\n\n // Here's the reduce part.\n let partialDecagon = startOfDecagonSketch\n for i in [1..10]:\n let x = cos(stepAngle * i) * radius\n let y = sin(stepAngle * i) * radius\n partialDecagon = lineTo([x, y], partialDecagon)\n fullDecagon = partialDecagon // it's now full\n return fullDecagon */\n\n\n// Use the `decagon` function declared above, to sketch a decagon with radius 5.\ndecagon(5.0)\n |> close(%)" "// Declare a function that sketches a decagon.\nfn decagon = (radius) => {\n // Each side of the decagon is turned this many degrees from the previous angle.\n stepAngle = 1 / 10 * tau()\n\n // Start the decagon sketch at this point.\n startOfDecagonSketch = startSketchAt([cos(0) * radius, sin(0) * radius])\n\n // Use a `reduce` to draw the remaining decagon sides.\n // For each number in the array 1..10, run the given function,\n // which takes a partially-sketched decagon and adds one more edge to it.\n fullDecagon = reduce([1..10], startOfDecagonSketch, (i, partialDecagon) => {\n // Draw one edge of the decagon.\n x = cos(stepAngle * i) * radius\n y = sin(stepAngle * i) * radius\n return lineTo([x, y], partialDecagon)\n})\n\n return fullDecagon\n}\n\n/* The `decagon` above is basically like this pseudo-code:\nfn decagon(radius):\n let stepAngle = (1/10) * tau()\n let startOfDecagonSketch = startSketchAt([(cos(0)*radius), (sin(0) * radius)])\n\n // Here's the reduce part.\n let partialDecagon = startOfDecagonSketch\n for i in [1..10]:\n let x = cos(stepAngle * i) * radius\n let y = sin(stepAngle * i) * radius\n partialDecagon = lineTo([x, y], partialDecagon)\n fullDecagon = partialDecagon // it's now full\n return fullDecagon */\n\n\n// Use the `decagon` function declared above, to sketch a decagon with radius 5.\ndecagon(5.0)\n |> close(%)"
] ]
}, },

View File

@ -1691,6 +1691,7 @@ dependencies = [
"databake", "databake",
"derive-docs", "derive-docs",
"expectorate", "expectorate",
"fnv",
"form_urlencoded", "form_urlencoded",
"futures", "futures",
"git_rev", "git_rev",

View File

@ -21,6 +21,7 @@ convert_case = "0.6.0"
dashmap = "6.1.0" dashmap = "6.1.0"
databake = { version = "0.1.8", features = ["derive"] } databake = { version = "0.1.8", features = ["derive"] }
derive-docs = { version = "0.1.29", path = "../derive-docs" } derive-docs = { version = "0.1.29", path = "../derive-docs" }
fnv = "1.0.7"
form_urlencoded = "1.2.1" form_urlencoded = "1.2.1"
futures = { version = "0.3.31" } futures = { version = "0.3.31" }
git_rev = "0.1.0" git_rev = "0.1.0"

View File

@ -3052,14 +3052,14 @@ for var in [[3, 6, 10, [0,0]], [1.5, 3, 5, [-10,-10]]] {
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn test_get_member_of_array_with_function() { async fn test_get_member_of_array_with_function() {
let ast = r#"fn box = (array) => { let ast = r#"fn box = (arr) => {
let myBox =startSketchOn('XY') let myBox =startSketchOn('XY')
|> startProfileAt(array[0], %) |> startProfileAt(arr[0], %)
|> line([0, array[1]], %) |> line([0, arr[1]], %)
|> line([array[2], 0], %) |> line([arr[2], 0], %)
|> line([0, -array[1]], %) |> line([0, -arr[1]], %)
|> close(%) |> close(%)
|> extrude(array[3], %) |> extrude(arr[3], %)
return myBox return myBox
} }

View File

@ -2040,11 +2040,39 @@ fn fn_call(i: TokenSlice) -> PResult<Node<CallExpression>> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use itertools::Itertools;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use super::*; use super::*;
use crate::ast::types::{BodyItem, Expr, ModuleId, VariableKind}; use crate::ast::types::{BodyItem, Expr, ModuleId, VariableKind};
fn assert_reserved(word: &str) {
// Try to use it as a variable name.
let code = format!(r#"{} = 0"#, word);
let result = crate::parser::top_level_parse(code.as_str());
let err = result.unwrap_err();
// Which token causes the error may change. In "return = 0", for
// example, "return" is the problem.
assert!(
err.message().starts_with("Unexpected token: ")
|| err
.message()
.starts_with("Cannot assign a variable to a reserved keyword: "),
"Error message is: {}",
err.message(),
);
}
#[test]
fn reserved_words() {
// Since these are stored in a set, we sort to make the tests
// deterministic.
for word in crate::token::RESERVED_WORDS.keys().sorted() {
assert_reserved(word);
}
assert_reserved("import");
}
#[test] #[test]
fn parse_args() { fn parse_args() {
for (i, (test, expected_len)) in [("someVar", 1), ("5, 3", 2), (r#""a""#, 1)].into_iter().enumerate() { for (i, (test, expected_len)) in [("someVar", 1), ("5, 3", 2), (r#""a""#, 1)].into_iter().enumerate() {

View File

@ -107,14 +107,14 @@ pub async fn reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
/// ///
/// // This function adds an array of numbers. /// // This function adds an array of numbers.
/// // It uses the `reduce` function, to call the `add` function on every /// // It uses the `reduce` function, to call the `add` function on every
/// // element of the `array` parameter. The starting value is 0. /// // element of the `arr` parameter. The starting value is 0.
/// fn sum = (array) => { return reduce(array, 0, add) } /// fn sum = (arr) => { return reduce(arr, 0, add) }
/// ///
/// /* /// /*
/// The above is basically like this pseudo-code: /// The above is basically like this pseudo-code:
/// fn sum(array): /// fn sum(arr):
/// let sumSoFar = 0 /// let sumSoFar = 0
/// for i in array: /// for i in arr:
/// sumSoFar = add(sumSoFar, i) /// sumSoFar = add(sumSoFar, i)
/// return sumSoFar /// return sumSoFar
/// */ /// */
@ -127,8 +127,8 @@ pub async fn reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
/// // This example works just like the previous example above, but it uses /// // This example works just like the previous example above, but it uses
/// // an anonymous `add` function as its parameter, instead of declaring a /// // an anonymous `add` function as its parameter, instead of declaring a
/// // named function outside. /// // named function outside.
/// array = [1, 2, 3] /// arr = [1, 2, 3]
/// sum = reduce(array, 0, (i, result_so_far) => { return i + result_so_far }) /// sum = reduce(arr, 0, (i, result_so_far) => { return i + result_so_far })
/// ///
/// // We use `assertEqual` to check that our `sum` function gives the /// // We use `assertEqual` to check that our `sum` function gives the
/// // expected result. It's good to check your work! /// // expected result. It's good to check your work!

View File

@ -17,6 +17,8 @@ mod tokeniser;
// Re-export // Re-export
pub use tokeniser::Input; pub use tokeniser::Input;
#[cfg(test)]
pub(crate) use tokeniser::RESERVED_WORDS;
/// The types of tokens. /// The types of tokens.
#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize, ts_rs::TS, JsonSchema, FromStr, Display)] #[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize, ts_rs::TS, JsonSchema, FromStr, Display)]

View File

@ -1,6 +1,8 @@
use fnv::FnvHashMap;
use lazy_static::lazy_static;
use winnow::{ use winnow::{
ascii::{digit1, multispace1}, ascii::{digit1, multispace1},
combinator::{alt, opt, peek, preceded, repeat, terminated}, combinator::{alt, opt, peek, preceded, repeat},
error::{ContextError, ParseError}, error::{ContextError, ParseError},
prelude::*, prelude::*,
stream::{Location, Stream}, stream::{Location, Stream},
@ -13,6 +15,52 @@ use crate::{
token::{Token, TokenType}, token::{Token, TokenType},
}; };
lazy_static! {
pub(crate) static ref RESERVED_WORDS: FnvHashMap<&'static str, TokenType> = {
let mut set = FnvHashMap::default();
set.insert("if", TokenType::Keyword);
set.insert("else", TokenType::Keyword);
set.insert("for", TokenType::Keyword);
set.insert("while", TokenType::Keyword);
set.insert("return", TokenType::Keyword);
set.insert("break", TokenType::Keyword);
set.insert("continue", TokenType::Keyword);
set.insert("fn", TokenType::Keyword);
set.insert("let", TokenType::Keyword);
set.insert("mut", TokenType::Keyword);
set.insert("as", TokenType::Keyword);
set.insert("loop", TokenType::Keyword);
set.insert("true", TokenType::Keyword);
set.insert("false", TokenType::Keyword);
set.insert("nil", TokenType::Keyword);
// This isn't a type because brackets are used for the type.
set.insert("array", TokenType::Keyword);
set.insert("and", TokenType::Keyword);
set.insert("or", TokenType::Keyword);
set.insert("not", TokenType::Keyword);
set.insert("var", TokenType::Keyword);
set.insert("const", TokenType::Keyword);
// "import" is special because of import().
set.insert("export", TokenType::Keyword);
set.insert("interface", TokenType::Keyword);
set.insert("new", TokenType::Keyword);
set.insert("self", TokenType::Keyword);
set.insert("record", TokenType::Keyword);
set.insert("struct", TokenType::Keyword);
set.insert("object", TokenType::Keyword);
set.insert("_", TokenType::Keyword);
set.insert("string", TokenType::Type);
set.insert("number", TokenType::Type);
set.insert("bool", TokenType::Type);
set.insert("sketch", TokenType::Type);
set.insert("sketch_surface", TokenType::Type);
set.insert("solid", TokenType::Type);
set
};
}
pub fn lexer(i: &str, module_id: ModuleId) -> Result<Vec<Token>, ParseError<Input<'_>, ContextError>> { pub fn lexer(i: &str, module_id: ModuleId) -> Result<Vec<Token>, ParseError<Input<'_>, ContextError>> {
let state = State::new(module_id); let state = State::new(module_id);
let input = Input { let input = Input {
@ -50,7 +98,7 @@ pub fn token(i: &mut Input<'_>) -> PResult<Token> {
'$' => dollar, '$' => dollar,
'!' => alt((operator, bang)), '!' => alt((operator, bang)),
' ' | '\t' | '\n' => whitespace, ' ' | '\t' | '\n' => whitespace,
_ => alt((operator, keyword,type_, word)) _ => alt((operator, keyword_type_or_word))
} }
.parse_next(i) .parse_next(i)
{ {
@ -287,47 +335,16 @@ fn import_keyword(i: &mut Input<'_>) -> PResult<Token> {
)) ))
} }
fn unambiguous_keywords(i: &mut Input<'_>) -> PResult<Token> { fn unambiguous_keyword_type_or_word(i: &mut Input<'_>) -> PResult<Token> {
// These are the keywords themselves. let mut w = word.parse_next(i)?;
let keyword_candidates = alt(( if let Some(token_type) = RESERVED_WORDS.get(w.value.as_str()) {
"if", "else", "for", "while", "return", "break", "continue", "fn", "let", "mut", "loop", "true", "false", w.token_type = *token_type;
"nil", "and", "or", "not", "var", "const", "export", }
)); Ok(w)
// Look ahead. If any of these characters follow the keyword, then it's not a keyword, it's just
// the start of a normal word.
let keyword = terminated(
keyword_candidates,
peek(none_of(('a'..='z', 'A'..='Z', '-', '_', '0'..='9'))),
);
let (value, range) = keyword.with_span().parse_next(i)?;
Ok(Token::from_range(
range,
i.state.module_id,
TokenType::Keyword,
value.to_owned(),
))
} }
fn keyword(i: &mut Input<'_>) -> PResult<Token> { fn keyword_type_or_word(i: &mut Input<'_>) -> PResult<Token> {
alt((import_keyword, unambiguous_keywords)).parse_next(i) alt((import_keyword, unambiguous_keyword_type_or_word)).parse_next(i)
}
fn type_(i: &mut Input<'_>) -> PResult<Token> {
// These are the types themselves.
let type_candidates = alt(("string", "number", "bool", "sketch", "sketch_surface", "solid"));
// Look ahead. If any of these characters follow the type, then it's not a type, it's just
// the start of a normal word.
let type_ = terminated(
type_candidates,
peek(none_of(('a'..='z', 'A'..='Z', '-', '_', '0'..='9'))),
);
let (value, range) = type_.with_span().parse_next(i)?;
Ok(Token::from_range(
range,
i.state.module_id,
TokenType::Type,
value.to_owned(),
))
} }
#[cfg(test)] #[cfg(test)]

View File

@ -9,42 +9,42 @@ snapshot_kind: text
{ {
"declarations": [ "declarations": [
{ {
"end": 55, "end": 53,
"id": { "id": {
"end": 40, "end": 38,
"name": "array", "name": "arr",
"start": 35, "start": 35,
"type": "Identifier" "type": "Identifier"
}, },
"init": { "init": {
"elements": [ "elements": [
{ {
"end": 46, "end": 44,
"raw": "90", "raw": "90",
"start": 44, "start": 42,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": 90 "value": 90
}, },
{ {
"end": 50, "end": 48,
"raw": "91", "raw": "91",
"start": 48, "start": 46,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": 91 "value": 91
}, },
{ {
"end": 54, "end": 52,
"raw": "92", "raw": "92",
"start": 52, "start": 50,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": 92 "value": 92
} }
], ],
"end": 55, "end": 53,
"start": 43, "start": 41,
"type": "ArrayExpression", "type": "ArrayExpression",
"type": "ArrayExpression" "type": "ArrayExpression"
}, },
@ -52,7 +52,7 @@ snapshot_kind: text
"type": "VariableDeclarator" "type": "VariableDeclarator"
} }
], ],
"end": 55, "end": 53,
"kind": "const", "kind": "const",
"start": 35, "start": 35,
"type": "VariableDeclaration", "type": "VariableDeclaration",
@ -61,328 +61,328 @@ snapshot_kind: text
{ {
"declarations": [ "declarations": [
{ {
"end": 101, "end": 97,
"id": { "id": {
"end": 90, "end": 88,
"name": "result0", "name": "result0",
"start": 83, "start": 81,
"type": "Identifier" "type": "Identifier"
}, },
"init": { "init": {
"computed": false, "computed": false,
"end": 101, "end": 97,
"object": { "object": {
"end": 98, "end": 94,
"name": "array", "name": "arr",
"start": 93, "start": 91,
"type": "Identifier", "type": "Identifier",
"type": "Identifier" "type": "Identifier"
}, },
"property": { "property": {
"end": 100, "end": 96,
"raw": "1", "raw": "1",
"start": 99, "start": 95,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": 1 "value": 1
}, },
"start": 93, "start": 91,
"type": "MemberExpression", "type": "MemberExpression",
"type": "MemberExpression" "type": "MemberExpression"
}, },
"start": 83, "start": 81,
"type": "VariableDeclarator" "type": "VariableDeclarator"
} }
], ],
"end": 101, "end": 97,
"kind": "const", "kind": "const",
"start": 83, "start": 81,
"type": "VariableDeclaration", "type": "VariableDeclaration",
"type": "VariableDeclaration" "type": "VariableDeclaration"
}, },
{ {
"end": 161, "end": 157,
"expression": { "expression": {
"arguments": [ "arguments": [
{ {
"end": 129, "end": 125,
"name": "result0", "name": "result0",
"start": 122, "start": 118,
"type": "Identifier", "type": "Identifier",
"type": "Identifier" "type": "Identifier"
}, },
{ {
"end": 133, "end": 129,
"raw": "91", "raw": "91",
"start": 131, "start": 127,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": 91 "value": 91
}, },
{ {
"end": 160, "end": 156,
"raw": "\"Literal property lookup\"", "raw": "\"Literal property lookup\"",
"start": 135, "start": 131,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": "Literal property lookup" "value": "Literal property lookup"
} }
], ],
"callee": { "callee": {
"end": 121, "end": 117,
"name": "assertLessThanOrEq", "name": "assertLessThanOrEq",
"start": 103, "start": 99,
"type": "Identifier" "type": "Identifier"
}, },
"end": 161, "end": 157,
"optional": false, "optional": false,
"start": 103, "start": 99,
"type": "CallExpression", "type": "CallExpression",
"type": "CallExpression" "type": "CallExpression"
}, },
"start": 103, "start": 99,
"type": "ExpressionStatement", "type": "ExpressionStatement",
"type": "ExpressionStatement" "type": "ExpressionStatement"
}, },
{ {
"end": 223, "end": 219,
"expression": { "expression": {
"arguments": [ "arguments": [
{ {
"end": 191, "end": 187,
"name": "result0", "name": "result0",
"start": 184, "start": 180,
"type": "Identifier", "type": "Identifier",
"type": "Identifier" "type": "Identifier"
}, },
{ {
"end": 195, "end": 191,
"raw": "91", "raw": "91",
"start": 193, "start": 189,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": 91 "value": 91
}, },
{ {
"end": 222, "end": 218,
"raw": "\"Literal property lookup\"", "raw": "\"Literal property lookup\"",
"start": 197, "start": 193,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": "Literal property lookup" "value": "Literal property lookup"
} }
], ],
"callee": { "callee": {
"end": 183, "end": 179,
"name": "assertGreaterThanOrEq", "name": "assertGreaterThanOrEq",
"start": 162, "start": 158,
"type": "Identifier" "type": "Identifier"
}, },
"end": 223, "end": 219,
"optional": false, "optional": false,
"start": 162, "start": 158,
"type": "CallExpression", "type": "CallExpression",
"type": "CallExpression" "type": "CallExpression"
}, },
"start": 162, "start": 158,
"type": "ExpressionStatement", "type": "ExpressionStatement",
"type": "ExpressionStatement" "type": "ExpressionStatement"
}, },
{ {
"declarations": [ "declarations": [
{ {
"end": 266, "end": 262,
"id": { "id": {
"end": 253, "end": 249,
"name": "i", "name": "i",
"start": 252, "start": 248,
"type": "Identifier" "type": "Identifier"
}, },
"init": { "init": {
"arguments": [ "arguments": [
{ {
"end": 265,
"left": {
"end": 261, "end": 261,
"left": {
"end": 257,
"raw": "1", "raw": "1",
"start": 260, "start": 256,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": 1 "value": 1
}, },
"operator": "+", "operator": "+",
"right": { "right": {
"end": 265, "end": 261,
"raw": "0", "raw": "0",
"start": 264, "start": 260,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": 0 "value": 0
}, },
"start": 260, "start": 256,
"type": "BinaryExpression", "type": "BinaryExpression",
"type": "BinaryExpression" "type": "BinaryExpression"
} }
], ],
"callee": { "callee": {
"end": 259, "end": 255,
"name": "int", "name": "int",
"start": 256, "start": 252,
"type": "Identifier" "type": "Identifier"
}, },
"end": 266, "end": 262,
"optional": false, "optional": false,
"start": 256, "start": 252,
"type": "CallExpression", "type": "CallExpression",
"type": "CallExpression" "type": "CallExpression"
}, },
"start": 252, "start": 248,
"type": "VariableDeclarator" "type": "VariableDeclarator"
} }
], ],
"end": 266, "end": 262,
"kind": "const", "kind": "const",
"start": 252, "start": 248,
"type": "VariableDeclaration", "type": "VariableDeclaration",
"type": "VariableDeclaration" "type": "VariableDeclaration"
}, },
{ {
"declarations": [ "declarations": [
{ {
"end": 285, "end": 279,
"id": { "id": {
"end": 274, "end": 270,
"name": "result1", "name": "result1",
"start": 267, "start": 263,
"type": "Identifier" "type": "Identifier"
}, },
"init": { "init": {
"computed": true, "computed": true,
"end": 285, "end": 279,
"object": { "object": {
"end": 282, "end": 276,
"name": "array", "name": "arr",
"start": 277, "start": 273,
"type": "Identifier", "type": "Identifier",
"type": "Identifier" "type": "Identifier"
}, },
"property": { "property": {
"end": 284, "end": 278,
"name": "i", "name": "i",
"start": 283, "start": 277,
"type": "Identifier", "type": "Identifier",
"type": "Identifier" "type": "Identifier"
}, },
"start": 277, "start": 273,
"type": "MemberExpression", "type": "MemberExpression",
"type": "MemberExpression" "type": "MemberExpression"
}, },
"start": 267, "start": 263,
"type": "VariableDeclarator" "type": "VariableDeclarator"
} }
], ],
"end": 285, "end": 279,
"kind": "const", "kind": "const",
"start": 267, "start": 263,
"type": "VariableDeclaration", "type": "VariableDeclaration",
"type": "VariableDeclaration" "type": "VariableDeclaration"
}, },
{ {
"end": 346, "end": 340,
"expression": { "expression": {
"arguments": [ "arguments": [
{ {
"end": 313, "end": 307,
"name": "result1", "name": "result1",
"start": 306, "start": 300,
"type": "Identifier", "type": "Identifier",
"type": "Identifier" "type": "Identifier"
}, },
{ {
"end": 317, "end": 311,
"raw": "91", "raw": "91",
"start": 315, "start": 309,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": 91 "value": 91
}, },
{ {
"end": 345, "end": 339,
"raw": "\"Computed property lookup\"", "raw": "\"Computed property lookup\"",
"start": 319, "start": 313,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": "Computed property lookup" "value": "Computed property lookup"
} }
], ],
"callee": { "callee": {
"end": 305, "end": 299,
"name": "assertLessThanOrEq", "name": "assertLessThanOrEq",
"start": 287, "start": 281,
"type": "Identifier" "type": "Identifier"
}, },
"end": 346, "end": 340,
"optional": false, "optional": false,
"start": 287, "start": 281,
"type": "CallExpression", "type": "CallExpression",
"type": "CallExpression" "type": "CallExpression"
}, },
"start": 287, "start": 281,
"type": "ExpressionStatement", "type": "ExpressionStatement",
"type": "ExpressionStatement" "type": "ExpressionStatement"
}, },
{ {
"end": 409, "end": 403,
"expression": { "expression": {
"arguments": [ "arguments": [
{ {
"end": 376, "end": 370,
"name": "result1", "name": "result1",
"start": 369, "start": 363,
"type": "Identifier", "type": "Identifier",
"type": "Identifier" "type": "Identifier"
}, },
{ {
"end": 380, "end": 374,
"raw": "91", "raw": "91",
"start": 378, "start": 372,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": 91 "value": 91
}, },
{ {
"end": 408, "end": 402,
"raw": "\"Computed property lookup\"", "raw": "\"Computed property lookup\"",
"start": 382, "start": 376,
"type": "Literal", "type": "Literal",
"type": "Literal", "type": "Literal",
"value": "Computed property lookup" "value": "Computed property lookup"
} }
], ],
"callee": { "callee": {
"end": 368, "end": 362,
"name": "assertGreaterThanOrEq", "name": "assertGreaterThanOrEq",
"start": 347, "start": 341,
"type": "Identifier" "type": "Identifier"
}, },
"end": 409, "end": 403,
"optional": false, "optional": false,
"start": 347, "start": 341,
"type": "CallExpression", "type": "CallExpression",
"type": "CallExpression" "type": "CallExpression"
}, },
"start": 347, "start": 341,
"type": "ExpressionStatement", "type": "ExpressionStatement",
"type": "ExpressionStatement" "type": "ExpressionStatement"
} }
], ],
"end": 410, "end": 404,
"nonCodeMeta": { "nonCodeMeta": {
"nonCodeNodes": { "nonCodeNodes": {
"0": [ "0": [
{ {
"end": 80, "end": 78,
"start": 55, "start": 53,
"type": "NonCodeNode", "type": "NonCodeNode",
"value": { "value": {
"type": "newLineBlockComment", "type": "newLineBlockComment",
@ -391,8 +391,8 @@ snapshot_kind: text
} }
}, },
{ {
"end": 83, "end": 81,
"start": 80, "start": 78,
"type": "NonCodeNode", "type": "NonCodeNode",
"value": { "value": {
"type": "newLine" "type": "newLine"
@ -401,8 +401,8 @@ snapshot_kind: text
], ],
"1": [ "1": [
{ {
"end": 103, "end": 99,
"start": 101, "start": 97,
"type": "NonCodeNode", "type": "NonCodeNode",
"value": { "value": {
"type": "newLine" "type": "newLine"
@ -411,8 +411,8 @@ snapshot_kind: text
], ],
"3": [ "3": [
{ {
"end": 249, "end": 245,
"start": 223, "start": 219,
"type": "NonCodeNode", "type": "NonCodeNode",
"value": { "value": {
"type": "newLineBlockComment", "type": "newLineBlockComment",
@ -421,8 +421,8 @@ snapshot_kind: text
} }
}, },
{ {
"end": 252, "end": 248,
"start": 249, "start": 245,
"type": "NonCodeNode", "type": "NonCodeNode",
"value": { "value": {
"type": "newLine" "type": "newLine"
@ -431,8 +431,8 @@ snapshot_kind: text
], ],
"5": [ "5": [
{ {
"end": 287, "end": 281,
"start": 285, "start": 279,
"type": "NonCodeNode", "type": "NonCodeNode",
"value": { "value": {
"type": "newLine" "type": "newLine"

View File

@ -1,12 +1,12 @@
// This tests indexing an array. // This tests indexing an array.
array = [90, 91, 92] arr = [90, 91, 92]
// Test: literal index. // Test: literal index.
result0 = array[1] result0 = arr[1]
assertLessThanOrEq(result0, 91, "Literal property lookup") assertLessThanOrEq(result0, 91, "Literal property lookup")
assertGreaterThanOrEq(result0, 91, "Literal property lookup") assertGreaterThanOrEq(result0, 91, "Literal property lookup")
@ -15,7 +15,7 @@ assertGreaterThanOrEq(result0, 91, "Literal property lookup")
i = int(1 + 0) i = int(1 + 0)
result1 = array[i] result1 = arr[i]
assertLessThanOrEq(result1, 91, "Computed property lookup") assertLessThanOrEq(result1, 91, "Computed property lookup")
assertGreaterThanOrEq(result1, 91, "Computed property lookup") assertGreaterThanOrEq(result1, 91, "Computed property lookup")

View File

@ -27,7 +27,7 @@ snapshot_kind: text
"value": 0.0, "value": 0.0,
"__meta": [] "__meta": []
}, },
"array": { "arr": {
"type": "Array", "type": "Array",
"value": [ "value": [
{ {
@ -36,8 +36,8 @@ snapshot_kind: text
"__meta": [ "__meta": [
{ {
"sourceRange": [ "sourceRange": [
42,
44, 44,
46,
0 0
] ]
} }
@ -49,8 +49,8 @@ snapshot_kind: text
"__meta": [ "__meta": [
{ {
"sourceRange": [ "sourceRange": [
46,
48, 48,
50,
0 0
] ]
} }
@ -62,8 +62,8 @@ snapshot_kind: text
"__meta": [ "__meta": [
{ {
"sourceRange": [ "sourceRange": [
50,
52, 52,
54,
0 0
] ]
} }
@ -73,8 +73,8 @@ snapshot_kind: text
"__meta": [ "__meta": [
{ {
"sourceRange": [ "sourceRange": [
43, 41,
55, 53,
0 0
] ]
} }
@ -86,8 +86,8 @@ snapshot_kind: text
"__meta": [ "__meta": [
{ {
"sourceRange": [ "sourceRange": [
256, 252,
266, 262,
0 0
] ]
} }
@ -99,8 +99,8 @@ snapshot_kind: text
"__meta": [ "__meta": [
{ {
"sourceRange": [ "sourceRange": [
46,
48, 48,
50,
0 0
] ]
} }
@ -112,8 +112,8 @@ snapshot_kind: text
"__meta": [ "__meta": [
{ {
"sourceRange": [ "sourceRange": [
46,
48, 48,
50,
0 0
] ]
} }

View File

@ -20,8 +20,20 @@ snapshot_kind: text
{ {
"type": "word", "type": "word",
"start": 35, "start": 35,
"end": 38,
"value": "arr"
},
{
"type": "whitespace",
"start": 38,
"end": 39,
"value": " "
},
{
"type": "operator",
"start": 39,
"end": 40, "end": 40,
"value": "array" "value": "="
}, },
{ {
"type": "whitespace", "type": "whitespace",
@ -30,161 +42,167 @@ snapshot_kind: text
"value": " " "value": " "
}, },
{ {
"type": "operator", "type": "brace",
"start": 41, "start": 41,
"end": 42, "end": 42,
"value": "="
},
{
"type": "whitespace",
"start": 42,
"end": 43,
"value": " "
},
{
"type": "brace",
"start": 43,
"end": 44,
"value": "[" "value": "["
}, },
{ {
"type": "number", "type": "number",
"start": 44, "start": 42,
"end": 46, "end": 44,
"value": "90" "value": "90"
}, },
{ {
"type": "comma", "type": "comma",
"start": 46, "start": 44,
"end": 47, "end": 45,
"value": "," "value": ","
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 47, "start": 45,
"end": 48, "end": 46,
"value": " " "value": " "
}, },
{ {
"type": "number", "type": "number",
"start": 48, "start": 46,
"end": 50, "end": 48,
"value": "91" "value": "91"
}, },
{ {
"type": "comma", "type": "comma",
"start": 50, "start": 48,
"end": 51, "end": 49,
"value": "," "value": ","
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 51, "start": 49,
"end": 52, "end": 50,
"value": " " "value": " "
}, },
{ {
"type": "number", "type": "number",
"start": 52, "start": 50,
"end": 54, "end": 52,
"value": "92" "value": "92"
}, },
{ {
"type": "brace", "type": "brace",
"start": 54, "start": 52,
"end": 55, "end": 53,
"value": "]" "value": "]"
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 55, "start": 53,
"end": 57, "end": 55,
"value": "\n\n" "value": "\n\n"
}, },
{ {
"type": "lineComment", "type": "lineComment",
"start": 57, "start": 55,
"end": 80, "end": 78,
"value": "// Test: literal index." "value": "// Test: literal index."
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 80, "start": 78,
"end": 83, "end": 81,
"value": "\n\n\n" "value": "\n\n\n"
}, },
{ {
"type": "word", "type": "word",
"start": 83, "start": 81,
"end": 90, "end": 88,
"value": "result0" "value": "result0"
}, },
{
"type": "whitespace",
"start": 88,
"end": 89,
"value": " "
},
{
"type": "operator",
"start": 89,
"end": 90,
"value": "="
},
{ {
"type": "whitespace", "type": "whitespace",
"start": 90, "start": 90,
"end": 91, "end": 91,
"value": " " "value": " "
}, },
{
"type": "operator",
"start": 91,
"end": 92,
"value": "="
},
{
"type": "whitespace",
"start": 92,
"end": 93,
"value": " "
},
{ {
"type": "word", "type": "word",
"start": 93, "start": 91,
"end": 98, "end": 94,
"value": "array" "value": "arr"
}, },
{ {
"type": "brace", "type": "brace",
"start": 98, "start": 94,
"end": 99, "end": 95,
"value": "[" "value": "["
}, },
{ {
"type": "number", "type": "number",
"start": 99, "start": 95,
"end": 100, "end": 96,
"value": "1" "value": "1"
}, },
{ {
"type": "brace", "type": "brace",
"start": 100, "start": 96,
"end": 101, "end": 97,
"value": "]" "value": "]"
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 101, "start": 97,
"end": 103, "end": 99,
"value": "\n\n" "value": "\n\n"
}, },
{ {
"type": "word", "type": "word",
"start": 103, "start": 99,
"end": 121, "end": 117,
"value": "assertLessThanOrEq" "value": "assertLessThanOrEq"
}, },
{ {
"type": "brace", "type": "brace",
"start": 121, "start": 117,
"end": 122, "end": 118,
"value": "(" "value": "("
}, },
{ {
"type": "word", "type": "word",
"start": 122, "start": 118,
"end": 129, "end": 125,
"value": "result0" "value": "result0"
}, },
{
"type": "comma",
"start": 125,
"end": 126,
"value": ","
},
{
"type": "whitespace",
"start": 126,
"end": 127,
"value": " "
},
{
"type": "number",
"start": 127,
"end": 129,
"value": "91"
},
{ {
"type": "comma", "type": "comma",
"start": 129, "start": 129,
@ -197,60 +215,60 @@ snapshot_kind: text
"end": 131, "end": 131,
"value": " " "value": " "
}, },
{
"type": "number",
"start": 131,
"end": 133,
"value": "91"
},
{
"type": "comma",
"start": 133,
"end": 134,
"value": ","
},
{
"type": "whitespace",
"start": 134,
"end": 135,
"value": " "
},
{ {
"type": "string", "type": "string",
"start": 135, "start": 131,
"end": 160, "end": 156,
"value": "\"Literal property lookup\"" "value": "\"Literal property lookup\""
}, },
{ {
"type": "brace", "type": "brace",
"start": 160, "start": 156,
"end": 161, "end": 157,
"value": ")" "value": ")"
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 161, "start": 157,
"end": 162, "end": 158,
"value": "\n" "value": "\n"
}, },
{ {
"type": "word", "type": "word",
"start": 162, "start": 158,
"end": 183, "end": 179,
"value": "assertGreaterThanOrEq" "value": "assertGreaterThanOrEq"
}, },
{ {
"type": "brace", "type": "brace",
"start": 183, "start": 179,
"end": 184, "end": 180,
"value": "(" "value": "("
}, },
{ {
"type": "word", "type": "word",
"start": 184, "start": 180,
"end": 191, "end": 187,
"value": "result0" "value": "result0"
}, },
{
"type": "comma",
"start": 187,
"end": 188,
"value": ","
},
{
"type": "whitespace",
"start": 188,
"end": 189,
"value": " "
},
{
"type": "number",
"start": 189,
"end": 191,
"value": "91"
},
{ {
"type": "comma", "type": "comma",
"start": 191, "start": 191,
@ -263,316 +281,298 @@ snapshot_kind: text
"end": 193, "end": 193,
"value": " " "value": " "
}, },
{
"type": "number",
"start": 193,
"end": 195,
"value": "91"
},
{
"type": "comma",
"start": 195,
"end": 196,
"value": ","
},
{
"type": "whitespace",
"start": 196,
"end": 197,
"value": " "
},
{ {
"type": "string", "type": "string",
"start": 197, "start": 193,
"end": 222, "end": 218,
"value": "\"Literal property lookup\"" "value": "\"Literal property lookup\""
}, },
{ {
"type": "brace", "type": "brace",
"start": 222, "start": 218,
"end": 223, "end": 219,
"value": ")" "value": ")"
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 223, "start": 219,
"end": 225, "end": 221,
"value": "\n\n" "value": "\n\n"
}, },
{ {
"type": "lineComment", "type": "lineComment",
"start": 225, "start": 221,
"end": 249, "end": 245,
"value": "// Test: computed index." "value": "// Test: computed index."
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 249, "start": 245,
"end": 252, "end": 248,
"value": "\n\n\n" "value": "\n\n\n"
}, },
{ {
"type": "word", "type": "word",
"start": 252, "start": 248,
"end": 253, "end": 249,
"value": "i" "value": "i"
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 253, "start": 249,
"end": 254, "end": 250,
"value": " " "value": " "
}, },
{ {
"type": "operator", "type": "operator",
"start": 254, "start": 250,
"end": 255, "end": 251,
"value": "=" "value": "="
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 255, "start": 251,
"end": 256, "end": 252,
"value": " " "value": " "
}, },
{ {
"type": "word", "type": "word",
"start": 256, "start": 252,
"end": 259, "end": 255,
"value": "int" "value": "int"
}, },
{ {
"type": "brace", "type": "brace",
"start": 255,
"end": 256,
"value": "("
},
{
"type": "number",
"start": 256,
"end": 257,
"value": "1"
},
{
"type": "whitespace",
"start": 257,
"end": 258,
"value": " "
},
{
"type": "operator",
"start": 258,
"end": 259,
"value": "+"
},
{
"type": "whitespace",
"start": 259, "start": 259,
"end": 260, "end": 260,
"value": "(" "value": " "
}, },
{ {
"type": "number", "type": "number",
"start": 260, "start": 260,
"end": 261, "end": 261,
"value": "1"
},
{
"type": "whitespace",
"start": 261,
"end": 262,
"value": " "
},
{
"type": "operator",
"start": 262,
"end": 263,
"value": "+"
},
{
"type": "whitespace",
"start": 263,
"end": 264,
"value": " "
},
{
"type": "number",
"start": 264,
"end": 265,
"value": "0" "value": "0"
}, },
{ {
"type": "brace", "type": "brace",
"start": 265, "start": 261,
"end": 266, "end": 262,
"value": ")" "value": ")"
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 266, "start": 262,
"end": 267, "end": 263,
"value": "\n" "value": "\n"
}, },
{ {
"type": "word", "type": "word",
"start": 267, "start": 263,
"end": 274, "end": 270,
"value": "result1" "value": "result1"
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 274, "start": 270,
"end": 275, "end": 271,
"value": " " "value": " "
}, },
{ {
"type": "operator", "type": "operator",
"start": 275, "start": 271,
"end": 276, "end": 272,
"value": "=" "value": "="
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 276, "start": 272,
"end": 277, "end": 273,
"value": " " "value": " "
}, },
{ {
"type": "word", "type": "word",
"start": 277, "start": 273,
"end": 282, "end": 276,
"value": "array" "value": "arr"
}, },
{ {
"type": "brace", "type": "brace",
"start": 282, "start": 276,
"end": 283, "end": 277,
"value": "[" "value": "["
}, },
{ {
"type": "word", "type": "word",
"start": 283, "start": 277,
"end": 284, "end": 278,
"value": "i" "value": "i"
}, },
{ {
"type": "brace", "type": "brace",
"start": 284, "start": 278,
"end": 285, "end": 279,
"value": "]" "value": "]"
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 285, "start": 279,
"end": 287, "end": 281,
"value": "\n\n" "value": "\n\n"
}, },
{ {
"type": "word", "type": "word",
"start": 287, "start": 281,
"end": 305, "end": 299,
"value": "assertLessThanOrEq" "value": "assertLessThanOrEq"
}, },
{ {
"type": "brace", "type": "brace",
"start": 305, "start": 299,
"end": 306, "end": 300,
"value": "(" "value": "("
}, },
{ {
"type": "word", "type": "word",
"start": 306, "start": 300,
"end": 313, "end": 307,
"value": "result1" "value": "result1"
}, },
{ {
"type": "comma", "type": "comma",
"start": 313, "start": 307,
"end": 314, "end": 308,
"value": "," "value": ","
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 314, "start": 308,
"end": 315, "end": 309,
"value": " " "value": " "
}, },
{ {
"type": "number", "type": "number",
"start": 315, "start": 309,
"end": 317, "end": 311,
"value": "91" "value": "91"
}, },
{ {
"type": "comma", "type": "comma",
"start": 317, "start": 311,
"end": 318, "end": 312,
"value": "," "value": ","
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 318, "start": 312,
"end": 319, "end": 313,
"value": " " "value": " "
}, },
{ {
"type": "string", "type": "string",
"start": 319, "start": 313,
"end": 345, "end": 339,
"value": "\"Computed property lookup\"" "value": "\"Computed property lookup\""
}, },
{ {
"type": "brace", "type": "brace",
"start": 345, "start": 339,
"end": 346, "end": 340,
"value": ")" "value": ")"
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 346, "start": 340,
"end": 347, "end": 341,
"value": "\n" "value": "\n"
}, },
{ {
"type": "word", "type": "word",
"start": 347, "start": 341,
"end": 368, "end": 362,
"value": "assertGreaterThanOrEq" "value": "assertGreaterThanOrEq"
}, },
{ {
"type": "brace", "type": "brace",
"start": 368, "start": 362,
"end": 369, "end": 363,
"value": "(" "value": "("
}, },
{ {
"type": "word", "type": "word",
"start": 369, "start": 363,
"end": 376, "end": 370,
"value": "result1" "value": "result1"
}, },
{ {
"type": "comma", "type": "comma",
"start": 376, "start": 370,
"end": 377, "end": 371,
"value": "," "value": ","
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 377, "start": 371,
"end": 378, "end": 372,
"value": " " "value": " "
}, },
{ {
"type": "number", "type": "number",
"start": 378, "start": 372,
"end": 380, "end": 374,
"value": "91" "value": "91"
}, },
{ {
"type": "comma", "type": "comma",
"start": 380, "start": 374,
"end": 381, "end": 375,
"value": "," "value": ","
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 381, "start": 375,
"end": 382, "end": 376,
"value": " " "value": " "
}, },
{ {
"type": "string", "type": "string",
"start": 382, "start": 376,
"end": 408, "end": 402,
"value": "\"Computed property lookup\"" "value": "\"Computed property lookup\""
}, },
{ {
"type": "brace", "type": "brace",
"start": 408, "start": 402,
"end": 409, "end": 403,
"value": ")" "value": ")"
}, },
{ {
"type": "whitespace", "type": "whitespace",
"start": 409, "start": 403,
"end": 410, "end": 404,
"value": "\n" "value": "\n"
} }
] ]

View File

@ -27,7 +27,7 @@ fn Gte = (a, b) => { return Not(Lt(a, b)) }
deg = pi()*2 / 360 deg = pi()*2 / 360
fn setSketch = (state, _) => { fn setSketch = (state, _q) => {
return { return {
depthMax: state.depthMax, depthMax: state.depthMax,
depth: state.depth + 1, depth: state.depth + 1,
@ -35,43 +35,43 @@ fn setSketch = (state, _) => {
factor: state.factor, factor: state.factor,
currentAngle: state.currentAngle, currentAngle: state.currentAngle,
angle: state.angle, angle: state.angle,
_: _ _q: _q
} }
} }
fn setDepth = (state, _) => { fn setDepth = (state, _q) => {
return { return {
depthMax: state.depthMax, depthMax: state.depthMax,
depth: _, depth: _q,
currentLength: state.currentLength, currentLength: state.currentLength,
factor: state.factor, factor: state.factor,
currentAngle: state.currentAngle, currentAngle: state.currentAngle,
angle: state.angle, angle: state.angle,
_: state._ _q: state._q
} }
} }
fn setAngle = (state, _) => { fn setAngle = (state, _q) => {
return { return {
depthMax: state.depthMax, depthMax: state.depthMax,
depth: state.depth, depth: state.depth,
currentLength: state.currentLength, currentLength: state.currentLength,
factor: state.factor, factor: state.factor,
currentAngle: _, currentAngle: _q,
angle: state.angle, angle: state.angle,
_: state._ _q: state._q
} }
} }
fn setLength = (state, _) => { fn setLength = (state, _q) => {
return { return {
depthMax: state.depthMax, depthMax: state.depthMax,
depth: state.depth, depth: state.depth,
currentLength: _, currentLength: _q,
factor: state.factor, factor: state.factor,
currentAngle: state.currentAngle, currentAngle: state.currentAngle,
angle: state.angle, angle: state.angle,
_: state._ _q: state._q
} }
} }
@ -95,7 +95,7 @@ fn F = (state, F) => {
} else { } else {
// Pass onto the next instruction // Pass onto the next instruction
state |> setSketch(%, angledLine({ angle: state.currentAngle, length: state.currentLength }, state._)) state |> setSketch(%, angledLine({ angle: state.currentAngle, length: state.currentLength }, state._q))
} }
} }
@ -107,7 +107,7 @@ fn LSystem = (args, axioms) => {
factor: args.factor, factor: args.factor,
currentAngle: 0, currentAngle: 0,
angle: args.angle, angle: args.angle,
_: startSketchAt([0, 0]), _q: startSketchAt([0, 0]),
}) })
} }
@ -115,7 +115,7 @@ LSystem({
iterations: 1, iterations: 1,
factor: 1.36, factor: 1.36,
angle: 60, angle: 60,
}, (_) => { }, (_q) => {
result = _ |> F(%, F) |> Add(%) |> Add(%) |> F(%, F) |> Add(%) |> Add(%) |> F(%, F) result = _q |> F(%, F) |> Add(%) |> Add(%) |> F(%, F) |> Add(%) |> Add(%) |> F(%, F)
return result._ return result._q
}) })

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB