big refactor of var values for astMods

This commit is contained in:
Kurt Hutten Irev-Dev
2024-09-07 09:04:07 +10:00
parent 72e522dd51
commit 94b0510521
11 changed files with 1196 additions and 491 deletions

View File

@ -40,7 +40,6 @@ import { InstanceProps, create } from 'react-modal-promise'
import { executeAst } from 'lang/langHelpers' import { executeAst } from 'lang/langHelpers'
import { import {
deleteSegmentFromPipeExpression, deleteSegmentFromPipeExpression,
makeRemoveSingleConstraintInput,
removeSingleConstraintInfo, removeSingleConstraintInfo,
} from 'lang/modifyAst' } from 'lang/modifyAst'
import { ActionButton } from 'components/ActionButton' import { ActionButton } from 'components/ActionButton'
@ -515,6 +514,11 @@ const ConstraintSymbol = ({
displayName: 'Intersection Offset', displayName: 'Intersection Offset',
iconName: 'intersection-offset', iconName: 'intersection-offset',
}, },
radius: {
varName: 'radius',
displayName: 'Radius',
iconName: 'dimension',
},
// implicit constraints // implicit constraints
vertical: { vertical: {
@ -605,13 +609,10 @@ const ConstraintSymbol = ({
if (trap(_node1)) return Promise.reject(_node1) if (trap(_node1)) return Promise.reject(_node1)
const shallowPath = _node1.shallowPath const shallowPath = _node1.shallowPath
const input = makeRemoveSingleConstraintInput( if (!context.sketchDetails || !argPosition) return
argPosition,
shallowPath
)
if (!input || !context.sketchDetails) return
const transform = removeSingleConstraintInfo( const transform = removeSingleConstraintInfo(
input, shallowPath,
argPosition,
kclManager.ast, kclManager.ast,
kclManager.programMemory kclManager.programMemory
) )

View File

@ -89,6 +89,7 @@ import {
createArrayExpression, createArrayExpression,
createCallExpressionStdLib, createCallExpressionStdLib,
createLiteral, createLiteral,
createObjectExpression,
createPipeExpression, createPipeExpression,
createPipeSubstitution, createPipeSubstitution,
findUniqueName, findUniqueName,
@ -108,6 +109,7 @@ import { getThemeColorForThreeJs } from 'lib/theme'
import { err, trap } from 'lib/trap' import { err, trap } from 'lib/trap'
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer' import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { Point3d } from 'wasm-lib/kcl/bindings/Point3d' import { Point3d } from 'wasm-lib/kcl/bindings/Point3d'
import { c } from 'vite/dist/node/types.d-aGj9QkWt'
type DraftSegment = 'line' | 'tangentialArcTo' type DraftSegment = 'line' | 'tangentialArcTo'
@ -665,8 +667,11 @@ export class SceneEntities {
const mod = addNewSketchLn({ const mod = addNewSketchLn({
node: _ast, node: _ast,
programMemory: kclManager.programMemory, programMemory: kclManager.programMemory,
to: [lastSeg.to[0], lastSeg.to[1]], input: {
from: [lastSeg.to[0], lastSeg.to[1]], type: 'straight-segment',
to: [lastSeg.to[0], lastSeg.to[1]],
from: [lastSeg.to[0], lastSeg.to[1]],
},
fnName: segmentName, fnName: segmentName,
pathToNode: sketchPathToNode, pathToNode: sketchPathToNode,
}) })
@ -736,8 +741,11 @@ export class SceneEntities {
const tmp = addNewSketchLn({ const tmp = addNewSketchLn({
node: kclManager.ast, node: kclManager.ast,
programMemory: kclManager.programMemory, programMemory: kclManager.programMemory,
to: [intersection2d.x, intersection2d.y], input: {
from: [lastSegment.to[0], lastSegment.to[1]], type: 'straight-segment',
to: [intersection2d.x, intersection2d.y],
from: [lastSegment.to[0], lastSegment.to[1]],
},
fnName: fnName:
lastSegment.type === 'TangentialArcTo' lastSegment.type === 'TangentialArcTo'
? 'tangentialArcTo' ? 'tangentialArcTo'
@ -962,11 +970,13 @@ export class SceneEntities {
startSketchOn[0].init = createPipeExpression([ startSketchOn[0].init = createPipeExpression([
startSketchOnInit, startSketchOnInit,
createCallExpressionStdLib('circle', [ createCallExpressionStdLib('circle', [
createArrayExpression([ createObjectExpression({
createLiteral(roundOff(circleCenter[0])), center: createArrayExpression([
createLiteral(roundOff(circleCenter[1])), createLiteral(roundOff(circleCenter[0])),
]), createLiteral(roundOff(circleCenter[1])),
createLiteral(1), ]),
radius: createLiteral(1),
}),
createPipeSubstitution(), createPipeSubstitution(),
]), ]),
]) ])
@ -1147,8 +1157,11 @@ export class SceneEntities {
const mod = addNewSketchLn({ const mod = addNewSketchLn({
node: kclManager.ast, node: kclManager.ast,
programMemory: kclManager.programMemory, programMemory: kclManager.programMemory,
to: [intersectionPoint.twoD.x, intersectionPoint.twoD.y], input: {
from: [prevSegment.from[0], prevSegment.from[1]], type: 'straight-segment',
to: [intersectionPoint.twoD.x, intersectionPoint.twoD.y],
from: [prevSegment.from[0], prevSegment.from[1]],
},
// TODO assuming it's always a straight segments being added // TODO assuming it's always a straight segments being added
// as this is easiest, and we'll need to add "tabbing" behavior // as this is easiest, and we'll need to add "tabbing" behavior
// to support other segment types // to support other segment types
@ -1293,41 +1306,55 @@ export class SceneEntities {
modded = updateStartProfileAtArgs({ modded = updateStartProfileAtArgs({
node: modifiedAst, node: modifiedAst,
pathToNode, pathToNode,
to: dragTo, input: {
from, type: 'straight-segment',
to: dragTo,
from,
},
previousProgramMemory: kclManager.programMemory, previousProgramMemory: kclManager.programMemory,
}) })
} else if (group.name === CIRCLE_SEGMENT && subGroup?.name === ARROWHEAD) { } else if (group.name === CIRCLE_SEGMENT && subGroup?.name === ARROWHEAD) {
// is dragging the radius handle // is dragging the radius handle
modded = changeCircleArguments(
modded = changeSketchArguments(
modifiedAst, modifiedAst,
kclManager.programMemory, kclManager.programMemory,
getNodePathFromSourceRange(modifiedAst, [node.start, node.end]), [node.start, node.end],
group.userData.center, {
Math.sqrt( type: 'arc-segment',
(group.userData.center[0] - dragTo[0]) ** 2 + from,
(group.userData.center[0] - dragTo[0]) ** 2 center: group.userData.center,
) radius: Math.sqrt(
(group.userData.center[0] - dragTo[0]) ** 2 +
(group.userData.center[0] - dragTo[0]) ** 2
),
}
) )
} else if ( } else if (
group.name === CIRCLE_SEGMENT && group.name === CIRCLE_SEGMENT &&
subGroup?.name === CIRCLE_CENTER_HANDLE subGroup?.name === CIRCLE_CENTER_HANDLE
) { ) {
// is dragging the center handle modded = changeSketchArguments(
modded = changeCircleArguments(
modifiedAst, modifiedAst,
kclManager.programMemory, kclManager.programMemory,
getNodePathFromSourceRange(modifiedAst, [node.start, node.end]), [node.start, node.end],
dragTo, {
group.userData.radius type: 'arc-segment',
from,
center: dragTo,
radius: group.userData.radius,
}
) )
} else { } else {
modded = changeSketchArguments( modded = changeSketchArguments(
modifiedAst, modifiedAst,
kclManager.programMemory, kclManager.programMemory,
[node.start, node.end], [node.start, node.end],
dragTo, {
from type: 'straight-segment',
from,
to: dragTo,
}
) )
} }
if (trap(modded)) return if (trap(modded)) return
@ -1683,7 +1710,7 @@ export class SceneEntities {
arrowGroup, arrowGroup,
group, group,
isHandlesVisible, isHandlesVisible,
from, from: to,
to: [center[0], center[1]], to: [center[0], center[1]],
angle, angle,
}) })

View File

@ -24,11 +24,9 @@ export type ToolTip =
| 'yLineTo' | 'yLineTo'
| 'angledLineThatIntersects' | 'angledLineThatIntersects'
| 'tangentialArcTo' | 'tangentialArcTo'
| 'circle'
export const toolTips = [ export const toolTips: Array<ToolTip> = [
'sketch_line',
'move',
// original tooltips
'line', 'line',
'lineTo', 'lineTo',
'angledLine', 'angledLine',
@ -42,7 +40,7 @@ export const toolTips = [
'yLineTo', 'yLineTo',
'angledLineThatIntersects', 'angledLineThatIntersects',
'tangentialArcTo', 'tangentialArcTo',
] as any as ToolTip[] ]
export async function executeAst({ export async function executeAst({
ast, ast,

View File

@ -20,6 +20,7 @@ import {
import { enginelessExecutor } from '../lib/testHelpers' import { enginelessExecutor } from '../lib/testHelpers'
import { findUsesOfTagInPipe, getNodePathFromSourceRange } from './queryAst' import { findUsesOfTagInPipe, getNodePathFromSourceRange } from './queryAst'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { SimplifiedVarValue, VarValueKeys } from './std/stdTypes'
beforeAll(async () => { beforeAll(async () => {
await initPromise await initPromise
@ -638,11 +639,21 @@ describe('Testing removeSingleConstraintInfo', () => {
code.indexOf(lineOfInterest) + lineOfInterest.length, code.indexOf(lineOfInterest) + lineOfInterest.length,
] ]
const pathToNode = getNodePathFromSourceRange(ast, range) const pathToNode = getNodePathFromSourceRange(ast, range)
let argPosition: SimplifiedVarValue
if (key === 'arrayIndex' && typeof value === 'number') {
argPosition = { type: 'arrayItem', argIndex: 0, index: value ? 0 : 1 }
} else if (key === 'objectProperty' && typeof value === 'string') {
argPosition = {
type: 'objectProperty',
key: value as VarValueKeys,
argIndex: 0,
}
} else {
throw new Error('argPosition is undefined')
}
const mod = removeSingleConstraintInfo( const mod = removeSingleConstraintInfo(
{ pathToNode,
pathToCallExp: pathToNode, argPosition,
[key]: value,
},
ast, ast,
programMemory programMemory
) )
@ -675,12 +686,22 @@ describe('Testing removeSingleConstraintInfo', () => {
code.indexOf(lineOfInterest) + 1, code.indexOf(lineOfInterest) + 1,
code.indexOf(lineOfInterest) + lineOfInterest.length, code.indexOf(lineOfInterest) + lineOfInterest.length,
] ]
let argPosition: SimplifiedVarValue
if (key === 'arrayIndex' && typeof value === 'number') {
argPosition = { type: 'arrayItem', argIndex: 0, index: value ? 0 : 1 }
} else if (key === 'objectProperty' && typeof value === 'string') {
argPosition = {
type: 'objectProperty',
key: value as VarValueKeys,
argIndex: 0,
}
} else {
throw new Error('argPosition is undefined')
}
const pathToNode = getNodePathFromSourceRange(ast, range) const pathToNode = getNodePathFromSourceRange(ast, range)
const mod = removeSingleConstraintInfo( const mod = removeSingleConstraintInfo(
{ pathToNode,
pathToCallExp: pathToNode, argPosition,
[key]: value,
},
ast, ast,
programMemory programMemory
) )

View File

@ -38,7 +38,7 @@ import {
import { DefaultPlaneStr } from 'clientSideScene/sceneEntities' import { DefaultPlaneStr } from 'clientSideScene/sceneEntities'
import { isOverlap, roundOff } from 'lib/utils' import { isOverlap, roundOff } from 'lib/utils'
import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants' import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants'
import { ConstrainInfo } from './std/stdTypes' import { SimplifiedVarValue } from './std/stdTypes'
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator' import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
import { Models } from '@kittycad/lib' import { Models } from '@kittycad/lib'
@ -799,15 +799,10 @@ export function deleteSegmentFromPipeExpression(
) )
if (!constraintInfo) return if (!constraintInfo) return
const input = makeRemoveSingleConstraintInput( if (!constraintInfo.argPosition) return
constraintInfo.argPosition,
callExp.shallowPath
)
if (!input) return
const transform = removeSingleConstraintInfo( const transform = removeSingleConstraintInfo(
{ callExp.shallowPath,
...input, constraintInfo.argPosition,
},
_modifiedAst, _modifiedAst,
programMemory programMemory
) )
@ -834,37 +829,9 @@ export function deleteSegmentFromPipeExpression(
return _modifiedAst return _modifiedAst
} }
export function makeRemoveSingleConstraintInput(
argPosition: ConstrainInfo['argPosition'],
pathToNode: PathToNode
): Parameters<typeof removeSingleConstraintInfo>[0] | false {
return argPosition?.type === 'singleValue'
? {
pathToCallExp: pathToNode,
}
: argPosition?.type === 'arrayItem'
? {
pathToCallExp: pathToNode,
arrayIndex: argPosition.index,
}
: argPosition?.type === 'objectProperty'
? {
pathToCallExp: pathToNode,
objectProperty: argPosition.key,
}
: false
}
export function removeSingleConstraintInfo( export function removeSingleConstraintInfo(
{ pathToCallExp: PathToNode,
pathToCallExp, varValue: SimplifiedVarValue,
arrayIndex,
objectProperty,
}: {
pathToCallExp: PathToNode
arrayIndex?: number
objectProperty?: string
},
ast: Program, ast: Program,
programMemory: ProgramMemory programMemory: ProgramMemory
): ):
@ -875,8 +842,7 @@ export function removeSingleConstraintInfo(
| false { | false {
const transform = removeSingleConstraint({ const transform = removeSingleConstraint({
pathToCallExp, pathToCallExp,
arrayIndex, inputDetails: varValue,
objectProperty,
ast, ast,
}) })
if (!transform) return false if (!transform) return false

View File

@ -16,6 +16,7 @@ import {
VariableDeclaration, VariableDeclaration,
VariableDeclarator, VariableDeclarator,
sketchGroupFromKclValue, sketchGroupFromKclValue,
ObjectExpression,
} from './wasm' } from './wasm'
import { createIdentifier, splitPathAtLastIndex } from './modifyAst' import { createIdentifier, splitPathAtLastIndex } from './modifyAst'
import { getSketchSegmentFromSourceRange } from './std/sketchConstraints' import { getSketchSegmentFromSourceRange } from './std/sketchConstraints'
@ -934,3 +935,12 @@ export function hasExtrudableGeometry(ast: Program) {
}) })
return Object.keys(theMap).length > 0 return Object.keys(theMap).length > 0
} }
export function getObjExpProperty(
node: ObjectExpression,
propName: string
): { exp: Expr; index: number } | null {
const index = node.properties.findIndex(({ key }) => key.name === propName)
if (index === -1) return null
return { exp: node.properties[index].value, index }
}

View File

@ -123,8 +123,11 @@ describe('testing changeSketchArguments', () => {
ast, ast,
programMemory, programMemory,
[sourceStart, sourceStart + lineToChange.length], [sourceStart, sourceStart + lineToChange.length],
[2, 3], {
[0, 0] type: 'straight-segment',
from: [0, 0],
to: [2, 3],
}
) )
if (err(changeSketchArgsRetVal)) return changeSketchArgsRetVal if (err(changeSketchArgsRetVal)) return changeSketchArgsRetVal
expect(recast(changeSketchArgsRetVal.modifiedAst)).toBe(expectedCode) expect(recast(changeSketchArgsRetVal.modifiedAst)).toBe(expectedCode)
@ -150,8 +153,11 @@ const mySketch001 = startSketchOn('XY')
const newSketchLnRetVal = addNewSketchLn({ const newSketchLnRetVal = addNewSketchLn({
node: ast, node: ast,
programMemory, programMemory,
to: [2, 3], input: {
from: [0, 0], type: 'straight-segment',
from: [0, 0],
to: [2, 3],
},
fnName: 'lineTo', fnName: 'lineTo',
pathToNode: [ pathToNode: [
['body', ''], ['body', ''],

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,16 @@ export function getSketchSegmentFromSourceRange(
index: number index: number
} }
| Error { | Error {
const lineIndex = sketchGroup.value.findIndex(
({ __geoMeta: { sourceRange } }: Path) =>
sourceRange[0] <= rangeStart && sourceRange[1] >= rangeEnd
)
const line = sketchGroup.value[lineIndex]
if (line)
return {
segment: line,
index: lineIndex,
}
const startSourceRange = sketchGroup.start?.__geoMeta.sourceRange const startSourceRange = sketchGroup.start?.__geoMeta.sourceRange
if ( if (
startSourceRange && startSourceRange &&
@ -51,17 +61,7 @@ export function getSketchSegmentFromSourceRange(
sketchGroup.start sketchGroup.start
) )
return { segment: { ...sketchGroup.start, type: 'Base' }, index: -1 } return { segment: { ...sketchGroup.start, type: 'Base' }, index: -1 }
return new Error('could not find matching segment')
const lineIndex = sketchGroup.value.findIndex(
({ __geoMeta: { sourceRange } }: Path) =>
sourceRange[0] <= rangeStart && sourceRange[1] >= rangeEnd
)
const line = sketchGroup.value[lineIndex]
if (!line) return new Error('could not find matching line')
return {
segment: line,
index: lineIndex,
}
} }
export function isSketchVariablesLinked( export function isSketchVariablesLinked(

File diff suppressed because it is too large Load Diff

View File

@ -37,9 +37,36 @@ export interface AddTagInfo {
pathToNode: PathToNode pathToNode: PathToNode
} }
interface addCall extends ModifyAstBase { /** Inputs for all straight segments, to and from are absolute values, as this gives a
to: [number, number] * consistent base that can be converted to all of the line, angledLine, etc segment types
* One notable exception to "straight segment" is that tangentialArcTo is included in this
* Input type since it too only takes x-y values and is able to get extra info it needs
* to be tangential from the previous segment */
interface StraightSegmentInput {
type: 'straight-segment'
from: [number, number] from: [number, number]
to: [number, number]
}
/** Inputs for arcs, excluding tangentialArcTo for reasons explain in
* the @straightSegmentInput comment */
interface ArcSegmentInput {
type: 'arc-segment'
from: [number, number]
center: [number, number]
radius: number
}
/**
* SegmentInputs is a union type that can be either a StraightSegmentInput or an ArcSegmentInput.
*
* - StraightSegmentInput: Represents a straight segment with a starting point (from) and an ending point (to).
* - ArcSegmentInput: Represents an arc segment with a starting point (from), a center point, and a radius.
*/
export type SegmentInputs = StraightSegmentInput | ArcSegmentInput
interface addCall extends ModifyAstBase {
input: SegmentInputs
referencedSegment?: Path referencedSegment?: Path
replaceExisting?: boolean replaceExisting?: boolean
createCallback?: TransformCallback // TODO: #29 probably should not be optional createCallback?: TransformCallback // TODO: #29 probably should not be optional
@ -48,35 +75,54 @@ interface addCall extends ModifyAstBase {
} }
interface updateArgs extends ModifyAstBase { interface updateArgs extends ModifyAstBase {
from: [number, number] input: SegmentInputs
to: [number, number]
} }
export type VarValueKeys = 'angle' | 'offset' | 'length' | 'to' | 'intersectTag' export type VarValueKeys =
| 'angle'
| 'offset'
| 'length'
| 'to'
| 'intersectTag'
| 'radius'
| 'center'
export interface SingleValueInput<T> { export interface SingleValueInput<T> {
type: 'singleValue' type: 'singleValue'
argType: LineInputsType argType: LineInputsType | 'radius'
value: T value: T
argIndex: number
} }
export interface ArrayItemInput<T> { export interface ArrayItemInput<T> {
type: 'arrayItem' type: 'arrayItem'
index: 0 | 1 index: 0 | 1
argType: LineInputsType argType: LineInputsType | 'radius'
value: T value: T
argIndex: number
} }
export interface ObjectPropertyInput<T> { export interface ObjectPropertyInput<T> {
type: 'objectProperty' type: 'objectProperty'
key: VarValueKeys key: VarValueKeys
argType: LineInputsType argType: LineInputsType | 'radius'
value: T value: T
argIndex: number
} }
export interface ArrayOrObjItemInput<T> { export interface ArrayOrObjItemInput<T> {
type: 'arrayOrObjItem' type: 'arrayOrObjItem'
key: VarValueKeys key: VarValueKeys
index: 0 | 1 index: 0 | 1
argType: LineInputsType argType: LineInputsType | 'radius'
value: T value: T
argIndex: number
}
export interface ObjectPropertyArrayInput<T> {
type: 'objectPropertyArray'
key: VarValueKeys
argType: LineInputsType | 'radius'
index: 0 | 1
value: T
argIndex: number
} }
export type _VarValue<T> = export type _VarValue<T> =
@ -84,6 +130,7 @@ export type _VarValue<T> =
| ArrayItemInput<T> | ArrayItemInput<T>
| ObjectPropertyInput<T> | ObjectPropertyInput<T>
| ArrayOrObjItemInput<T> | ArrayOrObjItemInput<T>
| ObjectPropertyArrayInput<T>
export type VarValue = _VarValue<Expr> export type VarValue = _VarValue<Expr>
export type RawValue = _VarValue<Literal> export type RawValue = _VarValue<Literal>
@ -91,16 +138,25 @@ export type RawValue = _VarValue<Literal>
export type VarValues = Array<VarValue> export type VarValues = Array<VarValue>
export type RawValues = Array<RawValue> export type RawValues = Array<RawValue>
type SimplifiedVarValue = export type SimplifiedVarValue =
| { | {
type: 'singleValue' type: 'singleValue'
argIndex: number
}
| { type: 'arrayItem'; index: 0 | 1; argIndex: number }
| { type: 'objectProperty'; key: VarValueKeys; argIndex: number }
| {
type: 'arrayInObject'
key: VarValueKeys
index: 0 | 1
} }
| { type: 'arrayItem'; index: 0 | 1 }
| { type: 'objectProperty'; key: VarValueKeys }
export type TransformCallback = ( export type TransformCallback = (
args: [Expr, Expr], // args: Array<Expr>,
literalValues: RawValues, inputs: {
varExpression: Expr
varDetails: VarValue
}[],
referencedSegment?: Path referencedSegment?: Path
) => { ) => {
callExp: Expr callExp: Expr
@ -109,7 +165,12 @@ export type TransformCallback = (
export interface ConstrainInfo { export interface ConstrainInfo {
stdLibFnName: ToolTip stdLibFnName: ToolTip
type: LineInputsType | 'vertical' | 'horizontal' | 'tangentialWithPrevious' type:
| LineInputsType
| 'vertical'
| 'horizontal'
| 'tangentialWithPrevious'
| 'radius'
isConstrained: boolean isConstrained: boolean
sourceRange: SourceRange sourceRange: SourceRange
pathToNode: PathToNode pathToNode: PathToNode