KCL: User-defined KCL functions in examples etc now use keywords (#6603)

Preparing for the removal of positional functions from the language. The first big step is to change all our KCL code examples, test code, public samples etc to all use keyword functions.

Apologies for how large this PR is. Most of it is:

- Changing example KCL that defined its own functions, so the functions now use keyword arguments rather than positional arguments. E.g. change `cube([20, 20])` to be `cube(center = [20, 20])`.
- Some parts of the code assumed positional code and didn't handle keyword calls, e.g. the linter would only check for positional calls to startSketchOn. Now they should work with either positional or keyword.
- Update all the artifacts

This does _not_ remove support for positional calls. That will be in a follow-up PR.
This commit is contained in:
Adam Chalmers
2025-05-01 11:36:51 -05:00
committed by GitHub
parent 16f5d9c284
commit 89bae66257
254 changed files with 32085 additions and 20108 deletions

View File

@ -2187,7 +2187,15 @@ fn assign_args_to_params_kw(
.mut_stack()
.add(param.identifier.name.clone(), arg_val, (&param.identifier).into())?;
} else {
let Some(unlabeled) = args.unlabeled.take() else {
// TODO: Get the actual source range.
// Part of https://github.com/KittyCAD/modeling-app/issues/6613
let pipe_value_source_range = Default::default();
let default_unlabeled = exec_state
.mod_local
.pipe_value
.clone()
.map(|val| Arg::new(val, pipe_value_source_range));
let Some(unlabeled) = args.unlabeled.take().or(default_unlabeled) else {
let param_name = &param.identifier.name;
return Err(if args.labeled.contains_key(param_name) {
KclError::Semantic(KclErrorDetails {

View File

@ -1298,16 +1298,16 @@ mod tests {
#[tokio::test(flavor = "multi_thread")]
async fn test_execute_fn_definitions() {
let ast = r#"fn def(x) {
let ast = r#"fn def(@x) {
return x
}
fn ghi(x) {
fn ghi(@x) {
return x
}
fn jkl(x) {
fn jkl(@x) {
return x
}
fn hmm(x) {
fn hmm(@x) {
return x
}
@ -1408,7 +1408,7 @@ firstExtrude = startSketchOn(XY)
l = 8
h = 10
fn thing(x) {
fn thing(@x) {
return -x
}
@ -1429,7 +1429,7 @@ firstExtrude = startSketchOn(XY)
l = 8
h = 10
fn thing(x) {
fn thing(@x) {
return [0, -x]
}
@ -1450,11 +1450,11 @@ firstExtrude = startSketchOn(XY)
l = 8
h = 10
fn other_thing(y) {
fn other_thing(@y) {
return -y
}
fn thing(x) {
fn thing(@x) {
return other_thing(x)
}
@ -1483,14 +1483,14 @@ firstExtrude = startSketchOn(XY)
return myBox
}
fnBox = box(3, 6, 10)"#;
fnBox = box(h = 3, l = 6, w = 10)"#;
parse_execute(ast).await.unwrap();
}
#[tokio::test(flavor = "multi_thread")]
async fn test_get_member_of_object_with_function_period() {
let ast = r#"fn box(obj) {
let ast = r#"fn box(@obj) {
myBox = startSketchOn(XY)
|> startProfile(at = obj.start)
|> line(end = [0, obj.l])
@ -1577,7 +1577,7 @@ 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(arr) {
let ast = r#"fn box(@arr) {
myBox =startSketchOn(XY)
|> startProfile(at = arr[0])
|> line(end = [0, arr[1]])
@ -1623,7 +1623,7 @@ answer = returnX()"#;
#[tokio::test(flavor = "multi_thread")]
async fn type_aliases() {
let text = r#"type MyTy = [number; 2]
fn foo(x: MyTy) {
fn foo(@x: MyTy) {
return x[0]
}
@ -1783,7 +1783,7 @@ fn check(x) {
assertIs(!x, error = "expected argument to be false")
return true
}
check(false)
check(x = false)
"#;
let result = parse_execute(ast).await.unwrap();
assert_eq!(
@ -1961,7 +1961,7 @@ bracket = startSketchOn(XY)
#[tokio::test(flavor = "multi_thread")]
async fn test_execute_function_no_return() {
let ast = r#"fn test(origin) {
let ast = r#"fn test(@origin) {
origin
}
@ -2154,7 +2154,7 @@ w = f() + f()
#[tokio::test(flavor = "multi_thread")]
async fn read_tag_version() {
let ast = r#"fn bar(t) {
let ast = r#"fn bar(@t) {
return startSketchOn(XY)
|> startProfile(at = [0,0])
|> angledLine(

View File

@ -5,7 +5,10 @@ use crate::{
errors::Suggestion,
execution::{types::UnitLen, PlaneInfo, Point3d},
lint::rule::{def_finding, Discovered, Finding},
parsing::ast::types::{BinaryPart, Expr, LiteralValue, Node as AstNode, ObjectExpression, Program, UnaryOperator},
parsing::ast::types::{
BinaryPart, CallExpression, CallExpressionKw, Expr, LiteralValue, Node as AstNode, ObjectExpression, Program,
UnaryOperator,
},
walk::Node,
SourceRange,
};
@ -124,10 +127,16 @@ fn get_offset(info: &PlaneInfo) -> Option<f64> {
}
pub fn start_sketch_on_check_specific_plane(node: Node) -> Result<Option<(SourceRange, PlaneName, f64)>> {
let Node::CallExpression(call) = node else {
return Ok(None);
};
match node {
Node::CallExpression(node) => start_sketch_on_check_specific_plane_pos(node),
Node::CallExpressionKw(node) => start_sketch_on_check_specific_plane_kw(node),
_ => Ok(None),
}
}
pub fn start_sketch_on_check_specific_plane_pos(
call: &AstNode<CallExpression>,
) -> Result<Option<(SourceRange, PlaneName, f64)>> {
if call.inner.callee.inner.name.name != "startSketchOn" {
return Ok(None);
}
@ -147,7 +156,34 @@ pub fn start_sketch_on_check_specific_plane(node: Node) -> Result<Option<(Source
let Expr::ObjectExpression(arg) = &call.arguments[0] else {
return Ok(None);
};
common(arg, call_source_range)
}
pub fn start_sketch_on_check_specific_plane_kw(
call: &AstNode<CallExpressionKw>,
) -> Result<Option<(SourceRange, PlaneName, f64)>> {
if call.inner.callee.inner.name.name != "startSketchOn" {
return Ok(None);
}
let Some(ref unlabeled) = call.inner.unlabeled else {
// we only look for single-argument object patterns, if there's more
// than that we don't have a plane decl
return Ok(None);
};
let call_source_range = SourceRange::new(unlabeled.start(), unlabeled.end(), unlabeled.module_id());
let Expr::ObjectExpression(arg) = &unlabeled else {
return Ok(None);
};
common(arg, call_source_range)
}
pub fn common(
arg: &AstNode<ObjectExpression>,
call_source_range: SourceRange,
) -> Result<Option<(SourceRange, PlaneName, f64)>> {
let mut origin: Option<Point3d> = None;
let mut x_vec: Option<Point3d> = None;
let mut y_vec: Option<Point3d> = None;

View File

@ -533,6 +533,23 @@ impl Backend {
return Ok(false);
}
}
crate::walk::Node::CallExpressionKw(call_expr) => {
let sr: SourceRange = (&call_expr.callee).into();
if sr.contains(source_range.start()) {
let mut ti = token_index.lock().map_err(|_| anyhow::anyhow!("mutex"))?;
*ti = match self.get_semantic_token_type_index(&SemanticTokenType::FUNCTION) {
Some(index) => index,
None => token_type_index,
};
if self.stdlib_completions.contains_key(&call_expr.callee.name.name) {
// This is a stdlib function.
return get_modifier(vec![SemanticTokenModifier::DEFAULT_LIBRARY]);
}
return Ok(false);
}
}
_ => {}
}
Ok(true)

View File

@ -895,7 +895,7 @@ async fn test_kcl_lsp_on_hover() {
foo = 42
foo
fn bar(x: string): string {
fn bar(@x: string): string {
return x
}
@ -971,7 +971,7 @@ startSketchOn(XY)
match hover.unwrap().contents {
tower_lsp::lsp_types::HoverContents::Markup(tower_lsp::lsp_types::MarkupContent { value, .. }) => {
assert!(value.contains("bar(x: string): string"));
assert!(value.contains("bar(@x: string): string"));
}
_ => unreachable!(),
}
@ -2027,7 +2027,7 @@ insideRevolve = startSketchOn(XZ)
|> line(end = [0, -thickness])
|> line(end = [-overHangLength, 0])
|> close()
|> revolve({ axis = Y }, %)
|> revolve(axis = Y)
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
sphere = startSketchOn(XZ)
@ -2035,7 +2035,7 @@ sphere = startSketchOn(XZ)
|> line(end = [sphereDia - 0.1, 0])
|> arc(angle_start = 0, angle_end = -180, radius = sphereDia / 2 - 0.05)
|> close()
|> revolve({ axis = X }, %)
|> revolve(axis = X)
|> patternCircular3d(
axis = [0, 0, 1],
center = [0, 0, 0],
@ -2056,7 +2056,7 @@ outsideRevolve = startSketchOn(XZ)
|> line(end = [0, thickness])
|> line(end = [overHangLength - thickness, 0])
|> close()
|> revolve({ axis = Y }, %)"#
|> revolve(axis = Y)"#
.to_string(),
},
})
@ -2090,7 +2090,7 @@ outsideRevolve = startSketchOn(XZ)
start: tower_lsp::lsp_types::Position { line: 0, character: 0 },
end: tower_lsp::lsp_types::Position {
line: 50,
character: 29
character: 22
}
}
);
@ -2117,7 +2117,7 @@ insideRevolve = startSketchOn(XZ)
|> line(end = [0, -thickness])
|> line(end = [-overHangLength, 0])
|> close()
|> revolve({ axis = Y }, %)
|> revolve(axis = Y)
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
sphere = startSketchOn(XZ)
@ -2128,7 +2128,7 @@ sphere = startSketchOn(XZ)
|> line(end = [sphereDia - 0.1, 0])
|> arc(angle_start = 0, angle_end = -180, radius = sphereDia / 2 - 0.05)
|> close()
|> revolve({ axis = X }, %)
|> revolve(axis = X)
|> patternCircular3d(
axis = [0, 0, 1],
center = [0, 0, 0],
@ -2152,7 +2152,7 @@ outsideRevolve = startSketchOn(XZ)
|> line(end = [0, thickness])
|> line(end = [overHangLength - thickness, 0])
|> close()
|> revolve({ axis = Y }, %)"#
|> revolve(axis = Y)"#
);
}
@ -3891,7 +3891,7 @@ async fn test_kcl_lsp_on_hover_untitled_file_scheme() {
foo = 42
foo
fn bar(x: string): string {
fn bar(@x: string): string {
return x
}
@ -3967,7 +3967,7 @@ startSketchOn(XY)
match hover.unwrap().contents {
tower_lsp::lsp_types::HoverContents::Markup(tower_lsp::lsp_types::MarkupContent { value, .. }) => {
assert!(value.contains("bar(x: string): string"));
assert!(value.contains("bar(@x: string): string"));
}
_ => unreachable!(),
}

View File

@ -529,13 +529,13 @@ mod test {
async fn test_parse_digest() {
let prog1_string = r#"startSketchOn(XY)
|> startProfile(at = [0, 0])
|> line([5, 5], %)
|> line([5, 5])
"#;
let prog1_digest = crate::parsing::top_level_parse(prog1_string).unwrap().compute_digest();
let prog2_string = r#"startSketchOn(XY)
|> startProfile(at = [0, 2])
|> line([5, 5], %)
|> line([5, 5])
"#;
let prog2_digest = crate::parsing::top_level_parse(prog2_string).unwrap().compute_digest();
@ -543,7 +543,7 @@ mod test {
let prog3_string = r#"startSketchOn(XY)
|> startProfile(at = [0, 0])
|> line([5, 5], %)
|> line([5, 5])
"#;
let prog3_digest = crate::parsing::top_level_parse(prog3_string).unwrap().compute_digest();

View File

@ -3739,11 +3739,11 @@ mod tests {
fn test_get_lsp_folding_ranges() {
let code = r#"part001 = startSketchOn(XY)
|> startProfile(at = [0.0000000000, 5.0000000000])
|> line([0.4900857016, -0.0240763666], %)
|> line([0.4900857016, -0.0240763666])
startSketchOn(XY)
|> startProfile(at = [0.0000000000, 5.0000000000])
|> line([0.4900857016, -0.0240763666], %)
|> line([0.4900857016, -0.0240763666])
part002 = "part002"
things = [part001, 0.0]
@ -3751,7 +3751,7 @@ blah = 1
foo = false
baz = {a = 1, b = "thing"}
fn ghi(x) {
fn ghi(@x) {
return x
}
@ -3761,24 +3761,24 @@ ghi("things")
let folding_ranges = program.get_lsp_folding_ranges();
assert_eq!(folding_ranges.len(), 3);
assert_eq!(folding_ranges[0].start_line, 27);
assert_eq!(folding_ranges[0].end_line, 126);
assert_eq!(folding_ranges[0].end_line, 123);
assert_eq!(
folding_ranges[0].collapsed_text,
Some("part001 = startSketchOn(XY)".to_string())
);
assert_eq!(folding_ranges[1].start_line, 145);
assert_eq!(folding_ranges[1].end_line, 244);
assert_eq!(folding_ranges[1].start_line, 142);
assert_eq!(folding_ranges[1].end_line, 238);
assert_eq!(folding_ranges[1].collapsed_text, Some("startSketchOn(XY)".to_string()));
assert_eq!(folding_ranges[2].start_line, 350);
assert_eq!(folding_ranges[2].end_line, 363);
assert_eq!(folding_ranges[2].collapsed_text, Some("fn ghi(x) {".to_string()));
assert_eq!(folding_ranges[2].start_line, 345);
assert_eq!(folding_ranges[2].end_line, 358);
assert_eq!(folding_ranges[2].collapsed_text, Some("fn ghi(@x) {".to_string()));
}
#[test]
fn test_get_lsp_symbols() {
let code = r#"part001 = startSketchOn(XY)
|> startProfile(at = [0.0000000000, 5.0000000000])
|> line([0.4900857016, -0.0240763666], %)
|> line([0.4900857016, -0.0240763666])
part002 = "part002"
things = [part001, 0.0]
@ -3804,12 +3804,12 @@ h = 30
cylinder = startSketchOn(-XZ)
|> startProfile(at = [50, 0])
|> arc({
|> arc(
angle_end = 360,
angle_start = 0,
radius = r
}, %)
|> extrude(h, %)
)
|> extrude(h)
"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
@ -3825,12 +3825,12 @@ h = 30
cylinder = startSketchOn(-XZ)
|> startProfile(at = [50, 0])
// comment
|> arc({
|> arc(
angle_end= 360,
angle_start= 0,
radius= r
}, %)
|> extrude(h, %)
)
|> extrude(h)
"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
@ -4105,7 +4105,7 @@ cylinder = startSketchOn(-XZ)
#[tokio::test(flavor = "multi_thread")]
async fn test_parse_object_bool() {
let some_program_string = r#"some_func({thing: true, other_thing: false})"#;
let some_program_string = r#"some_func({thing = true, other_thing = false})"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
// We want to get the bool and verify it is a bool.
@ -4123,14 +4123,22 @@ cylinder = startSketchOn(-XZ)
panic!("expected a function!");
};
let Expr::CallExpression(ce) = expression else {
panic!("expected a function!");
};
let oe = match expression {
Expr::CallExpressionKw(ce) => {
assert!(ce.unlabeled.is_some());
assert!(!ce.arguments.is_empty());
let Expr::ObjectExpression(oe) = ce.arguments.first().unwrap() else {
panic!("expected a object!");
let Expr::ObjectExpression(oe) = ce.unlabeled.as_ref().unwrap() else {
panic!("expected a object!");
};
oe
}
Expr::CallExpression(ce) => {
let Expr::ObjectExpression(ref oe) = (ce.arguments).first().unwrap() else {
panic!("expected an object!");
};
oe
}
other => panic!("expected a Call or CallKw, found {other:?}"),
};
assert_eq!(oe.properties.len(), 2);

View File

@ -14,7 +14,7 @@ use winnow::{
};
use super::{
ast::types::{AscribedExpression, ImportPath, LabelledExpression},
ast::types::{AscribedExpression, CallExpression, ImportPath, LabelledExpression},
token::{NumericSuffix, RESERVED_WORDS},
DeprecationKind,
};
@ -24,13 +24,12 @@ use crate::{
parsing::{
ast::types::{
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
BoxNode, CallExpression, CallExpressionKw, CommentStyle, DefaultParamVal, ElseIf, Expr,
ExpressionStatement, FunctionExpression, Identifier, IfExpression, ImportItem, ImportSelector,
ImportStatement, ItemVisibility, LabeledArg, Literal, LiteralIdentifier, LiteralValue, MemberExpression,
MemberObject, Name, Node, NodeList, NonCodeMeta, NonCodeNode, NonCodeValue, ObjectExpression,
ObjectProperty, Parameter, PipeExpression, PipeSubstitution, PrimitiveType, Program, ReturnStatement,
Shebang, TagDeclarator, Type, TypeDeclaration, UnaryExpression, UnaryOperator, VariableDeclaration,
VariableDeclarator, VariableKind,
BoxNode, CallExpressionKw, CommentStyle, DefaultParamVal, ElseIf, Expr, ExpressionStatement,
FunctionExpression, Identifier, IfExpression, ImportItem, ImportSelector, ImportStatement, ItemVisibility,
LabeledArg, Literal, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, Name, Node, NodeList,
NonCodeMeta, NonCodeNode, NonCodeValue, ObjectExpression, ObjectProperty, Parameter, PipeExpression,
PipeSubstitution, PrimitiveType, Program, ReturnStatement, Shebang, TagDeclarator, Type, TypeDeclaration,
UnaryExpression, UnaryOperator, VariableDeclaration, VariableDeclarator, VariableKind,
},
math::BinaryExpressionToken,
token::{Token, TokenSlice, TokenType},
@ -3047,6 +3046,46 @@ fn fn_call_kw(i: &mut TokenSlice) -> PResult<Node<CallExpressionKw>> {
let _ = open_paren.parse_next(i)?;
ignore_whitespace(i);
// Special case: no args
let early_close = peek(close_paren).parse_next(i);
if early_close.is_ok() {
let cl = close_paren.parse_next(i)?;
let result = Node::new_node(
fn_name.start,
cl.end,
fn_name.module_id,
CallExpressionKw {
callee: fn_name,
unlabeled: Default::default(),
arguments: Default::default(),
digest: None,
non_code_meta: Default::default(),
},
);
return Ok(result);
}
// Special case: one arg (unlabeled)
let early_close = peek((expression, opt(whitespace), close_paren)).parse_next(i);
if early_close.is_ok() {
let first_expression = expression.parse_next(i)?;
ignore_whitespace(i);
let end = close_paren.parse_next(i)?.end;
let result = Node::new_node(
fn_name.start,
end,
fn_name.module_id,
CallExpressionKw {
callee: fn_name,
unlabeled: Some(first_expression),
arguments: Default::default(),
digest: None,
non_code_meta: Default::default(),
},
);
return Ok(result);
}
#[allow(clippy::large_enum_variant)]
enum ArgPlace {
NonCode(Node<NonCodeNode>),
@ -3834,7 +3873,7 @@ mySk1 = startSketchOn(XY)
#[test]
fn pipes_on_pipes_minimal() {
let test_program = r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(endAbsolute = [0, -0]) // MoveRelative
"#;
@ -4105,7 +4144,7 @@ mySk1 = startSketchOn(XY)
fn test_parse_half_pipe_small() {
assert_err_contains(
"secondExtrude = startSketchOn(XY)
|> startProfileAt([0,0], %)
|> startProfile(at = [0,0])
|",
"Unexpected token: |",
);
@ -4169,7 +4208,7 @@ height = [obj["a"] -1, 0]"#;
#[test]
fn test_anon_fn() {
crate::parsing::top_level_parse("foo(42, fn(x) { return x + 1 })").unwrap();
crate::parsing::top_level_parse("foo(num=42, closure=fn(x) { return x + 1 })").unwrap();
}
#[test]
@ -4198,15 +4237,15 @@ height = [obj["a"] -1, 0]"#;
let code = "height = 10
firstExtrude = startSketchOn(XY)
|> startProfileAt([0,0], %)
|> line([0, 8], %)
|> line([20, 0], %)
|> line([0, -8], %)
|> startProfile(at = [0,0])
|> line(at = [0, 8])
|> line(at = [20, 0])
|> line(at = [0, -8])
|> close()
|> extrude(length=2)
secondExtrude = startSketchOn(XY)
|> startProfileAt([0,0], %)
|> startProfile(at = [0,0])
|";
assert_err_contains(code, "Unexpected token: |");
}
@ -4477,7 +4516,7 @@ e
///
/// ```
/// exampleSketch = startSketchOn(XZ)
/// |> startProfileAt([0, 0], %)
/// |> startProfile(at = [0, 0])
/// |> angledLine(
/// angle = 30,
/// length = 3 / cos(toRadians(30)),
@ -4517,7 +4556,7 @@ export fn cos(num: number(rad)): number(_) {}"#;
#[test]
fn error_underscore() {
let (_, errs) = assert_no_fatal("_foo(_blah, _)");
let (_, errs) = assert_no_fatal("_foo(a=_blah, b=_)");
assert_eq!(errs.len(), 3, "found: {errs:#?}");
}
@ -4629,11 +4668,11 @@ thing(false)
#[test]
fn random_words_fail() {
let test_program = r#"part001 = startSketchOn(-XZ)
|> startProfileAt([8.53, 11.8], %)
|> startProfile(at = [8.53, 11.8])
asdasd asdasd
|> line([11.12, -14.82], %)
|> line([-13.27, -6.98], %)
|> line([-5.09, 12.33], %)
|> line(at = [11.12, -14.82])
|> line(at = [-13.27, -6.98])
|> line(at = [-5.09, 12.33])
asdasd
"#;
let _ = crate::parsing::top_level_parse(test_program).unwrap_errs();
@ -4643,16 +4682,16 @@ thing(false)
fn test_member_expression_sketch() {
let some_program_string = r#"fn cube(pos, scale) {
sg = startSketchOn(XY)
|> startProfileAt(pos, %)
|> line([0, scale], %)
|> line([scale, 0], %)
|> line([0, -scale], %)
|> startProfile(pos)
|> line(at = [0, scale])
|> line(at = [scale, 0])
|> line(at = [0, -scale])
return sg
}
b1 = cube([0,0], 10)
b2 = cube([3,3], 4)
b1 = cube(pos=[0,0], scale=10)
b2 = cube(pos=[3,3], scale=4)
pt1 = b1[0]
pt2 = b2[0]
@ -4671,16 +4710,16 @@ let other_thing = 2 * cos(3)"#;
fn test_negative_arguments() {
let some_program_string = r#"fn box(p, h, l, w) {
myBox = startSketchOn(XY)
|> startProfileAt(p, %)
|> line([0, l], %)
|> line([w, 0], %)
|> line([0, -l], %)
|> startProfile(p)
|> line(at = [0, l])
|> line(at = [w, 0])
|> line(at = [0, -l])
|> close()
|> extrude(length=h)
return myBox
}
let myBox = box([0,0], -3, -16, -10)
let myBox = box(p=[0,0], h=-3, l=-16, w=-10)
"#;
crate::parsing::top_level_parse(some_program_string).unwrap();
}
@ -4697,20 +4736,20 @@ let myBox = box([0,0], -3, -16, -10)
#[test]
fn test_parse_tag_named_std_lib() {
let some_program_string = r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line([5, 5], %, $xLine)
|> startProfile(at = [0, 0])
|> line(%, end = [5, 5], tag = $xLine)
"#;
assert_err(
some_program_string,
"Cannot assign a tag to a reserved keyword: xLine",
[74, 80],
[86, 92],
);
}
#[test]
fn test_parse_empty_tag_brace() {
let some_program_string = r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(%, $)
"#;
assert_err(some_program_string, "Tag names must not be empty", [67, 68]);
@ -4718,7 +4757,7 @@ let myBox = box([0,0], -3, -16, -10)
#[test]
fn test_parse_empty_tag_whitespace() {
let some_program_string = r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(%, $ ,01)
"#;
assert_err(some_program_string, "Tag names must not be empty", [67, 68]);
@ -4727,7 +4766,7 @@ let myBox = box([0,0], -3, -16, -10)
#[test]
fn test_parse_empty_tag_comma() {
let some_program_string = r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(%, $,)
"#;
assert_err(some_program_string, "Tag names must not be empty", [67, 68]);
@ -4736,7 +4775,7 @@ let myBox = box([0,0], -3, -16, -10)
fn test_parse_tag_starting_with_digit() {
let some_program_string = r#"
startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(%, $01)"#;
assert_err(
some_program_string,
@ -4748,14 +4787,14 @@ let myBox = box([0,0], -3, -16, -10)
fn test_parse_tag_including_digit() {
let some_program_string = r#"
startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line(%, $var01)"#;
|> startProfile(at = [0, 0])
|> line(%, tag = $var01)"#;
assert_no_err(some_program_string);
}
#[test]
fn test_parse_tag_starting_with_bang() {
let some_program_string = r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(%, $!var,01)
"#;
assert_err(some_program_string, "Tag names must not start with a bang", [67, 68]);
@ -4763,7 +4802,7 @@ let myBox = box([0,0], -3, -16, -10)
#[test]
fn test_parse_tag_starting_with_dollar() {
let some_program_string = r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(%, $$,01)
"#;
assert_err(some_program_string, "Tag names must not start with a dollar", [67, 68]);
@ -4771,7 +4810,7 @@ let myBox = box([0,0], -3, -16, -10)
#[test]
fn test_parse_tag_starting_with_fn() {
let some_program_string = r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(%, $fn,01)
"#;
assert_err(some_program_string, "Tag names must not start with a keyword", [67, 69]);
@ -4779,7 +4818,7 @@ let myBox = box([0,0], -3, -16, -10)
#[test]
fn test_parse_tag_starting_with_a_comment() {
let some_program_string = r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(%, $//
,01)
"#;
@ -4794,8 +4833,8 @@ let myBox = box([0,0], -3, -16, -10)
fn test_parse_tag_with_reserved_in_middle_works() {
let some_program_string = r#"
startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line([5, 5], %, $sketching)
|> startProfile(at = [0, 0])
|> line(end = [5, 5], tag = $sketching)
"#;
assert_no_err(some_program_string);
}
@ -4803,21 +4842,21 @@ let myBox = box([0,0], -3, -16, -10)
#[test]
fn test_parse_array_missing_closing_bracket() {
let some_program_string = r#"
sketch001 = startSketchOn(XZ) |> startProfileAt([90.45, 119.09, %)"#;
sketch001 = startSketchOn(XZ) |> startProfile(at = [90.45, 119.09)"#;
assert_err(
some_program_string,
"Encountered an unexpected character(s) before finding a closing bracket(`]`) for the array",
[49, 65],
[52, 60],
);
}
#[test]
fn test_parse_array_missing_comma() {
let some_program_string = r#"
sketch001 = startSketchOn(XZ) |> startProfileAt([90.45 119.09], %)"#;
sketch001 = startSketchOn(XZ) |> startProfile(at = [90.45 119.09])"#;
assert_err(
some_program_string,
"Unexpected character encountered. You might be missing a comma in between elements.",
[50, 63],
[53, 66],
);
}
#[test]
@ -4825,21 +4864,21 @@ sketch001 = startSketchOn(XZ) |> startProfileAt([90.45 119.09], %)"#;
// since there is an early exit if encountering a reserved word, the error should be about
// that and not the missing comma
let some_program_string = r#"
sketch001 = startSketchOn(XZ) |> startProfileAt([90.45 $struct], %)"#;
sketch001 = startSketchOn(XZ) |> startProfile(at = [90.45 $struct])"#;
assert_err(
some_program_string,
"Encountered an unexpected character(s) before finding a closing bracket(`]`) for the array",
[49, 50],
[52, 53],
);
}
#[test]
fn test_parse_array_random_brace() {
let some_program_string = r#"
sketch001 = startSketchOn(XZ) |> startProfileAt([}], %)"#;
sketch001 = startSketchOn(XZ) |> startProfile(at = [}])"#;
assert_err(
some_program_string,
"Encountered an unexpected character(s) before finding a closing bracket(`]`) for the array",
[49, 50],
[52, 53],
);
}
@ -5075,17 +5114,17 @@ mod snapshot_tests {
snapshot_test!(
a,
r#"boxSketch = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line([0, 10], %)
|> tangentialArc([-5, 5], %)
|> line([5, -15], %)
|> startProfileAt(at = [0, 0])
|> line(at = [0, 10])
|> tangentialArc(end = [-5, 5])
|> line(at = [5, -15])
|> extrude(length=10)
"#
);
snapshot_test!(b, "myVar = min(5 , -legLen(5, 4))"); // Space before comma
snapshot_test!(b, "myVar = min(x=5 , y=-legLen(5, z=4))"); // Space before comma
snapshot_test!(c, "myVar = min(-legLen(5, 4), 5)");
snapshot_test!(d, "myVar = 5 + 6 |> myFunc(45, %)");
snapshot_test!(c, "myVar = min(x=-legLen(a=5, b=4), y=5)");
snapshot_test!(d, "myVar = 5 + 6 |> myFunc(45)");
snapshot_test!(e, "x = 1 * (3 - 4)");
snapshot_test!(f, r#"x = 1 // this is an inline comment"#);
snapshot_test!(
@ -5141,11 +5180,11 @@ mod snapshot_tests {
snapshot_test!(v, r#"pt1 = b1[0]"#);
snapshot_test!(w, r#"pt1 = b1['zero']"#);
snapshot_test!(x, r#"pt1 = b1.zero"#);
snapshot_test!(y, r#"sg = startSketchOn(XY) |> startProfileAt(pos, %)"#);
snapshot_test!(y, r#"sg = startSketchOn(XY) |> startProfile(pos)"#);
snapshot_test!(
z,
"sg = startSketchOn(XY)
|> startProfileAt(pos) |> line([0, -scale], %)"
|> startProfile(pos) |> line([0, -scale])"
);
snapshot_test!(aa, r#"sg = -scale"#);
snapshot_test!(ab, "line(endAbsolute = [0, -1])");
@ -5168,7 +5207,7 @@ mod snapshot_tests {
snapshot_test!(
af,
r#"mySketch = startSketchOn(XY)
|> startProfileAt([0,0], %)
|> startProfile(at = [0,0])
|> line(endAbsolute = [0, 1], tag = $myPath)
|> line(endAbsolute = [1, 1])
|> line(endAbsolute = [1, 0], tag = $rightPath)
@ -5176,21 +5215,21 @@ mod snapshot_tests {
);
snapshot_test!(
ag,
"mySketch = startSketchOn(XY) |> startProfileAt([0,0], %) |> line(endAbsolute = [1, 1]) |> close()"
"mySketch = startSketchOn(XY) |> startProfile(at = [0,0]) |> line(endAbsolute = [1, 1]) |> close()"
);
snapshot_test!(ah, "myBox = startSketchOn(XY) |> startProfileAt(p, %)");
snapshot_test!(ai, r#"myBox = f(1) |> g(2, %)"#);
snapshot_test!(ah, "myBox = startSketchOn(XY) |> startProfile(at = p)");
snapshot_test!(ai, r#"myBox = f(1) |> g(2)"#);
snapshot_test!(
aj,
r#"myBox = startSketchOn(XY) |> startProfileAt(p, %) |> line(end = [0, l])"#
r#"myBox = startSketchOn(XY) |> startProfile(at = p) |> line(end = [0, l])"#
);
snapshot_test!(ak, "line(endAbsolute = [0, 1])");
snapshot_test!(ap, "mySketch = startSketchOn(XY) |> startProfileAt([0,0], %)");
snapshot_test!(aq, "log(5, \"hello\", aIdentifier)");
snapshot_test!(ap, "mySketch = startSketchOn(XY) |> startProfile(at = [0,0])");
snapshot_test!(aq, "log(number = 5, msg = \"hello\", id=aIdentifier)");
snapshot_test!(ar, r#"5 + "a""#);
snapshot_test!(at, "line([0, l], %)");
snapshot_test!(at, "line([0, l])");
snapshot_test!(au, include_str!("../../e2e/executor/inputs/cylinder.kcl"));
snapshot_test!(av, "fn f(angle?) { return default(angle, 360) }");
snapshot_test!(av, "fn f(angle?) { return default(maybe=angle, otherwise=360) }");
snapshot_test!(
aw,
"numbers = [

View File

@ -8,7 +8,7 @@ expression: actual
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 170,
"end": 179,
"id": {
"commentStart": 0,
"end": 9,
@ -61,44 +61,47 @@ expression: actual
{
"arguments": [
{
"commentStart": 52,
"elements": [
{
"commentStart": 53,
"end": 54,
"raw": "0",
"start": 53,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
"type": "LabeledArg",
"label": {
"commentStart": 52,
"end": 54,
"name": "at",
"start": 52,
"type": "Identifier"
},
"arg": {
"commentStart": 57,
"elements": [
{
"commentStart": 58,
"end": 59,
"raw": "0",
"start": 58,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
},
{
"commentStart": 61,
"end": 62,
"raw": "0",
"start": 61,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
},
{
"commentStart": 56,
"end": 57,
"raw": "0",
"start": 56,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
],
"end": 58,
"start": 52,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 60,
"end": 61,
"start": 60,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
],
"end": 63,
"start": 57,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
}
],
"callee": {
@ -117,86 +120,175 @@ expression: actual
"type": "Name"
},
"commentStart": 37,
"end": 62,
"end": 64,
"start": 37,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [
{
"commentStart": 75,
"elements": [
{
"commentStart": 76,
"end": 77,
"raw": "0",
"start": 76,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
"type": "LabeledArg",
"label": {
"commentStart": 77,
"end": 79,
"name": "at",
"start": 77,
"type": "Identifier"
},
"arg": {
"commentStart": 82,
"elements": [
{
"commentStart": 83,
"end": 84,
"raw": "0",
"start": 83,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
},
{
"commentStart": 86,
"end": 88,
"raw": "10",
"start": 86,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
}
},
{
"commentStart": 79,
"end": 81,
"raw": "10",
"start": 79,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
}
],
"end": 82,
"start": 75,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 84,
"end": 85,
"start": 84,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
],
"end": 89,
"start": 82,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 70,
"end": 74,
"commentStart": 72,
"end": 76,
"name": {
"commentStart": 70,
"end": 74,
"commentStart": 72,
"end": 76,
"name": "line",
"start": 70,
"start": 72,
"type": "Identifier"
},
"path": [],
"start": 70,
"start": 72,
"type": "Name"
},
"commentStart": 70,
"end": 86,
"start": 70,
"type": "CallExpression",
"type": "CallExpression"
"commentStart": 72,
"end": 90,
"start": 72,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [
{
"commentStart": 108,
"elements": [
{
"argument": {
"commentStart": 110,
"end": 111,
"type": "LabeledArg",
"label": {
"commentStart": 112,
"end": 115,
"name": "end",
"start": 112,
"type": "Identifier"
},
"arg": {
"commentStart": 118,
"elements": [
{
"argument": {
"commentStart": 120,
"end": 121,
"raw": "5",
"start": 120,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
}
},
"commentStart": 119,
"end": 121,
"operator": "-",
"start": 119,
"type": "UnaryExpression",
"type": "UnaryExpression"
},
{
"commentStart": 123,
"end": 124,
"raw": "5",
"start": 110,
"start": 123,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
}
}
],
"end": 125,
"start": 118,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 98,
"end": 111,
"name": {
"commentStart": 98,
"end": 111,
"name": "tangentialArc",
"start": 98,
"type": "Identifier"
},
"path": [],
"start": 98,
"type": "Name"
},
"commentStart": 98,
"end": 126,
"start": 98,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 139,
"end": 141,
"name": "at",
"start": 139,
"type": "Identifier"
},
"arg": {
"commentStart": 144,
"elements": [
{
"commentStart": 145,
"end": 146,
"raw": "5",
"start": 145,
"type": "Literal",
"type": "Literal",
"value": {
@ -204,148 +296,72 @@ expression: actual
"suffix": "None"
}
},
"commentStart": 109,
"end": 111,
"operator": "-",
"start": 109,
"type": "UnaryExpression",
"type": "UnaryExpression"
},
{
"commentStart": 113,
"end": 114,
"raw": "5",
"start": 113,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
{
"argument": {
"commentStart": 149,
"end": 151,
"raw": "15",
"start": 149,
"type": "Literal",
"type": "Literal",
"value": {
"value": 15.0,
"suffix": "None"
}
},
"commentStart": 148,
"end": 151,
"operator": "-",
"start": 148,
"type": "UnaryExpression",
"type": "UnaryExpression"
}
}
],
"end": 115,
"start": 108,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 117,
"end": 118,
"start": 117,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
],
"end": 152,
"start": 144,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 94,
"end": 107,
"commentStart": 134,
"end": 138,
"name": {
"commentStart": 94,
"end": 107,
"name": "tangentialArc",
"start": 94,
"type": "Identifier"
},
"path": [],
"start": 94,
"type": "Name"
},
"commentStart": 94,
"end": 119,
"start": 94,
"type": "CallExpression",
"type": "CallExpression"
},
{
"arguments": [
{
"commentStart": 132,
"elements": [
{
"commentStart": 133,
"end": 134,
"raw": "5",
"start": 133,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
}
},
{
"argument": {
"commentStart": 137,
"end": 139,
"raw": "15",
"start": 137,
"type": "Literal",
"type": "Literal",
"value": {
"value": 15.0,
"suffix": "None"
}
},
"commentStart": 136,
"end": 139,
"operator": "-",
"start": 136,
"type": "UnaryExpression",
"type": "UnaryExpression"
}
],
"end": 140,
"start": 132,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 142,
"end": 143,
"start": 142,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
"abs_path": false,
"commentStart": 127,
"end": 131,
"name": {
"commentStart": 127,
"end": 131,
"commentStart": 134,
"end": 138,
"name": "line",
"start": 127,
"start": 134,
"type": "Identifier"
},
"path": [],
"start": 127,
"start": 134,
"type": "Name"
},
"commentStart": 127,
"end": 144,
"start": 127,
"type": "CallExpression",
"type": "CallExpression"
"commentStart": 134,
"end": 153,
"start": 134,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 160,
"end": 166,
"commentStart": 169,
"end": 175,
"name": "length",
"start": 160,
"start": 169,
"type": "Identifier"
},
"arg": {
"commentStart": 167,
"end": 169,
"commentStart": 176,
"end": 178,
"raw": "10",
"start": 167,
"start": 176,
"type": "Literal",
"type": "Literal",
"value": {
@ -357,29 +373,29 @@ expression: actual
],
"callee": {
"abs_path": false,
"commentStart": 152,
"end": 159,
"commentStart": 161,
"end": 168,
"name": {
"commentStart": 152,
"end": 159,
"commentStart": 161,
"end": 168,
"name": "extrude",
"start": 152,
"start": 161,
"type": "Identifier"
},
"path": [],
"start": 152,
"start": 161,
"type": "Name"
},
"commentStart": 152,
"end": 170,
"start": 152,
"commentStart": 161,
"end": 179,
"start": 161,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
}
],
"commentStart": 12,
"end": 170,
"end": 179,
"start": 12,
"type": "PipeExpression",
"type": "PipeExpression"
@ -387,7 +403,7 @@ expression: actual
"start": 0,
"type": "VariableDeclarator"
},
"end": 170,
"end": 179,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
@ -395,6 +411,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 171,
"end": 180,
"start": 0
}

View File

@ -61,54 +61,57 @@ expression: actual
{
"arguments": [
{
"commentStart": 55,
"elements": [
{
"commentStart": 56,
"end": 57,
"raw": "0",
"start": 56,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
"type": "LabeledArg",
"label": {
"commentStart": 53,
"end": 55,
"name": "at",
"start": 53,
"type": "Identifier"
},
"arg": {
"commentStart": 58,
"elements": [
{
"commentStart": 59,
"end": 60,
"raw": "0",
"start": 59,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
},
{
"commentStart": 61,
"end": 62,
"raw": "0",
"start": 61,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
},
{
"commentStart": 58,
"end": 59,
"raw": "0",
"start": 58,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
],
"end": 60,
"start": 55,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 62,
"end": 63,
"start": 62,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
],
"end": 63,
"start": 58,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 40,
"end": 54,
"end": 52,
"name": {
"commentStart": 40,
"end": 54,
"name": "startProfileAt",
"end": 52,
"name": "startProfile",
"start": 40,
"type": "Identifier"
},
@ -119,8 +122,9 @@ expression: actual
"commentStart": 40,
"end": 64,
"start": 40,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [

View File

@ -61,54 +61,57 @@ expression: actual
{
"arguments": [
{
"commentStart": 47,
"elements": [
{
"commentStart": 48,
"end": 49,
"raw": "0",
"start": 48,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
"type": "LabeledArg",
"label": {
"commentStart": 45,
"end": 47,
"name": "at",
"start": 45,
"type": "Identifier"
},
"arg": {
"commentStart": 50,
"elements": [
{
"commentStart": 51,
"end": 52,
"raw": "0",
"start": 51,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
},
{
"commentStart": 53,
"end": 54,
"raw": "0",
"start": 53,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
},
{
"commentStart": 50,
"end": 51,
"raw": "0",
"start": 50,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
],
"end": 52,
"start": 47,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 54,
"end": 55,
"start": 54,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
],
"end": 55,
"start": 50,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 32,
"end": 46,
"end": 44,
"name": {
"commentStart": 32,
"end": 46,
"name": "startProfileAt",
"end": 44,
"name": "startProfile",
"start": 32,
"type": "Identifier"
},
@ -119,8 +122,9 @@ expression: actual
"commentStart": 32,
"end": 56,
"start": 32,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [

View File

@ -61,37 +61,40 @@ expression: actual
{
"arguments": [
{
"abs_path": false,
"commentStart": 44,
"end": 45,
"name": {
"commentStart": 44,
"end": 45,
"name": "p",
"start": 44,
"type": "LabeledArg",
"label": {
"commentStart": 42,
"end": 44,
"name": "at",
"start": 42,
"type": "Identifier"
},
"path": [],
"start": 44,
"type": "Name",
"type": "Name"
},
{
"commentStart": 47,
"end": 48,
"start": 47,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
"arg": {
"abs_path": false,
"commentStart": 47,
"end": 48,
"name": {
"commentStart": 47,
"end": 48,
"name": "p",
"start": 47,
"type": "Identifier"
},
"path": [],
"start": 47,
"type": "Name",
"type": "Name"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 29,
"end": 43,
"end": 41,
"name": {
"commentStart": 29,
"end": 43,
"name": "startProfileAt",
"end": 41,
"name": "startProfile",
"start": 29,
"type": "Identifier"
},
@ -102,8 +105,9 @@ expression: actual
"commentStart": 29,
"end": 49,
"start": 29,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
}
],
"commentStart": 8,

View File

@ -8,7 +8,7 @@ expression: actual
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 23,
"end": 20,
"id": {
"commentStart": 0,
"end": 5,
@ -67,13 +67,6 @@ expression: actual
"value": 2.0,
"suffix": "None"
}
},
{
"commentStart": 21,
"end": 22,
"start": 21,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
@ -92,14 +85,14 @@ expression: actual
"type": "Name"
},
"commentStart": 16,
"end": 23,
"end": 20,
"start": 16,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 8,
"end": 23,
"end": 20,
"start": 8,
"type": "PipeExpression",
"type": "PipeExpression"
@ -107,7 +100,7 @@ expression: actual
"start": 0,
"type": "VariableDeclarator"
},
"end": 23,
"end": 20,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
@ -115,6 +108,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 23,
"end": 20,
"start": 0
}

View File

@ -61,37 +61,40 @@ expression: actual
{
"arguments": [
{
"abs_path": false,
"commentStart": 44,
"end": 45,
"name": {
"commentStart": 44,
"end": 45,
"name": "p",
"start": 44,
"type": "LabeledArg",
"label": {
"commentStart": 42,
"end": 44,
"name": "at",
"start": 42,
"type": "Identifier"
},
"path": [],
"start": 44,
"type": "Name",
"type": "Name"
},
{
"commentStart": 47,
"end": 48,
"start": 47,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
"arg": {
"abs_path": false,
"commentStart": 47,
"end": 48,
"name": {
"commentStart": 47,
"end": 48,
"name": "p",
"start": 47,
"type": "Identifier"
},
"path": [],
"start": 47,
"type": "Name",
"type": "Name"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 29,
"end": 43,
"end": 41,
"name": {
"commentStart": 29,
"end": 43,
"name": "startProfileAt",
"end": 41,
"name": "startProfile",
"start": 29,
"type": "Identifier"
},
@ -102,8 +105,9 @@ expression: actual
"commentStart": 29,
"end": 49,
"start": 29,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
{
"arguments": [

View File

@ -61,54 +61,57 @@ expression: actual
{
"arguments": [
{
"commentStart": 47,
"elements": [
{
"commentStart": 48,
"end": 49,
"raw": "0",
"start": 48,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
"type": "LabeledArg",
"label": {
"commentStart": 45,
"end": 47,
"name": "at",
"start": 45,
"type": "Identifier"
},
"arg": {
"commentStart": 50,
"elements": [
{
"commentStart": 51,
"end": 52,
"raw": "0",
"start": 51,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
},
{
"commentStart": 53,
"end": 54,
"raw": "0",
"start": 53,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
},
{
"commentStart": 50,
"end": 51,
"raw": "0",
"start": 50,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
],
"end": 52,
"start": 47,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 54,
"end": 55,
"start": 54,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
],
"end": 55,
"start": 50,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 32,
"end": 46,
"end": 44,
"name": {
"commentStart": 32,
"end": 46,
"name": "startProfileAt",
"end": 44,
"name": "startProfile",
"start": 32,
"type": "Identifier"
},
@ -119,8 +122,9 @@ expression: actual
"commentStart": 32,
"end": 56,
"start": 32,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
}
],
"commentStart": 11,

View File

@ -6,45 +6,75 @@ expression: actual
"body": [
{
"commentStart": 0,
"end": 28,
"end": 46,
"expression": {
"arguments": [
{
"commentStart": 4,
"end": 5,
"raw": "5",
"start": 4,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
"type": "LabeledArg",
"label": {
"commentStart": 4,
"end": 10,
"name": "number",
"start": 4,
"type": "Identifier"
},
"arg": {
"commentStart": 13,
"end": 14,
"raw": "5",
"start": 13,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
}
}
},
{
"commentStart": 7,
"end": 14,
"raw": "\"hello\"",
"start": 7,
"type": "Literal",
"type": "Literal",
"value": "hello"
},
{
"abs_path": false,
"commentStart": 16,
"end": 27,
"name": {
"type": "LabeledArg",
"label": {
"commentStart": 16,
"end": 27,
"name": "aIdentifier",
"end": 19,
"name": "msg",
"start": 16,
"type": "Identifier"
},
"path": [],
"start": 16,
"type": "Name",
"type": "Name"
"arg": {
"commentStart": 22,
"end": 29,
"raw": "\"hello\"",
"start": 22,
"type": "Literal",
"type": "Literal",
"value": "hello"
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 31,
"end": 33,
"name": "id",
"start": 31,
"type": "Identifier"
},
"arg": {
"abs_path": false,
"commentStart": 34,
"end": 45,
"name": {
"commentStart": 34,
"end": 45,
"name": "aIdentifier",
"start": 34,
"type": "Identifier"
},
"path": [],
"start": 34,
"type": "Name",
"type": "Name"
}
}
],
"callee": {
@ -63,10 +93,11 @@ expression: actual
"type": "Name"
},
"commentStart": 0,
"end": 28,
"end": 46,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
"start": 0,
"type": "ExpressionStatement",
@ -74,6 +105,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 28,
"end": 46,
"start": 0
}

View File

@ -6,7 +6,7 @@ expression: actual
"body": [
{
"commentStart": 0,
"end": 15,
"end": 12,
"expression": {
"arguments": [
{
@ -45,13 +45,6 @@ expression: actual
"start": 5,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 13,
"end": 14,
"start": 13,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
@ -70,7 +63,7 @@ expression: actual
"type": "Name"
},
"commentStart": 0,
"end": 15,
"end": 12,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
@ -81,6 +74,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 15,
"end": 12,
"start": 0
}

View File

@ -8,7 +8,7 @@ expression: actual
"commentStart": 0,
"declaration": {
"commentStart": 3,
"end": 43,
"end": 59,
"id": {
"commentStart": 3,
"end": 4,
@ -23,31 +23,51 @@ expression: actual
"argument": {
"arguments": [
{
"abs_path": false,
"commentStart": 30,
"end": 35,
"name": {
"type": "LabeledArg",
"label": {
"commentStart": 30,
"end": 35,
"name": "angle",
"name": "maybe",
"start": 30,
"type": "Identifier"
},
"path": [],
"start": 30,
"type": "Name",
"type": "Name"
"arg": {
"abs_path": false,
"commentStart": 36,
"end": 41,
"name": {
"commentStart": 36,
"end": 41,
"name": "angle",
"start": 36,
"type": "Identifier"
},
"path": [],
"start": 36,
"type": "Name",
"type": "Name"
}
},
{
"commentStart": 37,
"end": 40,
"raw": "360",
"start": 37,
"type": "Literal",
"type": "Literal",
"value": {
"value": 360.0,
"suffix": "None"
"type": "LabeledArg",
"label": {
"commentStart": 43,
"end": 52,
"name": "otherwise",
"start": 43,
"type": "Identifier"
},
"arg": {
"commentStart": 53,
"end": 56,
"raw": "360",
"start": 53,
"type": "Literal",
"type": "Literal",
"value": {
"value": 360.0,
"suffix": "None"
}
}
}
],
@ -67,24 +87,25 @@ expression: actual
"type": "Name"
},
"commentStart": 22,
"end": 41,
"end": 57,
"start": 22,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
"commentStart": 15,
"end": 41,
"end": 57,
"start": 15,
"type": "ReturnStatement",
"type": "ReturnStatement"
}
],
"commentStart": 13,
"end": 43,
"end": 59,
"start": 13
},
"commentStart": 4,
"end": 43,
"end": 59,
"params": [
{
"type": "Parameter",
@ -109,7 +130,7 @@ expression: actual
"start": 3,
"type": "VariableDeclarator"
},
"end": 43,
"end": 59,
"kind": "fn",
"start": 0,
"type": "VariableDeclaration",
@ -117,6 +138,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 43,
"end": 59,
"start": 0
}

View File

@ -8,7 +8,7 @@ expression: actual
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 30,
"end": 36,
"id": {
"commentStart": 0,
"end": 5,
@ -19,72 +19,102 @@ expression: actual
"init": {
"arguments": [
{
"commentStart": 12,
"end": 13,
"raw": "5",
"start": 12,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
"type": "LabeledArg",
"label": {
"commentStart": 12,
"end": 13,
"name": "x",
"start": 12,
"type": "Identifier"
},
"arg": {
"commentStart": 14,
"end": 15,
"raw": "5",
"start": 14,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
}
}
},
{
"argument": {
"arguments": [
{
"commentStart": 24,
"end": 25,
"type": "LabeledArg",
"label": {
"commentStart": 18,
"end": 19,
"name": "y",
"start": 18,
"type": "Identifier"
},
"arg": {
"argument": {
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 31,
"end": 32,
"name": "z",
"start": 31,
"type": "Identifier"
},
"arg": {
"commentStart": 33,
"end": 34,
"raw": "4",
"start": 33,
"type": "Literal",
"type": "Literal",
"value": {
"value": 4.0,
"suffix": "None"
}
}
}
],
"callee": {
"abs_path": false,
"commentStart": 21,
"end": 27,
"name": {
"commentStart": 21,
"end": 27,
"name": "legLen",
"start": 21,
"type": "Identifier"
},
"path": [],
"start": 21,
"type": "Name"
},
"commentStart": 21,
"end": 35,
"start": 21,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": {
"commentStart": 28,
"end": 29,
"raw": "5",
"start": 24,
"start": 28,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
}
},
{
"commentStart": 27,
"end": 28,
"raw": "4",
"start": 27,
"type": "Literal",
"type": "Literal",
"value": {
"value": 4.0,
"suffix": "None"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 17,
"end": 23,
"name": {
"commentStart": 17,
"end": 23,
"name": "legLen",
"start": 17,
"type": "Identifier"
},
"path": [],
"start": 17,
"type": "Name"
},
"commentStart": 17,
"end": 29,
"start": 17,
"type": "CallExpression",
"type": "CallExpression"
},
"commentStart": 16,
"end": 29,
"operator": "-",
"start": 16,
"type": "UnaryExpression",
"type": "UnaryExpression"
"commentStart": 20,
"end": 35,
"operator": "-",
"start": 20,
"type": "UnaryExpression",
"type": "UnaryExpression"
}
}
],
"callee": {
@ -103,15 +133,16 @@ expression: actual
"type": "Name"
},
"commentStart": 8,
"end": 30,
"end": 36,
"start": 8,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
"start": 0,
"type": "VariableDeclarator"
},
"end": 30,
"end": 36,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
@ -119,6 +150,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 30,
"end": 36,
"start": 0
}

View File

@ -8,7 +8,7 @@ expression: actual
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 29,
"end": 37,
"id": {
"commentStart": 0,
"end": 5,
@ -19,71 +19,112 @@ expression: actual
"init": {
"arguments": [
{
"argument": {
"arguments": [
{
"commentStart": 20,
"end": 21,
"raw": "5",
"start": 20,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
}
},
{
"commentStart": 23,
"end": 24,
"raw": "4",
"start": 23,
"type": "Literal",
"type": "Literal",
"value": {
"value": 4.0,
"suffix": "None"
}
}
],
"callee": {
"abs_path": false,
"commentStart": 13,
"end": 19,
"name": {
"commentStart": 13,
"end": 19,
"name": "legLen",
"start": 13,
"type": "Identifier"
},
"path": [],
"start": 13,
"type": "Name"
},
"commentStart": 13,
"end": 25,
"start": 13,
"type": "CallExpression",
"type": "CallExpression"
"type": "LabeledArg",
"label": {
"commentStart": 12,
"end": 13,
"name": "x",
"start": 12,
"type": "Identifier"
},
"commentStart": 12,
"end": 25,
"operator": "-",
"start": 12,
"type": "UnaryExpression",
"type": "UnaryExpression"
"arg": {
"argument": {
"arguments": [
{
"type": "LabeledArg",
"label": {
"commentStart": 22,
"end": 23,
"name": "a",
"start": 22,
"type": "Identifier"
},
"arg": {
"commentStart": 24,
"end": 25,
"raw": "5",
"start": 24,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
}
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 27,
"end": 28,
"name": "b",
"start": 27,
"type": "Identifier"
},
"arg": {
"commentStart": 29,
"end": 30,
"raw": "4",
"start": 29,
"type": "Literal",
"type": "Literal",
"value": {
"value": 4.0,
"suffix": "None"
}
}
}
],
"callee": {
"abs_path": false,
"commentStart": 15,
"end": 21,
"name": {
"commentStart": 15,
"end": 21,
"name": "legLen",
"start": 15,
"type": "Identifier"
},
"path": [],
"start": 15,
"type": "Name"
},
"commentStart": 15,
"end": 31,
"start": 15,
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
"commentStart": 14,
"end": 31,
"operator": "-",
"start": 14,
"type": "UnaryExpression",
"type": "UnaryExpression"
}
},
{
"commentStart": 27,
"end": 28,
"raw": "5",
"start": 27,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
"type": "LabeledArg",
"label": {
"commentStart": 33,
"end": 34,
"name": "y",
"start": 33,
"type": "Identifier"
},
"arg": {
"commentStart": 35,
"end": 36,
"raw": "5",
"start": 35,
"type": "Literal",
"type": "Literal",
"value": {
"value": 5.0,
"suffix": "None"
}
}
}
],
@ -103,15 +144,16 @@ expression: actual
"type": "Name"
},
"commentStart": 8,
"end": 29,
"end": 37,
"start": 8,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
},
"start": 0,
"type": "VariableDeclarator"
},
"end": 29,
"end": 37,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
@ -119,6 +161,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 29,
"end": 37,
"start": 0
}

View File

@ -8,7 +8,7 @@ expression: actual
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 30,
"end": 27,
"id": {
"commentStart": 0,
"end": 5,
@ -63,13 +63,6 @@ expression: actual
"value": 45.0,
"suffix": "None"
}
},
{
"commentStart": 28,
"end": 29,
"start": 28,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
@ -88,14 +81,14 @@ expression: actual
"type": "Name"
},
"commentStart": 17,
"end": 30,
"end": 27,
"start": 17,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 8,
"end": 30,
"end": 27,
"start": 8,
"type": "PipeExpression",
"type": "PipeExpression"
@ -103,7 +96,7 @@ expression: actual
"start": 0,
"type": "VariableDeclarator"
},
"end": 30,
"end": 27,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
@ -111,6 +104,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 30,
"end": 27,
"start": 0
}

View File

@ -8,7 +8,7 @@ expression: actual
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 48,
"end": 43,
"id": {
"commentStart": 0,
"end": 2,
@ -62,36 +62,29 @@ expression: actual
"arguments": [
{
"abs_path": false,
"commentStart": 41,
"end": 44,
"commentStart": 39,
"end": 42,
"name": {
"commentStart": 41,
"end": 44,
"commentStart": 39,
"end": 42,
"name": "pos",
"start": 41,
"start": 39,
"type": "Identifier"
},
"path": [],
"start": 41,
"start": 39,
"type": "Name",
"type": "Name"
},
{
"commentStart": 46,
"end": 47,
"start": 46,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
"abs_path": false,
"commentStart": 26,
"end": 40,
"end": 38,
"name": {
"commentStart": 26,
"end": 40,
"name": "startProfileAt",
"end": 38,
"name": "startProfile",
"start": 26,
"type": "Identifier"
},
@ -100,14 +93,14 @@ expression: actual
"type": "Name"
},
"commentStart": 26,
"end": 48,
"end": 43,
"start": 26,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 5,
"end": 48,
"end": 43,
"start": 5,
"type": "PipeExpression",
"type": "PipeExpression"
@ -115,7 +108,7 @@ expression: actual
"start": 0,
"type": "VariableDeclarator"
},
"end": 48,
"end": 43,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
@ -123,6 +116,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 48,
"end": 43,
"start": 0
}

View File

@ -8,7 +8,7 @@ expression: actual
"commentStart": 0,
"declaration": {
"commentStart": 0,
"end": 73,
"end": 68,
"id": {
"commentStart": 0,
"end": 2,
@ -62,17 +62,17 @@ expression: actual
"arguments": [
{
"abs_path": false,
"commentStart": 45,
"end": 48,
"commentStart": 43,
"end": 46,
"name": {
"commentStart": 45,
"end": 48,
"commentStart": 43,
"end": 46,
"name": "pos",
"start": 45,
"start": 43,
"type": "Identifier"
},
"path": [],
"start": 45,
"start": 43,
"type": "Name",
"type": "Name"
}
@ -80,11 +80,11 @@ expression: actual
"callee": {
"abs_path": false,
"commentStart": 30,
"end": 44,
"end": 42,
"name": {
"commentStart": 30,
"end": 44,
"name": "startProfileAt",
"end": 42,
"name": "startProfile",
"start": 30,
"type": "Identifier"
},
@ -93,7 +93,7 @@ expression: actual
"type": "Name"
},
"commentStart": 30,
"end": 49,
"end": 47,
"start": 30,
"type": "CallExpression",
"type": "CallExpression"
@ -101,13 +101,13 @@ expression: actual
{
"arguments": [
{
"commentStart": 58,
"commentStart": 56,
"elements": [
{
"commentStart": 59,
"end": 60,
"commentStart": 57,
"end": 58,
"raw": "0",
"start": 59,
"start": 57,
"type": "Literal",
"type": "Literal",
"value": {
@ -118,65 +118,58 @@ expression: actual
{
"argument": {
"abs_path": false,
"commentStart": 63,
"end": 68,
"commentStart": 61,
"end": 66,
"name": {
"commentStart": 63,
"end": 68,
"commentStart": 61,
"end": 66,
"name": "scale",
"start": 63,
"start": 61,
"type": "Identifier"
},
"path": [],
"start": 63,
"start": 61,
"type": "Name",
"type": "Name"
},
"commentStart": 62,
"end": 68,
"commentStart": 60,
"end": 66,
"operator": "-",
"start": 62,
"start": 60,
"type": "UnaryExpression",
"type": "UnaryExpression"
}
],
"end": 69,
"start": 58,
"end": 67,
"start": 56,
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 71,
"end": 72,
"start": 71,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
],
"callee": {
"abs_path": false,
"commentStart": 53,
"end": 57,
"commentStart": 51,
"end": 55,
"name": {
"commentStart": 53,
"end": 57,
"commentStart": 51,
"end": 55,
"name": "line",
"start": 53,
"start": 51,
"type": "Identifier"
},
"path": [],
"start": 53,
"start": 51,
"type": "Name"
},
"commentStart": 53,
"end": 73,
"start": 53,
"commentStart": 51,
"end": 68,
"start": 51,
"type": "CallExpression",
"type": "CallExpression"
}
],
"commentStart": 5,
"end": 73,
"end": 68,
"start": 5,
"type": "PipeExpression",
"type": "PipeExpression"
@ -184,7 +177,7 @@ expression: actual
"start": 0,
"type": "VariableDeclarator"
},
"end": 73,
"end": 68,
"kind": "const",
"start": 0,
"type": "VariableDeclaration",
@ -192,6 +185,6 @@ expression: actual
}
],
"commentStart": 0,
"end": 73,
"end": 68,
"start": 0
}

View File

@ -282,6 +282,7 @@ fn assert_common_snapshots(
insta::assert_json_snapshot!("ops", operations, {
"[].unlabeledArg.*.value.**[].from[]" => rounded_redaction(4),
"[].unlabeledArg.*.value.**[].to[]" => rounded_redaction(4),
"[].*.unlabeledArg.value.value" => rounded_redaction(4),
"[].labeledArgs.*.value.**[].from[]" => rounded_redaction(4),
"[].labeledArgs.*.value.**[].to[]" => rounded_redaction(4),
".**.sourceRange" => Vec::new(),

View File

@ -51,6 +51,7 @@ async fn unparse_test(test: &Test) {
.map(|file| {
tokio::spawn(async move {
let contents = tokio::fs::read_to_string(&file).await.unwrap();
eprintln!("{}", file.display());
let program = crate::Program::parse_no_errs(&contents).unwrap();
let recast = program.recast_with_options(&Default::default());

View File

@ -91,9 +91,9 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
/// |> extrude(length = 10)
/// }
///
/// example0 = cube([0, 0])
/// example1 = cube([20, 0])
/// example2 = cube([40, 0])
/// example0 = cube(center = [0, 0])
/// example1 = cube(center = [20, 0])
/// example2 = cube(center = [40, 0])
///
/// appearance([example0, example1], color='#ff0000', metalness=50, roughness=50)
/// appearance(example2, color='#00ff00', metalness=50, roughness=50)

View File

@ -26,7 +26,7 @@ pub async fn map(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
/// `[f(a), f(b), f(c)]`
/// ```no_run
/// r = 10 // radius
/// fn drawCircle(id) {
/// fn drawCircle(@id) {
/// return startSketchOn(XY)
/// |> circle( center= [id * 2 * r, 0], radius= r)
/// }
@ -110,7 +110,7 @@ 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 `arr` parameter. The starting value is 0.
/// fn sum(arr) { return reduce(arr, initial = 0, f = add) }
/// fn sum(@arr) { return reduce(arr, initial = 0, f = add) }
///
/// /*
/// The above is basically like this pseudo-code:
@ -138,7 +138,7 @@ pub async fn reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
/// ```
/// ```no_run
/// // Declare a function that sketches a decagon.
/// fn decagon(radius) {
/// fn decagon(@radius) {
/// // Each side of the decagon is turned this many radians from the previous angle.
/// stepAngle = ((1/10) * TAU): number(rad)
///

View File

@ -49,8 +49,8 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// unionedPart = union([part001, part002])
@ -71,8 +71,8 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: union([part001, part002])
@ -94,8 +94,8 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: union([part001, part002])
@ -199,8 +199,8 @@ pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValu
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// intersectedPart = intersect([part001, part002])
@ -221,8 +221,8 @@ pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValu
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: intersect([part001, part002])
@ -332,8 +332,8 @@ pub async fn subtract(exec_state: &mut ExecState, args: Args) -> Result<KclValue
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// subtractedPart = subtract([part001], tools=[part002])
@ -354,8 +354,8 @@ pub async fn subtract(exec_state: &mut ExecState, args: Args) -> Result<KclValue
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// part001 = cube(center = [0, 0], size = 10)
/// part002 = cube(center = [7, 3], size = 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: subtract([part001], tools=[part002])

View File

@ -96,7 +96,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
///
/// ```no_run
/// // Each instance will be shifted along the X axis.
/// fn transform(id) {
/// fn transform(@id) {
/// return { translate = [4 * id, 0, 0] }
/// }
///
@ -110,7 +110,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
/// // Each instance will be shifted along the X axis,
/// // with a gap between the original (at x = 0) and the first replica
/// // (at x = 8). This is because `id` starts at 1.
/// fn transform(id) {
/// fn transform(@id) {
/// return { translate = [4 * (1+id), 0, 0] }
/// }
///
@ -140,7 +140,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
/// }
///
/// width = 20
/// fn transform(i) {
/// fn transform(@i) {
/// return {
/// // Move down each time.
/// translate = [0, 0, -i * width],
@ -155,7 +155,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
/// }
///
/// myCubes =
/// cube(width, [100,0])
/// cube(length = width, center = [100,0])
/// |> patternTransform(instances = 25, transform = transform)
/// ```
///
@ -180,7 +180,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
/// }
///
/// width = 20
/// fn transform(i) {
/// fn transform(@i) {
/// return {
/// translate = [0, 0, -i * width],
/// rotation = {
@ -191,7 +191,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
/// }
/// }
/// myCubes =
/// cube(width, [100,100])
/// cube(length = width, center = [100,100])
/// |> patternTransform(instances = 4, transform = transform)
/// ```
/// ```no_run
@ -201,7 +201,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
/// t = 0.005 // taper factor [0-1)
/// // Defines how to modify each layer of the vase.
/// // Each replica is shifted up the Z axis, and has a smoothly-varying radius
/// fn transform(replicaId) {
/// fn transform(@replicaId) {
/// scale = r * abs(1 - (t * replicaId)) * (5 + cos((replicaId / 8): number(rad)))
/// return {
/// translate = [0, 0, replicaId * 10],
@ -219,7 +219,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
/// vase = layer() |> patternTransform(instances = 100, transform = transform)
/// ```
/// ```
/// fn transform(i) {
/// fn transform(@i) {
/// // Transform functions can return multiple transforms. They'll be applied in order.
/// return [
/// { translate = [30 * i, 0, 0] },
@ -282,7 +282,7 @@ async fn inner_pattern_transform<'a>(
/// Just like patternTransform, but works on 2D sketches not 3D solids.
/// ```no_run
/// // Each instance will be shifted along the X axis.
/// fn transform(id) {
/// fn transform(@id) {
/// return { translate = [4 * id, 0] }
/// }
///

View File

@ -42,10 +42,10 @@ pub async fn segment_end(exec_state: &mut ExecState, args: Args) -> Result<KclVa
/// |> extrude(length = radius)
/// }
///
/// cylinder(1, line1)
/// cylinder(2, line2)
/// cylinder(3, line3)
/// cylinder(4, line4)
/// cylinder(radius = 1, tag = line1)
/// cylinder(radius = 2, tag = line2)
/// cylinder(radius = 3, tag = line3)
/// cylinder(radius = 4, tag = line4)
/// ```
#[stdlib {
name = "segEnd",
@ -178,10 +178,10 @@ pub async fn segment_start(exec_state: &mut ExecState, args: Args) -> Result<Kcl
/// |> extrude(length = radius)
/// }
///
/// cylinder(1, line1)
/// cylinder(2, line2)
/// cylinder(3, line3)
/// cylinder(4, line4)
/// cylinder(radius = 1, tag = line1)
/// cylinder(radius = 2, tag = line2)
/// cylinder(radius = 3, tag = line3)
/// cylinder(radius = 4, tag = line4)
/// ```
#[stdlib {
name = "segStart",

View File

@ -326,7 +326,7 @@ pub async fn translate(exec_state: &mut ExecState, args: Args) -> Result<KclValu
/// ```no_run
/// // Move a sketch.
///
/// fn square(length){
/// fn square(@length){
/// l = length / 2
/// p0 = [-l, -l]
/// p1 = [-l, l]

View File

@ -1125,27 +1125,27 @@ d = 1
fn rect(x, y, w, h) {
startSketchOn(XY)
|> startProfileAt([x, y], %)
|> startProfile(at = [x, y])
|> xLine(length = w)
|> yLine(length = h)
|> xLine(length = -w)
|> close()
|> extrude(d, %)
|> extrude(d)
}
fn quad(x1, y1, x2, y2, x3, y3, x4, y4) {
startSketchOn(XY)
|> startProfileAt([x1, y1], %)
|> startProfile(at = [x1, y1])
|> line(endAbsolute = [x2, y2])
|> line(endAbsolute = [x3, y3])
|> line(endAbsolute = [x4, y4])
|> close()
|> extrude(d, %)
|> extrude(d)
}
fn crosshair(x, y) {
startSketchOn(XY)
|> startProfileAt([x, y], %)
|> startProfile(at = [x, y])
|> yLine(length = 1)
|> yLine(length = -2)
|> yLine(length = 1)
@ -1159,11 +1159,30 @@ fn z(z_x, z_y) {
z_corner = s * 2
z_w = z_end_w + 2 * z_corner
z_h = z_w * 1.08130081300813
rect(z_x, z_y, z_end_w, -z_end_h)
rect(z_x + z_w, z_y, -z_corner, -z_corner)
rect(z_x + z_w, z_y - z_h, -z_end_w, z_end_h)
rect(z_x, z_y - z_h, z_corner, z_corner)
quad(z_x, z_y - z_h + z_corner, z_x + z_w - z_corner, z_y, z_x + z_w, z_y - z_corner, z_x + z_corner, z_y - z_h)
rect(
z_x,
a = z_y,
b = z_end_w,
c = -z_end_h,
)
rect(
z_x + z_w,
a = z_y,
b = -z_corner,
c = -z_corner,
)
rect(
z_x + z_w,
a = z_y - z_h,
b = -z_end_w,
c = z_end_h,
)
rect(
z_x,
a = z_y - z_h,
b = z_corner,
c = z_corner,
)
}
fn o(c_x, c_y) {
@ -1175,61 +1194,45 @@ fn o(c_x, c_y) {
a = 7
// Start point for the top sketch
o_x1 = c_x + o_r * cos((45 + a) / 360 * tau())
o_y1 = c_y + o_r * sin((45 + a) / 360 * tau())
o_x1 = c_x + o_r * cos((45 + a) / 360 * TAU)
o_y1 = c_y + o_r * sin((45 + a) / 360 * TAU)
// Start point for the bottom sketch
o_x2 = c_x + o_r * cos((225 + a) / 360 * tau())
o_y2 = c_y + o_r * sin((225 + a) / 360 * tau())
o_x2 = c_x + o_r * cos((225 + a) / 360 * TAU)
o_y2 = c_y + o_r * sin((225 + a) / 360 * TAU)
// End point for the bottom startSketch
o_x3 = c_x + o_r * cos((45 - a) / 360 * tau())
o_y3 = c_y + o_r * sin((45 - a) / 360 * tau())
o_x3 = c_x + o_r * cos((45 - a) / 360 * TAU)
o_y3 = c_y + o_r * sin((45 - a) / 360 * TAU)
// Where is the center?
// crosshair(c_x, c_y)
startSketchOn(XY)
|> startProfileAt([o_x1, o_y1], %)
|> arc({
radius = o_r,
angle_start = 45 + a,
angle_end = 225 - a
}, %)
|> startProfile(at = [o_x1, o_y1])
|> arc(radius = o_r, angle_start = 45 + a, angle_end = 225 - a)
|> angledLine(angle = 45, length = o_r - i_r)
|> arc({
radius = i_r,
angle_start = 225 - a,
angle_end = 45 + a
}, %)
|> arc(radius = i_r, angle_start = 225 - a, angle_end = 45 + a)
|> close()
|> extrude(d, %)
|> extrude(d)
startSketchOn(XY)
|> startProfileAt([o_x2, o_y2], %)
|> arc({
radius = o_r,
angle_start = 225 + a,
angle_end = 360 + 45 - a
}, %)
|> startProfile(at = [o_x2, o_y2])
|> arc(radius = o_r, angle_start = 225 + a, angle_end = 360 + 45 - a)
|> angledLine(angle = 225, length = o_r - i_r)
|> arc({
radius = i_r,
angle_start = 45 - a,
angle_end = 225 + a - 360
}, %)
|> arc(radius = i_r, angle_start = 45 - a, angle_end = 225 + a - 360)
|> close()
|> extrude(d, %)
|> extrude(d)
}
fn zoo(x0, y0) {
z(x0, y0)
o(x0 + s * 20, y0 - (s * 6.7))
o(x0 + s * 35, y0 - (s * 6.7))
z(x = x0, y = y0)
o(x = x0 + s * 20, y = y0 - (s * 6.7))
o(x = x0 + s * 35, y = y0 - (s * 6.7))
}
zoo(zoo_x, zoo_y)
zoo(x = zoo_x, y = zoo_y)
"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
@ -1250,32 +1253,32 @@ overHangLength = .4
// Sketch and revolve the inside bearing piece
insideRevolve = startSketchOn(XZ)
|> startProfileAt([insideDia / 2, 0], %)
|> line([0, thickness + sphereDia / 2], %)
|> line([overHangLength, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, -sphereDia], %)
|> line([overHangLength - thickness, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength, 0], %)
|> startProfile(at = [insideDia / 2, 0])
|> line(end = [0, thickness + sphereDia / 2])
|> line(end = [overHangLength, 0])
|> line(end = [0, -thickness])
|> line(end = [-overHangLength + thickness, 0])
|> line(end = [0, -sphereDia])
|> line(end = [overHangLength - thickness, 0])
|> line(end = [0, -thickness])
|> line(end = [-overHangLength, 0])
|> close()
|> revolve({ axis = Y }, %)
|> revolve(axis = Y)
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
sphere = startSketchOn(XZ)
|> startProfileAt([
|> startProfile(at = [
0.05 + insideDia / 2 + thickness,
0 - 0.05
], %)
|> line([sphereDia - 0.1, 0], %)
|> arc({
])
|> line(end = [sphereDia - 0.1, 0])
|> arc(
angle_start = 0,
angle_end = -180,
radius = sphereDia / 2 - 0.05
}, %)
)
|> close()
|> revolve({ axis = X }, %)
|> revolve(axis = X)
|> patternCircular3d(
axis = [0, 0, 1],
center = [0, 0, 0],
@ -1286,20 +1289,21 @@ sphere = startSketchOn(XZ)
// Sketch and revolve the outside bearing
outsideRevolve = startSketchOn(XZ)
|> startProfileAt([
|> startProfile(at = [
insideDia / 2 + thickness + sphereDia,
0
], %)
|> line([0, sphereDia / 2], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, thickness], %)
|> line([overHangLength, 0], %)
|> line([0, -2 * thickness - sphereDia], %)
|> line([-overHangLength, 0], %)
|> line([0, thickness], %)
|> line([overHangLength - thickness, 0], %)
]
)
|> line(end = [0, sphereDia / 2])
|> line(end = [-overHangLength + thickness, 0])
|> line(end = [0, thickness])
|> line(end = [overHangLength, 0])
|> line(end = [0, -2 * thickness - sphereDia])
|> line(end = [-overHangLength, 0])
|> line(end = [0, thickness])
|> line(end = [overHangLength - thickness, 0])
|> close()
|> revolve({ axis = Y }, %)"#;
|> revolve(axis = Y)"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let recasted = program.recast(&Default::default(), 0);
@ -1316,32 +1320,28 @@ overHangLength = .4
// Sketch and revolve the inside bearing piece
insideRevolve = startSketchOn(XZ)
|> startProfileAt([insideDia / 2, 0], %)
|> line([0, thickness + sphereDia / 2], %)
|> line([overHangLength, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, -sphereDia], %)
|> line([overHangLength - thickness, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength, 0], %)
|> startProfile(at = [insideDia / 2, 0])
|> line(end = [0, thickness + sphereDia / 2])
|> line(end = [overHangLength, 0])
|> line(end = [0, -thickness])
|> line(end = [-overHangLength + thickness, 0])
|> line(end = [0, -sphereDia])
|> line(end = [overHangLength - thickness, 0])
|> line(end = [0, -thickness])
|> line(end = [-overHangLength, 0])
|> close()
|> revolve({ axis = Y }, %)
|> revolve(axis = Y)
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
sphere = startSketchOn(XZ)
|> startProfileAt([
|> startProfile(at = [
0.05 + insideDia / 2 + thickness,
0 - 0.05
], %)
|> line([sphereDia - 0.1, 0], %)
|> arc({
angle_start = 0,
angle_end = -180,
radius = sphereDia / 2 - 0.05
}, %)
])
|> line(end = [sphereDia - 0.1, 0])
|> arc(angle_start = 0, angle_end = -180, radius = sphereDia / 2 - 0.05)
|> close()
|> revolve({ axis = X }, %)
|> revolve(axis = X)
|> patternCircular3d(
axis = [0, 0, 1],
center = [0, 0, 0],
@ -1352,20 +1352,20 @@ sphere = startSketchOn(XZ)
// Sketch and revolve the outside bearing
outsideRevolve = startSketchOn(XZ)
|> startProfileAt([
|> startProfile(at = [
insideDia / 2 + thickness + sphereDia,
0
], %)
|> line([0, sphereDia / 2], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, thickness], %)
|> line([overHangLength, 0], %)
|> line([0, -2 * thickness - sphereDia], %)
|> line([-overHangLength, 0], %)
|> line([0, thickness], %)
|> line([overHangLength - thickness, 0], %)
])
|> line(end = [0, sphereDia / 2])
|> line(end = [-overHangLength + thickness, 0])
|> line(end = [0, thickness])
|> line(end = [overHangLength, 0])
|> line(end = [0, -2 * thickness - sphereDia])
|> line(end = [-overHangLength, 0])
|> line(end = [0, thickness])
|> line(end = [overHangLength - thickness, 0])
|> close()
|> revolve({ axis = Y }, %)
|> revolve(axis = Y)
"#
);
}
@ -1458,7 +1458,7 @@ f = [1, 2, 3]: [number; 1+]
let some_program_string = r#"bing = { yo = 55 }
myNestedVar = [
{
prop: line([bing.yo, 21], sketch001)
prop: line(a = [bing.yo, 21], b = sketch001)
}
]
"#;
@ -1470,7 +1470,7 @@ myNestedVar = [
r#"bing = { yo = 55 }
myNestedVar = [
{
prop = line([bing.yo, 21], sketch001)
prop = line(a = [bing.yo, 21], b = sketch001)
}
]
"#
@ -1502,10 +1502,10 @@ myNestedVar = [
fn test_recast_shebang() {
let some_program_string = r#"#!/usr/local/env zoo kcl
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> startProfile(at = [-10, -10])
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()
"#;
@ -1517,10 +1517,10 @@ part001 = startSketchOn(XY)
r#"#!/usr/local/env zoo kcl
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> startProfile(at = [-10, -10])
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()
"#
);
@ -1533,10 +1533,10 @@ part001 = startSketchOn(XY)
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> startProfile(at = [-10, -10])
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()
"#;
@ -1548,10 +1548,10 @@ part001 = startSketchOn(XY)
r#"#!/usr/local/env zoo kcl
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> startProfile(at = [-10, -10])
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()
"#
);
@ -1563,10 +1563,10 @@ part001 = startSketchOn(XY)
// Yo yo my comments.
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> startProfile(at = [-10, -10])
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()
"#;
@ -1579,10 +1579,10 @@ part001 = startSketchOn(XY)
// Yo yo my comments.
part001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> startProfile(at = [-10, -10])
|> line(end = [20, 0])
|> line(end = [0, 20])
|> line(end = [-20, 0])
|> close()
"#
);
@ -1613,7 +1613,7 @@ hole_diam = 5
// define a rectangular shape func
fn rectShape(pos, w, l) {
rr = startSketchOn(XY)
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
|> startProfile(at = [pos[0] - (w / 2), pos[1] - (l / 2)])
|> line(endAbsolute = [pos[0] + w / 2, pos[1] - (l / 2)], tag = $edge1)
|> line(endAbsolute = [pos[0] + w / 2, pos[1] + l / 2], tag = $edge2)
|> line(endAbsolute = [pos[0] - (w / 2), pos[1] + l / 2], tag = $edge3)
@ -1622,8 +1622,8 @@ fn rectShape(pos, w, l) {
}
// build the body of the focusrite scarlett solo gen 4
// only used for visualization
scarlett_body = rectShape([0, 0], width, length)
|> extrude(depth, %)
scarlett_body = rectShape(pos = [0, 0], w = width, l = length)
|> extrude(depth)
|> fillet(
radius = radius,
tags = [
@ -1636,14 +1636,14 @@ scarlett_body = rectShape([0, 0], width, length)
// build the bracket sketch around the body
fn bracketSketch(w, d, t) {
s = startSketchOn({
plane: {
plane = {
origin = { x = 0, y = length / 2 + thk, z = 0 },
x_axis = { x = 1, y = 0, z = 0 },
y_axis = { x = 0, y = 0, z = 1 },
z_axis = { x = 0, y = 1, z = 0 }
}
})
|> startProfileAt([-w / 2 - t, d + t], %)
|> startProfile(at = [-w / 2 - t, d + t])
|> line(endAbsolute = [-w / 2 - t, -t], tag = $edge1)
|> line(endAbsolute = [w / 2 + t, -t], tag = $edge2)
|> line(endAbsolute = [w / 2 + t, d + t], tag = $edge3)
@ -1655,8 +1655,8 @@ fn bracketSketch(w, d, t) {
return s
}
// build the body of the bracket
bracket_body = bracketSketch(width, depth, thk)
|> extrude(length + 10, %)
bracket_body = bracketSketch(w = width, d = depth, t = thk)
|> extrude(length + 10)
|> fillet(
radius = radius,
tags = [
@ -1668,26 +1668,26 @@ bracket_body = bracketSketch(width, depth, thk)
)
// build the tabs of the mounting bracket (right side)
tabs_r = startSketchOn({
plane: {
plane = {
origin = { x = 0, y = 0, z = depth + thk },
x_axis = { x = 1, y = 0, z = 0 },
y_axis = { x = 0, y = 1, z = 0 },
z_axis = { x = 0, y = 0, z = 1 }
}
})
|> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|> line([10, -5], %)
|> line([0, -10], %)
|> line([-10, -5], %)
|> startProfile(at = [width / 2 + thk, length / 2 + thk])
|> line(end = [10, -5])
|> line(end = [0, -10])
|> line(end = [-10, -5])
|> close()
|> hole(circle(
|> subtract2d(tool = circle(
center = [
width / 2 + thk + hole_diam,
length / 2 - hole_diam
],
radius = hole_diam / 2
), %)
|> extrude(-thk, %)
))
|> extrude(-thk)
|> patternLinear3d(
axis = [0, -1, 0],
repetitions = 1,
@ -1695,26 +1695,26 @@ tabs_r = startSketchOn({
)
// build the tabs of the mounting bracket (left side)
tabs_l = startSketchOn({
plane: {
plane = {
origin = { x = 0, y = 0, z = depth + thk },
x_axis = { x = 1, y = 0, z = 0 },
y_axis = { x = 0, y = 1, z = 0 },
z_axis = { x = 0, y = 0, z = 1 }
}
})
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|> line([-10, -5], %)
|> line([0, -10], %)
|> line([10, -5], %)
|> startProfile(at = [-width / 2 - thk, length / 2 + thk])
|> line(end = [-10, -5])
|> line(end = [0, -10])
|> line(end = [10, -5])
|> close()
|> hole(circle(
|> subtract2d(tool = circle(
center = [
-width / 2 - thk - hole_diam,
length / 2 - hole_diam
],
radius = hole_diam / 2
), %)
|> extrude(-thk, %)
))
|> extrude(-thk)
|> patternLinear3d(axis = [0, -1, 0], repetitions = 1, distance = length - 10ft)
"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
@ -1735,7 +1735,7 @@ hole_diam = 5
// define a rectangular shape func
fn rectShape(pos, w, l) {
rr = startSketchOn(XY)
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
|> startProfile(at = [pos[0] - (w / 2), pos[1] - (l / 2)])
|> line(endAbsolute = [pos[0] + w / 2, pos[1] - (l / 2)], tag = $edge1)
|> line(endAbsolute = [pos[0] + w / 2, pos[1] + l / 2], tag = $edge2)
|> line(endAbsolute = [pos[0] - (w / 2), pos[1] + l / 2], tag = $edge3)
@ -1744,8 +1744,8 @@ fn rectShape(pos, w, l) {
}
// build the body of the focusrite scarlett solo gen 4
// only used for visualization
scarlett_body = rectShape([0, 0], width, length)
|> extrude(depth, %)
scarlett_body = rectShape(pos = [0, 0], w = width, l = length)
|> extrude(depth)
|> fillet(
radius = radius,
tags = [
@ -1765,7 +1765,7 @@ fn bracketSketch(w, d, t) {
z_axis = { x = 0, y = 1, z = 0 }
}
})
|> startProfileAt([-w / 2 - t, d + t], %)
|> startProfile(at = [-w / 2 - t, d + t])
|> line(endAbsolute = [-w / 2 - t, -t], tag = $edge1)
|> line(endAbsolute = [w / 2 + t, -t], tag = $edge2)
|> line(endAbsolute = [w / 2 + t, d + t], tag = $edge3)
@ -1777,8 +1777,8 @@ fn bracketSketch(w, d, t) {
return s
}
// build the body of the bracket
bracket_body = bracketSketch(width, depth, thk)
|> extrude(length + 10, %)
bracket_body = bracketSketch(w = width, d = depth, t = thk)
|> extrude(length + 10)
|> fillet(
radius = radius,
tags = [
@ -1797,19 +1797,19 @@ tabs_r = startSketchOn({
z_axis = { x = 0, y = 0, z = 1 }
}
})
|> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|> line([10, -5], %)
|> line([0, -10], %)
|> line([-10, -5], %)
|> startProfile(at = [width / 2 + thk, length / 2 + thk])
|> line(end = [10, -5])
|> line(end = [0, -10])
|> line(end = [-10, -5])
|> close()
|> hole(circle(
|> subtract2d(tool = circle(
center = [
width / 2 + thk + hole_diam,
length / 2 - hole_diam
],
radius = hole_diam / 2,
), %)
|> extrude(-thk, %)
))
|> extrude(-thk)
|> patternLinear3d(axis = [0, -1, 0], repetitions = 1, distance = length - 10)
// build the tabs of the mounting bracket (left side)
tabs_l = startSketchOn({
@ -1820,19 +1820,19 @@ tabs_l = startSketchOn({
z_axis = { x = 0, y = 0, z = 1 }
}
})
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|> line([-10, -5], %)
|> line([0, -10], %)
|> line([10, -5], %)
|> startProfile(at = [-width / 2 - thk, length / 2 + thk])
|> line(end = [-10, -5])
|> line(end = [0, -10])
|> line(end = [10, -5])
|> close()
|> hole(circle(
|> subtract2d(tool = circle(
center = [
-width / 2 - thk - hole_diam,
length / 2 - hole_diam
],
radius = hole_diam / 2,
), %)
|> extrude(-thk, %)
))
|> extrude(-thk)
|> patternLinear3d(axis = [0, -1, 0], repetitions = 1, distance = length - 10ft)
"#
);
@ -1842,12 +1842,12 @@ tabs_l = startSketchOn({
fn test_recast_nested_var_declaration_in_fn_body() {
let some_program_string = r#"fn cube(pos, scale) {
sg = startSketchOn(XY)
|> startProfileAt(pos, %)
|> line([0, scale], %)
|> line([scale, 0], %)
|> line([0, -scale], %)
|> startProfile(at = pos)
|> line(end = [0, scale])
|> line(end = [scale, 0])
|> line(end = [0, -scale])
|> close()
|> extrude(scale, %)
|> extrude(scale)
}"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
@ -1856,12 +1856,12 @@ tabs_l = startSketchOn({
recasted,
r#"fn cube(pos, scale) {
sg = startSketchOn(XY)
|> startProfileAt(pos, %)
|> line([0, scale], %)
|> line([scale, 0], %)
|> line([0, -scale], %)
|> startProfile(at = pos)
|> line(end = [0, scale])
|> line(end = [scale, 0])
|> line(end = [0, -scale])
|> close()
|> extrude(scale, %)
|> extrude(scale)
}
"#
);
@ -1873,15 +1873,15 @@ tabs_l = startSketchOn({
x = dfsfs + dfsfsd as y
sg = startSketchOn(XY)
|> startProfileAt(pos, %) as foo
|> line([0, scale], %)
|> line([scale, 0], %) as bar
|> line([0 as baz, -scale] as qux, %)
|> startProfile(at = pos) as foo
|> line([0, scale])
|> line([scale, 0]) as bar
|> line([0 as baz, -scale] as qux)
|> close()
|> extrude(scale, %)
|> extrude(length = scale)
}
cube(0, 0) as cub
cube(pos = 0, scale = 0) as cub
"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
@ -1892,18 +1892,18 @@ cube(0, 0) as cub
#[test]
fn test_recast_with_bad_indentation() {
let some_program_string = r#"part001 = startSketchOn(XY)
|> startProfileAt([0.0, 5.0], %)
|> line([0.4900857016, -0.0240763666], %)
|> line([0.6804562304, 0.9087880491], %)"#;
|> startProfile(at = [0.0, 5.0])
|> line(end = [0.4900857016, -0.0240763666])
|> line(end = [0.6804562304, 0.9087880491])"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let recasted = program.recast(&Default::default(), 0);
assert_eq!(
recasted,
r#"part001 = startSketchOn(XY)
|> startProfileAt([0.0, 5.0], %)
|> line([0.4900857016, -0.0240763666], %)
|> line([0.6804562304, 0.9087880491], %)
|> startProfile(at = [0.0, 5.0])
|> line(end = [0.4900857016, -0.0240763666])
|> line(end = [0.6804562304, 0.9087880491])
"#
);
}
@ -1911,38 +1911,38 @@ cube(0, 0) as cub
#[test]
fn test_recast_with_bad_indentation_and_inline_comment() {
let some_program_string = r#"part001 = startSketchOn(XY)
|> startProfileAt([0.0, 5.0], %)
|> line([0.4900857016, -0.0240763666], %) // hello world
|> line([0.6804562304, 0.9087880491], %)"#;
|> startProfile(at = [0.0, 5.0])
|> line(end = [0.4900857016, -0.0240763666]) // hello world
|> line(end = [0.6804562304, 0.9087880491])"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let recasted = program.recast(&Default::default(), 0);
assert_eq!(
recasted,
r#"part001 = startSketchOn(XY)
|> startProfileAt([0.0, 5.0], %)
|> line([0.4900857016, -0.0240763666], %) // hello world
|> line([0.6804562304, 0.9087880491], %)
|> startProfile(at = [0.0, 5.0])
|> line(end = [0.4900857016, -0.0240763666]) // hello world
|> line(end = [0.6804562304, 0.9087880491])
"#
);
}
#[test]
fn test_recast_with_bad_indentation_and_line_comment() {
let some_program_string = r#"part001 = startSketchOn(XY)
|> startProfileAt([0.0, 5.0], %)
|> line([0.4900857016, -0.0240763666], %)
|> startProfile(at = [0.0, 5.0])
|> line(end = [0.4900857016, -0.0240763666])
// hello world
|> line([0.6804562304, 0.9087880491], %)"#;
|> line(end = [0.6804562304, 0.9087880491])"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let recasted = program.recast(&Default::default(), 0);
assert_eq!(
recasted,
r#"part001 = startSketchOn(XY)
|> startProfileAt([0.0, 5.0], %)
|> line([0.4900857016, -0.0240763666], %)
|> startProfile(at = [0.0, 5.0])
|> line(end = [0.4900857016, -0.0240763666])
// hello world
|> line([0.6804562304, 0.9087880491], %)
|> line(end = [0.6804562304, 0.9087880491])
"#
);
}
@ -2085,7 +2085,7 @@ thing = 'foo'
/* comment at start */
mySk1 = startSketchOn(XY)
|> startProfileAt([0, 0], %)"#;
|> startProfile(at = [0, 0])"#;
let program = crate::parsing::top_level_parse(test_program).unwrap();
let recasted = program.recast(&Default::default(), 0);
@ -2094,7 +2094,7 @@ mySk1 = startSketchOn(XY)
r#"/* comment at start */
mySk1 = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
"#
);
}
@ -2103,7 +2103,7 @@ mySk1 = startSketchOn(XY)
fn test_recast_lots_of_comments() {
let some_program_string = r#"// comment at start
mySk1 = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(endAbsolute = [1, 1])
// comment here
|> line(endAbsolute = [0, 1], tag = $myTag)
@ -2112,10 +2112,10 @@ mySk1 = startSketchOn(XY)
here
*/
// a comment between pipe expression statements
|> rx(90, %)
|> rx(90)
// and another with just white space between others below
|> ry(45, %)
|> rx(45, %)
|> ry(45)
|> rx(45)
// one more for good measure"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
@ -2124,7 +2124,7 @@ mySk1 = startSketchOn(XY)
recasted,
r#"// comment at start
mySk1 = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> line(endAbsolute = [1, 1])
// comment here
|> line(endAbsolute = [0, 1], tag = $myTag)
@ -2132,10 +2132,10 @@ mySk1 = startSketchOn(XY)
/* and
here */
// a comment between pipe expression statements
|> rx(90, %)
|> rx(90)
// and another with just white space between others below
|> ry(45, %)
|> rx(45, %)
|> ry(45)
|> rx(45)
// one more for good measure
"#
);
@ -2223,10 +2223,10 @@ myVar3 = 6
myAng = 40
myAng2 = 134
part001 = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line([1, 3.82], %, $seg01) // ln-should-get-tag
|> angledLine(angle = -foo(seg01, myVar, %), length = myVar) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|> angledLine(angle = -bar(seg01, myVar, %), length = myVar) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper"#;
|> startProfile(at = [0, 0])
|> line(end = [1, 3.82], tag = $seg01) // ln-should-get-tag
|> angledLine(angle = -foo(x = seg01, y = myVar, z = %), length = myVar) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|> angledLine(angle = -bar(x = seg01, y = myVar, z = %), length = myVar) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let recasted = program.recast(&Default::default(), 0);
@ -2241,10 +2241,10 @@ myVar3 = 6
myAng = 40
myAng2 = 134
part001 = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line([1, 3.82], %, $seg01) // ln-should-get-tag
|> angledLine(angle = -foo(seg01, myVar, %), length = myVar) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|> angledLine(angle = -bar(seg01, myVar, %), length = myVar) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper
|> startProfile(at = [0, 0])
|> line(end = [1, 3.82], tag = $seg01) // ln-should-get-tag
|> angledLine(angle = -foo(x = seg01, y = myVar, z = %), length = myVar) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|> angledLine(angle = -bar(x = seg01, y = myVar, z = %), length = myVar) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper
"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
@ -2262,8 +2262,8 @@ part001 = startSketchOn(XY)
#[test]
fn test_recast_after_rename_std() {
let some_program_string = r#"part001 = startSketchOn(XY)
|> startProfileAt([0.0000000000, 5.0000000000], %)
|> line([0.4900857016, -0.0240763666], %)
|> startProfile(at = [0.0000000000, 5.0000000000])
|> line(end = [0.4900857016, -0.0240763666])
part002 = "part002"
things = [part001, 0.0]
@ -2282,8 +2282,8 @@ fn ghi(part001) {
assert_eq!(
recasted,
r#"mySuperCoolPart = startSketchOn(XY)
|> startProfileAt([0.0, 5.0], %)
|> line([0.4900857016, -0.0240763666], %)
|> startProfile(at = [0.0, 5.0])
|> line(end = [0.4900857016, -0.0240763666])
part002 = "part002"
things = [mySuperCoolPart, 0.0]
@ -2319,24 +2319,24 @@ fn ghi(part001) {
#[test]
fn test_recast_trailing_comma() {
let some_program_string = r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> arc({
radius = 1,
angle_start = 0,
angle_end = 180,
}, %)"#;
})"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let recasted = program.recast(&Default::default(), 0);
assert_eq!(
recasted,
r#"startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> startProfile(at = [0, 0])
|> arc({
radius = 1,
angle_start = 0,
angle_end = 180
}, %)
})
"#
);
}
@ -2348,12 +2348,12 @@ l = 8
h = 10
firstExtrude = startSketchOn(XY)
|> startProfileAt([0,0], %)
|> line([0, l], %)
|> line([w, 0], %)
|> line([0, -l], %)
|> startProfile(at = [0,0])
|> line(end = [0, l])
|> line(end = [w, 0])
|> line(end = [0, -l])
|> close()
|> extrude(h, %)
|> extrude(h)
"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
@ -2365,12 +2365,12 @@ l = 8
h = 10
firstExtrude = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line([0, l], %)
|> line([w, 0], %)
|> line([0, -l], %)
|> startProfile(at = [0, 0])
|> line(end = [0, l])
|> line(end = [w, 0])
|> line(end = [0, -l])
|> close()
|> extrude(h, %)
|> extrude(h)
"#
);
}
@ -2385,12 +2385,12 @@ h = 10
// It has multiple lines
// And it's really long
firstExtrude = startSketchOn(XY)
|> startProfileAt([0,0], %)
|> line([0, l], %)
|> line([w, 0], %)
|> line([0, -l], %)
|> startProfile(at = [0,0])
|> line(end = [0, l])
|> line(end = [w, 0])
|> line(end = [0, -l])
|> close()
|> extrude(h, %)
|> extrude(h)
"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
@ -2405,12 +2405,12 @@ h = 10
// It has multiple lines
// And it's really long
firstExtrude = startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line([0, l], %)
|> line([w, 0], %)
|> line([0, -l], %)
|> startProfile(at = [0, 0])
|> line(end = [0, l])
|> line(end = [w, 0])
|> line(end = [0, -l])
|> close()
|> extrude(h, %)
|> extrude(h)
"#
);
}
@ -2430,11 +2430,11 @@ firstExtrude = startSketchOn(XY)
thickness = 0.5
startSketchOn(XY)
|> startProfileAt([0, 0], %)
|> line([0, -(wallMountL - thickness)], %)
|> line([0, -(5 - thickness)], %)
|> line([0, -(5 - 1)], %)
|> line([0, -(-5 - 1)], %)"#;
|> startProfile(at = [0, 0])
|> line(end = [0, -(wallMountL - thickness)])
|> line(end = [0, -(5 - thickness)])
|> line(end = [0, -(5 - 1)])
|> line(end = [0, -(-5 - 1)])"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let recasted = program.recast(&Default::default(), 0);
@ -2560,9 +2560,13 @@ sketch002 = startSketchOn({
#[test]
fn unparse_fn_unnamed() {
let input = r#"squares_out = reduce(arr, 0: number, fn(i, squares) {
return 1
})
let input = r#"squares_out = reduce(
arr,
n = 0: number,
f = fn(i, squares) {
return 1
},
)
"#;
let ast = crate::parsing::top_level_parse(input).unwrap();
let actual = ast.recast(&FormatOptions::new(), 0);