Fix default memory so its always initialized in one place -> rust (#1395)

* initial redo

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* default memory

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* rename values

* find tricky case

* fix test

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
This commit is contained in:
Jess Frazelle
2024-02-11 18:26:09 -08:00
committed by GitHub
parent f1ea9b6ece
commit 5f0f3f40d0
9 changed files with 113 additions and 80 deletions

View File

@ -143,11 +143,11 @@ const part001 = startSketchOn('-XZ')
|> xLineTo({ to: totalLen, tag: 'seg03' }, %) |> xLineTo({ to: totalLen, tag: 'seg03' }, %)
|> yLine({ length: -armThick, tag: 'seg01' }, %) |> yLine({ length: -armThick, tag: 'seg01' }, %)
|> angledLineThatIntersects({ |> angledLineThatIntersects({
angle: _180, angle: HALF_TURN,
offset: -armThick, offset: -armThick,
intersectTag: 'seg04' intersectTag: 'seg04'
}, %) }, %)
|> angledLineToY([segAng('seg04', %) + 180, _0], %) |> angledLineToY([segAng('seg04', %) + 180, ZERO], %)
|> angledLineToY({ |> angledLineToY({
angle: -bottomAng, angle: -bottomAng,
to: -totalHeightHalf - armThick, to: -totalHeightHalf - armThick,
@ -156,12 +156,12 @@ const part001 = startSketchOn('-XZ')
|> xLineTo(segEndX('seg03', %) + 0, %) |> xLineTo(segEndX('seg03', %) + 0, %)
|> yLine(-segLen('seg01', %), %) |> yLine(-segLen('seg01', %), %)
|> angledLineThatIntersects({ |> angledLineThatIntersects({
angle: _180, angle: HALF_TURN,
offset: -armThick, offset: -armThick,
intersectTag: 'seg02' intersectTag: 'seg02'
}, %) }, %)
|> angledLineToY([segAng('seg02', %) + 180, -baseHeight], %) |> angledLineToY([segAng('seg02', %) + 180, -baseHeight], %)
|> xLineTo(_0, %) |> xLineTo(ZERO, %)
|> close(%) |> close(%)
|> extrude(4, %)` |> extrude(4, %)`
) )

View File

@ -42,6 +42,7 @@ import {
PipeExpression, PipeExpression,
Program, Program,
ProgramMemory, ProgramMemory,
programMemoryInit,
recast, recast,
SketchGroup, SketchGroup,
VariableDeclaration, VariableDeclaration,
@ -49,7 +50,7 @@ import {
} from 'lang/wasm' } from 'lang/wasm'
import { kclManager } from 'lang/KclSingleton' import { kclManager } from 'lang/KclSingleton'
import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst' import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst'
import { defaultProgramMemory, executeAst } from 'useStore' import { executeAst } from 'useStore'
import { engineCommandManager } from 'lang/std/engineConnection' import { engineCommandManager } from 'lang/std/engineConnection'
import { import {
createArcGeometry, createArcGeometry,
@ -869,10 +870,7 @@ function prepareTruncatedMemoryAndAst(
..._ast, ..._ast,
body: [JSON.parse(JSON.stringify(_ast.body[bodyIndex]))], body: [JSON.parse(JSON.stringify(_ast.body[bodyIndex]))],
} }
const programMemoryOverride: ProgramMemory = { const programMemoryOverride: ProgramMemory = programMemoryInit()
root: defaultProgramMemory(),
return: null,
}
for (let i = 0; i < bodyIndex; i++) { for (let i = 0; i < bodyIndex; i++) {
const node = _ast.body[i] const node = _ast.body[i]
if (node.type !== 'VariableDeclaration') { if (node.type !== 'VariableDeclaration') {

View File

@ -139,7 +139,7 @@ export function applyConstraintAxisAlign({
constraint, constraint,
}).transforms }).transforms
let finalValue = createIdentifier('_0') let finalValue = createIdentifier('ZERO')
return transformAstSketchLines({ return transformAstSketchLines({
ast: JSON.parse(JSON.stringify(kclManager.ast)), ast: JSON.parse(JSON.stringify(kclManager.ast)),

View File

@ -89,12 +89,16 @@ export async function applyConstraintAngleLength({
isReferencingXAxis && angleOrLength === 'setAngle' isReferencingXAxis && angleOrLength === 'setAngle'
let forceVal = valueUsedInTransform || 0 let forceVal = valueUsedInTransform || 0
let calcIdentifier = createIdentifier('_0') let calcIdentifier = createIdentifier('ZERO')
if (isReferencingYAxisAngle) { if (isReferencingYAxisAngle) {
calcIdentifier = createIdentifier(forceVal < 0 ? '_270' : '_90') calcIdentifier = createIdentifier(
forceVal < 0 ? 'THREE_QUARTER_TURN' : 'QUARTER_TURN'
)
forceVal = normaliseAngle(forceVal + (forceVal < 0 ? 90 : -90)) forceVal = normaliseAngle(forceVal + (forceVal < 0 ? 90 : -90))
} else if (isReferencingXAxisAngle) { } else if (isReferencingXAxisAngle) {
calcIdentifier = createIdentifier(Math.abs(forceVal) > 90 ? '_180' : '_0') calcIdentifier = createIdentifier(
Math.abs(forceVal) > 90 ? 'HALF_TURN' : 'ZERO'
)
forceVal = forceVal =
Math.abs(forceVal) > 90 ? normaliseAngle(forceVal - 180) : forceVal Math.abs(forceVal) > 90 ? normaliseAngle(forceVal - 180) : forceVal
} }
@ -112,7 +116,7 @@ export async function applyConstraintAngleLength({
) )
if ( if (
isReferencingYAxisAngle || isReferencingYAxisAngle ||
(isReferencingXAxisAngle && calcIdentifier.name !== '_0') (isReferencingXAxisAngle && calcIdentifier.name !== 'ZERO')
) { ) {
finalValue = createBinaryExpressionWithUnary([calcIdentifier, finalValue]) finalValue = createBinaryExpressionWithUnary([calcIdentifier, finalValue])
} }

View File

@ -405,8 +405,14 @@ const setAngledIntersectLineForLines: TransformInfo['createNode'] =
2 2
) )
const angle = args[0].type === 'Literal' ? Number(args[0].value) : 0 const angle = args[0].type === 'Literal' ? Number(args[0].value) : 0
const varNamMap: { [key: number]: string } = {
0: 'ZERO',
90: 'QUARTER_TURN',
180: 'HALF_TURN',
270: 'THREE_QUARTER_TURN',
}
const angleVal = [0, 90, 180, 270].includes(angle) const angleVal = [0, 90, 180, 270].includes(angle)
? createIdentifier(`_${angle}`) ? createIdentifier(varNamMap[angle])
: createLiteral(angle) : createLiteral(angle)
return intersectCallWrapper({ return intersectCallWrapper({
fnName: 'angledLineThatIntersects', fnName: 'angledLineThatIntersects',
@ -455,7 +461,7 @@ const setAngleBetweenCreateNode =
firstHalfValue = createBinaryExpression([ firstHalfValue = createBinaryExpression([
firstHalfValue, firstHalfValue,
'+', '+',
createIdentifier('_180'), createIdentifier('HALF_TURN'),
]) ])
valueUsedInTransform = normaliseAngle(valueUsedInTransform - 180) valueUsedInTransform = normaliseAngle(valueUsedInTransform - 180)
} }

View File

@ -6,6 +6,7 @@ import init, {
modify_ast_for_sketch_wasm, modify_ast_for_sketch_wasm,
is_points_ccw, is_points_ccw,
get_tangential_arc_to_info, get_tangential_arc_to_info,
program_memory_init,
} from '../wasm-lib/pkg/wasm_lib' } from '../wasm-lib/pkg/wasm_lib'
import { KCLError } from './errors' import { KCLError } from './errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError' import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
@ -252,3 +253,21 @@ export function getTangentialArcToInfo({
ccw: result.ccw > 0, ccw: result.ccw > 0,
} }
} }
export function programMemoryInit(): ProgramMemory {
try {
const memory: ProgramMemory = program_memory_init()
return memory
} catch (e: any) {
console.log(e)
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}

View File

@ -1,7 +1,13 @@
import { create } from 'zustand' import { create } from 'zustand'
import { persist } from 'zustand/middleware' import { persist } from 'zustand/middleware'
import { addLineHighlight, EditorView } from './editor/highlightextension' import { addLineHighlight, EditorView } from './editor/highlightextension'
import { parse, Program, _executor, ProgramMemory } from './lang/wasm' import {
parse,
Program,
_executor,
ProgramMemory,
programMemoryInit,
} from './lang/wasm'
import { Selection } from 'lib/selections' import { Selection } from 'lib/selections'
import { enginelessExecutor } from './lib/testHelpers' import { enginelessExecutor } from './lib/testHelpers'
import { EngineCommandManager } from './lang/std/engineConnection' import { EngineCommandManager } from './lang/std/engineConnection'
@ -156,34 +162,6 @@ export const useStore = create<StoreState>()(
) )
) )
export const defaultProgramMemory: () => ProgramMemory['root'] = () => ({
_0: {
type: 'UserVal',
value: 0,
__meta: [],
},
_90: {
type: 'UserVal',
value: 90,
__meta: [],
},
_180: {
type: 'UserVal',
value: 180,
__meta: [],
},
_270: {
type: 'UserVal',
value: 270,
__meta: [],
},
PI: {
type: 'UserVal',
value: Math.PI,
__meta: [],
},
})
export async function executeCode({ export async function executeCode({
engineCommandManager, engineCommandManager,
code, code,
@ -273,21 +251,8 @@ export async function executeAst({
engineCommandManager.startNewSession() engineCommandManager.startNewSession()
} }
const programMemory = await (useFakeExecutor const programMemory = await (useFakeExecutor
? enginelessExecutor( ? enginelessExecutor(ast, programMemoryOverride || programMemoryInit())
ast, : _executor(ast, programMemoryInit(), engineCommandManager))
programMemoryOverride || {
root: defaultProgramMemory(),
return: null,
}
)
: _executor(
ast,
{
root: defaultProgramMemory(),
return: null,
},
engineCommandManager
))
await engineCommandManager.waitForAllCommands() await engineCommandManager.waitForAllCommands()
return { return {

View File

@ -30,7 +30,36 @@ pub struct ProgramMemory {
impl ProgramMemory { impl ProgramMemory {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
root: HashMap::new(), root: HashMap::from([
(
"ZERO".to_string(),
MemoryItem::UserVal(UserVal {
value: serde_json::Value::Number(serde_json::value::Number::from(0)),
meta: Default::default(),
}),
),
(
"QUARTER_TURN".to_string(),
MemoryItem::UserVal(UserVal {
value: serde_json::Value::Number(serde_json::value::Number::from(90)),
meta: Default::default(),
}),
),
(
"HALF_TURN".to_string(),
MemoryItem::UserVal(UserVal {
value: serde_json::Value::Number(serde_json::value::Number::from(180)),
meta: Default::default(),
}),
),
(
"THREE_QUARTER_TURN".to_string(),
MemoryItem::UserVal(UserVal {
value: serde_json::Value::Number(serde_json::value::Number::from(270)),
meta: Default::default(),
}),
),
]),
return_: None, return_: None,
} }
} }
@ -1664,6 +1693,13 @@ show(bracket)
optional: false, optional: false,
} }
} }
fn additional_program_memory(items: &[(String, MemoryItem)]) -> ProgramMemory {
let mut program_memory = ProgramMemory::new();
for (name, item) in items {
program_memory.root.insert(name.to_string(), item.clone());
}
program_memory
}
// Declare the test cases. // Declare the test cases.
for (test_name, params, args, expected) in [ for (test_name, params, args, expected) in [
("empty", Vec::new(), Vec::new(), Ok(ProgramMemory::new())), ("empty", Vec::new(), Vec::new(), Ok(ProgramMemory::new())),
@ -1671,10 +1707,7 @@ show(bracket)
"all params required, and all given, should be OK", "all params required, and all given, should be OK",
vec![req_param("x")], vec![req_param("x")],
vec![mem(1)], vec![mem(1)],
Ok(ProgramMemory { Ok(additional_program_memory(&[("x".to_owned(), mem(1))])),
return_: None,
root: HashMap::from([("x".to_owned(), mem(1))]),
}),
), ),
( (
"all params required, none given, should error", "all params required, none given, should error",
@ -1689,10 +1722,10 @@ show(bracket)
"all params optional, none given, should be OK", "all params optional, none given, should be OK",
vec![opt_param("x")], vec![opt_param("x")],
vec![], vec![],
Ok(ProgramMemory { Ok(additional_program_memory(&[(
return_: None, "x".to_owned(),
root: HashMap::from([("x".to_owned(), MemoryItem::from(&KclNone::default()))]), MemoryItem::from(&KclNone::default()),
}), )])),
), ),
( (
"mixed params, too few given", "mixed params, too few given",
@ -1707,22 +1740,19 @@ show(bracket)
"mixed params, minimum given, should be OK", "mixed params, minimum given, should be OK",
vec![req_param("x"), opt_param("y")], vec![req_param("x"), opt_param("y")],
vec![mem(1)], vec![mem(1)],
Ok(ProgramMemory { Ok(additional_program_memory(&[
return_: None, ("x".to_owned(), mem(1)),
root: HashMap::from([ ("y".to_owned(), MemoryItem::from(&KclNone::default())),
("x".to_owned(), mem(1)), ])),
("y".to_owned(), MemoryItem::from(&KclNone::default())),
]),
}),
), ),
( (
"mixed params, maximum given, should be OK", "mixed params, maximum given, should be OK",
vec![req_param("x"), opt_param("y")], vec![req_param("x"), opt_param("y")],
vec![mem(1), mem(2)], vec![mem(1), mem(2)],
Ok(ProgramMemory { Ok(additional_program_memory(&[
return_: None, ("x".to_owned(), mem(1)),
root: HashMap::from([("x".to_owned(), mem(1)), ("y".to_owned(), mem(2))]), ("y".to_owned(), mem(2)),
}), ])),
), ),
( (
"mixed params, too many given", "mixed params, too many given",

View File

@ -251,3 +251,14 @@ pub fn get_tangential_arc_to_info(
ccw: result.ccw, ccw: result.ccw,
} }
} }
/// Create the default program memory.
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn program_memory_init() -> Result<JsValue, String> {
let memory = kcl_lib::executor::ProgramMemory::default();
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
// gloo-serialize crate instead.
JsValue::from_serde(&memory).map_err(|e| e.to_string())
}