2024-09-09 18:17:45 -04:00
|
|
|
import { err, reportRejection, trap } from 'lib/trap'
|
2024-11-21 15:04:30 +11:00
|
|
|
import { Selection } from 'lib/selections'
|
2023-01-06 09:29:26 +11:00
|
|
|
import {
|
|
|
|
Program,
|
|
|
|
CallExpression,
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
LabeledArg,
|
|
|
|
CallExpressionKw,
|
2023-01-06 09:29:26 +11:00
|
|
|
PipeExpression,
|
|
|
|
VariableDeclaration,
|
2023-02-12 10:56:45 +11:00
|
|
|
VariableDeclarator,
|
2024-08-12 15:38:42 -05:00
|
|
|
Expr,
|
2023-02-12 10:56:45 +11:00
|
|
|
Literal,
|
2024-11-18 10:04:09 -05:00
|
|
|
LiteralValue,
|
2023-02-12 10:56:45 +11:00
|
|
|
PipeSubstitution,
|
|
|
|
Identifier,
|
|
|
|
ArrayExpression,
|
|
|
|
ObjectExpression,
|
2023-03-02 21:19:11 +11:00
|
|
|
UnaryExpression,
|
|
|
|
BinaryExpression,
|
2023-09-29 11:11:01 -07:00
|
|
|
PathToNode,
|
2024-05-24 20:54:42 +10:00
|
|
|
SourceRange,
|
2024-09-27 15:44:44 -07:00
|
|
|
sketchFromKclValue,
|
2024-11-18 16:25:25 -05:00
|
|
|
isPathToNodeNumber,
|
2025-02-15 00:57:04 +11:00
|
|
|
parse,
|
2025-01-31 10:45:39 -05:00
|
|
|
formatNumber,
|
2025-02-15 00:57:04 +11:00
|
|
|
ArtifactGraph,
|
2025-02-12 10:22:56 +13:00
|
|
|
VariableMap,
|
2025-02-15 00:57:04 +11:00
|
|
|
KclValue,
|
2023-09-29 11:11:01 -07:00
|
|
|
} from './wasm'
|
2023-04-01 16:47:00 +11:00
|
|
|
import {
|
2024-05-24 20:54:42 +10:00
|
|
|
isNodeSafeToReplacePath,
|
2023-04-01 16:47:00 +11:00
|
|
|
findAllPreviousVariables,
|
2024-05-24 20:54:42 +10:00
|
|
|
findAllPreviousVariablesPath,
|
2023-04-01 16:47:00 +11:00
|
|
|
getNodeFromPath,
|
|
|
|
isNodeSafeToReplace,
|
2024-06-29 10:36:04 -07:00
|
|
|
traverse,
|
2025-02-15 00:57:04 +11:00
|
|
|
getBodyIndex,
|
|
|
|
isCallExprWithName,
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
ARG_INDEX_FIELD,
|
|
|
|
LABELED_ARG_FIELD,
|
2025-02-13 13:37:02 -06:00
|
|
|
UNLABELED_ARG,
|
2023-04-01 16:47:00 +11:00
|
|
|
} from './queryAst'
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
import {
|
|
|
|
addTagForSketchOnFace,
|
|
|
|
ARG_TAG,
|
|
|
|
getConstraintInfo,
|
|
|
|
getConstraintInfoKw,
|
|
|
|
} from './std/sketch'
|
2025-01-27 14:24:28 +01:00
|
|
|
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
|
2024-05-24 20:54:42 +10:00
|
|
|
import {
|
|
|
|
PathToNodeMap,
|
|
|
|
isLiteralArrayOrStatic,
|
|
|
|
removeSingleConstraint,
|
|
|
|
transformAstSketchLines,
|
|
|
|
} from './std/sketchcombos'
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
import { DefaultPlaneStr } from 'lib/planes'
|
2025-02-15 00:57:04 +11:00
|
|
|
import { isArray, isOverlap, roundOff } from 'lib/utils'
|
2024-06-04 13:57:01 -04:00
|
|
|
import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants'
|
2024-09-13 21:14:14 +10:00
|
|
|
import { SimplifiedArgDetails } from './std/stdTypes'
|
2024-06-24 22:39:04 -07:00
|
|
|
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
|
2024-06-29 10:36:04 -07:00
|
|
|
import { Models } from '@kittycad/lib'
|
2024-09-26 18:25:05 +10:00
|
|
|
import { ExtrudeFacePlane } from 'machines/modelingMachine'
|
2024-10-30 16:52:17 -04:00
|
|
|
import { Node } from 'wasm-lib/kcl/bindings/Node'
|
2024-12-09 16:43:58 -05:00
|
|
|
import { KclExpressionWithVariable } from 'lib/commandTypes'
|
2025-02-15 00:57:04 +11:00
|
|
|
import {
|
|
|
|
Artifact,
|
|
|
|
expandCap,
|
|
|
|
expandPlane,
|
|
|
|
expandWall,
|
|
|
|
getArtifactOfTypes,
|
|
|
|
getArtifactsOfTypes,
|
|
|
|
getFaceCodeRef,
|
|
|
|
getPathsFromArtifact,
|
|
|
|
} from './std/artifactGraph'
|
|
|
|
import { BodyItem } from 'wasm-lib/kcl/bindings/BodyItem'
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
import { findKwArg } from './util'
|
2025-02-03 18:11:26 +01:00
|
|
|
import { deleteEdgeTreatment } from './modifyAst/addEdgeTreatment'
|
2023-01-06 09:29:26 +11:00
|
|
|
|
2024-02-11 12:59:00 +11:00
|
|
|
export function startSketchOnDefault(
|
2024-10-30 16:52:17 -04:00
|
|
|
node: Node<Program>,
|
2024-02-11 12:59:00 +11:00
|
|
|
axis: DefaultPlaneStr,
|
|
|
|
name = ''
|
2024-10-30 16:52:17 -04:00
|
|
|
): { modifiedAst: Node<Program>; id: string; pathToNode: PathToNode } {
|
2023-09-13 08:36:47 +10:00
|
|
|
const _node = { ...node }
|
2024-06-04 13:57:01 -04:00
|
|
|
const _name =
|
|
|
|
name || findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.SKETCH)
|
2023-09-13 08:36:47 +10:00
|
|
|
|
2023-10-05 14:27:48 -07:00
|
|
|
const startSketchOn = createCallExpressionStdLib('startSketchOn', [
|
2024-02-11 12:59:00 +11:00
|
|
|
createLiteral(axis),
|
2023-09-13 08:36:47 +10:00
|
|
|
])
|
|
|
|
|
2024-02-11 12:59:00 +11:00
|
|
|
const variableDeclaration = createVariableDeclaration(_name, startSketchOn)
|
2023-09-13 08:36:47 +10:00
|
|
|
_node.body = [...node.body, variableDeclaration]
|
2024-02-11 12:59:00 +11:00
|
|
|
const sketchIndex = _node.body.length - 1
|
2023-09-13 08:36:47 +10:00
|
|
|
|
|
|
|
let pathToNode: PathToNode = [
|
|
|
|
['body', ''],
|
2024-02-11 12:59:00 +11:00
|
|
|
[sketchIndex, 'index'],
|
2024-12-07 07:16:04 +13:00
|
|
|
['declaration', 'VariableDeclaration'],
|
2023-09-13 08:36:47 +10:00
|
|
|
['init', 'VariableDeclarator'],
|
|
|
|
]
|
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst: _node,
|
|
|
|
id: _name,
|
|
|
|
pathToNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-15 00:57:04 +11:00
|
|
|
export function insertNewStartProfileAt(
|
2024-10-30 16:52:17 -04:00
|
|
|
node: Node<Program>,
|
2025-02-15 00:57:04 +11:00
|
|
|
sketchEntryNodePath: PathToNode,
|
|
|
|
sketchNodePaths: PathToNode[],
|
|
|
|
planeNodePath: PathToNode,
|
|
|
|
at: [number, number],
|
|
|
|
insertType: 'start' | 'end' = 'end'
|
|
|
|
):
|
|
|
|
| {
|
|
|
|
modifiedAst: Node<Program>
|
|
|
|
updatedSketchNodePaths: PathToNode[]
|
|
|
|
updatedEntryNodePath: PathToNode
|
|
|
|
}
|
|
|
|
| Error {
|
|
|
|
const varDec = getNodeFromPath<VariableDeclarator>(
|
2024-02-11 12:59:00 +11:00
|
|
|
node,
|
2025-02-15 00:57:04 +11:00
|
|
|
planeNodePath,
|
|
|
|
'VariableDeclarator'
|
2024-06-24 11:45:40 -04:00
|
|
|
)
|
2025-02-15 00:57:04 +11:00
|
|
|
if (err(varDec)) return varDec
|
|
|
|
if (varDec.node.type !== 'VariableDeclarator') return new Error('not a var')
|
|
|
|
|
|
|
|
const newExpression = createVariableDeclaration(
|
|
|
|
findUniqueName(node, 'profile'),
|
|
|
|
createCallExpressionStdLib('startProfileAt', [
|
|
|
|
createArrayExpression([
|
|
|
|
createLiteral(roundOff(at[0])),
|
|
|
|
createLiteral(roundOff(at[1])),
|
|
|
|
]),
|
|
|
|
createIdentifier(varDec.node.id.name),
|
2024-02-11 12:59:00 +11:00
|
|
|
])
|
2025-02-15 00:57:04 +11:00
|
|
|
)
|
|
|
|
const insertIndex = getInsertIndex(sketchNodePaths, planeNodePath, insertType)
|
|
|
|
|
|
|
|
const _node = structuredClone(node)
|
|
|
|
// TODO the rest of this function will not be robust to work for sketches defined within a function declaration
|
|
|
|
_node.body.splice(insertIndex, 0, newExpression)
|
|
|
|
|
|
|
|
const { updatedEntryNodePath, updatedSketchNodePaths } =
|
|
|
|
updateSketchNodePathsWithInsertIndex({
|
|
|
|
insertIndex,
|
|
|
|
insertType,
|
|
|
|
sketchNodePaths,
|
|
|
|
})
|
2024-02-11 12:59:00 +11:00
|
|
|
return {
|
|
|
|
modifiedAst: _node,
|
2025-02-15 00:57:04 +11:00
|
|
|
updatedSketchNodePaths,
|
|
|
|
updatedEntryNodePath,
|
2024-02-11 12:59:00 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-06 09:29:26 +11:00
|
|
|
export function addSketchTo(
|
2024-10-30 16:52:17 -04:00
|
|
|
node: Node<Program>,
|
2023-01-06 09:29:26 +11:00
|
|
|
axis: 'xy' | 'xz' | 'yz',
|
|
|
|
name = ''
|
2023-04-01 16:47:00 +11:00
|
|
|
): { modifiedAst: Program; id: string; pathToNode: PathToNode } {
|
2023-01-06 09:29:26 +11:00
|
|
|
const _node = { ...node }
|
2024-06-04 13:57:01 -04:00
|
|
|
const _name =
|
|
|
|
name || findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.SKETCH)
|
2023-01-06 09:29:26 +11:00
|
|
|
|
2023-10-05 14:27:48 -07:00
|
|
|
const startSketchOn = createCallExpressionStdLib('startSketchOn', [
|
|
|
|
createLiteral(axis.toUpperCase()),
|
2023-02-12 10:56:45 +11:00
|
|
|
])
|
2023-10-05 14:27:48 -07:00
|
|
|
const startProfileAt = createCallExpressionStdLib('startProfileAt', [
|
|
|
|
createLiteral('default'),
|
2023-02-12 10:56:45 +11:00
|
|
|
createPipeSubstitution(),
|
|
|
|
])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
const initialLineTo = createCallExpressionStdLibKw(
|
|
|
|
'line',
|
|
|
|
null, // Assumes this is being called in a pipeline, so the first arg is optional and if not given, will become pipeline substitution.
|
|
|
|
[createLabeledArg('end', createLiteral('default'))]
|
|
|
|
)
|
2023-01-06 09:29:26 +11:00
|
|
|
|
2023-10-05 14:27:48 -07:00
|
|
|
const pipeBody = [startSketchOn, startProfileAt, initialLineTo]
|
2023-02-12 10:56:45 +11:00
|
|
|
|
|
|
|
const variableDeclaration = createVariableDeclaration(
|
|
|
|
_name,
|
|
|
|
createPipeExpression(pipeBody)
|
|
|
|
)
|
2023-01-06 09:29:26 +11:00
|
|
|
|
2024-03-01 17:16:18 -08:00
|
|
|
_node.body = [...node.body, variableDeclaration]
|
|
|
|
let sketchIndex = _node.body.length - 1
|
2023-04-01 16:47:00 +11:00
|
|
|
let pathToNode: PathToNode = [
|
|
|
|
['body', ''],
|
|
|
|
[sketchIndex, 'index'],
|
2024-12-07 07:16:04 +13:00
|
|
|
['declaration', 'VariableDeclaration'],
|
2023-04-01 16:47:00 +11:00
|
|
|
['init', 'VariableDeclarator'],
|
2023-01-06 09:29:26 +11:00
|
|
|
]
|
|
|
|
if (axis !== 'xy') {
|
2023-04-01 16:47:00 +11:00
|
|
|
pathToNode = [...pathToNode, ['body', ''], ['0', 'index']]
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
2024-03-01 17:16:18 -08:00
|
|
|
modifiedAst: _node,
|
2023-01-06 09:29:26 +11:00
|
|
|
id: _name,
|
|
|
|
pathToNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function findUniqueName(
|
2023-01-06 09:29:26 +11:00
|
|
|
ast: Program | string,
|
|
|
|
name: string,
|
2023-01-09 13:19:14 +11:00
|
|
|
pad = 3,
|
2023-01-06 09:29:26 +11:00
|
|
|
index = 1
|
|
|
|
): string {
|
2024-02-23 11:24:22 -05:00
|
|
|
let searchStr: string = typeof ast === 'string' ? ast : JSON.stringify(ast)
|
|
|
|
const indexStr = String(index).padStart(pad, '0')
|
|
|
|
|
|
|
|
const endingDigitsMatcher = /\d+$/
|
|
|
|
const nameEndsInDigits = name.match(endingDigitsMatcher)
|
|
|
|
let nameIsInString = searchStr.includes(`:"${name}"`)
|
|
|
|
|
|
|
|
if (nameEndsInDigits !== null) {
|
|
|
|
// base case: name is unique and ends in digits
|
|
|
|
if (!nameIsInString) return name
|
|
|
|
|
|
|
|
// recursive case: name is not unique and ends in digits
|
|
|
|
const newPad = nameEndsInDigits[1].length
|
|
|
|
const newIndex = parseInt(nameEndsInDigits[1]) + 1
|
|
|
|
const nameWithoutDigits = name.replace(endingDigitsMatcher, '')
|
|
|
|
|
|
|
|
return findUniqueName(searchStr, nameWithoutDigits, newPad, newIndex)
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
2024-02-23 11:24:22 -05:00
|
|
|
|
2023-01-06 09:29:26 +11:00
|
|
|
const newName = `${name}${indexStr}`
|
2024-02-23 11:24:22 -05:00
|
|
|
nameIsInString = searchStr.includes(`:"${newName}"`)
|
|
|
|
|
|
|
|
// base case: name is unique and does not end in digits
|
|
|
|
if (!nameIsInString) return newName
|
|
|
|
|
|
|
|
// recursive case: name is not unique and does not end in digits
|
2023-01-09 13:19:14 +11:00
|
|
|
return findUniqueName(searchStr, name, pad, index + 1)
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
|
|
|
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
/**
|
|
|
|
Set the keyword argument to the given value.
|
|
|
|
Returns true if it overwrote an existing argument.
|
|
|
|
Returns false if no argument with the label existed before.
|
|
|
|
*/
|
|
|
|
export function mutateKwArg(
|
|
|
|
label: string,
|
|
|
|
node: CallExpressionKw,
|
|
|
|
val: Expr
|
|
|
|
): boolean {
|
|
|
|
for (let i = 0; i < node.arguments.length; i++) {
|
|
|
|
const arg = node.arguments[i]
|
|
|
|
if (arg.label.name === label) {
|
2025-02-15 00:57:04 +11:00
|
|
|
if (isLiteralArrayOrStatic(val) && isLiteralArrayOrStatic(arg.arg)) {
|
|
|
|
node.arguments[i].arg = val
|
|
|
|
return true
|
|
|
|
} else if (
|
|
|
|
arg.arg.type === 'ArrayExpression' &&
|
|
|
|
val.type === 'ArrayExpression'
|
|
|
|
) {
|
|
|
|
const arrExp = arg.arg
|
|
|
|
arrExp.elements.forEach((element, i) => {
|
|
|
|
if (isLiteralArrayOrStatic(element)) {
|
|
|
|
arrExp.elements[i] = val.elements[i]
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return true
|
|
|
|
}
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
node.arguments.push(createLabeledArg(label, val))
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2024-08-12 15:38:42 -05:00
|
|
|
export function mutateArrExp(node: Expr, updateWith: ArrayExpression): boolean {
|
2023-02-12 10:56:45 +11:00
|
|
|
if (node.type === 'ArrayExpression') {
|
|
|
|
node.elements.forEach((element, i) => {
|
2023-09-13 07:23:14 -07:00
|
|
|
if (isLiteralArrayOrStatic(element)) {
|
2023-02-12 10:56:45 +11:00
|
|
|
node.elements[i] = updateWith.elements[i]
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return true
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
return false
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function mutateObjExpProp(
|
2024-08-12 15:38:42 -05:00
|
|
|
node: Expr,
|
2024-10-30 16:52:17 -04:00
|
|
|
updateWith: Node<Literal> | Node<ArrayExpression>,
|
2023-02-12 10:56:45 +11:00
|
|
|
key: string
|
|
|
|
): boolean {
|
|
|
|
if (node.type === 'ObjectExpression') {
|
|
|
|
const keyIndex = node.properties.findIndex((a) => a.key.name === key)
|
|
|
|
if (keyIndex !== -1) {
|
|
|
|
if (
|
2023-09-13 07:23:14 -07:00
|
|
|
isLiteralArrayOrStatic(updateWith) &&
|
|
|
|
isLiteralArrayOrStatic(node.properties[keyIndex].value)
|
2023-02-12 10:56:45 +11:00
|
|
|
) {
|
|
|
|
node.properties[keyIndex].value = updateWith
|
|
|
|
return true
|
|
|
|
} else if (
|
|
|
|
node.properties[keyIndex].value.type === 'ArrayExpression' &&
|
|
|
|
updateWith.type === 'ArrayExpression'
|
|
|
|
) {
|
|
|
|
const arrExp = node.properties[keyIndex].value as ArrayExpression
|
|
|
|
arrExp.elements.forEach((element, i) => {
|
2023-09-13 07:23:14 -07:00
|
|
|
if (isLiteralArrayOrStatic(element)) {
|
2023-02-12 10:56:45 +11:00
|
|
|
arrExp.elements[i] = updateWith.elements[i]
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
} else {
|
|
|
|
node.properties.push({
|
|
|
|
type: 'ObjectProperty',
|
|
|
|
key: createIdentifier(key),
|
|
|
|
value: updateWith,
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2023-02-12 10:56:45 +11:00
|
|
|
})
|
|
|
|
}
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
return false
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
2023-01-06 12:45:34 +11:00
|
|
|
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
export function extrudeSketch({
|
|
|
|
node,
|
|
|
|
pathToNode,
|
|
|
|
distance = createLiteral(4),
|
|
|
|
extrudeName,
|
2025-02-15 00:57:04 +11:00
|
|
|
artifact,
|
|
|
|
artifactGraph,
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
}: {
|
|
|
|
node: Node<Program>
|
|
|
|
pathToNode: PathToNode
|
|
|
|
distance: Expr
|
|
|
|
extrudeName?: string
|
2025-02-15 00:57:04 +11:00
|
|
|
artifactGraph: ArtifactGraph
|
|
|
|
artifact?: Artifact
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
}):
|
2024-06-24 11:45:40 -04:00
|
|
|
| {
|
2024-10-30 16:52:17 -04:00
|
|
|
modifiedAst: Node<Program>
|
2024-06-24 11:45:40 -04:00
|
|
|
pathToNode: PathToNode
|
|
|
|
pathToExtrudeArg: PathToNode
|
|
|
|
}
|
|
|
|
| Error {
|
2025-02-15 00:57:04 +11:00
|
|
|
const orderedSketchNodePaths = getPathsFromArtifact({
|
|
|
|
artifact: artifact,
|
|
|
|
sketchPathToNode: pathToNode,
|
|
|
|
artifactGraph,
|
|
|
|
ast: node,
|
|
|
|
})
|
|
|
|
if (err(orderedSketchNodePaths)) return orderedSketchNodePaths
|
2024-09-17 08:29:52 -05:00
|
|
|
const _node = structuredClone(node)
|
2024-06-24 11:45:40 -04:00
|
|
|
const _node1 = getNodeFromPath(_node, pathToNode)
|
|
|
|
if (err(_node1)) return _node1
|
2023-01-06 12:45:34 +11:00
|
|
|
|
|
|
|
// determine if sketchExpression is in a pipeExpression or not
|
2024-06-24 11:45:40 -04:00
|
|
|
const _node2 = getNodeFromPath<PipeExpression>(
|
2023-01-06 12:45:34 +11:00
|
|
|
_node,
|
|
|
|
pathToNode,
|
2023-01-13 17:58:37 +11:00
|
|
|
'PipeExpression'
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(_node2)) return _node2
|
2023-01-13 17:58:37 +11:00
|
|
|
|
2024-06-24 11:45:40 -04:00
|
|
|
const _node3 = getNodeFromPath<VariableDeclarator>(
|
|
|
|
_node,
|
|
|
|
pathToNode,
|
|
|
|
'VariableDeclarator'
|
|
|
|
)
|
|
|
|
if (err(_node3)) return _node3
|
2025-02-15 00:57:04 +11:00
|
|
|
const { node: variableDeclarator } = _node3
|
2023-01-06 12:45:34 +11:00
|
|
|
|
2025-02-15 00:57:04 +11:00
|
|
|
const extrudeCall = createCallExpressionStdLibKw(
|
|
|
|
'extrude',
|
|
|
|
createIdentifier(variableDeclarator.id.name),
|
|
|
|
[createLabeledArg('length', distance)]
|
|
|
|
)
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
// index of the 'length' arg above. If you reorder the labeled args above,
|
|
|
|
// make sure to update this too.
|
|
|
|
const argIndex = 0
|
2023-03-02 21:19:11 +11:00
|
|
|
|
2024-06-04 13:57:01 -04:00
|
|
|
// We're not creating a pipe expression,
|
|
|
|
// but rather a separate constant for the extrusion
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
const name =
|
|
|
|
extrudeName ?? findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.EXTRUDE)
|
2023-03-02 21:19:11 +11:00
|
|
|
const VariableDeclaration = createVariableDeclaration(name, extrudeCall)
|
2024-06-04 13:57:01 -04:00
|
|
|
|
2025-02-15 00:57:04 +11:00
|
|
|
const lastSketchNodePath =
|
|
|
|
orderedSketchNodePaths[orderedSketchNodePaths.length - 1]
|
|
|
|
|
|
|
|
const sketchIndexInBody = Number(lastSketchNodePath[1][0])
|
2024-06-04 13:57:01 -04:00
|
|
|
_node.body.splice(sketchIndexInBody + 1, 0, VariableDeclaration)
|
|
|
|
|
2023-04-01 16:47:00 +11:00
|
|
|
const pathToExtrudeArg: PathToNode = [
|
|
|
|
['body', ''],
|
2024-06-04 13:57:01 -04:00
|
|
|
[sketchIndexInBody + 1, 'index'],
|
2024-12-07 07:16:04 +13:00
|
|
|
['declaration', 'VariableDeclaration'],
|
2023-04-01 16:47:00 +11:00
|
|
|
['init', 'VariableDeclarator'],
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
['arguments', 'CallExpressionKw'],
|
|
|
|
[argIndex, ARG_INDEX_FIELD],
|
|
|
|
['arg', LABELED_ARG_FIELD],
|
2023-01-13 17:58:37 +11:00
|
|
|
]
|
2023-01-06 12:45:34 +11:00
|
|
|
return {
|
2024-06-04 13:57:01 -04:00
|
|
|
modifiedAst: _node,
|
2024-03-01 17:16:18 -08:00
|
|
|
pathToNode: [...pathToNode.slice(0, -1), [-1, 'index']],
|
2023-01-13 17:58:37 +11:00
|
|
|
pathToExtrudeArg,
|
2023-01-06 12:45:34 +11:00
|
|
|
}
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
|
2024-12-04 17:24:16 -05:00
|
|
|
export function loftSketches(
|
|
|
|
node: Node<Program>,
|
|
|
|
declarators: VariableDeclarator[]
|
|
|
|
): {
|
|
|
|
modifiedAst: Node<Program>
|
|
|
|
pathToNode: PathToNode
|
|
|
|
} {
|
|
|
|
const modifiedAst = structuredClone(node)
|
|
|
|
const name = findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.LOFT)
|
|
|
|
const elements = declarators.map((d) => createIdentifier(d.id.name))
|
|
|
|
const loft = createCallExpressionStdLib('loft', [
|
|
|
|
createArrayExpression(elements),
|
|
|
|
])
|
|
|
|
const declaration = createVariableDeclaration(name, loft)
|
|
|
|
modifiedAst.body.push(declaration)
|
|
|
|
const pathToNode: PathToNode = [
|
|
|
|
['body', ''],
|
|
|
|
[modifiedAst.body.length - 1, 'index'],
|
2024-12-07 07:16:04 +13:00
|
|
|
['declaration', 'VariableDeclaration'],
|
2024-12-04 17:24:16 -05:00
|
|
|
['init', 'VariableDeclarator'],
|
|
|
|
['arguments', 'CallExpression'],
|
|
|
|
[0, 'index'],
|
|
|
|
]
|
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst,
|
|
|
|
pathToNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-11 08:20:49 -05:00
|
|
|
export function addSweep(
|
|
|
|
node: Node<Program>,
|
|
|
|
profileDeclarator: VariableDeclarator,
|
|
|
|
pathDeclarator: VariableDeclarator
|
|
|
|
): {
|
|
|
|
modifiedAst: Node<Program>
|
|
|
|
pathToNode: PathToNode
|
|
|
|
} {
|
|
|
|
const modifiedAst = structuredClone(node)
|
|
|
|
const name = findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.SWEEP)
|
2025-02-07 12:35:04 -06:00
|
|
|
const sweep = createCallExpressionStdLibKw(
|
|
|
|
'sweep',
|
2025-01-11 08:20:49 -05:00
|
|
|
createIdentifier(profileDeclarator.id.name),
|
2025-02-07 12:35:04 -06:00
|
|
|
[createLabeledArg('path', createIdentifier(pathDeclarator.id.name))]
|
|
|
|
)
|
2025-01-11 08:20:49 -05:00
|
|
|
const declaration = createVariableDeclaration(name, sweep)
|
|
|
|
modifiedAst.body.push(declaration)
|
|
|
|
const pathToNode: PathToNode = [
|
|
|
|
['body', ''],
|
|
|
|
[modifiedAst.body.length - 1, 'index'],
|
|
|
|
['declaration', 'VariableDeclaration'],
|
|
|
|
['init', 'VariableDeclarator'],
|
2025-02-07 12:35:04 -06:00
|
|
|
['arguments', 'CallExpressionKw'],
|
|
|
|
[0, ARG_INDEX_FIELD],
|
|
|
|
['arg', LABELED_ARG_FIELD],
|
2025-01-11 08:20:49 -05:00
|
|
|
]
|
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst,
|
|
|
|
pathToNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-17 08:29:52 -05:00
|
|
|
export function revolveSketch(
|
2024-10-30 16:52:17 -04:00
|
|
|
node: Node<Program>,
|
2024-09-17 08:29:52 -05:00
|
|
|
pathToNode: PathToNode,
|
|
|
|
shouldPipe = false,
|
|
|
|
angle: Expr = createLiteral(4)
|
|
|
|
):
|
|
|
|
| {
|
2024-10-30 16:52:17 -04:00
|
|
|
modifiedAst: Node<Program>
|
2024-09-17 08:29:52 -05:00
|
|
|
pathToNode: PathToNode
|
|
|
|
pathToRevolveArg: PathToNode
|
|
|
|
}
|
|
|
|
| Error {
|
|
|
|
const _node = structuredClone(node)
|
|
|
|
const _node1 = getNodeFromPath(_node, pathToNode)
|
|
|
|
if (err(_node1)) return _node1
|
|
|
|
const { node: sketchExpression } = _node1
|
|
|
|
|
|
|
|
// determine if sketchExpression is in a pipeExpression or not
|
|
|
|
const _node2 = getNodeFromPath<PipeExpression>(
|
|
|
|
_node,
|
|
|
|
pathToNode,
|
|
|
|
'PipeExpression'
|
|
|
|
)
|
|
|
|
if (err(_node2)) return _node2
|
|
|
|
const { node: pipeExpression } = _node2
|
|
|
|
|
|
|
|
const isInPipeExpression = pipeExpression.type === 'PipeExpression'
|
|
|
|
|
|
|
|
const _node3 = getNodeFromPath<VariableDeclarator>(
|
|
|
|
_node,
|
|
|
|
pathToNode,
|
|
|
|
'VariableDeclarator'
|
|
|
|
)
|
|
|
|
if (err(_node3)) return _node3
|
|
|
|
const { node: variableDeclarator, shallowPath: pathToDecleration } = _node3
|
|
|
|
|
|
|
|
const revolveCall = createCallExpressionStdLib('revolve', [
|
|
|
|
createObjectExpression({
|
|
|
|
angle: angle,
|
|
|
|
// TODO: hard coded 'X' axis for revolve MVP, should be changed.
|
|
|
|
axis: createLiteral('X'),
|
|
|
|
}),
|
|
|
|
createIdentifier(variableDeclarator.id.name),
|
|
|
|
])
|
|
|
|
|
|
|
|
if (shouldPipe) {
|
|
|
|
const pipeChain = createPipeExpression(
|
|
|
|
isInPipeExpression
|
|
|
|
? [...pipeExpression.body, revolveCall]
|
|
|
|
: [sketchExpression as any, revolveCall]
|
|
|
|
)
|
|
|
|
|
|
|
|
variableDeclarator.init = pipeChain
|
|
|
|
const pathToRevolveArg: PathToNode = [
|
|
|
|
...pathToDecleration,
|
|
|
|
['init', 'VariableDeclarator'],
|
|
|
|
['body', ''],
|
|
|
|
[pipeChain.body.length - 1, 'index'],
|
|
|
|
['arguments', 'CallExpression'],
|
|
|
|
[0, 'index'],
|
|
|
|
]
|
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst: _node,
|
|
|
|
pathToNode,
|
|
|
|
pathToRevolveArg,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We're not creating a pipe expression,
|
|
|
|
// but rather a separate constant for the extrusion
|
|
|
|
const name = findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.REVOLVE)
|
|
|
|
const VariableDeclaration = createVariableDeclaration(name, revolveCall)
|
|
|
|
const sketchIndexInPathToNode =
|
|
|
|
pathToDecleration.findIndex((a) => a[0] === 'body') + 1
|
|
|
|
const sketchIndexInBody = pathToDecleration[sketchIndexInPathToNode][0]
|
|
|
|
if (typeof sketchIndexInBody !== 'number')
|
|
|
|
return new Error('expected sketchIndexInBody to be a number')
|
|
|
|
_node.body.splice(sketchIndexInBody + 1, 0, VariableDeclaration)
|
|
|
|
|
|
|
|
const pathToRevolveArg: PathToNode = [
|
|
|
|
['body', ''],
|
|
|
|
[sketchIndexInBody + 1, 'index'],
|
2024-12-07 07:16:04 +13:00
|
|
|
['declaration', 'VariableDeclaration'],
|
2024-09-17 08:29:52 -05:00
|
|
|
['init', 'VariableDeclarator'],
|
|
|
|
['arguments', 'CallExpression'],
|
|
|
|
[0, 'index'],
|
|
|
|
]
|
|
|
|
return {
|
|
|
|
modifiedAst: _node,
|
|
|
|
pathToNode: [...pathToNode.slice(0, -1), [-1, 'index']],
|
|
|
|
pathToRevolveArg,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-09 13:19:14 +11:00
|
|
|
export function sketchOnExtrudedFace(
|
2024-10-30 16:52:17 -04:00
|
|
|
node: Node<Program>,
|
2024-06-04 13:57:01 -04:00
|
|
|
sketchPathToNode: PathToNode,
|
|
|
|
extrudePathToNode: PathToNode,
|
2024-09-26 18:25:05 +10:00
|
|
|
info: ExtrudeFacePlane['faceInfo'] = { type: 'wall' }
|
2024-06-24 11:45:40 -04:00
|
|
|
): { modifiedAst: Program; pathToNode: PathToNode } | Error {
|
2023-02-12 10:56:45 +11:00
|
|
|
let _node = { ...node }
|
2024-06-04 13:57:01 -04:00
|
|
|
const newSketchName = findUniqueName(
|
|
|
|
node,
|
|
|
|
KCL_DEFAULT_CONSTANT_PREFIXES.SKETCH
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
const _node1 = getNodeFromPath<VariableDeclarator>(
|
2024-03-22 10:23:04 +11:00
|
|
|
_node,
|
2024-06-04 13:57:01 -04:00
|
|
|
sketchPathToNode,
|
2024-03-22 10:23:04 +11:00
|
|
|
'VariableDeclarator',
|
|
|
|
true
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(_node1)) return _node1
|
|
|
|
const { node: oldSketchNode } = _node1
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
const oldSketchName = oldSketchNode.id.name
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
const _node2 = getNodeFromPath<CallExpression | CallExpressionKw>(
|
2023-01-10 15:40:34 +11:00
|
|
|
_node,
|
2024-06-04 13:57:01 -04:00
|
|
|
sketchPathToNode,
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
['CallExpression', 'CallExpressionKw']
|
2023-02-12 10:56:45 +11:00
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(_node2)) return _node2
|
|
|
|
const { node: expression } = _node2
|
|
|
|
|
|
|
|
const _node3 = getNodeFromPath<VariableDeclarator>(
|
2024-06-04 13:57:01 -04:00
|
|
|
_node,
|
|
|
|
extrudePathToNode,
|
|
|
|
'VariableDeclarator'
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(_node3)) return _node3
|
|
|
|
const { node: extrudeVarDec } = _node3
|
2024-06-04 13:57:01 -04:00
|
|
|
const extrudeName = extrudeVarDec.id?.name
|
2023-01-09 13:19:14 +11:00
|
|
|
|
2024-09-26 18:25:05 +10:00
|
|
|
let _tag
|
|
|
|
if (info.type !== 'cap') {
|
2024-06-24 11:45:40 -04:00
|
|
|
const __tag = addTagForSketchOnFace(
|
2024-03-22 10:23:04 +11:00
|
|
|
{
|
2024-06-04 13:57:01 -04:00
|
|
|
pathToNode: sketchPathToNode,
|
2024-03-22 10:23:04 +11:00
|
|
|
node: _node,
|
|
|
|
},
|
2024-09-26 18:25:05 +10:00
|
|
|
expression.callee.name,
|
|
|
|
info.type === 'edgeCut' ? info : null
|
2024-03-22 10:23:04 +11:00
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(__tag)) return __tag
|
|
|
|
const { modifiedAst, tag } = __tag
|
2024-06-24 22:39:04 -07:00
|
|
|
_tag = createIdentifier(tag)
|
2024-03-22 10:23:04 +11:00
|
|
|
_node = modifiedAst
|
|
|
|
} else {
|
2024-09-26 18:25:05 +10:00
|
|
|
_tag = createLiteral(info.subType.toUpperCase())
|
2024-03-22 10:23:04 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
|
|
|
|
const newSketch = createVariableDeclaration(
|
|
|
|
newSketchName,
|
2024-03-22 10:23:04 +11:00
|
|
|
createCallExpressionStdLib('startSketchOn', [
|
2024-06-04 13:57:01 -04:00
|
|
|
createIdentifier(extrudeName ? extrudeName : oldSketchName),
|
2024-06-24 22:39:04 -07:00
|
|
|
_tag,
|
2023-02-12 10:56:45 +11:00
|
|
|
]),
|
2024-10-17 00:48:33 -04:00
|
|
|
undefined,
|
2023-02-12 10:56:45 +11:00
|
|
|
'const'
|
|
|
|
)
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-06-04 13:57:01 -04:00
|
|
|
const expressionIndex = Math.max(
|
|
|
|
sketchPathToNode[1][0] as number,
|
|
|
|
extrudePathToNode[1][0] as number
|
|
|
|
)
|
2023-02-12 10:56:45 +11:00
|
|
|
_node.body.splice(expressionIndex + 1, 0, newSketch)
|
2024-03-22 10:23:04 +11:00
|
|
|
const newpathToNode: PathToNode = [
|
|
|
|
['body', ''],
|
|
|
|
[expressionIndex + 1, 'index'],
|
2024-12-07 07:16:04 +13:00
|
|
|
['declaration', 'VariableDeclaration'],
|
2024-03-22 10:23:04 +11:00
|
|
|
['init', 'VariableDeclarator'],
|
|
|
|
]
|
2023-02-12 10:56:45 +11:00
|
|
|
|
|
|
|
return {
|
2024-03-01 17:16:18 -08:00
|
|
|
modifiedAst: _node,
|
2024-03-22 10:23:04 +11:00
|
|
|
pathToNode: newpathToNode,
|
2023-02-12 10:56:45 +11:00
|
|
|
}
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
|
2024-11-26 11:36:14 -05:00
|
|
|
/**
|
|
|
|
* Append an offset plane to the AST
|
|
|
|
*/
|
|
|
|
export function addOffsetPlane({
|
|
|
|
node,
|
|
|
|
defaultPlane,
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
insertIndex,
|
2024-11-26 11:36:14 -05:00
|
|
|
offset,
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
planeName,
|
2024-11-26 11:36:14 -05:00
|
|
|
}: {
|
|
|
|
node: Node<Program>
|
|
|
|
defaultPlane: DefaultPlaneStr
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
insertIndex?: number
|
2024-11-26 11:36:14 -05:00
|
|
|
offset: Expr
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
planeName?: string
|
2024-11-26 11:36:14 -05:00
|
|
|
}): { modifiedAst: Node<Program>; pathToNode: PathToNode } {
|
|
|
|
const modifiedAst = structuredClone(node)
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
const newPlaneName =
|
|
|
|
planeName ?? findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.PLANE)
|
2024-11-26 11:36:14 -05:00
|
|
|
|
|
|
|
const newPlane = createVariableDeclaration(
|
|
|
|
newPlaneName,
|
2025-02-13 13:37:02 -06:00
|
|
|
createCallExpressionStdLibKw(
|
|
|
|
'offsetPlane',
|
2024-11-26 11:36:14 -05:00
|
|
|
createLiteral(defaultPlane.toUpperCase()),
|
2025-02-13 13:37:02 -06:00
|
|
|
[createLabeledArg('offset', offset)]
|
|
|
|
)
|
2024-11-26 11:36:14 -05:00
|
|
|
)
|
|
|
|
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
const insertAt =
|
|
|
|
insertIndex !== undefined
|
|
|
|
? insertIndex
|
|
|
|
: modifiedAst.body.length
|
|
|
|
? modifiedAst.body.length
|
|
|
|
: 0
|
|
|
|
|
|
|
|
modifiedAst.body.length
|
|
|
|
? modifiedAst.body.splice(insertAt, 0, newPlane)
|
|
|
|
: modifiedAst.body.push(newPlane)
|
2024-11-26 11:36:14 -05:00
|
|
|
const pathToNode: PathToNode = [
|
|
|
|
['body', ''],
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
[insertAt, 'index'],
|
2024-12-07 07:16:04 +13:00
|
|
|
['declaration', 'VariableDeclaration'],
|
2024-11-26 11:36:14 -05:00
|
|
|
['init', 'VariableDeclarator'],
|
2025-02-13 13:37:02 -06:00
|
|
|
['unlabeled', UNLABELED_ARG],
|
2024-11-26 11:36:14 -05:00
|
|
|
]
|
|
|
|
return {
|
|
|
|
modifiedAst,
|
|
|
|
pathToNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-07 10:16:36 -05:00
|
|
|
/**
|
|
|
|
* Append a helix to the AST
|
|
|
|
*/
|
|
|
|
export function addHelix({
|
|
|
|
node,
|
|
|
|
revolutions,
|
|
|
|
angleStart,
|
|
|
|
counterClockWise,
|
|
|
|
radius,
|
|
|
|
axis,
|
|
|
|
length,
|
|
|
|
}: {
|
|
|
|
node: Node<Program>
|
|
|
|
revolutions: Expr
|
|
|
|
angleStart: Expr
|
|
|
|
counterClockWise: boolean
|
|
|
|
radius: Expr
|
|
|
|
axis: string
|
|
|
|
length: Expr
|
|
|
|
}): { modifiedAst: Node<Program>; pathToNode: PathToNode } {
|
|
|
|
const modifiedAst = structuredClone(node)
|
|
|
|
const name = findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.HELIX)
|
|
|
|
const variable = createVariableDeclaration(
|
|
|
|
name,
|
|
|
|
createCallExpressionStdLibKw(
|
|
|
|
'helix',
|
|
|
|
null, // Not in a pipeline
|
|
|
|
[
|
|
|
|
createLabeledArg('revolutions', revolutions),
|
|
|
|
createLabeledArg('angleStart', angleStart),
|
|
|
|
createLabeledArg('counterClockWise', createLiteral(counterClockWise)),
|
|
|
|
createLabeledArg('radius', radius),
|
|
|
|
createLabeledArg('axis', createLiteral(axis)),
|
|
|
|
createLabeledArg('length', length),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
// TODO: figure out smart insertion than just appending at the end
|
|
|
|
const argIndex = 0
|
|
|
|
modifiedAst.body.push(variable)
|
|
|
|
const pathToNode: PathToNode = [
|
|
|
|
['body', ''],
|
|
|
|
[modifiedAst.body.length - 1, 'index'],
|
|
|
|
['declaration', 'VariableDeclaration'],
|
|
|
|
['init', 'VariableDeclarator'],
|
|
|
|
['arguments', 'CallExpressionKw'],
|
|
|
|
[argIndex, ARG_INDEX_FIELD],
|
|
|
|
['arg', LABELED_ARG_FIELD],
|
|
|
|
]
|
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst,
|
|
|
|
pathToNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-09 16:43:58 -05:00
|
|
|
/**
|
|
|
|
* Return a modified clone of an AST with a named constant inserted into the body
|
|
|
|
*/
|
|
|
|
export function insertNamedConstant({
|
|
|
|
node,
|
|
|
|
newExpression,
|
|
|
|
}: {
|
|
|
|
node: Node<Program>
|
|
|
|
newExpression: KclExpressionWithVariable
|
|
|
|
}): Node<Program> {
|
|
|
|
const ast = structuredClone(node)
|
|
|
|
ast.body.splice(
|
|
|
|
newExpression.insertIndex,
|
|
|
|
0,
|
|
|
|
newExpression.variableDeclarationAst
|
|
|
|
)
|
|
|
|
return ast
|
|
|
|
}
|
|
|
|
|
2024-11-18 16:25:25 -05:00
|
|
|
/**
|
|
|
|
* Modify the AST to create a new sketch using the variable declaration
|
|
|
|
* of an offset plane. The new sketch just has to come after the offset
|
|
|
|
* plane declaration.
|
|
|
|
*/
|
|
|
|
export function sketchOnOffsetPlane(
|
|
|
|
node: Node<Program>,
|
|
|
|
offsetPathToNode: PathToNode
|
|
|
|
) {
|
|
|
|
let _node = { ...node }
|
|
|
|
|
|
|
|
// Find the offset plane declaration
|
|
|
|
const offsetPlaneDeclarator = getNodeFromPath<VariableDeclarator>(
|
|
|
|
_node,
|
|
|
|
offsetPathToNode,
|
|
|
|
'VariableDeclarator',
|
|
|
|
true
|
|
|
|
)
|
|
|
|
if (err(offsetPlaneDeclarator)) return offsetPlaneDeclarator
|
|
|
|
const { node: offsetPlaneNode } = offsetPlaneDeclarator
|
|
|
|
const offsetPlaneName = offsetPlaneNode.id.name
|
|
|
|
|
|
|
|
// Create a new sketch declaration
|
|
|
|
const newSketchName = findUniqueName(
|
|
|
|
node,
|
|
|
|
KCL_DEFAULT_CONSTANT_PREFIXES.SKETCH
|
|
|
|
)
|
|
|
|
const newSketch = createVariableDeclaration(
|
|
|
|
newSketchName,
|
|
|
|
createCallExpressionStdLib('startSketchOn', [
|
|
|
|
createIdentifier(offsetPlaneName),
|
|
|
|
]),
|
|
|
|
undefined,
|
|
|
|
'const'
|
|
|
|
)
|
|
|
|
|
|
|
|
// Decide where to insert the new sketch declaration
|
|
|
|
const offsetIndex = offsetPathToNode[1][0]
|
|
|
|
|
|
|
|
if (!isPathToNodeNumber(offsetIndex)) {
|
|
|
|
return new Error('Expected offsetIndex to be a number')
|
|
|
|
}
|
|
|
|
// and insert it
|
|
|
|
_node.body.splice(offsetIndex + 1, 0, newSketch)
|
|
|
|
const newPathToNode = structuredClone(offsetPathToNode)
|
|
|
|
newPathToNode[1][0] = offsetIndex + 1
|
|
|
|
|
|
|
|
// Return the modified AST and the path to the new sketch declaration
|
|
|
|
return {
|
|
|
|
modifiedAst: _node,
|
|
|
|
pathToNode: newPathToNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-10 08:35:30 +11:00
|
|
|
export const getLastIndex = (pathToNode: PathToNode): number =>
|
|
|
|
splitPathAtLastIndex(pathToNode).index
|
|
|
|
|
|
|
|
export function splitPathAtLastIndex(pathToNode: PathToNode): {
|
|
|
|
path: PathToNode
|
|
|
|
index: number
|
|
|
|
} {
|
2023-02-12 10:56:45 +11:00
|
|
|
const last = pathToNode[pathToNode.length - 1]
|
2023-04-01 16:47:00 +11:00
|
|
|
if (last && typeof last[0] === 'number') {
|
2023-03-10 08:35:30 +11:00
|
|
|
return {
|
|
|
|
path: pathToNode.slice(0, -1),
|
2023-04-01 16:47:00 +11:00
|
|
|
index: last[0],
|
2023-03-10 08:35:30 +11:00
|
|
|
}
|
2023-03-21 19:02:18 +11:00
|
|
|
} else if (pathToNode.length === 0) {
|
|
|
|
return {
|
|
|
|
path: [],
|
|
|
|
index: -1,
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
2023-03-10 08:35:30 +11:00
|
|
|
return splitPathAtLastIndex(pathToNode.slice(0, -1))
|
2023-02-12 10:56:45 +11:00
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
|
2023-04-01 16:47:00 +11:00
|
|
|
export function splitPathAtPipeExpression(pathToNode: PathToNode): {
|
|
|
|
path: PathToNode
|
|
|
|
index: number
|
|
|
|
} {
|
|
|
|
const last = pathToNode[pathToNode.length - 1]
|
|
|
|
|
|
|
|
if (
|
|
|
|
last &&
|
|
|
|
last[1] === 'index' &&
|
|
|
|
pathToNode?.[pathToNode.length - 2]?.[1] === 'PipeExpression' &&
|
|
|
|
typeof last[0] === 'number'
|
|
|
|
) {
|
|
|
|
return {
|
|
|
|
path: pathToNode.slice(0, -1),
|
|
|
|
index: last[0],
|
|
|
|
}
|
|
|
|
} else if (pathToNode.length === 0) {
|
|
|
|
return {
|
|
|
|
path: [],
|
|
|
|
index: -1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return splitPathAtPipeExpression(pathToNode.slice(0, -1))
|
|
|
|
}
|
|
|
|
|
2025-01-31 10:45:39 -05:00
|
|
|
/**
|
|
|
|
* Note: This depends on WASM, but it's not async. Callers are responsible for
|
|
|
|
* awaiting init of the WASM module.
|
|
|
|
*/
|
2025-01-22 08:29:30 +13:00
|
|
|
export function createLiteral(value: LiteralValue | number): Node<Literal> {
|
|
|
|
if (typeof value === 'number') {
|
|
|
|
value = { value, suffix: 'None' }
|
|
|
|
}
|
2025-01-31 10:45:39 -05:00
|
|
|
let raw: string
|
|
|
|
if (typeof value === 'string') {
|
|
|
|
// TODO: Should we handle escape sequences?
|
|
|
|
raw = `${value}`
|
|
|
|
} else if (typeof value === 'boolean') {
|
|
|
|
raw = `${value}`
|
|
|
|
} else if (typeof value.value === 'number' && value.suffix === 'None') {
|
|
|
|
// Fast path for numbers when there are no units.
|
|
|
|
raw = `${value.value}`
|
|
|
|
} else {
|
|
|
|
raw = formatNumber(value.value, value.suffix)
|
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
return {
|
|
|
|
type: 'Literal',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2023-02-12 10:56:45 +11:00
|
|
|
value,
|
2025-01-22 08:29:30 +13:00
|
|
|
raw,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2023-02-12 10:56:45 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-30 16:52:17 -04:00
|
|
|
export function createTagDeclarator(value: string): Node<TagDeclarator> {
|
2024-06-24 22:39:04 -07:00
|
|
|
return {
|
|
|
|
type: 'TagDeclarator',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2024-06-24 22:39:04 -07:00
|
|
|
value,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-30 16:52:17 -04:00
|
|
|
export function createIdentifier(name: string): Node<Identifier> {
|
2023-02-12 10:56:45 +11:00
|
|
|
return {
|
|
|
|
type: 'Identifier',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-30 16:52:17 -04:00
|
|
|
export function createPipeSubstitution(): Node<PipeSubstitution> {
|
2023-02-12 10:56:45 +11:00
|
|
|
return {
|
|
|
|
type: 'PipeSubstitution',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2023-02-12 10:56:45 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-05 16:02:27 -07:00
|
|
|
export function createCallExpressionStdLib(
|
|
|
|
name: string,
|
|
|
|
args: CallExpression['arguments']
|
2024-10-30 16:52:17 -04:00
|
|
|
): Node<CallExpression> {
|
2023-09-05 16:02:27 -07:00
|
|
|
return {
|
|
|
|
type: 'CallExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2023-09-05 16:02:27 -07:00
|
|
|
callee: {
|
|
|
|
type: 'Identifier',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2023-09-05 16:02:27 -07:00
|
|
|
name,
|
|
|
|
},
|
|
|
|
arguments: args,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
export function createCallExpressionStdLibKw(
|
|
|
|
name: string,
|
|
|
|
unlabeled: CallExpressionKw['unlabeled'],
|
|
|
|
args: CallExpressionKw['arguments']
|
|
|
|
): Node<CallExpressionKw> {
|
|
|
|
return {
|
|
|
|
type: 'CallExpressionKw',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2025-02-13 17:18:54 -06:00
|
|
|
nonCodeMeta: nonCodeMetaEmpty(),
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
callee: {
|
|
|
|
type: 'Identifier',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|
|
|
|
name,
|
|
|
|
},
|
|
|
|
unlabeled,
|
|
|
|
arguments: args,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function createCallExpression(
|
|
|
|
name: string,
|
|
|
|
args: CallExpression['arguments']
|
2024-10-30 16:52:17 -04:00
|
|
|
): Node<CallExpression> {
|
2023-02-12 10:56:45 +11:00
|
|
|
return {
|
|
|
|
type: 'CallExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2023-02-12 10:56:45 +11:00
|
|
|
callee: {
|
|
|
|
type: 'Identifier',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
name,
|
|
|
|
},
|
|
|
|
arguments: args,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createArrayExpression(
|
|
|
|
elements: ArrayExpression['elements']
|
2024-10-30 16:52:17 -04:00
|
|
|
): Node<ArrayExpression> {
|
2023-02-12 10:56:45 +11:00
|
|
|
return {
|
|
|
|
type: 'ArrayExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2024-08-22 13:54:59 -05:00
|
|
|
nonCodeMeta: nonCodeMetaEmpty(),
|
2023-02-12 10:56:45 +11:00
|
|
|
elements,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createPipeExpression(
|
|
|
|
body: PipeExpression['body']
|
2024-10-30 16:52:17 -04:00
|
|
|
): Node<PipeExpression> {
|
2023-02-12 10:56:45 +11:00
|
|
|
return {
|
2023-01-09 13:19:14 +11:00
|
|
|
type: 'PipeExpression',
|
2023-02-12 10:56:45 +11:00
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
body,
|
2024-08-22 13:54:59 -05:00
|
|
|
nonCodeMeta: nonCodeMetaEmpty(),
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
export function createVariableDeclaration(
|
|
|
|
varName: string,
|
|
|
|
init: VariableDeclarator['init'],
|
2024-10-17 00:48:33 -04:00
|
|
|
visibility: VariableDeclaration['visibility'] = 'default',
|
2023-02-12 10:56:45 +11:00
|
|
|
kind: VariableDeclaration['kind'] = 'const'
|
2024-10-30 16:52:17 -04:00
|
|
|
): Node<VariableDeclaration> {
|
2023-02-12 10:56:45 +11:00
|
|
|
return {
|
2023-01-09 13:19:14 +11:00
|
|
|
type: 'VariableDeclaration',
|
2023-02-12 10:56:45 +11:00
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2024-12-07 07:16:04 +13:00
|
|
|
declaration: {
|
|
|
|
type: 'VariableDeclarator',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2024-12-07 07:16:04 +13:00
|
|
|
id: createIdentifier(varName),
|
|
|
|
init,
|
|
|
|
},
|
2024-10-17 00:48:33 -04:00
|
|
|
visibility,
|
2023-02-12 10:56:45 +11:00
|
|
|
kind,
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function createObjectExpression(properties: {
|
2024-08-12 15:38:42 -05:00
|
|
|
[key: string]: Expr
|
2024-10-30 16:52:17 -04:00
|
|
|
}): Node<ObjectExpression> {
|
2023-02-12 10:56:45 +11:00
|
|
|
return {
|
|
|
|
type: 'ObjectExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2024-08-22 13:54:59 -05:00
|
|
|
nonCodeMeta: nonCodeMetaEmpty(),
|
2023-02-12 10:56:45 +11:00
|
|
|
properties: Object.entries(properties).map(([key, value]) => ({
|
|
|
|
type: 'ObjectProperty',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2023-02-12 10:56:45 +11:00
|
|
|
key: createIdentifier(key),
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
value,
|
|
|
|
})),
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
|
|
|
}
|
2023-03-02 21:19:11 +11:00
|
|
|
|
|
|
|
export function createUnaryExpression(
|
|
|
|
argument: UnaryExpression['argument'],
|
|
|
|
operator: UnaryExpression['operator'] = '-'
|
2024-10-30 16:52:17 -04:00
|
|
|
): Node<UnaryExpression> {
|
2023-03-02 21:19:11 +11:00
|
|
|
return {
|
|
|
|
type: 'UnaryExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2023-03-02 21:19:11 +11:00
|
|
|
operator,
|
|
|
|
argument,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createBinaryExpression([left, operator, right]: [
|
|
|
|
BinaryExpression['left'],
|
|
|
|
BinaryExpression['operator'],
|
|
|
|
BinaryExpression['right']
|
2024-10-30 16:52:17 -04:00
|
|
|
]): Node<BinaryExpression> {
|
2023-03-02 21:19:11 +11:00
|
|
|
return {
|
|
|
|
type: 'BinaryExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2025-02-13 16:17:09 +13:00
|
|
|
outerAttrs: [],
|
2024-10-17 16:22:40 -07:00
|
|
|
|
2023-03-02 21:19:11 +11:00
|
|
|
operator,
|
|
|
|
left,
|
|
|
|
right,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-02 17:20:11 +10:00
|
|
|
export function createBinaryExpressionWithUnary([left, right]: [
|
|
|
|
BinaryExpression['left'],
|
|
|
|
BinaryExpression['right']
|
2024-10-30 16:52:17 -04:00
|
|
|
]): Node<BinaryExpression> {
|
2023-04-02 17:20:11 +10:00
|
|
|
if (right.type === 'UnaryExpression' && right.operator === '-')
|
|
|
|
return createBinaryExpression([left, '-', right.argument])
|
|
|
|
return createBinaryExpression([left, '+', right])
|
|
|
|
}
|
|
|
|
|
2023-03-02 21:19:11 +11:00
|
|
|
export function giveSketchFnCallTag(
|
2024-10-30 16:52:17 -04:00
|
|
|
ast: Node<Program>,
|
2024-11-21 15:04:30 +11:00
|
|
|
range: SourceRange,
|
2023-03-07 15:45:59 +11:00
|
|
|
tag?: string
|
2024-06-24 11:45:40 -04:00
|
|
|
):
|
|
|
|
| {
|
2024-10-30 16:52:17 -04:00
|
|
|
modifiedAst: Node<Program>
|
2024-06-24 11:45:40 -04:00
|
|
|
tag: string
|
|
|
|
isTagExisting: boolean
|
|
|
|
pathToNode: PathToNode
|
|
|
|
}
|
|
|
|
| Error {
|
2023-04-14 07:49:36 +10:00
|
|
|
const path = getNodePathFromSourceRange(ast, range)
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
const maybeTag = (() => {
|
|
|
|
const callNode = getNodeFromPath<CallExpression | CallExpressionKw>(
|
|
|
|
ast,
|
|
|
|
path,
|
|
|
|
['CallExpression', 'CallExpressionKw']
|
|
|
|
)
|
|
|
|
if (!err(callNode) && callNode.node.type === 'CallExpressionKw') {
|
|
|
|
const { node: primaryCallExp } = callNode
|
|
|
|
const existingTag = findKwArg(ARG_TAG, primaryCallExp)
|
|
|
|
const tagDeclarator =
|
|
|
|
existingTag || createTagDeclarator(tag || findUniqueName(ast, 'seg', 2))
|
|
|
|
const isTagExisting = !!existingTag
|
|
|
|
if (!isTagExisting) {
|
|
|
|
callNode.node.arguments.push(createLabeledArg(ARG_TAG, tagDeclarator))
|
|
|
|
}
|
|
|
|
return { tagDeclarator, isTagExisting }
|
|
|
|
}
|
|
|
|
|
|
|
|
// We've handled CallExpressionKw above, so this has to be positional.
|
|
|
|
const _node1 = getNodeFromPath<CallExpression>(ast, path, 'CallExpression')
|
|
|
|
if (err(_node1)) return _node1
|
|
|
|
const { node: primaryCallExp } = _node1
|
|
|
|
|
|
|
|
// Tag is always 3rd expression now, using arg index feels brittle
|
|
|
|
// but we can come up with a better way to identify tag later.
|
|
|
|
const thirdArg = primaryCallExp.arguments?.[2]
|
|
|
|
const tagDeclarator =
|
|
|
|
thirdArg ||
|
|
|
|
(createTagDeclarator(
|
|
|
|
tag || findUniqueName(ast, 'seg', 2)
|
|
|
|
) as TagDeclarator)
|
|
|
|
const isTagExisting = !!thirdArg
|
|
|
|
if (!isTagExisting) {
|
|
|
|
primaryCallExp.arguments[2] = tagDeclarator
|
|
|
|
}
|
|
|
|
return { tagDeclarator, isTagExisting }
|
|
|
|
})()
|
|
|
|
|
|
|
|
if (err(maybeTag)) return maybeTag
|
|
|
|
const { tagDeclarator, isTagExisting } = maybeTag
|
2024-06-24 22:39:04 -07:00
|
|
|
if ('value' in tagDeclarator) {
|
|
|
|
// Now TypeScript knows tagDeclarator has a value property
|
2024-03-15 17:03:42 -04:00
|
|
|
return {
|
|
|
|
modifiedAst: ast,
|
2024-06-24 22:39:04 -07:00
|
|
|
tag: String(tagDeclarator.value),
|
2024-03-15 17:03:42 -04:00
|
|
|
isTagExisting,
|
|
|
|
pathToNode: path,
|
|
|
|
}
|
|
|
|
} else {
|
2024-06-24 11:45:40 -04:00
|
|
|
return new Error('Unable to assign tag without value')
|
2023-03-02 21:19:11 +11:00
|
|
|
}
|
|
|
|
}
|
2023-04-01 16:47:00 +11:00
|
|
|
|
2024-12-09 16:43:58 -05:00
|
|
|
/**
|
|
|
|
* Replace a
|
|
|
|
*/
|
|
|
|
export function replaceValueAtNodePath({
|
|
|
|
ast,
|
|
|
|
pathToNode,
|
|
|
|
newExpressionString,
|
|
|
|
}: {
|
|
|
|
ast: Node<Program>
|
|
|
|
pathToNode: PathToNode
|
|
|
|
newExpressionString: string
|
|
|
|
}) {
|
|
|
|
const replaceCheckResult = isNodeSafeToReplacePath(ast, pathToNode)
|
|
|
|
if (err(replaceCheckResult)) {
|
|
|
|
return replaceCheckResult
|
|
|
|
}
|
|
|
|
const { isSafe, value, replacer } = replaceCheckResult
|
|
|
|
|
|
|
|
if (!isSafe || value.type === 'Identifier') {
|
|
|
|
return new Error('Not safe to replace')
|
|
|
|
}
|
|
|
|
|
|
|
|
return replacer(ast, newExpressionString)
|
|
|
|
}
|
|
|
|
|
2024-05-24 20:54:42 +10:00
|
|
|
export function moveValueIntoNewVariablePath(
|
2024-10-30 16:52:17 -04:00
|
|
|
ast: Node<Program>,
|
2025-02-12 10:22:56 +13:00
|
|
|
memVars: VariableMap,
|
2024-05-24 20:54:42 +10:00
|
|
|
pathToNode: PathToNode,
|
|
|
|
variableName: string
|
|
|
|
): {
|
|
|
|
modifiedAst: Program
|
|
|
|
pathToReplacedNode?: PathToNode
|
|
|
|
} {
|
2024-06-24 11:45:40 -04:00
|
|
|
const meta = isNodeSafeToReplacePath(ast, pathToNode)
|
|
|
|
if (trap(meta)) return { modifiedAst: ast }
|
|
|
|
const { isSafe, value, replacer } = meta
|
|
|
|
|
2024-05-24 20:54:42 +10:00
|
|
|
if (!isSafe || value.type === 'Identifier') return { modifiedAst: ast }
|
|
|
|
|
2025-02-12 10:22:56 +13:00
|
|
|
const { insertIndex } = findAllPreviousVariablesPath(ast, memVars, pathToNode)
|
2024-07-25 20:11:46 -04:00
|
|
|
let _node = structuredClone(ast)
|
2024-05-24 20:54:42 +10:00
|
|
|
const boop = replacer(_node, variableName)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(boop)) return { modifiedAst: ast }
|
|
|
|
|
2024-05-24 20:54:42 +10:00
|
|
|
_node = boop.modifiedAst
|
|
|
|
_node.body.splice(
|
|
|
|
insertIndex,
|
|
|
|
0,
|
|
|
|
createVariableDeclaration(variableName, value)
|
|
|
|
)
|
|
|
|
return { modifiedAst: _node, pathToReplacedNode: boop.pathToReplaced }
|
|
|
|
}
|
|
|
|
|
2023-04-01 16:47:00 +11:00
|
|
|
export function moveValueIntoNewVariable(
|
2024-10-30 16:52:17 -04:00
|
|
|
ast: Node<Program>,
|
2025-02-12 10:22:56 +13:00
|
|
|
memVars: VariableMap,
|
2024-11-21 15:04:30 +11:00
|
|
|
sourceRange: SourceRange,
|
2023-04-01 16:47:00 +11:00
|
|
|
variableName: string
|
|
|
|
): {
|
2024-10-30 16:52:17 -04:00
|
|
|
modifiedAst: Node<Program>
|
2024-05-24 20:54:42 +10:00
|
|
|
pathToReplacedNode?: PathToNode
|
2023-04-01 16:47:00 +11:00
|
|
|
} {
|
2024-06-24 11:45:40 -04:00
|
|
|
const meta = isNodeSafeToReplace(ast, sourceRange)
|
|
|
|
if (trap(meta)) return { modifiedAst: ast }
|
|
|
|
const { isSafe, value, replacer } = meta
|
2023-04-01 16:47:00 +11:00
|
|
|
if (!isSafe || value.type === 'Identifier') return { modifiedAst: ast }
|
|
|
|
|
2025-02-12 10:22:56 +13:00
|
|
|
const { insertIndex } = findAllPreviousVariables(ast, memVars, sourceRange)
|
2024-07-25 20:11:46 -04:00
|
|
|
let _node = structuredClone(ast)
|
2024-06-24 11:45:40 -04:00
|
|
|
const replaced = replacer(_node, variableName)
|
|
|
|
if (trap(replaced)) return { modifiedAst: ast }
|
|
|
|
|
|
|
|
const { modifiedAst, pathToReplaced } = replaced
|
2024-05-24 20:54:42 +10:00
|
|
|
_node = modifiedAst
|
2023-04-01 16:47:00 +11:00
|
|
|
_node.body.splice(
|
|
|
|
insertIndex,
|
|
|
|
0,
|
|
|
|
createVariableDeclaration(variableName, value)
|
|
|
|
)
|
2024-05-24 20:54:42 +10:00
|
|
|
return { modifiedAst: _node, pathToReplacedNode: pathToReplaced }
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deletes a segment from a pipe expression, if the segment has a tag that other segments use, it will remove that value and replace it with the equivalent literal
|
|
|
|
* @param dependentRanges - The ranges of the segments that are dependent on the segment being deleted, this is usually the output of `findUsesOfTagInPipe`
|
|
|
|
*/
|
|
|
|
export function deleteSegmentFromPipeExpression(
|
|
|
|
dependentRanges: SourceRange[],
|
2024-10-30 16:52:17 -04:00
|
|
|
modifiedAst: Node<Program>,
|
2025-02-12 10:22:56 +13:00
|
|
|
memVars: VariableMap,
|
2024-05-24 20:54:42 +10:00
|
|
|
code: string,
|
|
|
|
pathToNode: PathToNode
|
2024-10-30 16:52:17 -04:00
|
|
|
): Node<Program> | Error {
|
2024-07-25 20:11:46 -04:00
|
|
|
let _modifiedAst = structuredClone(modifiedAst)
|
2024-05-24 20:54:42 +10:00
|
|
|
|
|
|
|
dependentRanges.forEach((range) => {
|
|
|
|
const path = getNodePathFromSourceRange(_modifiedAst, range)
|
|
|
|
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
const callExp = getNodeFromPath<Node<CallExpression | CallExpressionKw>>(
|
2024-05-24 20:54:42 +10:00
|
|
|
_modifiedAst,
|
|
|
|
path,
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
['CallExpression', 'CallExpressionKw'],
|
2024-05-24 20:54:42 +10:00
|
|
|
true
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(callExp)) return callExp
|
|
|
|
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
const constraintInfo =
|
|
|
|
callExp.node.type === 'CallExpression'
|
|
|
|
? getConstraintInfo(callExp.node, code, path).find(({ sourceRange }) =>
|
|
|
|
isOverlap(sourceRange, range)
|
|
|
|
)
|
|
|
|
: getConstraintInfoKw(callExp.node, code, path).find(
|
|
|
|
({ sourceRange }) => isOverlap(sourceRange, range)
|
|
|
|
)
|
2024-05-24 20:54:42 +10:00
|
|
|
if (!constraintInfo) return
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2024-09-13 21:14:14 +10:00
|
|
|
if (!constraintInfo.argPosition) return
|
2024-05-24 20:54:42 +10:00
|
|
|
const transform = removeSingleConstraintInfo(
|
2024-09-13 21:14:14 +10:00
|
|
|
callExp.shallowPath,
|
|
|
|
constraintInfo.argPosition,
|
2024-05-24 20:54:42 +10:00
|
|
|
_modifiedAst,
|
2025-02-12 10:22:56 +13:00
|
|
|
memVars
|
2024-05-24 20:54:42 +10:00
|
|
|
)
|
|
|
|
if (!transform) return
|
|
|
|
_modifiedAst = transform.modifiedAst
|
|
|
|
})
|
|
|
|
|
|
|
|
const pipeExpression = getNodeFromPath<PipeExpression>(
|
|
|
|
_modifiedAst,
|
|
|
|
pathToNode,
|
|
|
|
'PipeExpression'
|
2024-06-24 11:45:40 -04:00
|
|
|
)
|
|
|
|
if (err(pipeExpression)) return pipeExpression
|
2024-05-24 20:54:42 +10:00
|
|
|
|
|
|
|
const pipeInPathIndex = pathToNode.findIndex(
|
|
|
|
([_, desc]) => desc === 'PipeExpression'
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
const segmentIndexInPipe = pathToNode[pipeInPathIndex + 1]
|
|
|
|
pipeExpression.node.body.splice(segmentIndexInPipe[0] as number, 1)
|
|
|
|
|
|
|
|
// Move up to the next segment.
|
|
|
|
segmentIndexInPipe[0] = Math.max((segmentIndexInPipe[0] as number) - 1, 0)
|
2024-05-24 20:54:42 +10:00
|
|
|
|
|
|
|
return _modifiedAst
|
|
|
|
}
|
|
|
|
|
|
|
|
export function removeSingleConstraintInfo(
|
2024-09-13 21:14:14 +10:00
|
|
|
pathToCallExp: PathToNode,
|
|
|
|
argDetails: SimplifiedArgDetails,
|
2024-10-30 16:52:17 -04:00
|
|
|
ast: Node<Program>,
|
2025-02-12 10:22:56 +13:00
|
|
|
memVars: VariableMap
|
2024-05-24 20:54:42 +10:00
|
|
|
):
|
|
|
|
| {
|
2024-10-30 16:52:17 -04:00
|
|
|
modifiedAst: Node<Program>
|
2024-05-24 20:54:42 +10:00
|
|
|
pathToNodeMap: PathToNodeMap
|
|
|
|
}
|
|
|
|
| false {
|
|
|
|
const transform = removeSingleConstraint({
|
|
|
|
pathToCallExp,
|
2024-09-13 21:14:14 +10:00
|
|
|
inputDetails: argDetails,
|
2024-05-24 20:54:42 +10:00
|
|
|
ast,
|
|
|
|
})
|
|
|
|
if (!transform) return false
|
2024-06-24 11:45:40 -04:00
|
|
|
const retval = transformAstSketchLines({
|
2024-05-24 20:54:42 +10:00
|
|
|
ast,
|
|
|
|
selectionRanges: [pathToCallExp],
|
|
|
|
transformInfos: [transform],
|
2025-02-12 10:22:56 +13:00
|
|
|
memVars,
|
2024-05-24 20:54:42 +10:00
|
|
|
referenceSegName: '',
|
|
|
|
})
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(retval)) return false
|
|
|
|
return retval
|
2023-04-01 16:47:00 +11:00
|
|
|
}
|
2024-06-29 10:36:04 -07:00
|
|
|
|
|
|
|
export async function deleteFromSelection(
|
2024-10-30 16:52:17 -04:00
|
|
|
ast: Node<Program>,
|
2024-06-29 10:36:04 -07:00
|
|
|
selection: Selection,
|
2025-02-12 10:22:56 +13:00
|
|
|
variables: VariableMap,
|
2025-02-15 00:57:04 +11:00
|
|
|
artifactGraph: ArtifactGraph,
|
2024-06-29 10:36:04 -07:00
|
|
|
getFaceDetails: (id: string) => Promise<Models['FaceIsPlanar_type']> = () =>
|
|
|
|
({} as any)
|
2024-10-30 16:52:17 -04:00
|
|
|
): Promise<Node<Program> | Error> {
|
2024-07-25 20:11:46 -04:00
|
|
|
const astClone = structuredClone(ast)
|
2025-02-15 00:57:04 +11:00
|
|
|
if (
|
|
|
|
(selection.artifact?.type === 'plane' ||
|
|
|
|
selection.artifact?.type === 'cap' ||
|
|
|
|
selection.artifact?.type === 'wall') &&
|
|
|
|
selection.artifact?.pathIds?.length
|
|
|
|
) {
|
|
|
|
const plane =
|
|
|
|
selection.artifact.type === 'plane'
|
|
|
|
? expandPlane(selection.artifact, artifactGraph)
|
|
|
|
: selection.artifact.type === 'wall'
|
|
|
|
? expandWall(selection.artifact, artifactGraph)
|
|
|
|
: expandCap(selection.artifact, artifactGraph)
|
|
|
|
for (const path of plane.paths.sort(
|
|
|
|
(a, b) => b.codeRef.range?.[0] - a.codeRef.range?.[0]
|
|
|
|
)) {
|
|
|
|
const varDec = getNodeFromPath<VariableDeclarator>(
|
|
|
|
ast,
|
|
|
|
path.codeRef.pathToNode,
|
|
|
|
'VariableDeclarator'
|
|
|
|
)
|
|
|
|
if (err(varDec)) return varDec
|
|
|
|
const bodyIndex = Number(varDec.shallowPath[1][0])
|
|
|
|
astClone.body.splice(bodyIndex, 1)
|
|
|
|
}
|
|
|
|
// If it's a cap, we're not going to continue and try to
|
|
|
|
// delete the extrusion
|
|
|
|
if (
|
|
|
|
selection.artifact.type === 'cap' ||
|
|
|
|
selection.artifact.type === 'wall'
|
|
|
|
) {
|
|
|
|
// Delete the sketch node, which would not work if
|
|
|
|
// we continued down the traditional code path below.
|
|
|
|
// faceCodeRef's pathToNode is empty for some reason
|
|
|
|
// so using source range instead
|
|
|
|
const codeRef = getFaceCodeRef(selection.artifact)
|
|
|
|
if (!codeRef) return new Error('Could not find face code ref')
|
|
|
|
const sketchVarDec = getNodePathFromSourceRange(astClone, codeRef.range)
|
|
|
|
const sketchBodyIndex = Number(sketchVarDec[1][0])
|
|
|
|
astClone.body.splice(sketchBodyIndex, 1)
|
|
|
|
return astClone
|
|
|
|
}
|
|
|
|
}
|
2024-06-29 10:36:04 -07:00
|
|
|
const varDec = getNodeFromPath<VariableDeclarator>(
|
|
|
|
ast,
|
2024-11-21 15:04:30 +11:00
|
|
|
selection?.codeRef?.pathToNode,
|
2024-06-29 10:36:04 -07:00
|
|
|
'VariableDeclarator'
|
|
|
|
)
|
|
|
|
if (err(varDec)) return varDec
|
|
|
|
if (
|
2024-12-20 16:19:59 -05:00
|
|
|
((selection?.artifact?.type === 'wall' ||
|
2024-11-21 15:04:30 +11:00
|
|
|
selection?.artifact?.type === 'cap') &&
|
2024-12-20 16:19:59 -05:00
|
|
|
varDec.node.init.type === 'PipeExpression') ||
|
2025-01-09 15:36:50 -05:00
|
|
|
selection.artifact?.type === 'sweep' ||
|
|
|
|
selection.artifact?.type === 'plane' ||
|
2025-02-10 14:24:00 -05:00
|
|
|
selection.artifact?.type === 'helix' ||
|
2025-01-09 15:36:50 -05:00
|
|
|
!selection.artifact // aka expected to be a shell at this point
|
2024-06-29 10:36:04 -07:00
|
|
|
) {
|
|
|
|
let extrudeNameToDelete = ''
|
2024-12-20 16:19:59 -05:00
|
|
|
let pathToNode: PathToNode | null = null
|
2025-01-09 15:36:50 -05:00
|
|
|
if (
|
|
|
|
selection.artifact &&
|
|
|
|
selection.artifact.type !== 'sweep' &&
|
2025-02-10 14:24:00 -05:00
|
|
|
selection.artifact.type !== 'plane' &&
|
|
|
|
selection.artifact.type !== 'helix'
|
2025-01-09 15:36:50 -05:00
|
|
|
) {
|
2024-12-20 16:19:59 -05:00
|
|
|
const varDecName = varDec.node.id.name
|
|
|
|
traverse(astClone, {
|
|
|
|
enter: (node, path) => {
|
|
|
|
if (node.type === 'VariableDeclaration') {
|
|
|
|
const dec = node.declaration
|
|
|
|
if (
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
(dec.init.type === 'CallExpression' &&
|
|
|
|
(dec.init.callee.name === 'extrude' ||
|
|
|
|
dec.init.callee.name === 'revolve') &&
|
|
|
|
dec.init.arguments?.[1].type === 'Identifier' &&
|
|
|
|
dec.init.arguments?.[1].name === varDecName) ||
|
|
|
|
(dec.init.type === 'CallExpressionKw' &&
|
|
|
|
(dec.init.callee.name === 'extrude' ||
|
|
|
|
dec.init.callee.name === 'revolve') &&
|
|
|
|
dec.init.unlabeled?.type === 'Identifier' &&
|
|
|
|
dec.init.unlabeled?.name === varDecName)
|
2024-12-20 16:19:59 -05:00
|
|
|
) {
|
|
|
|
pathToNode = path
|
|
|
|
extrudeNameToDelete = dec.id.name
|
|
|
|
}
|
2025-01-09 15:36:50 -05:00
|
|
|
if (
|
|
|
|
dec.init.type === 'CallExpression' &&
|
|
|
|
dec.init.callee.name === 'loft' &&
|
|
|
|
dec.init.arguments?.[0].type === 'ArrayExpression' &&
|
|
|
|
dec.init.arguments?.[0].elements.some(
|
|
|
|
(a) => a.type === 'Identifier' && a.name === varDecName
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
pathToNode = path
|
|
|
|
extrudeNameToDelete = dec.id.name
|
|
|
|
}
|
2024-06-29 10:36:04 -07:00
|
|
|
}
|
2024-12-20 16:19:59 -05:00
|
|
|
},
|
|
|
|
})
|
|
|
|
if (!pathToNode) return new Error('Could not find extrude variable')
|
|
|
|
} else {
|
|
|
|
pathToNode = selection.codeRef.pathToNode
|
2025-02-10 14:24:00 -05:00
|
|
|
if (varDec.node.type !== 'VariableDeclarator') {
|
|
|
|
const callExp = getNodeFromPath<CallExpression>(
|
|
|
|
astClone,
|
|
|
|
pathToNode,
|
|
|
|
'CallExpression'
|
|
|
|
)
|
|
|
|
if (err(callExp)) return callExp
|
|
|
|
extrudeNameToDelete = callExp.node.callee.name
|
|
|
|
} else {
|
|
|
|
extrudeNameToDelete = varDec.node.id.name
|
|
|
|
}
|
2024-12-20 16:19:59 -05:00
|
|
|
}
|
2024-06-29 10:36:04 -07:00
|
|
|
|
|
|
|
const expressionIndex = pathToNode[1][0] as number
|
|
|
|
astClone.body.splice(expressionIndex, 1)
|
|
|
|
if (extrudeNameToDelete) {
|
2024-09-09 18:17:45 -04:00
|
|
|
await new Promise((resolve) => {
|
|
|
|
;(async () => {
|
|
|
|
const pathsDependingOnExtrude: Array<{
|
|
|
|
path: PathToNode
|
2025-02-15 00:57:04 +11:00
|
|
|
variable: KclValue
|
2024-09-09 18:17:45 -04:00
|
|
|
}> = []
|
|
|
|
const roundLiteral = (x: number) => createLiteral(roundOff(x))
|
|
|
|
const modificationDetails: {
|
2025-02-15 00:57:04 +11:00
|
|
|
parentPipe: PipeExpression['body']
|
|
|
|
parentInit: VariableDeclarator
|
2024-09-09 18:17:45 -04:00
|
|
|
faceDetails: Models['FaceIsPlanar_type']
|
2025-02-15 00:57:04 +11:00
|
|
|
lastKey: number | string
|
2024-09-09 18:17:45 -04:00
|
|
|
}[] = []
|
2025-02-15 00:57:04 +11:00
|
|
|
const wallArtifact =
|
|
|
|
selection.artifact?.type === 'wall'
|
|
|
|
? selection.artifact
|
|
|
|
: selection.artifact?.type === 'segment' &&
|
|
|
|
selection.artifact.surfaceId
|
|
|
|
? getArtifactOfTypes(
|
|
|
|
{ key: selection.artifact.surfaceId, types: ['wall'] },
|
|
|
|
artifactGraph
|
|
|
|
)
|
|
|
|
: null
|
|
|
|
if (err(wallArtifact)) return
|
|
|
|
if (wallArtifact) {
|
|
|
|
const sweep = getArtifactOfTypes(
|
|
|
|
{ key: wallArtifact.sweepId, types: ['sweep'] },
|
|
|
|
artifactGraph
|
|
|
|
)
|
|
|
|
if (err(sweep)) return
|
|
|
|
const wallsWithDependencies = Array.from(
|
|
|
|
getArtifactsOfTypes(
|
|
|
|
{ keys: sweep.surfaceIds, types: ['wall', 'cap'] },
|
|
|
|
artifactGraph
|
|
|
|
).values()
|
|
|
|
).filter((wall) => wall?.pathIds?.length)
|
|
|
|
const wallIds = wallsWithDependencies.map((wall) => wall.id)
|
|
|
|
Object.entries(variables).forEach(([key, _var]) => {
|
|
|
|
if (
|
|
|
|
_var?.type === 'Face' &&
|
|
|
|
wallIds.includes(_var.value.artifactId)
|
|
|
|
) {
|
|
|
|
const pathToStartSketchOn = getNodePathFromSourceRange(
|
|
|
|
astClone,
|
|
|
|
_var.value.__meta[0].sourceRange
|
|
|
|
)
|
|
|
|
pathsDependingOnExtrude.push({
|
|
|
|
path: pathToStartSketchOn,
|
|
|
|
variable: _var,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
_var?.type === 'Sketch' &&
|
|
|
|
_var.value.on.type === 'face' &&
|
|
|
|
wallIds.includes(_var.value.on.artifactId)
|
|
|
|
) {
|
|
|
|
const pathToStartSketchOn = getNodePathFromSourceRange(
|
|
|
|
astClone,
|
|
|
|
_var.value.on.__meta[0].sourceRange
|
|
|
|
)
|
|
|
|
pathsDependingOnExtrude.push({
|
|
|
|
path: pathToStartSketchOn,
|
|
|
|
variable: {
|
|
|
|
type: 'Face',
|
|
|
|
value: _var.value.on,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
for (const { path, variable } of pathsDependingOnExtrude) {
|
|
|
|
// `parentPipe` and `parentInit` are the exact same node, but because it could either be an array or on object node
|
|
|
|
// putting them in two different variables was the only way to get TypeScript to stop complaining
|
|
|
|
// the reason why we're grabbing the parent and the last key is because we want to mutate the ast
|
|
|
|
// so `parent[lastKey]` does the trick, if there's a better way of doing this I'm all years
|
|
|
|
const parentPipe = getNodeFromPath<PipeExpression['body']>(
|
|
|
|
astClone,
|
|
|
|
path.slice(0, -1)
|
|
|
|
)
|
|
|
|
const parentInit = getNodeFromPath<VariableDeclarator>(
|
2024-09-09 18:17:45 -04:00
|
|
|
astClone,
|
|
|
|
path.slice(0, -1)
|
|
|
|
)
|
2025-02-15 00:57:04 +11:00
|
|
|
if (err(parentPipe) || err(parentInit)) {
|
2024-09-09 18:17:45 -04:00
|
|
|
return
|
2024-06-29 10:36:04 -07:00
|
|
|
}
|
2025-02-15 00:57:04 +11:00
|
|
|
if (!variable) return new Error('Could not find sketch')
|
|
|
|
const artifactId =
|
|
|
|
variable.type === 'Sketch'
|
|
|
|
? variable.value.artifactId
|
|
|
|
: variable.type === 'Face'
|
|
|
|
? variable.value.artifactId
|
|
|
|
: ''
|
|
|
|
if (!artifactId) return new Error('Sketch not on anything')
|
|
|
|
const onId =
|
|
|
|
variable.type === 'Sketch'
|
|
|
|
? variable.value.on.id
|
|
|
|
: variable.type === 'Face'
|
|
|
|
? variable.value.id
|
|
|
|
: ''
|
|
|
|
if (!onId) return new Error('Sketch not on anything')
|
2024-09-09 18:17:45 -04:00
|
|
|
// Can't kick off multiple requests at once as getFaceDetails
|
|
|
|
// is three engine calls in one and they conflict
|
2025-02-15 00:57:04 +11:00
|
|
|
const faceDetails = await getFaceDetails(onId)
|
2024-06-29 10:36:04 -07:00
|
|
|
if (
|
2024-09-09 18:17:45 -04:00
|
|
|
!(
|
|
|
|
faceDetails.origin &&
|
|
|
|
faceDetails.x_axis &&
|
|
|
|
faceDetails.y_axis &&
|
|
|
|
faceDetails.z_axis
|
|
|
|
)
|
2024-06-29 10:36:04 -07:00
|
|
|
) {
|
2024-09-09 18:17:45 -04:00
|
|
|
return
|
2024-06-29 10:36:04 -07:00
|
|
|
}
|
2025-02-15 00:57:04 +11:00
|
|
|
const lastKey = path.slice(-1)[0][0]
|
2024-09-09 18:17:45 -04:00
|
|
|
modificationDetails.push({
|
2025-02-15 00:57:04 +11:00
|
|
|
parentPipe: parentPipe.node,
|
|
|
|
parentInit: parentInit.node,
|
2024-09-09 18:17:45 -04:00
|
|
|
faceDetails,
|
|
|
|
lastKey,
|
|
|
|
})
|
2024-06-29 10:36:04 -07:00
|
|
|
}
|
2025-02-15 00:57:04 +11:00
|
|
|
for (const {
|
|
|
|
parentInit,
|
|
|
|
parentPipe,
|
|
|
|
faceDetails,
|
|
|
|
lastKey,
|
|
|
|
} of modificationDetails) {
|
2024-09-09 18:17:45 -04:00
|
|
|
if (
|
|
|
|
!(
|
|
|
|
faceDetails.origin &&
|
|
|
|
faceDetails.x_axis &&
|
|
|
|
faceDetails.y_axis &&
|
|
|
|
faceDetails.z_axis
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
continue
|
|
|
|
}
|
2025-02-15 00:57:04 +11:00
|
|
|
const expression = createCallExpressionStdLib('startSketchOn', [
|
2024-09-09 18:17:45 -04:00
|
|
|
createObjectExpression({
|
|
|
|
plane: createObjectExpression({
|
|
|
|
origin: createObjectExpression({
|
|
|
|
x: roundLiteral(faceDetails.origin.x),
|
|
|
|
y: roundLiteral(faceDetails.origin.y),
|
|
|
|
z: roundLiteral(faceDetails.origin.z),
|
|
|
|
}),
|
2025-01-07 19:10:53 -08:00
|
|
|
xAxis: createObjectExpression({
|
2024-09-09 18:17:45 -04:00
|
|
|
x: roundLiteral(faceDetails.x_axis.x),
|
|
|
|
y: roundLiteral(faceDetails.x_axis.y),
|
|
|
|
z: roundLiteral(faceDetails.x_axis.z),
|
|
|
|
}),
|
2025-01-07 19:10:53 -08:00
|
|
|
yAxis: createObjectExpression({
|
2024-09-09 18:17:45 -04:00
|
|
|
x: roundLiteral(faceDetails.y_axis.x),
|
|
|
|
y: roundLiteral(faceDetails.y_axis.y),
|
|
|
|
z: roundLiteral(faceDetails.y_axis.z),
|
|
|
|
}),
|
2025-01-07 19:10:53 -08:00
|
|
|
zAxis: createObjectExpression({
|
2024-09-09 18:17:45 -04:00
|
|
|
x: roundLiteral(faceDetails.z_axis.x),
|
|
|
|
y: roundLiteral(faceDetails.z_axis.y),
|
|
|
|
z: roundLiteral(faceDetails.z_axis.z),
|
|
|
|
}),
|
2024-06-29 10:36:04 -07:00
|
|
|
}),
|
|
|
|
}),
|
2024-09-09 18:17:45 -04:00
|
|
|
])
|
2025-02-15 00:57:04 +11:00
|
|
|
if (
|
|
|
|
parentInit.type === 'VariableDeclarator' &&
|
|
|
|
lastKey === 'init'
|
|
|
|
) {
|
|
|
|
parentInit[lastKey] = expression
|
|
|
|
} else if (isArray(parentPipe) && typeof lastKey === 'number') {
|
|
|
|
parentPipe[lastKey] = expression
|
|
|
|
}
|
2024-09-09 18:17:45 -04:00
|
|
|
}
|
|
|
|
resolve(true)
|
|
|
|
})().catch(reportRejection)
|
2024-06-29 10:36:04 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
// await prom
|
|
|
|
return astClone
|
2025-02-03 18:11:26 +01:00
|
|
|
} else if (selection.artifact?.type === 'edgeCut') {
|
|
|
|
return deleteEdgeTreatment(astClone, selection)
|
2024-06-29 10:36:04 -07:00
|
|
|
} else if (varDec.node.init.type === 'PipeExpression') {
|
|
|
|
const pipeBody = varDec.node.init.body
|
2025-02-15 00:57:04 +11:00
|
|
|
const doNotDeleteProfileIfItHasBeenExtruded = !(
|
|
|
|
selection?.artifact?.type === 'segment' && selection?.artifact?.surfaceId
|
|
|
|
)
|
2024-06-29 10:36:04 -07:00
|
|
|
if (
|
|
|
|
pipeBody[0].type === 'CallExpression' &&
|
2025-02-15 00:57:04 +11:00
|
|
|
doNotDeleteProfileIfItHasBeenExtruded &&
|
|
|
|
(pipeBody[0].callee.name === 'startSketchOn' ||
|
|
|
|
pipeBody[0].callee.name === 'startProfileAt')
|
2024-06-29 10:36:04 -07:00
|
|
|
) {
|
|
|
|
// remove varDec
|
|
|
|
const varDecIndex = varDec.shallowPath[1][0] as number
|
|
|
|
astClone.body.splice(varDecIndex, 1)
|
|
|
|
return astClone
|
|
|
|
}
|
2025-02-15 00:57:04 +11:00
|
|
|
} else if (
|
|
|
|
// single expression profiles
|
|
|
|
(varDec.node.init.type === 'CallExpressionKw' ||
|
|
|
|
varDec.node.init.type === 'CallExpression') &&
|
|
|
|
['circleThreePoint', 'circle'].includes(varDec.node.init.callee.name)
|
|
|
|
) {
|
|
|
|
const varDecIndex = varDec.shallowPath[1][0] as number
|
|
|
|
astClone.body.splice(varDecIndex, 1)
|
|
|
|
return astClone
|
2024-06-29 10:36:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return new Error('Selection not recognised, could not delete')
|
|
|
|
}
|
2024-08-22 13:54:59 -05:00
|
|
|
|
2025-02-13 17:18:54 -06:00
|
|
|
export const nonCodeMetaEmpty = () => {
|
2024-10-30 16:52:17 -04:00
|
|
|
return { nonCodeNodes: {}, startNodes: [], start: 0, end: 0 }
|
2024-08-22 13:54:59 -05:00
|
|
|
}
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|
2025-02-15 00:57:04 +11:00
|
|
|
export function getInsertIndex(
|
|
|
|
sketchNodePaths: PathToNode[],
|
|
|
|
planeNodePath: PathToNode,
|
|
|
|
insertType: 'start' | 'end'
|
|
|
|
) {
|
|
|
|
let minIndex = 0
|
|
|
|
let maxIndex = 0
|
|
|
|
for (const path of sketchNodePaths) {
|
|
|
|
const index = Number(path[1][0])
|
|
|
|
if (index < minIndex) minIndex = index
|
|
|
|
if (index > maxIndex) maxIndex = index
|
|
|
|
}
|
|
|
|
|
|
|
|
const insertIndex = !sketchNodePaths.length
|
|
|
|
? Number(planeNodePath[1][0]) + 1
|
|
|
|
: insertType === 'start'
|
|
|
|
? minIndex
|
|
|
|
: maxIndex + 1
|
|
|
|
return insertIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
export function updateSketchNodePathsWithInsertIndex({
|
|
|
|
insertIndex,
|
|
|
|
insertType,
|
|
|
|
sketchNodePaths,
|
|
|
|
}: {
|
|
|
|
insertIndex: number
|
|
|
|
insertType: 'start' | 'end'
|
|
|
|
sketchNodePaths: PathToNode[]
|
|
|
|
}): {
|
|
|
|
updatedEntryNodePath: PathToNode
|
|
|
|
updatedSketchNodePaths: PathToNode[]
|
|
|
|
} {
|
|
|
|
// TODO the rest of this function will not be robust to work for sketches defined within a function declaration
|
|
|
|
const newExpressionPathToNode: PathToNode = [
|
|
|
|
['body', ''],
|
|
|
|
[insertIndex, 'index'],
|
|
|
|
['declaration', 'VariableDeclaration'],
|
|
|
|
['init', 'VariableDeclarator'],
|
|
|
|
]
|
|
|
|
let updatedSketchNodePaths = structuredClone(sketchNodePaths)
|
|
|
|
if (insertType === 'start') {
|
|
|
|
updatedSketchNodePaths = updatedSketchNodePaths.map((path) => {
|
|
|
|
path[1][0] = Number(path[1][0]) + 1
|
|
|
|
return path
|
|
|
|
})
|
|
|
|
updatedSketchNodePaths.unshift(newExpressionPathToNode)
|
|
|
|
} else {
|
|
|
|
updatedSketchNodePaths.push(newExpressionPathToNode)
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
updatedSketchNodePaths,
|
|
|
|
updatedEntryNodePath: newExpressionPathToNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Split the following pipe expression into
|
|
|
|
* ```ts
|
|
|
|
* part001 = startSketchOn('XZ')
|
|
|
|
|> startProfileAt([1, 2], %)
|
|
|
|
|> line([3, 4], %)
|
|
|
|
|> line([5, 6], %)
|
|
|
|
|> close(%)
|
|
|
|
extrude001 = extrude(5, part001)
|
|
|
|
```
|
|
|
|
into
|
|
|
|
```ts
|
|
|
|
sketch001 = startSketchOn('XZ')
|
|
|
|
part001 = startProfileAt([1, 2], sketch001)
|
|
|
|
|> line([3, 4], %)
|
|
|
|
|> line([5, 6], %)
|
|
|
|
|> close(%)
|
|
|
|
extrude001 = extrude(5, part001)
|
|
|
|
```
|
|
|
|
Notice that the `startSketchOn` is what gets the new variable name, this is so part001 still has the same data as before
|
|
|
|
making it safe for later code that uses part001 (the extrude in this example)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
export function splitPipedProfile(
|
|
|
|
ast: Program,
|
|
|
|
pathToPipe: PathToNode
|
|
|
|
):
|
|
|
|
| {
|
|
|
|
modifiedAst: Program
|
|
|
|
pathToProfile: PathToNode
|
|
|
|
pathToPlane: PathToNode
|
|
|
|
}
|
|
|
|
| Error {
|
|
|
|
const _ast = structuredClone(ast)
|
|
|
|
const varDec = getNodeFromPath<VariableDeclaration>(
|
|
|
|
_ast,
|
|
|
|
pathToPipe,
|
|
|
|
'VariableDeclaration'
|
|
|
|
)
|
|
|
|
if (err(varDec)) return varDec
|
|
|
|
if (
|
|
|
|
varDec.node.type !== 'VariableDeclaration' ||
|
|
|
|
varDec.node.declaration.init.type !== 'PipeExpression'
|
|
|
|
) {
|
|
|
|
return new Error('pathToNode does not point to pipe')
|
|
|
|
}
|
|
|
|
const init = varDec.node.declaration.init
|
|
|
|
const firstCall = init.body[0]
|
|
|
|
if (!isCallExprWithName(firstCall, 'startSketchOn'))
|
|
|
|
return new Error('First call is not startSketchOn')
|
|
|
|
const secondCall = init.body[1]
|
|
|
|
if (!isCallExprWithName(secondCall, 'startProfileAt'))
|
|
|
|
return new Error('Second call is not startProfileAt')
|
|
|
|
|
|
|
|
const varName = varDec.node.declaration.id.name
|
|
|
|
const newVarName = findUniqueName(_ast, 'sketch')
|
|
|
|
const secondCallArgs = structuredClone(secondCall.arguments)
|
|
|
|
secondCallArgs[1] = createIdentifier(newVarName)
|
|
|
|
const firstCallOfNewPipe = createCallExpression(
|
|
|
|
'startProfileAt',
|
|
|
|
secondCallArgs
|
|
|
|
)
|
|
|
|
const newSketch = createVariableDeclaration(
|
|
|
|
newVarName,
|
|
|
|
varDec.node.declaration.init.body[0]
|
|
|
|
)
|
|
|
|
const newProfile = createVariableDeclaration(
|
|
|
|
varName,
|
|
|
|
varDec.node.declaration.init.body.length <= 2
|
|
|
|
? firstCallOfNewPipe
|
|
|
|
: createPipeExpression([
|
|
|
|
firstCallOfNewPipe,
|
|
|
|
...varDec.node.declaration.init.body.slice(2),
|
|
|
|
])
|
|
|
|
)
|
|
|
|
const index = getBodyIndex(pathToPipe)
|
|
|
|
if (err(index)) return index
|
|
|
|
_ast.body.splice(index, 1, newSketch, newProfile)
|
|
|
|
const pathToPlane = structuredClone(pathToPipe)
|
|
|
|
const pathToProfile = structuredClone(pathToPipe)
|
|
|
|
pathToProfile[1][0] = index + 1
|
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst: _ast,
|
|
|
|
pathToProfile,
|
|
|
|
pathToPlane,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createNodeFromExprSnippet(
|
|
|
|
strings: TemplateStringsArray,
|
|
|
|
...expressions: any[]
|
|
|
|
): Node<BodyItem> | Error {
|
|
|
|
const code = strings.reduce(
|
|
|
|
(acc, str, i) => acc + str + (expressions[i] || ''),
|
|
|
|
''
|
|
|
|
)
|
|
|
|
let program = parse(code)
|
|
|
|
if (err(program)) return program
|
|
|
|
const node = program.program?.body[0]
|
|
|
|
if (!node) return new Error('No node found')
|
|
|
|
return node
|
|
|
|
}
|
|
|
|
|
|
|
|
export const createLabeledArg = (label: string, arg: Expr): LabeledArg => {
|
|
|
|
return { label: createIdentifier(label), arg, type: 'LabeledArg' }
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
}
|