Grackle: handle complicated nested computed objects (#1348)

Previously, Grackle could compile a single computed property like `array[x]`. But it couldn't handle:

- Nested properties like `array[x][y]`
- Nested objects like `obj[x][y]`
- Arrays nested in objects, like `{x: [1,2,3]}`
- Objects in arrays like `[{a: 1}]`

It was quite difficult to find a way to handle this, which is why I started the EP Debugger project. The debugger helped me understand the VM much better and figure out a better way to handle these cases (the two new instructions AddrOfMember and CopyLen). Now Grackle can compile those cases!
This commit is contained in:
Adam Chalmers
2024-02-06 22:44:30 +11:00
committed by GitHub
parent a4d3263b88
commit 379c30824e
12 changed files with 370 additions and 245 deletions

View File

@ -498,7 +498,7 @@
}
],
"asset": {
"generator": "kittycad.io",
"generator": "zoo.dev",
"version": "2.0"
},
"buffers": [
@ -882,7 +882,7 @@
"loops": [
[
14,
-1
1
]
]
},
@ -1953,12 +1953,17 @@
{
"type": "plane",
"plane": {
"normal": [
-1,
"xAxis": [
0,
1,
0
],
"point": [
"yAxis": [
0,
0,
-1
],
"origin": [
0,
-0.0127,
0.050800000000000005
@ -1968,12 +1973,17 @@
{
"type": "plane",
"plane": {
"normal": [
"xAxis": [
1,
0,
-1,
-0
0
],
"point": [
"yAxis": [
-0,
0,
1
],
"origin": [
0.039310000000000005,
-0.0254,
0.050800000000000005
@ -1983,12 +1993,17 @@
{
"type": "plane",
"plane": {
"normal": [
"xAxis": [
0.81915,
-0.5735800000000001,
-0.81915,
0
],
"point": [
"yAxis": [
0,
0,
1
],
"origin": [
0.11489,
-0.050800000000000005,
0.050800000000000005
@ -1998,12 +2013,17 @@
{
"type": "plane",
"plane": {
"normal": [
"xAxis": [
1,
0,
-1,
-0
0
],
"point": [
"yAxis": [
-0,
0,
1
],
"origin": [
0.19623,
-0.0762,
0.050800000000000005
@ -2013,12 +2033,17 @@
{
"type": "plane",
"plane": {
"normal": [
1,
"xAxis": [
0,
-0
1,
0
],
"point": [
"yAxis": [
-0,
0,
1
],
"origin": [
0.2413,
-0.06985000000000001,
0.050800000000000005
@ -2028,12 +2053,17 @@
{
"type": "plane",
"plane": {
"normal": [
0,
"xAxis": [
1,
-0
0,
0
],
"point": [
"yAxis": [
0,
-0,
-1
],
"origin": [
0.19823,
-0.0635,
0.050800000000000005
@ -2043,12 +2073,17 @@
{
"type": "plane",
"plane": {
"normal": [
0.5735800000000001,
"xAxis": [
0.81915,
-0.5735800000000001,
0
],
"point": [
"yAxis": [
0,
0,
-1
],
"origin": [
0.10982,
-0.03175,
0.050800000000000005
@ -2058,12 +2093,17 @@
{
"type": "plane",
"plane": {
"normal": [
"xAxis": [
0.90631,
0.4226200000000001,
-0.90631,
-0
0
],
"point": [
"yAxis": [
-0,
0,
1
],
"origin": [
0.10533,
0.01905,
0.050800000000000005
@ -2073,12 +2113,17 @@
{
"type": "plane",
"plane": {
"normal": [
"xAxis": [
1,
0,
-1,
-0
0
],
"point": [
"yAxis": [
-0,
0,
1
],
"origin": [
0.19374,
0.0381,
0.050800000000000005
@ -2088,12 +2133,17 @@
{
"type": "plane",
"plane": {
"normal": [
1,
"xAxis": [
0,
-0
1,
0
],
"point": [
"yAxis": [
-0,
0,
1
],
"origin": [
0.2413,
0.04445,
0.050800000000000005
@ -2103,12 +2153,17 @@
{
"type": "plane",
"plane": {
"normal": [
0,
"xAxis": [
1,
-0
0,
0
],
"point": [
"yAxis": [
0,
-0,
-1
],
"origin": [
0.19234,
0.050800000000000005,
0.050800000000000005
@ -2118,12 +2173,17 @@
{
"type": "plane",
"plane": {
"normal": [
-0.4226200000000001,
"xAxis": [
0.90631,
0.4226200000000001,
0
],
"point": [
"yAxis": [
0,
0,
-1
],
"origin": [
0.11614,
0.0381,
0.050800000000000005
@ -2133,12 +2193,17 @@
{
"type": "plane",
"plane": {
"normal": [
0,
"xAxis": [
1,
-0
0,
0
],
"point": [
"yAxis": [
0,
-0,
-1
],
"origin": [
0.04445,
0.0254,
0.050800000000000005
@ -2148,12 +2213,17 @@
{
"type": "plane",
"plane": {
"normal": [
-1,
"xAxis": [
0,
1,
0
],
"point": [
"yAxis": [
0,
0,
-1
],
"origin": [
0,
0.0127,
0.050800000000000005
@ -2163,12 +2233,17 @@
{
"type": "plane",
"plane": {
"normal": [
"xAxis": [
1,
0,
0,
1
0
],
"point": [
"yAxis": [
0,
1,
0
],
"origin": [
0,
0,
0
@ -2178,12 +2253,17 @@
{
"type": "plane",
"plane": {
"normal": [
"xAxis": [
1,
0,
0,
1
-0
],
"point": [
"yAxis": [
-0,
1,
0
],
"origin": [
0,
0,
0.1016
@ -2191,7 +2271,7 @@
}
}
],
"curves": [
"curves3D": [
{
"type": "line",
"line": {

View File

@ -1,7 +1,7 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION((('kittycad.io export')), '2;1');
FILE_NAME('dump.step', '1970-01-01T00:00:00.0+00:00', ('Author unknown'), ('Organization unknown'), 'kittycad.io beta', 'kittycad.io', 'Authorization unknown');
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
FILE_NAME('dump.step', '1970-01-01T00:00:00.0+00:00', ('Author unknown'), ('Organization unknown'), 'zoo.dev beta', 'zoo.dev', 'Authorization unknown');
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
ENDSEC;
DATA;
@ -384,23 +384,23 @@ DATA;
#368 = ORIENTED_EDGE('NONE', *, *, #269, .T.);
#369 = EDGE_LOOP('NONE', (#355, #356, #357, #358, #359, #360, #361, #362, #363, #364, #365, #366, #367, #368));
#370 = CARTESIAN_POINT('NONE', (0, -0.0127, 0.0508));
#371 = DIRECTION('NONE', (-1, 0, -0));
#371 = DIRECTION('NONE', (-1, -0, 0));
#372 = AXIS2_PLACEMENT_3D('NONE', #370, #371, $);
#373 = PLANE('NONE', #372);
#374 = CARTESIAN_POINT('NONE', (0.039306734695977924, -0.025399999999999995, 0.0508));
#375 = DIRECTION('NONE', (0, -1, -0));
#375 = DIRECTION('NONE', (0, -1, 0));
#376 = AXIS2_PLACEMENT_3D('NONE', #374, #375, $);
#377 = PLANE('NONE', #376);
#378 = CARTESIAN_POINT('NONE', (0.11488842876320533, -0.05079999999999996, 0.05079999999999999));
#379 = DIRECTION('NONE', (-0.5735764363510459, -0.819152044288992, 0));
#379 = DIRECTION('NONE', (-0.5735764363510459, -0.8191520442889919, 0));
#380 = AXIS2_PLACEMENT_3D('NONE', #378, #379, $);
#381 = PLANE('NONE', #380);
#382 = CARTESIAN_POINT('NONE', (0.19623169406722757, -0.07619999999999999, 0.0508));
#383 = DIRECTION('NONE', (0, -1, -0));
#383 = DIRECTION('NONE', (0, -1, 0));
#384 = AXIS2_PLACEMENT_3D('NONE', #382, #383, $);
#385 = PLANE('NONE', #384);
#386 = CARTESIAN_POINT('NONE', (0.2413, -0.06985, 0.0508));
#387 = DIRECTION('NONE', (1, 0, -0));
#387 = DIRECTION('NONE', (1, -0, 0));
#388 = AXIS2_PLACEMENT_3D('NONE', #386, #387, $);
#389 = PLANE('NONE', #388);
#390 = CARTESIAN_POINT('NONE', (0.19823384137660915, -0.0635, 0.0508));
@ -408,19 +408,19 @@ DATA;
#392 = AXIS2_PLACEMENT_3D('NONE', #390, #391, $);
#393 = PLANE('NONE', #392);
#394 = CARTESIAN_POINT('NONE', (0.10982398353915601, -0.03174999999999997, 0.0508));
#395 = DIRECTION('NONE', (0.573576436351046, 0.8191520442889918, -0));
#395 = DIRECTION('NONE', (0.5735764363510459, 0.8191520442889917, -0));
#396 = AXIS2_PLACEMENT_3D('NONE', #394, #395, $);
#397 = PLANE('NONE', #396);
#398 = CARTESIAN_POINT('NONE', (0.105333141160801, 0.019049999999999987, 0.0508));
#399 = DIRECTION('NONE', (0.4226182617406993, -0.90630778703665, -0));
#399 = DIRECTION('NONE', (0.4226182617406993, -0.90630778703665, 0));
#400 = AXIS2_PLACEMENT_3D('NONE', #398, #399, $);
#401 = PLANE('NONE', #400);
#402 = CARTESIAN_POINT('NONE', (0.19374299899825406, 0.0381, 0.0508));
#403 = DIRECTION('NONE', (0, -1, -0));
#403 = DIRECTION('NONE', (0, -1, 0));
#404 = AXIS2_PLACEMENT_3D('NONE', #402, #403, $);
#405 = PLANE('NONE', #404);
#406 = CARTESIAN_POINT('NONE', (0.2413, 0.044449999999999996, 0.0508));
#407 = DIRECTION('NONE', (1, 0, -0));
#407 = DIRECTION('NONE', (1, -0, 0));
#408 = AXIS2_PLACEMENT_3D('NONE', #406, #407, $);
#409 = PLANE('NONE', #408);
#410 = CARTESIAN_POINT('NONE', (0.19233523789047138, 0.0508, 0.0508));
@ -436,7 +436,7 @@ DATA;
#420 = AXIS2_PLACEMENT_3D('NONE', #418, #419, $);
#421 = PLANE('NONE', #420);
#422 = CARTESIAN_POINT('NONE', (0, 0.0127, 0.0508));
#423 = DIRECTION('NONE', (-1, 0, -0));
#423 = DIRECTION('NONE', (-1, -0, 0));
#424 = AXIS2_PLACEMENT_3D('NONE', #422, #423, $);
#425 = PLANE('NONE', #424);
#426 = CARTESIAN_POINT('NONE', (0, 0, -0));
@ -475,7 +475,7 @@ DATA;
#459 = ADVANCED_FACE('NONE', (#458), #421, .T.);
#460 = FACE_OUTER_BOUND('NONE', #339, .T.);
#461 = ADVANCED_FACE('NONE', (#460), #425, .T.);
#462 = FACE_OUTER_BOUND('NONE', #354, .T.);
#462 = FACE_OUTER_BOUND('NONE', #354, .F.);
#463 = ADVANCED_FACE('NONE', (#462), #429, .F.);
#464 = FACE_OUTER_BOUND('NONE', #369, .T.);
#465 = ADVANCED_FACE('NONE', (#464), #433, .T.);

View File

@ -100,15 +100,15 @@ endfacet
facet normal 0.57357645 0 0.819152
outer loop
vertex 3.4311862 -0 -0.625
vertex 2.5385938 -0 0
vertex 2.5385938 -4 0
vertex 3.4311862 -4 -0.625
endloop
endfacet
facet normal 0.57357645 -0 0.819152
facet normal 0.5735763 0 0.8191522
outer loop
vertex 3.4311862 -4 -0.625
vertex 4.323779 -0 -1.25
vertex 3.4311862 -0 -0.625
vertex 2.5385938 -4 0
vertex 3.4311862 -4 -0.625
endloop
endfacet
facet normal 0.57357645 -0 0.819152
@ -118,11 +118,11 @@ facet normal 0.57357645 -0 0.819152
vertex 4.323779 -0 -1.25
endloop
endfacet
facet normal 0.5735763 0 0.8191522
facet normal 0.57357645 -0 0.819152
outer loop
vertex 2.5385938 -4 0
vertex 3.4311862 -0 -0.625
vertex 3.4311862 -4 -0.625
vertex 4.323779 -0 -1.25
vertex 2.5385938 -0 0
endloop
endfacet
facet normal 0.42261824 0 -0.9063078
@ -142,29 +142,29 @@ endfacet
facet normal 0.42261824 0 -0.9063078
outer loop
vertex 3.342784 -0 0.375
vertex 4.146974 -0 0.75
vertex 4.146974 -4 0.75
vertex 3.342784 -4 0.375
vertex 2.5385938 -0 0
endloop
endfacet
facet normal 0.42261833 0 -0.90630776
outer loop
vertex 4.146974 -0 0.75
vertex 5.755354 -0 1.5
vertex 5.755354 -4 1.5
vertex 4.146974 -4 0.75
endloop
endfacet
facet normal 0.42261824 0 -0.9063078
outer loop
vertex 3.342784 -4 0.375
vertex 2.5385938 -0 0
vertex 4.146974 -4 0.75
vertex 3.342784 -0 0.375
vertex 4.146974 -0 0.75
endloop
endfacet
facet normal 0.42261833 0 -0.90630776
outer loop
vertex 5.755354 -4 1.5
vertex 4.146974 -4 0.75
vertex 4.146974 -0 0.75
vertex 5.755354 -0 1.5
endloop
endfacet
facet normal 0 0 -1
@ -258,6 +258,13 @@ facet normal 0 1 -0
vertex 3.5 -0 1
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 4.146974 -0 0.75
vertex 3.342784 -0 0.375
vertex 3.5 -0 1
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 3.4311862 -0 -0.625
@ -265,11 +272,53 @@ facet normal 0 1 0
vertex 3.0950184 -0 -1
endloop
endfacet
facet normal 0 0.99999994 0
outer loop
vertex 4.146974 -0 0.75
vertex 5.644507 -0 2
vertex 5.755354 -0 1.5
endloop
endfacet
facet normal -0 1 0
outer loop
vertex 0 -0 1
vertex 3.5 -0 1
vertex 2.5385938 -0 0
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 3.342784 -0 0.375
vertex 3.5 -0 1
vertex 0 -0 1
vertex 2.5385938 -0 0
vertex 0 -0 0
endloop
endfacet
facet normal -0 1 0
outer loop
vertex 5.644507 -0 2
vertex 9.5 -0 2
vertex 5.755354 -0 1.5
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 9.5 -0 2
vertex 9.5 -0 1.5
vertex 5.755354 -0 1.5
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 4.146974 -0 0.75
vertex 3.5 -0 1
vertex 5.644507 -0 2
endloop
endfacet
facet normal 0 0.99999994 0
outer loop
vertex 2.5385938 -0 0
vertex 3.4311862 -0 -0.625
vertex 3.0950184 -0 -1
endloop
endfacet
facet normal 0 0.99999994 0
@ -281,86 +330,37 @@ facet normal 0 0.99999994 0
endfacet
facet normal 0 1 0
outer loop
vertex 0 -0 -1
vertex 2.5385938 -0 0
vertex 3.0950184 -0 -1
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 0 -0 -1
vertex 0 -0 0
vertex 2.5385938 -0 0
endloop
endfacet
facet normal 0 0.99999994 -0
outer loop
vertex 9.5 -0 -3
vertex 6.108964 -0 -2.5
vertex 9.5 -0 -2.5
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 9.5 -0 -3
vertex 5.9513144 -0 -3
vertex 6.108964 -0 -2.5
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 5.9513144 -0 -3
vertex 4.323779 -0 -1.25
endloop
endfacet
facet normal 0 0.99999994 0
outer loop
vertex 9.5 -0 -2.5
vertex 9.5 -0 -3
vertex 6.108964 -0 -2.5
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 5.644507 -0 2
vertex 5.755354 -0 1.5
vertex 4.146974 -0 0.75
vertex 6.108964 -0 -2.5
vertex 9.5 -0 -3
vertex 5.9513144 -0 -3
endloop
endfacet
facet normal 0 0.99999994 -0
facet normal 0 1 0
outer loop
vertex 2.5385938 -0 0
vertex 3.0950184 -0 -1
vertex 2.5385938 -0 0
vertex 3.4311862 -0 -0.625
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 4.146974 -0 0.75
vertex 3.5 -0 1
vertex 5.644507 -0 2
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 9.5 -0 1.5
vertex 5.755354 -0 1.5
vertex 9.5 -0 2
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 5.755354 -0 1.5
vertex 5.644507 -0 2
vertex 9.5 -0 2
vertex 0 -0 -1
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 2.5385938 -0 0
vertex 0 -0 -1
vertex 0 -0 0
vertex 0 -0 1
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 3.5 -0 1
vertex 2.5385938 -0 0
vertex 0 -0 1
endloop
endfacet
facet normal -0 -1 0

View File

@ -1431,6 +1431,7 @@ dependencies = [
"kittycad-execution-plan-traits",
"kittycad-modeling-session",
"pretty_assertions",
"serde_json",
"thiserror",
"tokio",
]
@ -1458,7 +1459,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http 0.2.9",
"indexmap 2.0.2",
"indexmap 2.2.2",
"slab",
"tokio",
"tokio-util",
@ -1718,9 +1719,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.0.2"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
dependencies = [
"equivalent",
"hashbrown 0.14.2",
@ -1877,7 +1878,7 @@ dependencies = [
"itertools 0.12.0",
"js-sys",
"kittycad",
"kittycad-execution-plan-macros 0.1.2 (git+https://github.com/KittyCAD/modeling-api?branch=main)",
"kittycad-execution-plan-macros 0.1.4 (git+https://github.com/KittyCAD/modeling-api?branch=main)",
"kittycad-execution-plan-traits",
"lazy_static",
"parse-display",
@ -1950,7 +1951,7 @@ dependencies = [
[[package]]
name = "kittycad-execution-plan"
version = "0.1.0"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#0d1fb31b8624abea0d270365cc459e78577d26f8"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#186ea7c04d0a6f0f57220c2134cf3d9be10d6cbe"
dependencies = [
"bytes",
"insta",
@ -1968,9 +1969,9 @@ dependencies = [
[[package]]
name = "kittycad-execution-plan-macros"
version = "0.1.2"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e86c3ddefd89be816db24186c3e2fbd427675198f4d64b6d244dd2c1a3bae3"
checksum = "71d31b689c944d00aadda2ef83d8422a6efff97e1be5654a61f9d95496f0c19e"
dependencies = [
"proc-macro2",
"quote",
@ -1979,8 +1980,8 @@ dependencies = [
[[package]]
name = "kittycad-execution-plan-macros"
version = "0.1.2"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#0d1fb31b8624abea0d270365cc459e78577d26f8"
version = "0.1.4"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#186ea7c04d0a6f0f57220c2134cf3d9be10d6cbe"
dependencies = [
"proc-macro2",
"quote",
@ -1989,9 +1990,9 @@ dependencies = [
[[package]]
name = "kittycad-execution-plan-traits"
version = "0.1.6"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f893f7837d95bb669781581842511307e42622221c6d241031f1c35c11a2af"
checksum = "a3ec8efd57b59697eb140b63c0ffe7db44fdfe5a55f14e45513411eba2280ba5"
dependencies = [
"serde",
"thiserror",
@ -2000,8 +2001,8 @@ dependencies = [
[[package]]
name = "kittycad-modeling-cmds"
version = "0.1.12"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#0d1fb31b8624abea0d270365cc459e78577d26f8"
version = "0.1.14"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#186ea7c04d0a6f0f57220c2134cf3d9be10d6cbe"
dependencies = [
"anyhow",
"chrono",
@ -2011,7 +2012,7 @@ dependencies = [
"enum-iterator-derive",
"euler",
"http 0.2.9",
"kittycad-execution-plan-macros 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kittycad-execution-plan-macros 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"kittycad-execution-plan-traits",
"kittycad-unit-conversion-derive",
"measurements",
@ -2028,7 +2029,7 @@ dependencies = [
[[package]]
name = "kittycad-modeling-session"
version = "0.1.0"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#0d1fb31b8624abea0d270365cc459e78577d26f8"
source = "git+https://github.com/KittyCAD/modeling-api?branch=main#186ea7c04d0a6f0f57220c2134cf3d9be10d6cbe"
dependencies = [
"futures",
"kittycad",
@ -2408,7 +2409,7 @@ dependencies = [
"format_serde_error",
"futures-util",
"http 0.2.9",
"indexmap 2.0.2",
"indexmap 2.2.2",
"json-patch",
"log",
"numeral",
@ -2443,7 +2444,7 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75e56d5c441965b6425165b7e3223cc933ca469834f4a8b4786817a1f9dc4f13"
dependencies = [
"indexmap 2.0.2",
"indexmap 2.2.2",
"serde",
"serde_json",
]
@ -2537,9 +2538,9 @@ dependencies = [
[[package]]
name = "papergrid"
version = "0.10.0"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2ccbe15f2b6db62f9a9871642746427e297b0ceb85f9a7f1ee5ff47d184d0c8"
checksum = "9ad43c07024ef767f9160710b3a6773976194758c7919b17e63b863db0bdf7fb"
dependencies = [
"bytecount",
"fnv",
@ -3472,9 +3473,9 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]]
name = "serde"
version = "1.0.193"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
@ -3490,9 +3491,9 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.193"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
@ -3512,11 +3513,11 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.108"
version = "1.0.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
dependencies = [
"indexmap 2.0.2",
"indexmap 2.2.2",
"itoa",
"ryu",
"serde",
@ -3584,7 +3585,7 @@ version = "0.9.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574"
dependencies = [
"indexmap 2.0.2",
"indexmap 2.2.2",
"itoa",
"ryu",
"serde",
@ -3941,9 +3942,9 @@ dependencies = [
[[package]]
name = "tabled"
version = "0.14.0"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfe9c3632da101aba5131ed63f9eed38665f8b3c68703a6bb18124835c1a5d22"
checksum = "4c998b0c8b921495196a48aabaf1901ff28be0760136e31604f7967b0792050e"
dependencies = [
"papergrid",
"tabled_derive",
@ -3952,9 +3953,9 @@ dependencies = [
[[package]]
name = "tabled_derive"
version = "0.6.0"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99f688a08b54f4f02f0a3c382aefdb7884d3d69609f785bd253dc033243e3fe4"
checksum = "4c138f99377e5d653a371cdad263615634cfc8467685dfe8e73e2b8e98f44b17"
dependencies = [
"heck",
"proc-macro-error",
@ -4242,7 +4243,7 @@ version = "0.20.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "380f9e8120405471f7c9ad1860a713ef5ece6a670c7eae39225e477340f32fc4"
dependencies = [
"indexmap 2.0.2",
"indexmap 2.2.2",
"serde",
"serde_spanned",
"toml_datetime",

View File

@ -60,7 +60,7 @@ members = [
[workspace.dependencies]
kittycad = { version = "0.2.45", default-features = false, features = ["js"] }
kittycad-execution-plan = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" }
kittycad-execution-plan-traits = "0.1.6"
kittycad-execution-plan-traits = "0.1.10"
kittycad-modeling-session = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" }
kittycad-execution-plan-macros = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" }

View File

@ -17,3 +17,4 @@ tokio = { version = "1.35.1", features = ["macros", "rt"] }
[dev-dependencies]
pretty_assertions = "1"
serde_json = "1.0.113"

View File

@ -12,9 +12,9 @@ use kcl_lib::{
ast::types::{BodyItem, FunctionExpressionParts, KclNone, LiteralValue, Program},
};
use kcl_value_group::into_single_value;
use kittycad_execution_plan::{self as ep, Address, Destination, Instruction};
use kittycad_execution_plan::{self as ep, Destination, Instruction};
use kittycad_execution_plan_traits as ept;
use kittycad_execution_plan_traits::NumericPrimitive;
use kittycad_execution_plan_traits::{Address, NumericPrimitive};
use kittycad_modeling_session::Session;
use self::binding_scope::{BindingScope, EpBinding, GetFnResult};
@ -323,32 +323,27 @@ impl Planner {
}
}
};
let (properties, id) = parse();
let (mut properties, id) = parse();
let name = id.name;
let mut binding = self.binding_scope.get(&name).ok_or(CompileError::Undefined { name })?;
if properties.iter().any(|(_property, computed)| *computed) {
// There's a computed property, so the property/index can only be determined at runtime.
let mut instructions: Vec<Instruction> = Vec::new();
// For now we can only handle computed properties of arrays and objects, no other type.
enum ValType {
Array,
Object,
}
// TODO: `val_type` might need to be mutable so we can properly process
// arrays within objects within arrays etc.
let (val_type, mut val_start) = match binding {
EpBinding::Sequence { length_at, elements: _ } => (ValType::Array, *length_at),
let starting_address = match binding {
EpBinding::Sequence { length_at, elements: _ } => *length_at,
EpBinding::Map {
length_at,
properties: _,
} => (ValType::Object, *length_at),
_ => todo!("handle computed properties besides arrays"),
} => *length_at,
_ => return Err(CompileError::CannotIndex),
};
let mut structure_start = ep::Operand::Literal(starting_address.into());
properties.reverse();
for (property, _computed) in properties {
// Where is the index stored?
let index = match property {
// Where is the member stored?
let addr_of_member = match property {
// If it's some identifier, then look up where that identifier will be stored.
// That's the memory address the index should be in.
// That's the memory address the index/property should be in.
ast::types::LiteralIdentifier::Identifier(id) => {
let b = self
.binding_scope
@ -365,27 +360,28 @@ impl Planner {
ep::Operand::Literal(kcl_literal_to_kcep_literal(litval.value))
}
};
instructions.push(match val_type {
ValType::Array => Instruction::GetElement {
index,
start: val_start,
},
ValType::Object => Instruction::GetProperty {
start: val_start,
property: index,
},
// Find the address of the member, push to stack.
instructions.push(Instruction::AddrOfMember {
member: addr_of_member,
start: structure_start,
});
// If there's another member after this one, its starting object is the
// address we just pushed to the stack.
structure_start = ep::Operand::StackPop;
}
// The final address is on the stack.
// Move it to addressable memory.
let final_prop_addr = self.next_addr.offset_by(1);
instructions.push(Instruction::CopyLen {
source_range: ep::Operand::StackPop,
destination_range: ep::Operand::Literal(final_prop_addr.into()),
});
// Point `start_of_array` to the location we just indexed, so that if there's
// another index expression to a child array, `start_of_array` is in the right place.
val_start = self.next_addr.offset_by(1);
instructions.push(Instruction::StackPop {
destination: Some(val_start),
});
}
Ok(EvalPlan {
instructions,
binding: EpBinding::Single(val_start),
binding: EpBinding::Single(final_prop_addr),
})
} else {
// Compiler optimization:

View File

@ -3,8 +3,8 @@
//! But some other stdlib functions will be written in KCL.
use kcl_lib::std::sketch::PlaneData;
use kittycad_execution_plan::{Address, BinaryArithmetic, Destination, Instruction};
use kittycad_execution_plan_traits::Value;
use kittycad_execution_plan::{BinaryArithmetic, Destination, Instruction};
use kittycad_execution_plan_traits::{Address, Value};
use crate::{CompileError, EpBinding, EvalPlan};

View File

@ -309,6 +309,71 @@ async fn computed_object_property() {
assert_eq!(mem.get(address_of_val).unwrap(), &ept::Primitive::Bool(true));
}
#[tokio::test]
async fn computed_array_in_object() {
let program = r#"
let complicated = {a: [{b: true}]}
let i = 0
let prop0 = "a"
let prop1 = "b"
let val = complicated[prop0][i][prop1] // should be `true`
"#;
let (_plan, scope) = must_plan(program);
let Some(EpBinding::Single(address_of_val)) = scope.get("val") else {
panic!("Unexpected binding for variable 'val': {:?}", scope.get("val"));
};
let ast = kcl_lib::parser::Parser::new(kcl_lib::token::lexer(program))
.ast()
.unwrap();
let mem = crate::execute(ast, None).await.unwrap();
use ept::ReadMemory;
// Should be 'true', based on the above KCL program.
assert_eq!(mem.get(address_of_val).unwrap(), &ept::Primitive::Bool(true));
}
#[tokio::test]
async fn computed_object_in_array() {
let program = r#"
let complicated = [{a: {b: true}}]
let i = 0
let prop0 = "a"
let prop1 = "b"
let val = complicated[i][prop0][prop1] // should be `true`
"#;
let (_plan, scope) = must_plan(program);
let Some(EpBinding::Single(address_of_val)) = scope.get("val") else {
panic!("Unexpected binding for variable 'val': {:?}", scope.get("val"));
};
let ast = kcl_lib::parser::Parser::new(kcl_lib::token::lexer(program))
.ast()
.unwrap();
let mem = crate::execute(ast, None).await.unwrap();
use ept::ReadMemory;
// Should be 'true', based on the above KCL program.
assert_eq!(mem.get(address_of_val).unwrap(), &ept::Primitive::Bool(true));
}
#[tokio::test]
async fn computed_nested_object_property() {
let program = r#"
let obj = {a: {b: true}}
let prop0 = "a"
let prop1 = "b"
let val = obj[prop0][prop1] // should be `true`
"#;
let (_plan, scope) = must_plan(program);
let Some(EpBinding::Single(address_of_val)) = scope.get("val") else {
panic!("Unexpected binding for variable 'val': {:?}", scope.get("val"));
};
let ast = kcl_lib::parser::Parser::new(kcl_lib::token::lexer(program))
.ast()
.unwrap();
let mem = crate::execute(ast, None).await.unwrap();
use ept::ReadMemory;
// Should be 'true', based on the above KCL program.
assert_eq!(mem.get(address_of_val).unwrap(), &ept::Primitive::Bool(true));
}
#[tokio::test]
async fn computed_array_index() {
let program = r#"
@ -383,13 +448,14 @@ async fn computed_array_index() {
destination: Destination::Address(Address::ZERO + 9)
},
// Get the element at the index
Instruction::GetElement {
start: Address::ZERO,
index: ep::Operand::Reference(Address::ZERO + 9)
Instruction::AddrOfMember {
start: ep::Operand::Literal(Address::ZERO.into()),
member: ep::Operand::Reference(Address::ZERO + 9)
},
// Write it to the next free address.
Instruction::StackPop {
destination: Some(expected_address_of_prop)
Instruction::CopyLen {
source_range: ep::Operand::StackPop,
destination_range: ep::Operand::Literal(expected_address_of_prop.into()),
},
]
);
@ -406,25 +472,6 @@ async fn computed_array_index() {
);
}
#[test]
#[ignore = "haven't done computed properties yet"]
fn computed_member_expressions() {
let program = r#"
let obj = {x: 1, y: 2}
let index = "x"
let prop = obj[index]
"#;
let (_plan, scope) = must_plan(program);
match scope.get("prop").unwrap() {
EpBinding::Single(addr) => {
assert_eq!(*addr, Address::ZERO + 1);
}
other => {
panic!("expected 'prop' bound to 0x0 but it was bound to {other:?}");
}
}
}
#[test]
fn member_expressions_object() {
let program = r#"

View File

@ -2721,7 +2721,7 @@ show(b1)
show(b2)"#;
let tokens = crate::token::lexer(some_program_string);
let parser = crate::parser::Parser::new(tokens);
dbg!(parser.ast().unwrap());
parser.ast().unwrap();
}
#[test]