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.
// It uses the `reduce` function, to call the `add` function on every
// element of the `array` parameter. The starting value is 0.
fn sum = (array) => {
return reduce(array, 0, add)
// element of the `arr` parameter. The starting value is 0.
fn sum = (arr) => {
return reduce(arr, 0, add)
}
/* The above is basically like this pseudo-code:
fn sum(array):
fn sum(arr):
let sumSoFar = 0
for i in array:
for i in arr:
sumSoFar = add(sumSoFar, i)
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
// an anonymous `add` function as its parameter, instead of declaring a
// named function outside.
array = [1, 2, 3]
sum = reduce(array, 0, (i, result_so_far) => {
arr = [1, 2, 3]
sum = reduce(arr, 0, (i, result_so_far) => {
return i + result_so_far
})

View File

@ -162561,8 +162561,8 @@
"unpublished": false,
"deprecated": false,
"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 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 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.\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(%)"
]
},

View File

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

View File

@ -21,6 +21,7 @@ convert_case = "0.6.0"
dashmap = "6.1.0"
databake = { version = "0.1.8", features = ["derive"] }
derive-docs = { version = "0.1.29", path = "../derive-docs" }
fnv = "1.0.7"
form_urlencoded = "1.2.1"
futures = { version = "0.3.31" }
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")]
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')
|> startProfileAt(array[0], %)
|> line([0, array[1]], %)
|> line([array[2], 0], %)
|> line([0, -array[1]], %)
|> startProfileAt(arr[0], %)
|> line([0, arr[1]], %)
|> line([arr[2], 0], %)
|> line([0, -arr[1]], %)
|> close(%)
|> extrude(array[3], %)
|> extrude(arr[3], %)
return myBox
}

View File

@ -2040,11 +2040,39 @@ fn fn_call(i: TokenSlice) -> PResult<Node<CallExpression>> {
#[cfg(test)]
mod tests {
use itertools::Itertools;
use pretty_assertions::assert_eq;
use super::*;
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]
fn parse_args() {
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.
/// // It uses the `reduce` function, to call the `add` function on every
/// // element of the `array` parameter. The starting value is 0.
/// fn sum = (array) => { return reduce(array, 0, add) }
/// // element of the `arr` parameter. The starting value is 0.
/// fn sum = (arr) => { return reduce(arr, 0, add) }
///
/// /*
/// The above is basically like this pseudo-code:
/// fn sum(array):
/// fn sum(arr):
/// let sumSoFar = 0
/// for i in array:
/// for i in arr:
/// sumSoFar = add(sumSoFar, i)
/// 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
/// // an anonymous `add` function as its parameter, instead of declaring a
/// // named function outside.
/// array = [1, 2, 3]
/// sum = reduce(array, 0, (i, result_so_far) => { return i + result_so_far })
/// arr = [1, 2, 3]
/// sum = reduce(arr, 0, (i, result_so_far) => { return i + result_so_far })
///
/// // We use `assertEqual` to check that our `sum` function gives the
/// // expected result. It's good to check your work!

View File

@ -17,6 +17,8 @@ mod tokeniser;
// Re-export
pub use tokeniser::Input;
#[cfg(test)]
pub(crate) use tokeniser::RESERVED_WORDS;
/// The types of tokens.
#[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::{
ascii::{digit1, multispace1},
combinator::{alt, opt, peek, preceded, repeat, terminated},
combinator::{alt, opt, peek, preceded, repeat},
error::{ContextError, ParseError},
prelude::*,
stream::{Location, Stream},
@ -13,6 +15,52 @@ use crate::{
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>> {
let state = State::new(module_id);
let input = Input {
@ -50,7 +98,7 @@ pub fn token(i: &mut Input<'_>) -> PResult<Token> {
'$' => dollar,
'!' => alt((operator, bang)),
' ' | '\t' | '\n' => whitespace,
_ => alt((operator, keyword,type_, word))
_ => alt((operator, keyword_type_or_word))
}
.parse_next(i)
{
@ -287,47 +335,16 @@ fn import_keyword(i: &mut Input<'_>) -> PResult<Token> {
))
}
fn unambiguous_keywords(i: &mut Input<'_>) -> PResult<Token> {
// These are the keywords themselves.
let keyword_candidates = alt((
"if", "else", "for", "while", "return", "break", "continue", "fn", "let", "mut", "loop", "true", "false",
"nil", "and", "or", "not", "var", "const", "export",
));
// 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 unambiguous_keyword_type_or_word(i: &mut Input<'_>) -> PResult<Token> {
let mut w = word.parse_next(i)?;
if let Some(token_type) = RESERVED_WORDS.get(w.value.as_str()) {
w.token_type = *token_type;
}
Ok(w)
}
fn keyword(i: &mut Input<'_>) -> PResult<Token> {
alt((import_keyword, unambiguous_keywords)).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(),
))
fn keyword_type_or_word(i: &mut Input<'_>) -> PResult<Token> {
alt((import_keyword, unambiguous_keyword_type_or_word)).parse_next(i)
}
#[cfg(test)]

View File

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

View File

@ -1,12 +1,12 @@
// This tests indexing an array.
array = [90, 91, 92]
arr = [90, 91, 92]
// Test: literal index.
result0 = array[1]
result0 = arr[1]
assertLessThanOrEq(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)
result1 = array[i]
result1 = arr[i]
assertLessThanOrEq(result1, 91, "Computed property lookup")
assertGreaterThanOrEq(result1, 91, "Computed property lookup")

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB