Rename kcl Value to Expr (#3360)

Rename kcl's Value to Expr

As Jon pointed out, kcl's `Value` enum is actually an expression.
"2+2" isn't a value, it's an expression, which can compute a value.
So I renamed it `Expr`.
This commit is contained in:
Adam Chalmers
2024-08-12 15:38:42 -05:00
committed by GitHub
parent d1e21d673e
commit 13986fcfd7
34 changed files with 473 additions and 475 deletions

View File

@ -26,7 +26,7 @@ import {
PathToNode, PathToNode,
Program, Program,
SourceRange, SourceRange,
Value, Expr,
parse, parse,
recast, recast,
} from 'lang/wasm' } from 'lang/wasm'
@ -550,7 +550,7 @@ const ConstraintSymbol = ({
varNameMap[_type as LineInputsType]?.implicitConstraintDesc varNameMap[_type as LineInputsType]?.implicitConstraintDesc
const _node = useMemo( const _node = useMemo(
() => getNodeFromPath<Value>(kclManager.ast, pathToNode), () => getNodeFromPath<Expr>(kclManager.ast, pathToNode),
[kclManager.ast, pathToNode] [kclManager.ast, pathToNode]
) )
if (err(_node)) return if (err(_node)) return

View File

@ -1,5 +1,5 @@
import { useEffect, useState, useRef } from 'react' import { useEffect, useState, useRef } from 'react'
import { parse, BinaryPart, Value, ProgramMemory } from '../lang/wasm' import { parse, BinaryPart, Expr, ProgramMemory } from '../lang/wasm'
import { import {
createIdentifier, createIdentifier,
createLiteral, createLiteral,
@ -86,7 +86,7 @@ export function useCalc({
initialVariableName?: string initialVariableName?: string
}): { }): {
inputRef: React.RefObject<HTMLInputElement> inputRef: React.RefObject<HTMLInputElement>
valueNode: Value | null valueNode: Expr | null
calcResult: string calcResult: string
prevVariables: PrevVariable<unknown>[] prevVariables: PrevVariable<unknown>[]
newVariableName: string newVariableName: string
@ -105,7 +105,7 @@ export function useCalc({
insertIndex: 0, insertIndex: 0,
bodyPath: [], bodyPath: [],
}) })
const [valueNode, setValueNode] = useState<Value | null>(null) const [valueNode, setValueNode] = useState<Expr | null>(null)
const [calcResult, setCalcResult] = useState('NAN') const [calcResult, setCalcResult] = useState('NAN')
const [newVariableName, setNewVariableName] = useState('') const [newVariableName, setNewVariableName] = useState('')
const [isNewVariableNameUnique, setIsNewVariableNameUnique] = useState(true) const [isNewVariableNameUnique, setIsNewVariableNameUnique] = useState(true)

View File

@ -1,7 +1,7 @@
import { Dialog, Transition } from '@headlessui/react' import { Dialog, Transition } from '@headlessui/react'
import { Fragment, useState } from 'react' import { Fragment, useState } from 'react'
import { type InstanceProps, create } from 'react-modal-promise' import { type InstanceProps, create } from 'react-modal-promise'
import { Value } from '../lang/wasm' import { Expr } from '../lang/wasm'
import { import {
AvailableVars, AvailableVars,
addToInputHelper, addToInputHelper,
@ -13,7 +13,7 @@ import { useCalculateKclExpression } from 'lib/useCalculateKclExpression'
type ModalResolve = { type ModalResolve = {
value: string value: string
sign: number sign: number
valueNode: Value valueNode: Expr
variableName?: string variableName?: string
newVariableInsertIndex: number newVariableInsertIndex: number
} }

View File

@ -1,7 +1,7 @@
import { Dialog, Transition } from '@headlessui/react' import { Dialog, Transition } from '@headlessui/react'
import { Fragment, useState } from 'react' import { Fragment, useState } from 'react'
import { type InstanceProps, create } from 'react-modal-promise' import { type InstanceProps, create } from 'react-modal-promise'
import { Value } from '../lang/wasm' import { Expr } from '../lang/wasm'
import { import {
AvailableVars, AvailableVars,
addToInputHelper, addToInputHelper,
@ -13,7 +13,7 @@ import { useCalculateKclExpression } from 'lib/useCalculateKclExpression'
type ModalResolve = { type ModalResolve = {
value: string value: string
segName: string segName: string
valueNode: Value valueNode: Expr
variableName?: string variableName?: string
newVariableInsertIndex: number newVariableInsertIndex: number
sign: number sign: number

View File

@ -1,6 +1,6 @@
import { toolTips } from 'lang/langHelpers' import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { Program, Value, VariableDeclarator } from '../../lang/wasm' import { Program, Expr, VariableDeclarator } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
@ -29,13 +29,13 @@ export function equalAngleInfo({
getNodePathFromSourceRange(kclManager.ast, range) getNodePathFromSourceRange(kclManager.ast, range)
) )
const _nodes = paths.map((pathToNode) => { const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode) const tmp = getNodeFromPath<Expr>(kclManager.ast, pathToNode)
if (err(tmp)) return tmp if (err(tmp)) return tmp
return tmp.node return tmp.node
}) })
const _err1 = _nodes.find(err) const _err1 = _nodes.find(err)
if (err(_err1)) return _err1 if (err(_err1)) return _err1
const nodes = _nodes as Value[] const nodes = _nodes as Expr[]
const _varDecs = paths.map((pathToNode) => { const _varDecs = paths.map((pathToNode) => {
const tmp = getNodeFromPath<VariableDeclarator>( const tmp = getNodeFromPath<VariableDeclarator>(

View File

@ -1,6 +1,6 @@
import { toolTips } from 'lang/langHelpers' import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { Program, Value, VariableDeclarator } from '../../lang/wasm' import { Program, Expr, VariableDeclarator } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
@ -29,13 +29,13 @@ export function setEqualLengthInfo({
getNodePathFromSourceRange(kclManager.ast, range) getNodePathFromSourceRange(kclManager.ast, range)
) )
const _nodes = paths.map((pathToNode) => { const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode) const tmp = getNodeFromPath<Expr>(kclManager.ast, pathToNode)
if (err(tmp)) return tmp if (err(tmp)) return tmp
return tmp.node return tmp.node
}) })
const _err1 = _nodes.find(err) const _err1 = _nodes.find(err)
if (err(_err1)) return _err1 if (err(_err1)) return _err1
const nodes = _nodes as Value[] const nodes = _nodes as Expr[]
const _varDecs = paths.map((pathToNode) => { const _varDecs = paths.map((pathToNode) => {
const tmp = getNodeFromPath<VariableDeclarator>( const tmp = getNodeFromPath<VariableDeclarator>(

View File

@ -1,6 +1,6 @@
import { toolTips } from 'lang/langHelpers' import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { Program, ProgramMemory, Value } from '../../lang/wasm' import { Program, ProgramMemory, Expr } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
@ -27,13 +27,13 @@ export function horzVertInfo(
getNodePathFromSourceRange(kclManager.ast, range) getNodePathFromSourceRange(kclManager.ast, range)
) )
const _nodes = paths.map((pathToNode) => { const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode) const tmp = getNodeFromPath<Expr>(kclManager.ast, pathToNode)
if (err(tmp)) return tmp if (err(tmp)) return tmp
return tmp.node return tmp.node
}) })
const _err1 = _nodes.find(err) const _err1 = _nodes.find(err)
if (err(_err1)) return _err1 if (err(_err1)) return _err1
const nodes = _nodes as Value[] const nodes = _nodes as Expr[]
const isAllTooltips = nodes.every( const isAllTooltips = nodes.every(
(node) => (node) =>

View File

@ -1,6 +1,6 @@
import { toolTips } from 'lang/langHelpers' import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { BinaryPart, Program, Value, VariableDeclarator } from '../../lang/wasm' import { BinaryPart, Program, Expr, VariableDeclarator } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
@ -72,13 +72,13 @@ export function intersectInfo({
getNodePathFromSourceRange(kclManager.ast, range) getNodePathFromSourceRange(kclManager.ast, range)
) )
const _nodes = paths.map((pathToNode) => { const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode) const tmp = getNodeFromPath<Expr>(kclManager.ast, pathToNode)
if (err(tmp)) return tmp if (err(tmp)) return tmp
return tmp.node return tmp.node
}) })
const _err1 = _nodes.find(err) const _err1 = _nodes.find(err)
if (err(_err1)) return _err1 if (err(_err1)) return _err1
const nodes = _nodes as Value[] const nodes = _nodes as Expr[]
const _varDecs = paths.map((pathToNode) => { const _varDecs = paths.map((pathToNode) => {
const tmp = getNodeFromPath<VariableDeclarator>( const tmp = getNodeFromPath<VariableDeclarator>(

View File

@ -1,6 +1,6 @@
import { toolTips } from 'lang/langHelpers' import { toolTips } from 'lang/langHelpers'
import { Selection, Selections } from 'lib/selections' import { Selection, Selections } from 'lib/selections'
import { PathToNode, Program, Value } from '../../lang/wasm' import { PathToNode, Program, Expr } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
@ -33,13 +33,13 @@ export function removeConstrainingValuesInfo({
getNodePathFromSourceRange(kclManager.ast, range) getNodePathFromSourceRange(kclManager.ast, range)
) )
const _nodes = paths.map((pathToNode) => { const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode) const tmp = getNodeFromPath<Expr>(kclManager.ast, pathToNode)
if (err(tmp)) return tmp if (err(tmp)) return tmp
return tmp.node return tmp.node
}) })
const _err1 = _nodes.find(err) const _err1 = _nodes.find(err)
if (err(_err1)) return _err1 if (err(_err1)) return _err1
const nodes = _nodes as Value[] const nodes = _nodes as Expr[]
const updatedSelectionRanges = pathToNodes const updatedSelectionRanges = pathToNodes
? { ? {

View File

@ -1,6 +1,6 @@
import { toolTips } from 'lang/langHelpers' import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { BinaryPart, Program, Value } from '../../lang/wasm' import { BinaryPart, Program, Expr } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
@ -49,7 +49,7 @@ export function absDistanceInfo({
getNodePathFromSourceRange(kclManager.ast, range) getNodePathFromSourceRange(kclManager.ast, range)
) )
const _nodes = paths.map((pathToNode) => { const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>( const tmp = getNodeFromPath<Expr>(
kclManager.ast, kclManager.ast,
pathToNode, pathToNode,
'CallExpression' 'CallExpression'
@ -59,7 +59,7 @@ export function absDistanceInfo({
}) })
const _err1 = _nodes.find(err) const _err1 = _nodes.find(err)
if (err(_err1)) return _err1 if (err(_err1)) return _err1
const nodes = _nodes as Value[] const nodes = _nodes as Expr[]
const isAllTooltips = nodes.every( const isAllTooltips = nodes.every(
(node) => (node) =>

View File

@ -1,6 +1,6 @@
import { toolTips } from 'lang/langHelpers' import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { BinaryPart, Program, Value, VariableDeclarator } from '../../lang/wasm' import { BinaryPart, Program, Expr, VariableDeclarator } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
@ -35,13 +35,13 @@ export function angleBetweenInfo({
) )
const _nodes = paths.map((pathToNode) => { const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode) const tmp = getNodeFromPath<Expr>(kclManager.ast, pathToNode)
if (err(tmp)) return tmp if (err(tmp)) return tmp
return tmp.node return tmp.node
}) })
const _err1 = _nodes.find(err) const _err1 = _nodes.find(err)
if (err(_err1)) return _err1 if (err(_err1)) return _err1
const nodes = _nodes as Value[] const nodes = _nodes as Expr[]
const _varDecs = paths.map((pathToNode) => { const _varDecs = paths.map((pathToNode) => {
const tmp = getNodeFromPath<VariableDeclarator>( const tmp = getNodeFromPath<VariableDeclarator>(

View File

@ -1,5 +1,5 @@
import { toolTips } from 'lang/langHelpers' import { toolTips } from 'lang/langHelpers'
import { BinaryPart, Program, Value, VariableDeclarator } from '../../lang/wasm' import { BinaryPart, Program, Expr, VariableDeclarator } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
@ -36,14 +36,14 @@ export function horzVertDistanceInfo({
getNodePathFromSourceRange(kclManager.ast, range) getNodePathFromSourceRange(kclManager.ast, range)
) )
const _nodes = paths.map((pathToNode) => { const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode) const tmp = getNodeFromPath<Expr>(kclManager.ast, pathToNode)
if (err(tmp)) return tmp if (err(tmp)) return tmp
return tmp.node return tmp.node
}) })
const [hasErr, , nodesWErrs] = cleanErrs(_nodes) const [hasErr, , nodesWErrs] = cleanErrs(_nodes)
if (hasErr) return nodesWErrs[0] if (hasErr) return nodesWErrs[0]
const nodes = _nodes as Value[] const nodes = _nodes as Expr[]
const _varDecs = paths.map((pathToNode) => { const _varDecs = paths.map((pathToNode) => {
const tmp = getNodeFromPath<VariableDeclarator>( const tmp = getNodeFromPath<VariableDeclarator>(

View File

@ -1,6 +1,6 @@
import { toolTips } from 'lang/langHelpers' import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { BinaryPart, Program, Value } from '../../lang/wasm' import { BinaryPart, Program, Expr } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
@ -44,7 +44,7 @@ export function angleLengthInfo({
) )
const nodes = paths.map((pathToNode) => const nodes = paths.map((pathToNode) =>
getNodeFromPath<Value>(kclManager.ast, pathToNode, 'CallExpression') getNodeFromPath<Expr>(kclManager.ast, pathToNode, 'CallExpression')
) )
const _err1 = nodes.find(err) const _err1 = nodes.find(err)
if (err(_err1)) return _err1 if (err(_err1)) return _err1

View File

@ -6,7 +6,7 @@ import {
PipeExpression, PipeExpression,
VariableDeclaration, VariableDeclaration,
VariableDeclarator, VariableDeclarator,
Value, Expr,
Literal, Literal,
PipeSubstitution, PipeSubstitution,
Identifier, Identifier,
@ -195,10 +195,7 @@ export function findUniqueName(
return findUniqueName(searchStr, name, pad, index + 1) return findUniqueName(searchStr, name, pad, index + 1)
} }
export function mutateArrExp( export function mutateArrExp(node: Expr, updateWith: ArrayExpression): boolean {
node: Value,
updateWith: ArrayExpression
): boolean {
if (node.type === 'ArrayExpression') { if (node.type === 'ArrayExpression') {
node.elements.forEach((element, i) => { node.elements.forEach((element, i) => {
if (isLiteralArrayOrStatic(element)) { if (isLiteralArrayOrStatic(element)) {
@ -211,7 +208,7 @@ export function mutateArrExp(
} }
export function mutateObjExpProp( export function mutateObjExpProp(
node: Value, node: Expr,
updateWith: Literal | ArrayExpression, updateWith: Literal | ArrayExpression,
key: string key: string
): boolean { ): boolean {
@ -254,7 +251,7 @@ export function extrudeSketch(
node: Program, node: Program,
pathToNode: PathToNode, pathToNode: PathToNode,
shouldPipe = false, shouldPipe = false,
distance = createLiteral(4) as Value distance = createLiteral(4) as Expr
): ):
| { | {
modifiedAst: Program modifiedAst: Program
@ -608,7 +605,7 @@ export function createVariableDeclaration(
} }
export function createObjectExpression(properties: { export function createObjectExpression(properties: {
[key: string]: Value [key: string]: Expr
}): ObjectExpression { }): ObjectExpression {
return { return {
type: 'ObjectExpression', type: 'ObjectExpression',

View File

@ -3,7 +3,7 @@ import {
recast, recast,
initPromise, initPromise,
PathToNode, PathToNode,
Value, Expr,
Program, Program,
CallExpression, CallExpression,
} from '../wasm' } from '../wasm'
@ -25,7 +25,7 @@ const runFilletTest = async (
code: string, code: string,
segmentSnippet: string, segmentSnippet: string,
extrudeSnippet: string, extrudeSnippet: string,
radius = createLiteral(5) as Value, radius = createLiteral(5) as Expr,
expectedCode: string expectedCode: string
) => { ) => {
const astOrError = parse(code) const astOrError = parse(code)
@ -57,7 +57,7 @@ const runFilletTest = async (
return new Error('Path to extrude node not found') return new Error('Path to extrude node not found')
} }
// const radius = createLiteral(5) as Value // const radius = createLiteral(5) as Expr
const result = addFillet(ast, pathToSegmentNode, pathToExtrudeNode, radius) const result = addFillet(ast, pathToSegmentNode, pathToExtrudeNode, radius)
if (err(result)) { if (err(result)) {
@ -90,7 +90,7 @@ describe('Testing addFillet', () => {
` `
const segmentSnippet = `line([60.04, -55.72], %)` const segmentSnippet = `line([60.04, -55.72], %)`
const extrudeSnippet = `const extrude001 = extrude(50, sketch001)` const extrudeSnippet = `const extrude001 = extrude(50, sketch001)`
const radius = createLiteral(5) as Value const radius = createLiteral(5) as Expr
const expectedCode = `const sketch001 = startSketchOn('XZ') const expectedCode = `const sketch001 = startSketchOn('XZ')
|> startProfileAt([2.16, 49.67], %) |> startProfileAt([2.16, 49.67], %)
|> line([101.49, 139.93], %) |> line([101.49, 139.93], %)
@ -133,7 +133,7 @@ const extrude001 = extrude(50, sketch001)
` `
const segmentSnippet = `line([60.04, -55.72], %)` const segmentSnippet = `line([60.04, -55.72], %)`
const extrudeSnippet = `const extrude001 = extrude(50, sketch001)` const extrudeSnippet = `const extrude001 = extrude(50, sketch001)`
const radius = createLiteral(5) as Value const radius = createLiteral(5) as Expr
const expectedCode = `const sketch001 = startSketchOn('XZ') const expectedCode = `const sketch001 = startSketchOn('XZ')
|> startProfileAt([2.16, 49.67], %) |> startProfileAt([2.16, 49.67], %)
|> line([101.49, 139.93], %) |> line([101.49, 139.93], %)
@ -176,7 +176,7 @@ const extrude001 = extrude(50, sketch001)
` `
const segmentSnippet = `line([-87.24, -47.08], %, $seg03)` const segmentSnippet = `line([-87.24, -47.08], %, $seg03)`
const extrudeSnippet = `const extrude001 = extrude(50, sketch001)` const extrudeSnippet = `const extrude001 = extrude(50, sketch001)`
const radius = createLiteral(5) as Value const radius = createLiteral(5) as Expr
const expectedCode = `const sketch001 = startSketchOn('XZ') const expectedCode = `const sketch001 = startSketchOn('XZ')
|> startProfileAt([2.16, 49.67], %) |> startProfileAt([2.16, 49.67], %)
|> line([101.49, 139.93], %) |> line([101.49, 139.93], %)
@ -218,7 +218,7 @@ const extrude001 = extrude(50, sketch001)
|> fillet({ radius: 10, tags: [seg03] }, %)` |> fillet({ radius: 10, tags: [seg03] }, %)`
const segmentSnippet = `line([60.04, -55.72], %)` const segmentSnippet = `line([60.04, -55.72], %)`
const extrudeSnippet = `const extrude001 = extrude(50, sketch001)` const extrudeSnippet = `const extrude001 = extrude(50, sketch001)`
const radius = createLiteral(5) as Value const radius = createLiteral(5) as Expr
const expectedCode = `const sketch001 = startSketchOn('XZ') const expectedCode = `const sketch001 = startSketchOn('XZ')
|> startProfileAt([2.16, 49.67], %) |> startProfileAt([2.16, 49.67], %)
|> line([101.49, 139.93], %) |> line([101.49, 139.93], %)

View File

@ -4,7 +4,7 @@ import {
ObjectExpression, ObjectExpression,
PathToNode, PathToNode,
Program, Program,
Value, Expr,
VariableDeclaration, VariableDeclaration,
VariableDeclarator, VariableDeclarator,
} from '../wasm' } from '../wasm'
@ -35,7 +35,7 @@ export function addFillet(
node: Program, node: Program,
pathToSegmentNode: PathToNode, pathToSegmentNode: PathToNode,
pathToExtrudeNode: PathToNode, pathToExtrudeNode: PathToNode,
radius = createLiteral(5) as Value radius = createLiteral(5) as Expr
// shouldPipe = false, // TODO: Implement this feature // shouldPipe = false, // TODO: Implement this feature
): { modifiedAst: Program; pathToFilletNode: PathToNode } | Error { ): { modifiedAst: Program; pathToFilletNode: PathToNode } | Error {
// clone ast to make mutations safe // clone ast to make mutations safe

View File

@ -13,7 +13,7 @@ import {
SketchGroup, SketchGroup,
SourceRange, SourceRange,
SyntaxType, SyntaxType,
Value, Expr,
VariableDeclaration, VariableDeclaration,
VariableDeclarator, VariableDeclarator,
} from './wasm' } from './wasm'
@ -118,7 +118,7 @@ export function getNodeFromPathCurry(
} }
function moreNodePathFromSourceRange( function moreNodePathFromSourceRange(
node: Value | ExpressionStatement | VariableDeclaration | ReturnStatement, node: Expr | ExpressionStatement | VariableDeclaration | ReturnStatement,
sourceRange: Selection['range'], sourceRange: Selection['range'],
previousPath: PathToNode = [['body', '']] previousPath: PathToNode = [['body', '']]
): PathToNode { ): PathToNode {
@ -337,7 +337,7 @@ export function getNodePathFromSourceRange(
} }
type KCLNode = type KCLNode =
| Value | Expr
| ExpressionStatement | ExpressionStatement
| VariableDeclaration | VariableDeclaration
| VariableDeclarator | VariableDeclarator
@ -514,7 +514,7 @@ export function isNodeSafeToReplacePath(
): ):
| { | {
isSafe: boolean isSafe: boolean
value: Value value: Expr
replacer: ReplacerFn replacer: ReplacerFn
} }
| Error { | Error {
@ -538,7 +538,7 @@ export function isNodeSafeToReplacePath(
// binaryExpression should take precedence // binaryExpression should take precedence
const [finVal, finPath] = const [finVal, finPath] =
(binValue as Value)?.type === 'BinaryExpression' (binValue as Expr)?.type === 'BinaryExpression'
? [binValue, outBinPath] ? [binValue, outBinPath]
: [value, outPath] : [value, outPath]
@ -561,7 +561,7 @@ export function isNodeSafeToReplacePath(
return { modifiedAst: _ast, pathToReplaced } return { modifiedAst: _ast, pathToReplaced }
} }
const hasPipeSub = isTypeInValue(finVal as Value, 'PipeSubstitution') const hasPipeSub = isTypeInValue(finVal as Expr, 'PipeSubstitution')
const isIdentifierCallee = path[path.length - 1][0] !== 'callee' const isIdentifierCallee = path[path.length - 1][0] !== 'callee'
return { return {
isSafe: isSafe:
@ -569,7 +569,7 @@ export function isNodeSafeToReplacePath(
isIdentifierCallee && isIdentifierCallee &&
acceptedNodeTypes.includes((finVal as any)?.type) && acceptedNodeTypes.includes((finVal as any)?.type) &&
finPath.map(([_, type]) => type).includes('VariableDeclaration'), finPath.map(([_, type]) => type).includes('VariableDeclaration'),
value: finVal as Value, value: finVal as Expr,
replacer: replaceNodeWithIdentifier, replacer: replaceNodeWithIdentifier,
} }
} }
@ -580,7 +580,7 @@ export function isNodeSafeToReplace(
): ):
| { | {
isSafe: boolean isSafe: boolean
value: Value value: Expr
replacer: ReplacerFn replacer: ReplacerFn
} }
| Error { | Error {
@ -588,7 +588,7 @@ export function isNodeSafeToReplace(
return isNodeSafeToReplacePath(ast, path) return isNodeSafeToReplacePath(ast, path)
} }
export function isTypeInValue(node: Value, syntaxType: SyntaxType): boolean { export function isTypeInValue(node: Expr, syntaxType: SyntaxType): boolean {
if (node.type === syntaxType) return true if (node.type === syntaxType) return true
if (node.type === 'BinaryExpression') return isTypeInBinExp(node, syntaxType) if (node.type === 'BinaryExpression') return isTypeInBinExp(node, syntaxType)
if (node.type === 'CallExpression') return isTypeInCallExp(node, syntaxType) if (node.type === 'CallExpression') return isTypeInCallExp(node, syntaxType)
@ -625,7 +625,7 @@ function isTypeInArrayExp(
return node.elements.some((el) => isTypeInValue(el, syntaxType)) return node.elements.some((el) => isTypeInValue(el, syntaxType))
} }
export function isValueZero(val?: Value): boolean { export function isValueZero(val?: Expr): boolean {
return ( return (
(val?.type === 'Literal' && Number(val.value) === 0) || (val?.type === 'Literal' && Number(val.value) === 0) ||
(val?.type === 'UnaryExpression' && (val?.type === 'UnaryExpression' &&

View File

@ -8,7 +8,7 @@ import {
PipeExpression, PipeExpression,
CallExpression, CallExpression,
VariableDeclarator, VariableDeclarator,
Value, Expr,
Literal, Literal,
VariableDeclaration, VariableDeclaration,
Identifier, Identifier,
@ -72,8 +72,8 @@ export function getCoordsFromPaths(skGroup: SketchGroup, index = 0): Coords2d {
export function createFirstArg( export function createFirstArg(
sketchFn: ToolTip, sketchFn: ToolTip,
val: Value | [Value, Value] | [Value, Value, Value] val: Expr | [Expr, Expr] | [Expr, Expr, Expr]
): Value | Error { ): Expr | Error {
if (Array.isArray(val)) { if (Array.isArray(val)) {
if ( if (
[ [
@ -338,7 +338,7 @@ export const lineTo: SketchLineHelper = {
if (err(nodeMeta)) return nodeMeta if (err(nodeMeta)) return nodeMeta
const { node: pipe } = nodeMeta const { node: pipe } = nodeMeta
const newVals: [Value, Value] = [ const newVals: [Expr, Expr] = [
createLiteral(roundOff(to[0], 2)), createLiteral(roundOff(to[0], 2)),
createLiteral(roundOff(to[1], 2)), createLiteral(roundOff(to[1], 2)),
] ]
@ -1839,7 +1839,7 @@ export function getTagFromCallExpression(
return new Error(`"${callExp.callee.name}" is not a sketch line helper`) return new Error(`"${callExp.callee.name}" is not a sketch line helper`)
} }
function isAngleLiteral(lineArugement: Value): boolean { function isAngleLiteral(lineArugement: Expr): boolean {
return lineArugement?.type === 'ArrayExpression' return lineArugement?.type === 'ArrayExpression'
? isLiteralArrayOrStatic(lineArugement.elements[0]) ? isLiteralArrayOrStatic(lineArugement.elements[0])
: lineArugement?.type === 'ObjectExpression' : lineArugement?.type === 'ObjectExpression'
@ -1907,8 +1907,8 @@ export function getXComponent(
function getFirstArgValuesForXYFns(callExpression: CallExpression): function getFirstArgValuesForXYFns(callExpression: CallExpression):
| { | {
val: [Value, Value] val: [Expr, Expr]
tag?: Value tag?: Expr
} }
| Error { | Error {
// used for lineTo, line // used for lineTo, line
@ -1929,8 +1929,8 @@ function getFirstArgValuesForXYFns(callExpression: CallExpression):
function getFirstArgValuesForAngleFns(callExpression: CallExpression): function getFirstArgValuesForAngleFns(callExpression: CallExpression):
| { | {
val: [Value, Value] val: [Expr, Expr]
tag?: Value tag?: Expr
} }
| Error { | Error {
// used for angledLine, angledLineOfXLength, angledLineToX, angledLineOfYLength, angledLineToY // used for angledLine, angledLineOfXLength, angledLineToX, angledLineOfYLength, angledLineToY
@ -1957,8 +1957,8 @@ function getFirstArgValuesForAngleFns(callExpression: CallExpression):
} }
function getFirstArgValuesForXYLineFns(callExpression: CallExpression): { function getFirstArgValuesForXYLineFns(callExpression: CallExpression): {
val: Value val: Expr
tag?: Value tag?: Expr
} { } {
// used for xLine, yLine, xLineTo, yLineTo // used for xLine, yLine, xLineTo, yLineTo
const firstArg = callExpression.arguments[0] const firstArg = callExpression.arguments[0]
@ -1988,8 +1988,8 @@ const getAngledLineThatIntersects = (
callExp: CallExpression callExp: CallExpression
): ):
| { | {
val: [Value, Value, Value] val: [Expr, Expr, Expr]
tag?: Value tag?: Expr
} }
| Error => { | Error => {
const firstArg = callExp.arguments[0] const firstArg = callExp.arguments[0]
@ -2011,8 +2011,8 @@ const getAngledLineThatIntersects = (
export function getFirstArg(callExp: CallExpression): export function getFirstArg(callExp: CallExpression):
| { | {
val: Value | [Value, Value] | [Value, Value, Value] val: Expr | [Expr, Expr] | [Expr, Expr, Expr]
tag?: Value tag?: Expr
} }
| Error { | Error {
const name = callExp?.callee?.name const name = callExp?.callee?.name

View File

@ -8,7 +8,7 @@ import {
SourceRange, SourceRange,
Path, Path,
PathToNode, PathToNode,
Value, Expr,
} from '../wasm' } from '../wasm'
import { err } from 'lib/trap' import { err } from 'lib/trap'
@ -25,7 +25,7 @@ export function getSketchSegmentFromPathToNode(
// TODO: once pathTodNode is stored on program memory as part of execution, // TODO: once pathTodNode is stored on program memory as part of execution,
// we can check if the pathToNode matches the pathToNode of the sketchGroup. // we can check if the pathToNode matches the pathToNode of the sketchGroup.
// For now we fall back to the sourceRange // For now we fall back to the sourceRange
const nodeMeta = getNodeFromPath<Value>(ast, pathToNode) const nodeMeta = getNodeFromPath<Expr>(ast, pathToNode)
if (err(nodeMeta)) return nodeMeta if (err(nodeMeta)) return nodeMeta
const node = nodeMeta.node const node = nodeMeta.node

View File

@ -1,4 +1,4 @@
import { parse, Value, recast, initPromise } from '../wasm' import { parse, Expr, recast, initPromise } from '../wasm'
import { import {
getConstraintType, getConstraintType,
getTransformInfos, getTransformInfos,
@ -69,8 +69,8 @@ function getConstraintTypeFromSourceHelper(
if (err(ast)) return ast if (err(ast)) return ast
const args = (ast.body[0] as any).expression.arguments[0].elements as [ const args = (ast.body[0] as any).expression.arguments[0].elements as [
Value, Expr,
Value Expr
] ]
const fnName = (ast.body[0] as any).expression.callee.name as ToolTip const fnName = (ast.body[0] as any).expression.callee.name as ToolTip
return getConstraintType(args, fnName) return getConstraintType(args, fnName)
@ -81,7 +81,7 @@ function getConstraintTypeFromSourceHelper2(
const ast = parse(code) const ast = parse(code)
if (err(ast)) return ast if (err(ast)) return ast
const arg = (ast.body[0] as any).expression.arguments[0] as Value const arg = (ast.body[0] as any).expression.arguments[0] as Expr
const fnName = (ast.body[0] as any).expression.callee.name as ToolTip const fnName = (ast.body[0] as any).expression.callee.name as ToolTip
return getConstraintType(arg, fnName) return getConstraintType(arg, fnName)
} }

View File

@ -5,7 +5,7 @@ import { cleanErrs, err } from 'lib/trap'
import { import {
CallExpression, CallExpression,
Program, Program,
Value, Expr,
BinaryPart, BinaryPart,
VariableDeclarator, VariableDeclarator,
PathToNode, PathToNode,
@ -68,8 +68,8 @@ export type ConstraintType =
function createCallWrapper( function createCallWrapper(
a: ToolTip, a: ToolTip,
val: [Value, Value] | Value, val: [Expr, Expr] | Expr,
tag?: Value, tag?: Expr,
valueUsedInTransform?: number valueUsedInTransform?: number
): ReturnType<TransformCallback> { ): ReturnType<TransformCallback> {
const args = [createFirstArg(a, val), createPipeSubstitution()] const args = [createFirstArg(a, val), createPipeSubstitution()]
@ -103,8 +103,8 @@ function createCallWrapper(
*/ */
function createStdlibCallExpression( function createStdlibCallExpression(
tool: ToolTip, tool: ToolTip,
val: Value, val: Expr,
tag?: Value, tag?: Expr,
valueUsedInTransform?: number valueUsedInTransform?: number
): ReturnType<TransformCallback> { ): ReturnType<TransformCallback> {
const args = [val, createPipeSubstitution()] const args = [val, createPipeSubstitution()]
@ -126,10 +126,10 @@ function intersectCallWrapper({
valueUsedInTransform, valueUsedInTransform,
}: { }: {
fnName: string fnName: string
angleVal: Value angleVal: Expr
offsetVal: Value offsetVal: Expr
intersectTag: Value intersectTag: Expr
tag?: Value tag?: Expr
valueUsedInTransform?: number valueUsedInTransform?: number
}): ReturnType<TransformCallback> { }): ReturnType<TransformCallback> {
const firstArg: any = { const firstArg: any = {
@ -137,7 +137,7 @@ function intersectCallWrapper({
offset: offsetVal, offset: offsetVal,
intersectTag, intersectTag,
} }
const args: Value[] = [ const args: Expr[] = [
createObjectExpression(firstArg), createObjectExpression(firstArg),
createPipeSubstitution(), createPipeSubstitution(),
] ]
@ -154,11 +154,11 @@ export type TransformInfo = {
tooltip: ToolTip tooltip: ToolTip
createNode: (a: { createNode: (a: {
varValues: VarValues varValues: VarValues
varValA: Value // x / angle varValA: Expr // x / angle
varValB: Value // y / length or x y for angledLineOfXlength etc varValB: Expr // y / length or x y for angledLineOfXlength etc
referenceSegName: string referenceSegName: string
tag?: Value tag?: Expr
forceValueUsedInTransform?: Value forceValueUsedInTransform?: Expr
}) => TransformCallback }) => TransformCallback
} }
@ -234,8 +234,8 @@ const angledLineAngleCreateNode: TransformInfo['createNode'] =
const getMinAndSegLenVals = ( const getMinAndSegLenVals = (
referenceSegName: string, referenceSegName: string,
varVal: Value varVal: Expr
): [Value, BinaryPart] => { ): [Expr, BinaryPart] => {
const segLenVal = createSegLen(referenceSegName) const segLenVal = createSegLen(referenceSegName)
return [ return [
createCallExpression('min', [segLenVal, varVal]), createCallExpression('min', [segLenVal, varVal]),
@ -245,9 +245,9 @@ const getMinAndSegLenVals = (
const getMinAndSegAngVals = ( const getMinAndSegAngVals = (
referenceSegName: string, referenceSegName: string,
varVal: Value, varVal: Expr,
fnName: 'legAngX' | 'legAngY' = 'legAngX' fnName: 'legAngX' | 'legAngY' = 'legAngX'
): [Value, BinaryPart] => { ): [Expr, BinaryPart] => {
const minVal = createCallExpression('min', [ const minVal = createCallExpression('min', [
createSegLen(referenceSegName), createSegLen(referenceSegName),
varVal, varVal,
@ -259,12 +259,12 @@ const getMinAndSegAngVals = (
return [minVal, legAngle] return [minVal, legAngle]
} }
const getSignedLeg = (arg: Value, legLenVal: BinaryPart) => const getSignedLeg = (arg: Expr, legLenVal: BinaryPart) =>
arg.type === 'Literal' && Number(arg.value) < 0 arg.type === 'Literal' && Number(arg.value) < 0
? createUnaryExpression(legLenVal) ? createUnaryExpression(legLenVal)
: legLenVal : legLenVal
const getLegAng = (arg: Value, legAngleVal: BinaryPart) => { const getLegAng = (arg: Expr, legAngleVal: BinaryPart) => {
const ang = (arg.type === 'Literal' && Number(arg.value)) || 0 const ang = (arg.type === 'Literal' && Number(arg.value)) || 0
const normalisedAngle = ((ang % 360) + 360) % 360 // between 0 and 360 const normalisedAngle = ((ang % 360) + 360) % 360 // between 0 and 360
const truncatedTo90 = Math.floor(normalisedAngle / 90) * 90 const truncatedTo90 = Math.floor(normalisedAngle / 90) * 90
@ -275,14 +275,14 @@ const getLegAng = (arg: Value, legAngleVal: BinaryPart) => {
return truncatedTo90 === 0 ? legAngleVal : binExp return truncatedTo90 === 0 ? legAngleVal : binExp
} }
const getAngleLengthSign = (arg: Value, legAngleVal: BinaryPart) => { const getAngleLengthSign = (arg: Expr, legAngleVal: BinaryPart) => {
const ang = (arg.type === 'Literal' && Number(arg.value)) || 0 const ang = (arg.type === 'Literal' && Number(arg.value)) || 0
const normalisedAngle = ((ang % 180) + 180) % 180 // between 0 and 180 const normalisedAngle = ((ang % 180) + 180) % 180 // between 0 and 180
return normalisedAngle > 90 ? createUnaryExpression(legAngleVal) : legAngleVal return normalisedAngle > 90 ? createUnaryExpression(legAngleVal) : legAngleVal
} }
function getClosesAngleDirection( function getClosesAngleDirection(
arg: Value, arg: Expr,
refAngle: number, refAngle: number,
angleVal: BinaryPart angleVal: BinaryPart
) { ) {
@ -305,7 +305,7 @@ const setHorzVertDistanceCreateNode =
getArgLiteralVal(args?.[index]) - (referencedSegment?.to?.[index] || 0), getArgLiteralVal(args?.[index]) - (referencedSegment?.to?.[index] || 0),
2 2
) )
let finalValue: Value = createBinaryExpressionWithUnary([ let finalValue: Expr = createBinaryExpressionWithUnary([
createSegEnd(referenceSegName, !index), createSegEnd(referenceSegName, !index),
(forceValueUsedInTransform as BinaryPart) || (forceValueUsedInTransform as BinaryPart) ||
createLiteral(valueUsedInTransform), createLiteral(valueUsedInTransform),
@ -1374,7 +1374,7 @@ export function getTransformInfo(
} }
export function getConstraintType( export function getConstraintType(
val: Value | [Value, Value] | [Value, Value, Value], val: Expr | [Expr, Expr] | [Expr, Expr, Expr],
fnName: ToolTip fnName: ToolTip
): LineInputsType | null { ): LineInputsType | null {
// this function assumes that for two val sketch functions that one arg is locked down not both // this function assumes that for two val sketch functions that one arg is locked down not both
@ -1416,7 +1416,7 @@ export function getTransformInfos(
getNodePathFromSourceRange(ast, range) getNodePathFromSourceRange(ast, range)
) )
const nodes = paths.map((pathToNode) => const nodes = paths.map((pathToNode) =>
getNodeFromPath<Value>(ast, pathToNode, 'CallExpression') getNodeFromPath<Expr>(ast, pathToNode, 'CallExpression')
) )
try { try {
@ -1449,7 +1449,7 @@ export function getRemoveConstraintsTransforms(
getNodePathFromSourceRange(ast, selectionRange.range) getNodePathFromSourceRange(ast, selectionRange.range)
) )
const nodes = paths.map((pathToNode) => const nodes = paths.map((pathToNode) =>
getNodeFromPath<Value>(ast, pathToNode) getNodeFromPath<Expr>(ast, pathToNode)
) )
const theTransforms = nodes.map((nodeMeta) => { const theTransforms = nodes.map((nodeMeta) => {
@ -1484,7 +1484,7 @@ export function transformSecondarySketchLinesTagFirst({
transformInfos: TransformInfo[] transformInfos: TransformInfo[]
programMemory: ProgramMemory programMemory: ProgramMemory
forceSegName?: string forceSegName?: string
forceValueUsedInTransform?: Value forceValueUsedInTransform?: Expr
}): }):
| { | {
modifiedAst: Program modifiedAst: Program
@ -1555,7 +1555,7 @@ export function transformAstSketchLines({
transformInfos: TransformInfo[] transformInfos: TransformInfo[]
programMemory: ProgramMemory programMemory: ProgramMemory
referenceSegName: string referenceSegName: string
forceValueUsedInTransform?: Value forceValueUsedInTransform?: Expr
referencedSegmentRange?: Selection['range'] referencedSegmentRange?: Selection['range']
}): }):
| { | {
@ -1609,7 +1609,7 @@ export function transformAstSketchLines({
) )
return return
const nodeMeta = getNodeFromPath<Value>(ast, a.pathToNode) const nodeMeta = getNodeFromPath<Expr>(ast, a.pathToNode)
if (err(nodeMeta)) return if (err(nodeMeta)) return
if (a?.argPosition?.type === 'arrayItem') { if (a?.argPosition?.type === 'arrayItem') {
@ -1712,11 +1712,11 @@ export function transformAstSketchLines({
} }
} }
function createSegLen(referenceSegName: string): Value { function createSegLen(referenceSegName: string): Expr {
return createCallExpression('segLen', [createIdentifier(referenceSegName)]) return createCallExpression('segLen', [createIdentifier(referenceSegName)])
} }
function createSegAngle(referenceSegName: string): Value { function createSegAngle(referenceSegName: string): Expr {
return createCallExpression('segAng', [createIdentifier(referenceSegName)]) return createCallExpression('segAng', [createIdentifier(referenceSegName)])
} }
@ -1732,7 +1732,7 @@ function createLastSeg(isX: boolean): CallExpression {
]) ])
} }
function getArgLiteralVal(arg: Value): number { function getArgLiteralVal(arg: Expr): number {
return arg?.type === 'Literal' ? Number(arg.value) : 0 return arg?.type === 'Literal' ? Number(arg.value) : 0
} }
@ -1776,7 +1776,7 @@ export function getConstraintLevelFromSourceRange(
} }
export function isLiteralArrayOrStatic( export function isLiteralArrayOrStatic(
val: Value | [Value, Value] | [Value, Value, Value] | undefined val: Expr | [Expr, Expr] | [Expr, Expr, Expr] | undefined
): boolean { ): boolean {
if (!val) return false if (!val) return false
@ -1792,7 +1792,7 @@ export function isLiteralArrayOrStatic(
} }
export function isNotLiteralArrayOrStatic( export function isNotLiteralArrayOrStatic(
val: Value | [Value, Value] | [Value, Value, Value] val: Expr | [Expr, Expr] | [Expr, Expr, Expr]
): boolean { ): boolean {
if (Array.isArray(val)) { if (Array.isArray(val)) {
const a = val[0] const a = val[0]

View File

@ -4,7 +4,7 @@ import {
Path, Path,
SourceRange, SourceRange,
Program, Program,
Value, Expr,
PathToNode, PathToNode,
CallExpression, CallExpression,
Literal, Literal,
@ -85,7 +85,7 @@ export type _VarValue<T> =
| ObjectPropertyInput<T> | ObjectPropertyInput<T>
| ArrayOrObjItemInput<T> | ArrayOrObjItemInput<T>
export type VarValue = _VarValue<Value> export type VarValue = _VarValue<Expr>
export type RawValue = _VarValue<Literal> export type RawValue = _VarValue<Literal>
export type VarValues = Array<VarValue> export type VarValues = Array<VarValue>
@ -99,11 +99,11 @@ type SimplifiedVarValue =
| { type: 'objectProperty'; key: VarValueKeys } | { type: 'objectProperty'; key: VarValueKeys }
export type TransformCallback = ( export type TransformCallback = (
args: [Value, Value], args: [Expr, Expr],
literalValues: RawValues, literalValues: RawValues,
referencedSegment?: Path referencedSegment?: Path
) => { ) => {
callExp: Value callExp: Expr
valueUsedInTransform?: number valueUsedInTransform?: number
} }

View File

@ -39,7 +39,7 @@ import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute'
import { err } from 'lib/trap' import { err } from 'lib/trap'
export type { Program } from '../wasm-lib/kcl/bindings/Program' export type { Program } from '../wasm-lib/kcl/bindings/Program'
export type { Value } from '../wasm-lib/kcl/bindings/Value' export type { Expr } from '../wasm-lib/kcl/bindings/Expr'
export type { ObjectExpression } from '../wasm-lib/kcl/bindings/ObjectExpression' export type { ObjectExpression } from '../wasm-lib/kcl/bindings/ObjectExpression'
export type { MemberExpression } from '../wasm-lib/kcl/bindings/MemberExpression' export type { MemberExpression } from '../wasm-lib/kcl/bindings/MemberExpression'
export type { PipeExpression } from '../wasm-lib/kcl/bindings/PipeExpression' export type { PipeExpression } from '../wasm-lib/kcl/bindings/PipeExpression'

View File

@ -7,7 +7,7 @@ import {
InterpreterFrom, InterpreterFrom,
} from 'xstate' } from 'xstate'
import { Selection } from './selections' import { Selection } from './selections'
import { Identifier, Value, VariableDeclaration } from 'lang/wasm' import { Identifier, Expr, VariableDeclaration } from 'lang/wasm'
import { commandBarMachine } from 'machines/commandBarMachine' import { commandBarMachine } from 'machines/commandBarMachine'
type Icon = CustomIconName type Icon = CustomIconName
@ -20,7 +20,7 @@ const INPUT_TYPES = [
'boolean', 'boolean',
] as const ] as const
export interface KclExpression { export interface KclExpression {
valueAst: Value valueAst: Expr
valueText: string valueText: string
valueCalculated: string valueCalculated: string
} }

View File

@ -5,7 +5,7 @@ import {
kclManager, kclManager,
sceneEntitiesManager, sceneEntitiesManager,
} from 'lib/singletons' } from 'lib/singletons'
import { CallExpression, SourceRange, Value, parse, recast } from 'lang/wasm' import { CallExpression, SourceRange, Expr, parse, recast } from 'lang/wasm'
import { ModelingMachineEvent } from 'machines/modelingMachine' import { ModelingMachineEvent } from 'machines/modelingMachine'
import { uuidv4 } from 'lib/utils' import { uuidv4 } from 'lib/utils'
import { EditorSelection, SelectionRange } from '@codemirror/state' import { EditorSelection, SelectionRange } from '@codemirror/state'
@ -639,7 +639,7 @@ export function updateSelections(
const newSelections = Object.entries(pathToNodeMap) const newSelections = Object.entries(pathToNodeMap)
.map(([index, pathToNode]): Selection | undefined => { .map(([index, pathToNode]): Selection | undefined => {
const nodeMeta = getNodeFromPath<Value>(ast, pathToNode) const nodeMeta = getNodeFromPath<Expr>(ast, pathToNode)
if (err(nodeMeta)) return undefined if (err(nodeMeta)) return undefined
const node = nodeMeta.node const node = nodeMeta.node
return { return {

View File

@ -3,7 +3,7 @@ import { kclManager, engineCommandManager } from 'lib/singletons'
import { useKclContext } from 'lang/KclProvider' import { useKclContext } from 'lang/KclProvider'
import { findUniqueName } from 'lang/modifyAst' import { findUniqueName } from 'lang/modifyAst'
import { PrevVariable, findAllPreviousVariables } from 'lang/queryAst' import { PrevVariable, findAllPreviousVariables } from 'lang/queryAst'
import { ProgramMemory, Value, parse } from 'lang/wasm' import { ProgramMemory, Expr, parse } from 'lang/wasm'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { executeAst } from 'lang/langHelpers' import { executeAst } from 'lang/langHelpers'
import { err, trap } from 'lib/trap' import { err, trap } from 'lib/trap'
@ -24,7 +24,7 @@ export function useCalculateKclExpression({
initialVariableName?: string initialVariableName?: string
}): { }): {
inputRef: React.RefObject<HTMLInputElement> inputRef: React.RefObject<HTMLInputElement>
valueNode: Value | null valueNode: Expr | null
calcResult: string calcResult: string
prevVariables: PrevVariable<unknown>[] prevVariables: PrevVariable<unknown>[]
newVariableName: string newVariableName: string
@ -45,7 +45,7 @@ export function useCalculateKclExpression({
insertIndex: 0, insertIndex: 0,
bodyPath: [], bodyPath: [],
}) })
const [valueNode, setValueNode] = useState<Value | null>(null) const [valueNode, setValueNode] = useState<Expr | null>(null)
const [calcResult, setCalcResult] = useState('NAN') const [calcResult, setCalcResult] = useState('NAN')
const [newVariableName, setNewVariableName] = useState('') const [newVariableName, setNewVariableName] = useState('')
const [isNewVariableNameUnique, setIsNewVariableNameUnique] = useState(true) const [isNewVariableNameUnique, setIsNewVariableNameUnique] = useState(true)

View File

@ -1,6 +1,6 @@
extern crate alloc; extern crate alloc;
use kcl_lib::ast::types::{ use kcl_lib::ast::types::{
BodyItem, Identifier, Literal, LiteralValue, NonCodeMeta, Program, Value, VariableDeclaration, VariableDeclarator, BodyItem, Expr, Identifier, Literal, LiteralValue, NonCodeMeta, Program, VariableDeclaration, VariableDeclarator,
VariableKind, VariableKind,
}; };
use kcl_macros::parse; use kcl_macros::parse;
@ -24,7 +24,7 @@ fn basic() {
name: "y".to_owned(), name: "y".to_owned(),
digest: None, digest: None,
}, },
init: Value::Literal(Box::new(Literal { init: Expr::Literal(Box::new(Literal {
start: 10, start: 10,
end: 11, end: 11,
value: LiteralValue::IInteger(4), value: LiteralValue::IInteger(4),

View File

@ -266,7 +266,7 @@ impl Program {
/// Returns a value that includes the given character position. /// Returns a value that includes the given character position.
/// This is a bit more recursive than `get_body_item_for_position`. /// This is a bit more recursive than `get_body_item_for_position`.
pub fn get_value_for_position(&self, pos: usize) -> Option<&Value> { pub fn get_value_for_position(&self, pos: usize) -> Option<&Expr> {
let item = self.get_body_item_for_position(pos)?; let item = self.get_body_item_for_position(pos)?;
// Recurse over the item. // Recurse over the item.
@ -389,7 +389,7 @@ impl Program {
}; };
// Check if we have a function expression. // Check if we have a function expression.
if let Some(Value::FunctionExpression(ref mut function_expression)) = &mut value { if let Some(Expr::FunctionExpression(ref mut function_expression)) = &mut value {
// Check if the params to the function expression contain the position. // Check if the params to the function expression contain the position.
for param in &mut function_expression.params { for param in &mut function_expression.params {
let param_source_range: SourceRange = (&param.identifier).into(); let param_source_range: SourceRange = (&param.identifier).into();
@ -444,7 +444,7 @@ impl Program {
} }
/// Replace a value with the new value, use the source range for matching the exact value. /// Replace a value with the new value, use the source range for matching the exact value.
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
for item in &mut self.body { for item in &mut self.body {
match item { match item {
BodyItem::ExpressionStatement(ref mut expression_statement) => expression_statement BodyItem::ExpressionStatement(ref mut expression_statement) => expression_statement
@ -570,11 +570,12 @@ impl From<&BodyItem> for SourceRange {
} }
} }
/// An expression can be evaluated to yield a single KCL value.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)]
#[databake(path = kcl_lib::ast::types)] #[databake(path = kcl_lib::ast::types)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum Value { pub enum Expr {
Literal(Box<Literal>), Literal(Box<Literal>),
Identifier(Box<Identifier>), Identifier(Box<Identifier>),
TagDeclarator(Box<TagDeclarator>), TagDeclarator(Box<TagDeclarator>),
@ -590,22 +591,22 @@ pub enum Value {
None(KclNone), None(KclNone),
} }
impl Value { impl Expr {
pub fn compute_digest(&mut self) -> Digest { pub fn compute_digest(&mut self) -> Digest {
match self { match self {
Value::Literal(lit) => lit.compute_digest(), Expr::Literal(lit) => lit.compute_digest(),
Value::Identifier(id) => id.compute_digest(), Expr::Identifier(id) => id.compute_digest(),
Value::TagDeclarator(tag) => tag.compute_digest(), Expr::TagDeclarator(tag) => tag.compute_digest(),
Value::BinaryExpression(be) => be.compute_digest(), Expr::BinaryExpression(be) => be.compute_digest(),
Value::FunctionExpression(fe) => fe.compute_digest(), Expr::FunctionExpression(fe) => fe.compute_digest(),
Value::CallExpression(ce) => ce.compute_digest(), Expr::CallExpression(ce) => ce.compute_digest(),
Value::PipeExpression(pe) => pe.compute_digest(), Expr::PipeExpression(pe) => pe.compute_digest(),
Value::PipeSubstitution(ps) => ps.compute_digest(), Expr::PipeSubstitution(ps) => ps.compute_digest(),
Value::ArrayExpression(ae) => ae.compute_digest(), Expr::ArrayExpression(ae) => ae.compute_digest(),
Value::ObjectExpression(oe) => oe.compute_digest(), Expr::ObjectExpression(oe) => oe.compute_digest(),
Value::MemberExpression(me) => me.compute_digest(), Expr::MemberExpression(me) => me.compute_digest(),
Value::UnaryExpression(ue) => ue.compute_digest(), Expr::UnaryExpression(ue) => ue.compute_digest(),
Value::None(_) => { Expr::None(_) => {
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
hasher.update(b"Value::None"); hasher.update(b"Value::None");
hasher.finalize().into() hasher.finalize().into()
@ -615,19 +616,19 @@ impl Value {
fn recast(&self, options: &FormatOptions, indentation_level: usize, is_in_pipe: bool) -> String { fn recast(&self, options: &FormatOptions, indentation_level: usize, is_in_pipe: bool) -> String {
match &self { match &self {
Value::BinaryExpression(bin_exp) => bin_exp.recast(options), Expr::BinaryExpression(bin_exp) => bin_exp.recast(options),
Value::ArrayExpression(array_exp) => array_exp.recast(options, indentation_level, is_in_pipe), Expr::ArrayExpression(array_exp) => array_exp.recast(options, indentation_level, is_in_pipe),
Value::ObjectExpression(ref obj_exp) => obj_exp.recast(options, indentation_level, is_in_pipe), Expr::ObjectExpression(ref obj_exp) => obj_exp.recast(options, indentation_level, is_in_pipe),
Value::MemberExpression(mem_exp) => mem_exp.recast(), Expr::MemberExpression(mem_exp) => mem_exp.recast(),
Value::Literal(literal) => literal.recast(), Expr::Literal(literal) => literal.recast(),
Value::FunctionExpression(func_exp) => func_exp.recast(options, indentation_level), Expr::FunctionExpression(func_exp) => func_exp.recast(options, indentation_level),
Value::CallExpression(call_exp) => call_exp.recast(options, indentation_level, is_in_pipe), Expr::CallExpression(call_exp) => call_exp.recast(options, indentation_level, is_in_pipe),
Value::Identifier(ident) => ident.name.to_string(), Expr::Identifier(ident) => ident.name.to_string(),
Value::TagDeclarator(tag) => tag.recast(), Expr::TagDeclarator(tag) => tag.recast(),
Value::PipeExpression(pipe_exp) => pipe_exp.recast(options, indentation_level), Expr::PipeExpression(pipe_exp) => pipe_exp.recast(options, indentation_level),
Value::UnaryExpression(unary_exp) => unary_exp.recast(options), Expr::UnaryExpression(unary_exp) => unary_exp.recast(options),
Value::PipeSubstitution(_) => crate::parser::PIPE_SUBSTITUTION_OPERATOR.to_string(), Expr::PipeSubstitution(_) => crate::parser::PIPE_SUBSTITUTION_OPERATOR.to_string(),
Value::None(_) => { Expr::None(_) => {
unimplemented!("there is no literal None, see https://github.com/KittyCAD/modeling-app/issues/1115") unimplemented!("there is no literal None, see https://github.com/KittyCAD/modeling-app/issues/1115")
} }
} }
@ -656,78 +657,78 @@ impl Value {
// Get the non code meta for the value. // Get the non code meta for the value.
pub fn get_non_code_meta(&self) -> Option<&NonCodeMeta> { pub fn get_non_code_meta(&self) -> Option<&NonCodeMeta> {
match self { match self {
Value::BinaryExpression(_bin_exp) => None, Expr::BinaryExpression(_bin_exp) => None,
Value::ArrayExpression(_array_exp) => None, Expr::ArrayExpression(_array_exp) => None,
Value::ObjectExpression(_obj_exp) => None, Expr::ObjectExpression(_obj_exp) => None,
Value::MemberExpression(_mem_exp) => None, Expr::MemberExpression(_mem_exp) => None,
Value::Literal(_literal) => None, Expr::Literal(_literal) => None,
Value::FunctionExpression(_func_exp) => None, Expr::FunctionExpression(_func_exp) => None,
Value::CallExpression(_call_exp) => None, Expr::CallExpression(_call_exp) => None,
Value::Identifier(_ident) => None, Expr::Identifier(_ident) => None,
Value::TagDeclarator(_tag) => None, Expr::TagDeclarator(_tag) => None,
Value::PipeExpression(pipe_exp) => Some(&pipe_exp.non_code_meta), Expr::PipeExpression(pipe_exp) => Some(&pipe_exp.non_code_meta),
Value::UnaryExpression(_unary_exp) => None, Expr::UnaryExpression(_unary_exp) => None,
Value::PipeSubstitution(_pipe_substitution) => None, Expr::PipeSubstitution(_pipe_substitution) => None,
Value::None(_none) => None, Expr::None(_none) => None,
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
if source_range == self.clone().into() { if source_range == self.clone().into() {
*self = new_value; *self = new_value;
return; return;
} }
match self { match self {
Value::BinaryExpression(ref mut bin_exp) => bin_exp.replace_value(source_range, new_value), Expr::BinaryExpression(ref mut bin_exp) => bin_exp.replace_value(source_range, new_value),
Value::ArrayExpression(ref mut array_exp) => array_exp.replace_value(source_range, new_value), Expr::ArrayExpression(ref mut array_exp) => array_exp.replace_value(source_range, new_value),
Value::ObjectExpression(ref mut obj_exp) => obj_exp.replace_value(source_range, new_value), Expr::ObjectExpression(ref mut obj_exp) => obj_exp.replace_value(source_range, new_value),
Value::MemberExpression(_) => {} Expr::MemberExpression(_) => {}
Value::Literal(_) => {} Expr::Literal(_) => {}
Value::FunctionExpression(ref mut func_exp) => func_exp.replace_value(source_range, new_value), Expr::FunctionExpression(ref mut func_exp) => func_exp.replace_value(source_range, new_value),
Value::CallExpression(ref mut call_exp) => call_exp.replace_value(source_range, new_value), Expr::CallExpression(ref mut call_exp) => call_exp.replace_value(source_range, new_value),
Value::Identifier(_) => {} Expr::Identifier(_) => {}
Value::TagDeclarator(_) => {} Expr::TagDeclarator(_) => {}
Value::PipeExpression(ref mut pipe_exp) => pipe_exp.replace_value(source_range, new_value), Expr::PipeExpression(ref mut pipe_exp) => pipe_exp.replace_value(source_range, new_value),
Value::UnaryExpression(ref mut unary_exp) => unary_exp.replace_value(source_range, new_value), Expr::UnaryExpression(ref mut unary_exp) => unary_exp.replace_value(source_range, new_value),
Value::PipeSubstitution(_) => {} Expr::PipeSubstitution(_) => {}
Value::None(_) => {} Expr::None(_) => {}
} }
} }
pub fn start(&self) -> usize { pub fn start(&self) -> usize {
match self { match self {
Value::Literal(literal) => literal.start(), Expr::Literal(literal) => literal.start(),
Value::Identifier(identifier) => identifier.start(), Expr::Identifier(identifier) => identifier.start(),
Value::TagDeclarator(tag) => tag.start(), Expr::TagDeclarator(tag) => tag.start(),
Value::BinaryExpression(binary_expression) => binary_expression.start(), Expr::BinaryExpression(binary_expression) => binary_expression.start(),
Value::FunctionExpression(function_expression) => function_expression.start(), Expr::FunctionExpression(function_expression) => function_expression.start(),
Value::CallExpression(call_expression) => call_expression.start(), Expr::CallExpression(call_expression) => call_expression.start(),
Value::PipeExpression(pipe_expression) => pipe_expression.start(), Expr::PipeExpression(pipe_expression) => pipe_expression.start(),
Value::PipeSubstitution(pipe_substitution) => pipe_substitution.start(), Expr::PipeSubstitution(pipe_substitution) => pipe_substitution.start(),
Value::ArrayExpression(array_expression) => array_expression.start(), Expr::ArrayExpression(array_expression) => array_expression.start(),
Value::ObjectExpression(object_expression) => object_expression.start(), Expr::ObjectExpression(object_expression) => object_expression.start(),
Value::MemberExpression(member_expression) => member_expression.start(), Expr::MemberExpression(member_expression) => member_expression.start(),
Value::UnaryExpression(unary_expression) => unary_expression.start(), Expr::UnaryExpression(unary_expression) => unary_expression.start(),
Value::None(none) => none.start, Expr::None(none) => none.start,
} }
} }
pub fn end(&self) -> usize { pub fn end(&self) -> usize {
match self { match self {
Value::Literal(literal) => literal.end(), Expr::Literal(literal) => literal.end(),
Value::Identifier(identifier) => identifier.end(), Expr::Identifier(identifier) => identifier.end(),
Value::TagDeclarator(tag) => tag.end(), Expr::TagDeclarator(tag) => tag.end(),
Value::BinaryExpression(binary_expression) => binary_expression.end(), Expr::BinaryExpression(binary_expression) => binary_expression.end(),
Value::FunctionExpression(function_expression) => function_expression.end(), Expr::FunctionExpression(function_expression) => function_expression.end(),
Value::CallExpression(call_expression) => call_expression.end(), Expr::CallExpression(call_expression) => call_expression.end(),
Value::PipeExpression(pipe_expression) => pipe_expression.end(), Expr::PipeExpression(pipe_expression) => pipe_expression.end(),
Value::PipeSubstitution(pipe_substitution) => pipe_substitution.end(), Expr::PipeSubstitution(pipe_substitution) => pipe_substitution.end(),
Value::ArrayExpression(array_expression) => array_expression.end(), Expr::ArrayExpression(array_expression) => array_expression.end(),
Value::ObjectExpression(object_expression) => object_expression.end(), Expr::ObjectExpression(object_expression) => object_expression.end(),
Value::MemberExpression(member_expression) => member_expression.end(), Expr::MemberExpression(member_expression) => member_expression.end(),
Value::UnaryExpression(unary_expression) => unary_expression.end(), Expr::UnaryExpression(unary_expression) => unary_expression.end(),
Value::None(none) => none.end, Expr::None(none) => none.end,
} }
} }
@ -735,82 +736,82 @@ impl Value {
/// This is really recursive so keep that in mind. /// This is really recursive so keep that in mind.
pub fn get_hover_value_for_position(&self, pos: usize, code: &str) -> Option<Hover> { pub fn get_hover_value_for_position(&self, pos: usize, code: &str) -> Option<Hover> {
match self { match self {
Value::BinaryExpression(binary_expression) => binary_expression.get_hover_value_for_position(pos, code), Expr::BinaryExpression(binary_expression) => binary_expression.get_hover_value_for_position(pos, code),
Value::FunctionExpression(function_expression) => { Expr::FunctionExpression(function_expression) => {
function_expression.get_hover_value_for_position(pos, code) function_expression.get_hover_value_for_position(pos, code)
} }
Value::CallExpression(call_expression) => call_expression.get_hover_value_for_position(pos, code), Expr::CallExpression(call_expression) => call_expression.get_hover_value_for_position(pos, code),
Value::PipeExpression(pipe_expression) => pipe_expression.get_hover_value_for_position(pos, code), Expr::PipeExpression(pipe_expression) => pipe_expression.get_hover_value_for_position(pos, code),
Value::ArrayExpression(array_expression) => array_expression.get_hover_value_for_position(pos, code), Expr::ArrayExpression(array_expression) => array_expression.get_hover_value_for_position(pos, code),
Value::ObjectExpression(object_expression) => object_expression.get_hover_value_for_position(pos, code), Expr::ObjectExpression(object_expression) => object_expression.get_hover_value_for_position(pos, code),
Value::MemberExpression(member_expression) => member_expression.get_hover_value_for_position(pos, code), Expr::MemberExpression(member_expression) => member_expression.get_hover_value_for_position(pos, code),
Value::UnaryExpression(unary_expression) => unary_expression.get_hover_value_for_position(pos, code), Expr::UnaryExpression(unary_expression) => unary_expression.get_hover_value_for_position(pos, code),
// TODO: LSP hover information for values/types. https://github.com/KittyCAD/modeling-app/issues/1126 // TODO: LSP hover information for values/types. https://github.com/KittyCAD/modeling-app/issues/1126
Value::None(_) => None, Expr::None(_) => None,
Value::Literal(_) => None, Expr::Literal(_) => None,
Value::Identifier(_) => None, Expr::Identifier(_) => None,
Value::TagDeclarator(_) => None, Expr::TagDeclarator(_) => None,
// TODO: LSP hover information for symbols. https://github.com/KittyCAD/modeling-app/issues/1127 // TODO: LSP hover information for symbols. https://github.com/KittyCAD/modeling-app/issues/1127
Value::PipeSubstitution(_) => None, Expr::PipeSubstitution(_) => None,
} }
} }
/// Rename all identifiers that have the old name to the new given name. /// Rename all identifiers that have the old name to the new given name.
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) { fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
match self { match self {
Value::Literal(_literal) => {} Expr::Literal(_literal) => {}
Value::Identifier(ref mut identifier) => identifier.rename(old_name, new_name), Expr::Identifier(ref mut identifier) => identifier.rename(old_name, new_name),
Value::TagDeclarator(ref mut tag) => tag.rename(old_name, new_name), Expr::TagDeclarator(ref mut tag) => tag.rename(old_name, new_name),
Value::BinaryExpression(ref mut binary_expression) => { Expr::BinaryExpression(ref mut binary_expression) => {
binary_expression.rename_identifiers(old_name, new_name) binary_expression.rename_identifiers(old_name, new_name)
} }
Value::FunctionExpression(_function_identifier) => {} Expr::FunctionExpression(_function_identifier) => {}
Value::CallExpression(ref mut call_expression) => call_expression.rename_identifiers(old_name, new_name), Expr::CallExpression(ref mut call_expression) => call_expression.rename_identifiers(old_name, new_name),
Value::PipeExpression(ref mut pipe_expression) => pipe_expression.rename_identifiers(old_name, new_name), Expr::PipeExpression(ref mut pipe_expression) => pipe_expression.rename_identifiers(old_name, new_name),
Value::PipeSubstitution(_) => {} Expr::PipeSubstitution(_) => {}
Value::ArrayExpression(ref mut array_expression) => array_expression.rename_identifiers(old_name, new_name), Expr::ArrayExpression(ref mut array_expression) => array_expression.rename_identifiers(old_name, new_name),
Value::ObjectExpression(ref mut object_expression) => { Expr::ObjectExpression(ref mut object_expression) => {
object_expression.rename_identifiers(old_name, new_name) object_expression.rename_identifiers(old_name, new_name)
} }
Value::MemberExpression(ref mut member_expression) => { Expr::MemberExpression(ref mut member_expression) => {
member_expression.rename_identifiers(old_name, new_name) member_expression.rename_identifiers(old_name, new_name)
} }
Value::UnaryExpression(ref mut unary_expression) => unary_expression.rename_identifiers(old_name, new_name), Expr::UnaryExpression(ref mut unary_expression) => unary_expression.rename_identifiers(old_name, new_name),
Value::None(_) => {} Expr::None(_) => {}
} }
} }
/// Get the constraint level for a value type. /// Get the constraint level for a value type.
pub fn get_constraint_level(&self) -> ConstraintLevel { pub fn get_constraint_level(&self) -> ConstraintLevel {
match self { match self {
Value::Literal(literal) => literal.get_constraint_level(), Expr::Literal(literal) => literal.get_constraint_level(),
Value::Identifier(identifier) => identifier.get_constraint_level(), Expr::Identifier(identifier) => identifier.get_constraint_level(),
Value::TagDeclarator(tag) => tag.get_constraint_level(), Expr::TagDeclarator(tag) => tag.get_constraint_level(),
Value::BinaryExpression(binary_expression) => binary_expression.get_constraint_level(), Expr::BinaryExpression(binary_expression) => binary_expression.get_constraint_level(),
Value::FunctionExpression(function_identifier) => function_identifier.get_constraint_level(), Expr::FunctionExpression(function_identifier) => function_identifier.get_constraint_level(),
Value::CallExpression(call_expression) => call_expression.get_constraint_level(), Expr::CallExpression(call_expression) => call_expression.get_constraint_level(),
Value::PipeExpression(pipe_expression) => pipe_expression.get_constraint_level(), Expr::PipeExpression(pipe_expression) => pipe_expression.get_constraint_level(),
Value::PipeSubstitution(pipe_substitution) => ConstraintLevel::Ignore { Expr::PipeSubstitution(pipe_substitution) => ConstraintLevel::Ignore {
source_ranges: vec![pipe_substitution.into()], source_ranges: vec![pipe_substitution.into()],
}, },
Value::ArrayExpression(array_expression) => array_expression.get_constraint_level(), Expr::ArrayExpression(array_expression) => array_expression.get_constraint_level(),
Value::ObjectExpression(object_expression) => object_expression.get_constraint_level(), Expr::ObjectExpression(object_expression) => object_expression.get_constraint_level(),
Value::MemberExpression(member_expression) => member_expression.get_constraint_level(), Expr::MemberExpression(member_expression) => member_expression.get_constraint_level(),
Value::UnaryExpression(unary_expression) => unary_expression.get_constraint_level(), Expr::UnaryExpression(unary_expression) => unary_expression.get_constraint_level(),
Value::None(none) => none.get_constraint_level(), Expr::None(none) => none.get_constraint_level(),
} }
} }
} }
impl From<Value> for SourceRange { impl From<Expr> for SourceRange {
fn from(value: Value) -> Self { fn from(value: Expr) -> Self {
Self([value.start(), value.end()]) Self([value.start(), value.end()])
} }
} }
impl From<&Value> for SourceRange { impl From<&Expr> for SourceRange {
fn from(value: &Value) -> Self { fn from(value: &Expr) -> Self {
Self([value.start(), value.end()]) Self([value.start(), value.end()])
} }
} }
@ -864,7 +865,7 @@ impl BinaryPart {
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
match self { match self {
BinaryPart::Literal(_) => {} BinaryPart::Literal(_) => {}
BinaryPart::Identifier(_) => {} BinaryPart::Identifier(_) => {}
@ -1224,7 +1225,7 @@ impl NonCodeMeta {
pub struct ExpressionStatement { pub struct ExpressionStatement {
pub start: usize, pub start: usize,
pub end: usize, pub end: usize,
pub expression: Value, pub expression: Expr,
pub digest: Option<Digest>, pub digest: Option<Digest>,
} }
@ -1245,7 +1246,7 @@ pub struct CallExpression {
pub start: usize, pub start: usize,
pub end: usize, pub end: usize,
pub callee: Identifier, pub callee: Identifier,
pub arguments: Vec<Value>, pub arguments: Vec<Expr>,
pub optional: bool, pub optional: bool,
pub digest: Option<Digest>, pub digest: Option<Digest>,
@ -1253,14 +1254,14 @@ pub struct CallExpression {
impl_value_meta!(CallExpression); impl_value_meta!(CallExpression);
impl From<CallExpression> for Value { impl From<CallExpression> for Expr {
fn from(call_expression: CallExpression) -> Self { fn from(call_expression: CallExpression) -> Self {
Value::CallExpression(Box::new(call_expression)) Expr::CallExpression(Box::new(call_expression))
} }
} }
impl CallExpression { impl CallExpression {
pub fn new(name: &str, arguments: Vec<Value>) -> Result<Self, KclError> { pub fn new(name: &str, arguments: Vec<Expr>) -> Result<Self, KclError> {
Ok(Self { Ok(Self {
start: 0, start: 0,
end: 0, end: 0,
@ -1284,14 +1285,14 @@ impl CallExpression {
pub fn has_substitution_arg(&self) -> bool { pub fn has_substitution_arg(&self) -> bool {
self.arguments self.arguments
.iter() .iter()
.any(|arg| matches!(arg, Value::PipeSubstitution(_))) .any(|arg| matches!(arg, Expr::PipeSubstitution(_)))
} }
pub fn as_source_ranges(&self) -> Vec<SourceRange> { pub fn as_source_ranges(&self) -> Vec<SourceRange> {
vec![SourceRange([self.start, self.end])] vec![SourceRange([self.start, self.end])]
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
for arg in &mut self.arguments { for arg in &mut self.arguments {
arg.replace_value(source_range, new_value.clone()); arg.replace_value(source_range, new_value.clone());
} }
@ -1694,14 +1695,14 @@ impl VariableDeclaration {
}) })
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
for declaration in &mut self.declarations { for declaration in &mut self.declarations {
declaration.init.replace_value(source_range, new_value.clone()); declaration.init.replace_value(source_range, new_value.clone());
} }
} }
/// Returns a value that includes the given character position. /// Returns a value that includes the given character position.
pub fn get_value_for_position(&self, pos: usize) -> Option<&Value> { pub fn get_value_for_position(&self, pos: usize) -> Option<&Expr> {
for declaration in &self.declarations { for declaration in &self.declarations {
let source_range: SourceRange = declaration.into(); let source_range: SourceRange = declaration.into();
if source_range.contains(pos) { if source_range.contains(pos) {
@ -1713,7 +1714,7 @@ impl VariableDeclaration {
} }
/// Returns a value that includes the given character position. /// Returns a value that includes the given character position.
pub fn get_mut_value_for_position(&mut self, pos: usize) -> Option<&mut Value> { pub fn get_mut_value_for_position(&mut self, pos: usize) -> Option<&mut Expr> {
for declaration in &mut self.declarations { for declaration in &mut self.declarations {
let source_range: SourceRange = declaration.clone().into(); let source_range: SourceRange = declaration.clone().into();
if source_range.contains(pos) { if source_range.contains(pos) {
@ -1771,7 +1772,7 @@ impl VariableDeclaration {
}; };
let children = match &declaration.init { let children = match &declaration.init {
Value::FunctionExpression(function_expression) => { Expr::FunctionExpression(function_expression) => {
symbol_kind = SymbolKind::FUNCTION; symbol_kind = SymbolKind::FUNCTION;
let mut children = vec![]; let mut children = vec![];
for param in &function_expression.params { for param in &function_expression.params {
@ -1790,7 +1791,7 @@ impl VariableDeclaration {
} }
children children
} }
Value::ObjectExpression(object_expression) => { Expr::ObjectExpression(object_expression) => {
symbol_kind = SymbolKind::OBJECT; symbol_kind = SymbolKind::OBJECT;
let mut children = vec![]; let mut children = vec![];
for property in &object_expression.properties { for property in &object_expression.properties {
@ -1798,7 +1799,7 @@ impl VariableDeclaration {
} }
children children
} }
Value::ArrayExpression(_) => { Expr::ArrayExpression(_) => {
symbol_kind = SymbolKind::ARRAY; symbol_kind = SymbolKind::ARRAY;
vec![] vec![]
} }
@ -1886,7 +1887,7 @@ pub struct VariableDeclarator {
/// The identifier of the variable. /// The identifier of the variable.
pub id: Identifier, pub id: Identifier,
/// The value of the variable. /// The value of the variable.
pub init: Value, pub init: Expr,
pub digest: Option<Digest>, pub digest: Option<Digest>,
} }
@ -1894,7 +1895,7 @@ pub struct VariableDeclarator {
impl_value_meta!(VariableDeclarator); impl_value_meta!(VariableDeclarator);
impl VariableDeclarator { impl VariableDeclarator {
pub fn new(name: &str, init: Value) -> Self { pub fn new(name: &str, init: Expr) -> Self {
Self { Self {
start: 0, start: 0,
end: 0, end: 0,
@ -2217,9 +2218,9 @@ impl Default for PipeSubstitution {
} }
} }
impl From<PipeSubstitution> for Value { impl From<PipeSubstitution> for Expr {
fn from(pipe_substitution: PipeSubstitution) -> Self { fn from(pipe_substitution: PipeSubstitution) -> Self {
Value::PipeSubstitution(Box::new(pipe_substitution)) Expr::PipeSubstitution(Box::new(pipe_substitution))
} }
} }
@ -2230,21 +2231,21 @@ impl From<PipeSubstitution> for Value {
pub struct ArrayExpression { pub struct ArrayExpression {
pub start: usize, pub start: usize,
pub end: usize, pub end: usize,
pub elements: Vec<Value>, pub elements: Vec<Expr>,
pub digest: Option<Digest>, pub digest: Option<Digest>,
} }
impl_value_meta!(ArrayExpression); impl_value_meta!(ArrayExpression);
impl From<ArrayExpression> for Value { impl From<ArrayExpression> for Expr {
fn from(array_expression: ArrayExpression) -> Self { fn from(array_expression: ArrayExpression) -> Self {
Value::ArrayExpression(Box::new(array_expression)) Expr::ArrayExpression(Box::new(array_expression))
} }
} }
impl ArrayExpression { impl ArrayExpression {
pub fn new(elements: Vec<Value>) -> Self { pub fn new(elements: Vec<Expr>) -> Self {
Self { Self {
start: 0, start: 0,
end: 0, end: 0,
@ -2260,7 +2261,7 @@ impl ArrayExpression {
} }
}); });
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
for element in &mut self.elements { for element in &mut self.elements {
element.replace_value(source_range, new_value.clone()); element.replace_value(source_range, new_value.clone());
} }
@ -2340,45 +2341,45 @@ impl ArrayExpression {
for element in &self.elements { for element in &self.elements {
let result = match element { let result = match element {
Value::Literal(literal) => literal.into(), Expr::Literal(literal) => literal.into(),
Value::TagDeclarator(tag) => tag.execute(memory).await?, Expr::TagDeclarator(tag) => tag.execute(memory).await?,
Value::None(none) => none.into(), Expr::None(none) => none.into(),
Value::Identifier(identifier) => { Expr::Identifier(identifier) => {
let value = memory.get(&identifier.name, identifier.into())?; let value = memory.get(&identifier.name, identifier.into())?;
value.clone() value.clone()
} }
Value::BinaryExpression(binary_expression) => { Expr::BinaryExpression(binary_expression) => {
binary_expression binary_expression
.get_result(memory, dynamic_state, pipe_info, ctx) .get_result(memory, dynamic_state, pipe_info, ctx)
.await? .await?
} }
Value::CallExpression(call_expression) => { Expr::CallExpression(call_expression) => {
call_expression.execute(memory, dynamic_state, pipe_info, ctx).await? call_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
} }
Value::UnaryExpression(unary_expression) => { Expr::UnaryExpression(unary_expression) => {
unary_expression unary_expression
.get_result(memory, dynamic_state, pipe_info, ctx) .get_result(memory, dynamic_state, pipe_info, ctx)
.await? .await?
} }
Value::ObjectExpression(object_expression) => { Expr::ObjectExpression(object_expression) => {
object_expression.execute(memory, dynamic_state, pipe_info, ctx).await? object_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
} }
Value::ArrayExpression(array_expression) => { Expr::ArrayExpression(array_expression) => {
array_expression.execute(memory, dynamic_state, pipe_info, ctx).await? array_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
} }
Value::PipeExpression(pipe_expression) => { Expr::PipeExpression(pipe_expression) => {
pipe_expression pipe_expression
.get_result(memory, dynamic_state, pipe_info, ctx) .get_result(memory, dynamic_state, pipe_info, ctx)
.await? .await?
} }
Value::PipeSubstitution(pipe_substitution) => { Expr::PipeSubstitution(pipe_substitution) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution), message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
source_ranges: vec![pipe_substitution.into()], source_ranges: vec![pipe_substitution.into()],
})); }));
} }
Value::MemberExpression(member_expression) => member_expression.get_result(memory)?, Expr::MemberExpression(member_expression) => member_expression.get_result(memory)?,
Value::FunctionExpression(function_expression) => { Expr::FunctionExpression(function_expression) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("FunctionExpression not implemented here: {:?}", function_expression), message: format!("FunctionExpression not implemented here: {:?}", function_expression),
source_ranges: vec![function_expression.into()], source_ranges: vec![function_expression.into()],
@ -2435,7 +2436,7 @@ impl ObjectExpression {
} }
}); });
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
for property in &mut self.properties { for property in &mut self.properties {
property.value.replace_value(source_range, new_value.clone()); property.value.replace_value(source_range, new_value.clone());
} }
@ -2526,45 +2527,45 @@ impl ObjectExpression {
let mut object = Map::new(); let mut object = Map::new();
for property in &self.properties { for property in &self.properties {
let result = match &property.value { let result = match &property.value {
Value::Literal(literal) => literal.into(), Expr::Literal(literal) => literal.into(),
Value::TagDeclarator(tag) => tag.execute(memory).await?, Expr::TagDeclarator(tag) => tag.execute(memory).await?,
Value::None(none) => none.into(), Expr::None(none) => none.into(),
Value::Identifier(identifier) => { Expr::Identifier(identifier) => {
let value = memory.get(&identifier.name, identifier.into())?; let value = memory.get(&identifier.name, identifier.into())?;
value.clone() value.clone()
} }
Value::BinaryExpression(binary_expression) => { Expr::BinaryExpression(binary_expression) => {
binary_expression binary_expression
.get_result(memory, dynamic_state, pipe_info, ctx) .get_result(memory, dynamic_state, pipe_info, ctx)
.await? .await?
} }
Value::CallExpression(call_expression) => { Expr::CallExpression(call_expression) => {
call_expression.execute(memory, dynamic_state, pipe_info, ctx).await? call_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
} }
Value::UnaryExpression(unary_expression) => { Expr::UnaryExpression(unary_expression) => {
unary_expression unary_expression
.get_result(memory, dynamic_state, pipe_info, ctx) .get_result(memory, dynamic_state, pipe_info, ctx)
.await? .await?
} }
Value::ObjectExpression(object_expression) => { Expr::ObjectExpression(object_expression) => {
object_expression.execute(memory, dynamic_state, pipe_info, ctx).await? object_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
} }
Value::ArrayExpression(array_expression) => { Expr::ArrayExpression(array_expression) => {
array_expression.execute(memory, dynamic_state, pipe_info, ctx).await? array_expression.execute(memory, dynamic_state, pipe_info, ctx).await?
} }
Value::PipeExpression(pipe_expression) => { Expr::PipeExpression(pipe_expression) => {
pipe_expression pipe_expression
.get_result(memory, dynamic_state, pipe_info, ctx) .get_result(memory, dynamic_state, pipe_info, ctx)
.await? .await?
} }
Value::MemberExpression(member_expression) => member_expression.get_result(memory)?, Expr::MemberExpression(member_expression) => member_expression.get_result(memory)?,
Value::PipeSubstitution(pipe_substitution) => { Expr::PipeSubstitution(pipe_substitution) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution), message: format!("PipeSubstitution not implemented here: {:?}", pipe_substitution),
source_ranges: vec![pipe_substitution.into()], source_ranges: vec![pipe_substitution.into()],
})); }));
} }
Value::FunctionExpression(function_expression) => { Expr::FunctionExpression(function_expression) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: format!("FunctionExpression not implemented here: {:?}", function_expression), message: format!("FunctionExpression not implemented here: {:?}", function_expression),
source_ranges: vec![function_expression.into()], source_ranges: vec![function_expression.into()],
@ -2601,7 +2602,7 @@ pub struct ObjectProperty {
pub start: usize, pub start: usize,
pub end: usize, pub end: usize,
pub key: Identifier, pub key: Identifier,
pub value: Value, pub value: Expr,
pub digest: Option<Digest>, pub digest: Option<Digest>,
} }
@ -3046,7 +3047,7 @@ impl BinaryExpression {
hasher.update(slf.right.compute_digest()); hasher.update(slf.right.compute_digest());
}); });
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
self.left.replace_value(source_range, new_value.clone()); self.left.replace_value(source_range, new_value.clone());
self.right.replace_value(source_range, new_value); self.right.replace_value(source_range, new_value);
} }
@ -3309,7 +3310,7 @@ impl UnaryExpression {
hasher.update(slf.argument.compute_digest()); hasher.update(slf.argument.compute_digest());
}); });
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
self.argument.replace_value(source_range, new_value); self.argument.replace_value(source_range, new_value);
} }
@ -3404,7 +3405,7 @@ pub struct PipeExpression {
pub end: usize, pub end: usize,
// TODO: Only the first body expression can be any Value. // TODO: Only the first body expression can be any Value.
// The rest will be CallExpression, and the AST type should reflect this. // The rest will be CallExpression, and the AST type should reflect this.
pub body: Vec<Value>, pub body: Vec<Expr>,
pub non_code_meta: NonCodeMeta, pub non_code_meta: NonCodeMeta,
pub digest: Option<Digest>, pub digest: Option<Digest>,
@ -3412,14 +3413,14 @@ pub struct PipeExpression {
impl_value_meta!(PipeExpression); impl_value_meta!(PipeExpression);
impl From<PipeExpression> for Value { impl From<PipeExpression> for Expr {
fn from(pipe_expression: PipeExpression) -> Self { fn from(pipe_expression: PipeExpression) -> Self {
Value::PipeExpression(Box::new(pipe_expression)) Expr::PipeExpression(Box::new(pipe_expression))
} }
} }
impl PipeExpression { impl PipeExpression {
pub fn new(body: Vec<Value>) -> Self { pub fn new(body: Vec<Expr>) -> Self {
Self { Self {
start: 0, start: 0,
end: 0, end: 0,
@ -3437,7 +3438,7 @@ impl PipeExpression {
hasher.update(slf.non_code_meta.compute_digest()); hasher.update(slf.non_code_meta.compute_digest());
}); });
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
for value in &mut self.body { for value in &mut self.body {
value.replace_value(source_range, new_value.clone()); value.replace_value(source_range, new_value.clone());
} }
@ -3531,7 +3532,7 @@ impl PipeExpression {
async fn execute_pipe_body( async fn execute_pipe_body(
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState, dynamic_state: &DynamicState,
body: &[Value], body: &[Expr],
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
source_range: SourceRange, source_range: SourceRange,
ctx: &ExecutorContext, ctx: &ExecutorContext,
@ -3568,17 +3569,17 @@ async fn execute_pipe_body(
// Evaluate remaining elements. // Evaluate remaining elements.
for expression in body { for expression in body {
let output = match expression { let output = match expression {
Value::BinaryExpression(binary_expression) => { Expr::BinaryExpression(binary_expression) => {
binary_expression binary_expression
.get_result(memory, dynamic_state, &new_pipe_info, ctx) .get_result(memory, dynamic_state, &new_pipe_info, ctx)
.await? .await?
} }
Value::CallExpression(call_expression) => { Expr::CallExpression(call_expression) => {
call_expression call_expression
.execute(memory, dynamic_state, &new_pipe_info, ctx) .execute(memory, dynamic_state, &new_pipe_info, ctx)
.await? .await?
} }
Value::Identifier(identifier) => memory.get(&identifier.name, identifier.into())?.clone(), Expr::Identifier(identifier) => memory.get(&identifier.name, identifier.into())?.clone(),
_ => { _ => {
// Return an error this should not happen. // Return an error this should not happen.
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
@ -3813,7 +3814,7 @@ impl FunctionExpression {
self.required_params().len()..=self.params.len() self.required_params().len()..=self.params.len()
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) { pub fn replace_value(&mut self, source_range: SourceRange, new_value: Expr) {
self.body.replace_value(source_range, new_value); self.body.replace_value(source_range, new_value);
} }
@ -3850,7 +3851,7 @@ impl FunctionExpression {
pub struct ReturnStatement { pub struct ReturnStatement {
pub start: usize, pub start: usize,
pub end: usize, pub end: usize,
pub argument: Value, pub argument: Expr,
pub digest: Option<Digest>, pub digest: Option<Digest>,
} }
@ -5565,7 +5566,7 @@ const firstExtrude = startSketchOn('XY')
let BodyItem::VariableDeclaration(var_decl) = function else { let BodyItem::VariableDeclaration(var_decl) = function else {
panic!("expected a variable declaration") panic!("expected a variable declaration")
}; };
let Value::FunctionExpression(ref func_expr) = var_decl.declarations.first().unwrap().init else { let Expr::FunctionExpression(ref func_expr) = var_decl.declarations.first().unwrap().init else {
panic!("expected a function expression") panic!("expected a function expression")
}; };
let params = &func_expr.params; let params = &func_expr.params;
@ -5589,7 +5590,7 @@ const firstExtrude = startSketchOn('XY')
let BodyItem::VariableDeclaration(var_decl) = function else { let BodyItem::VariableDeclaration(var_decl) = function else {
panic!("expected a variable declaration") panic!("expected a variable declaration")
}; };
let Value::FunctionExpression(ref func_expr) = var_decl.declarations.first().unwrap().init else { let Expr::FunctionExpression(ref func_expr) = var_decl.declarations.first().unwrap().init else {
panic!("expected a function expression") panic!("expected a function expression")
}; };
let params = &func_expr.params; let params = &func_expr.params;
@ -5613,7 +5614,7 @@ const firstExtrude = startSketchOn('XY')
let BodyItem::VariableDeclaration(var_decl) = function else { let BodyItem::VariableDeclaration(var_decl) = function else {
panic!("expected a variable declaration") panic!("expected a variable declaration")
}; };
let Value::FunctionExpression(ref func_expr) = var_decl.declarations.first().unwrap().init else { let Expr::FunctionExpression(ref func_expr) = var_decl.declarations.first().unwrap().init else {
panic!("expected a function expression") panic!("expected a function expression")
}; };
let params = &func_expr.params; let params = &func_expr.params;
@ -5676,7 +5677,7 @@ const firstExtrude = startSketchOn('XY')
let BodyItem::VariableDeclaration(var_decl) = function else { let BodyItem::VariableDeclaration(var_decl) = function else {
panic!("expected a variable declaration") panic!("expected a variable declaration")
}; };
let Value::FunctionExpression(ref func_expr) = var_decl.declarations.first().unwrap().init else { let Expr::FunctionExpression(ref func_expr) = var_decl.declarations.first().unwrap().init else {
panic!("expected a function expression") panic!("expected a function expression")
}; };
let params = &func_expr.params; let params = &func_expr.params;
@ -5940,25 +5941,25 @@ const thickness = sqrt(distance * p * FOS * 6 / (sigmaAllow * width))"#;
panic!("expected a function!"); panic!("expected a function!");
}; };
let Value::CallExpression(ce) = expression else { let Expr::CallExpression(ce) = expression else {
panic!("expected a function!"); panic!("expected a function!");
}; };
assert!(!ce.arguments.is_empty()); assert!(!ce.arguments.is_empty());
let Value::ObjectExpression(oe) = ce.arguments.first().unwrap() else { let Expr::ObjectExpression(oe) = ce.arguments.first().unwrap() else {
panic!("expected a object!"); panic!("expected a object!");
}; };
assert_eq!(oe.properties.len(), 2); assert_eq!(oe.properties.len(), 2);
let Value::Literal(ref l) = oe.properties.first().unwrap().value else { let Expr::Literal(ref l) = oe.properties.first().unwrap().value else {
panic!("expected a literal!"); panic!("expected a literal!");
}; };
assert_eq!(l.raw, "true"); assert_eq!(l.raw, "true");
let Value::Literal(ref l) = oe.properties.get(1).unwrap().value else { let Expr::Literal(ref l) = oe.properties.get(1).unwrap().value else {
panic!("expected a literal!"); panic!("expected a literal!");
}; };

View File

@ -3,7 +3,7 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value as JValue; use serde_json::Value as JValue;
use crate::ast::types::{Literal, Value}; use crate::ast::types::{Expr, Literal};
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Bake)]
#[databake(path = kcl_lib::ast::types)] #[databake(path = kcl_lib::ast::types)]
@ -33,9 +33,9 @@ impl LiteralValue {
} }
} }
impl From<Literal> for Value { impl From<Literal> for Expr {
fn from(literal: Literal) -> Self { fn from(literal: Literal) -> Self {
Value::Literal(Box::new(literal)) Expr::Literal(Box::new(literal))
} }
} }

View File

@ -11,7 +11,7 @@ use serde_json::Value as JValue;
use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange}; use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange};
use crate::{ use crate::{
ast::types::{BodyItem, FunctionExpression, KclNone, Program, TagDeclarator, Value}, ast::types::{BodyItem, Expr, FunctionExpression, KclNone, Program, TagDeclarator},
engine::EngineManager, engine::EngineManager,
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
fs::FileManager, fs::FileManager,
@ -1745,9 +1745,9 @@ impl ExecutorContext {
for statement in &program.body { for statement in &program.body {
match statement { match statement {
BodyItem::ExpressionStatement(expression_statement) => { BodyItem::ExpressionStatement(expression_statement) => {
if let Value::PipeExpression(pipe_expr) = &expression_statement.expression { if let Expr::PipeExpression(pipe_expr) = &expression_statement.expression {
pipe_expr.get_result(memory, dynamic_state, &pipe_info, self).await?; pipe_expr.get_result(memory, dynamic_state, &pipe_info, self).await?;
} else if let Value::CallExpression(call_expr) = &expression_statement.expression { } else if let Expr::CallExpression(call_expr) = &expression_statement.expression {
call_expr.execute(memory, dynamic_state, &pipe_info, self).await?; call_expr.execute(memory, dynamic_state, &pipe_info, self).await?;
} }
} }
@ -1771,47 +1771,47 @@ impl ExecutorContext {
} }
} }
BodyItem::ReturnStatement(return_statement) => match &return_statement.argument { BodyItem::ReturnStatement(return_statement) => match &return_statement.argument {
Value::BinaryExpression(bin_expr) => { Expr::BinaryExpression(bin_expr) => {
let result = bin_expr.get_result(memory, dynamic_state, &pipe_info, self).await?; let result = bin_expr.get_result(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::UnaryExpression(unary_expr) => { Expr::UnaryExpression(unary_expr) => {
let result = unary_expr.get_result(memory, dynamic_state, &pipe_info, self).await?; let result = unary_expr.get_result(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::Identifier(identifier) => { Expr::Identifier(identifier) => {
let value = memory.get(&identifier.name, identifier.into())?.clone(); let value = memory.get(&identifier.name, identifier.into())?.clone();
memory.return_ = Some(ProgramReturn::Value(value)); memory.return_ = Some(ProgramReturn::Value(value));
} }
Value::Literal(literal) => { Expr::Literal(literal) => {
memory.return_ = Some(ProgramReturn::Value(literal.into())); memory.return_ = Some(ProgramReturn::Value(literal.into()));
} }
Value::TagDeclarator(tag) => { Expr::TagDeclarator(tag) => {
memory.return_ = Some(ProgramReturn::Value(tag.into())); memory.return_ = Some(ProgramReturn::Value(tag.into()));
} }
Value::ArrayExpression(array_expr) => { Expr::ArrayExpression(array_expr) => {
let result = array_expr.execute(memory, dynamic_state, &pipe_info, self).await?; let result = array_expr.execute(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::ObjectExpression(obj_expr) => { Expr::ObjectExpression(obj_expr) => {
let result = obj_expr.execute(memory, dynamic_state, &pipe_info, self).await?; let result = obj_expr.execute(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::CallExpression(call_expr) => { Expr::CallExpression(call_expr) => {
let result = call_expr.execute(memory, dynamic_state, &pipe_info, self).await?; let result = call_expr.execute(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::MemberExpression(member_expr) => { Expr::MemberExpression(member_expr) => {
let result = member_expr.get_result(memory)?; let result = member_expr.get_result(memory)?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::PipeExpression(pipe_expr) => { Expr::PipeExpression(pipe_expr) => {
let result = pipe_expr.get_result(memory, dynamic_state, &pipe_info, self).await?; let result = pipe_expr.get_result(memory, dynamic_state, &pipe_info, self).await?;
memory.return_ = Some(ProgramReturn::Value(result)); memory.return_ = Some(ProgramReturn::Value(result));
} }
Value::PipeSubstitution(_) => {} Expr::PipeSubstitution(_) => {}
Value::FunctionExpression(_) => {} Expr::FunctionExpression(_) => {}
Value::None(none) => { Expr::None(none) => {
memory.return_ = Some(ProgramReturn::Value(MemoryItem::from(none))); memory.return_ = Some(ProgramReturn::Value(MemoryItem::from(none)));
} }
}, },
@ -1835,7 +1835,7 @@ impl ExecutorContext {
pub async fn arg_into_mem_item<'a>( pub async fn arg_into_mem_item<'a>(
&self, &self,
init: &Value, init: &Expr,
memory: &mut ProgramMemory, memory: &mut ProgramMemory,
dynamic_state: &DynamicState, dynamic_state: &DynamicState,
pipe_info: &PipeInfo, pipe_info: &PipeInfo,
@ -1843,19 +1843,19 @@ impl ExecutorContext {
statement_kind: StatementKind<'a>, statement_kind: StatementKind<'a>,
) -> Result<MemoryItem, KclError> { ) -> Result<MemoryItem, KclError> {
let item = match init { let item = match init {
Value::None(none) => none.into(), Expr::None(none) => none.into(),
Value::Literal(literal) => literal.into(), Expr::Literal(literal) => literal.into(),
Value::TagDeclarator(tag) => tag.execute(memory).await?, Expr::TagDeclarator(tag) => tag.execute(memory).await?,
Value::Identifier(identifier) => { Expr::Identifier(identifier) => {
let value = memory.get(&identifier.name, identifier.into())?; let value = memory.get(&identifier.name, identifier.into())?;
value.clone() value.clone()
} }
Value::BinaryExpression(binary_expression) => { Expr::BinaryExpression(binary_expression) => {
binary_expression binary_expression
.get_result(memory, dynamic_state, pipe_info, self) .get_result(memory, dynamic_state, pipe_info, self)
.await? .await?
} }
Value::FunctionExpression(function_expression) => { Expr::FunctionExpression(function_expression) => {
let mem_func = force_memory_function( let mem_func = force_memory_function(
|args: Vec<MemoryItem>, |args: Vec<MemoryItem>,
memory: ProgramMemory, memory: ProgramMemory,
@ -1897,15 +1897,15 @@ impl ExecutorContext {
memory: Box::new(memory.clone()), memory: Box::new(memory.clone()),
} }
} }
Value::CallExpression(call_expression) => { Expr::CallExpression(call_expression) => {
call_expression.execute(memory, dynamic_state, pipe_info, self).await? call_expression.execute(memory, dynamic_state, pipe_info, self).await?
} }
Value::PipeExpression(pipe_expression) => { Expr::PipeExpression(pipe_expression) => {
pipe_expression pipe_expression
.get_result(memory, dynamic_state, pipe_info, self) .get_result(memory, dynamic_state, pipe_info, self)
.await? .await?
} }
Value::PipeSubstitution(pipe_substitution) => match statement_kind { Expr::PipeSubstitution(pipe_substitution) => match statement_kind {
StatementKind::Declaration { name } => { StatementKind::Declaration { name } => {
let message = format!( let message = format!(
"you cannot declare variable {name} as %, because % can only be used in function calls" "you cannot declare variable {name} as %, because % can only be used in function calls"
@ -1926,16 +1926,16 @@ impl ExecutorContext {
} }
}, },
}, },
Value::ArrayExpression(array_expression) => { Expr::ArrayExpression(array_expression) => {
array_expression.execute(memory, dynamic_state, pipe_info, self).await? array_expression.execute(memory, dynamic_state, pipe_info, self).await?
} }
Value::ObjectExpression(object_expression) => { Expr::ObjectExpression(object_expression) => {
object_expression object_expression
.execute(memory, dynamic_state, pipe_info, self) .execute(memory, dynamic_state, pipe_info, self)
.await? .await?
} }
Value::MemberExpression(member_expression) => member_expression.get_result(memory)?, Expr::MemberExpression(member_expression) => member_expression.get_result(memory)?,
Value::UnaryExpression(unary_expression) => { Expr::UnaryExpression(unary_expression) => {
unary_expression unary_expression
.get_result(memory, dynamic_state, pipe_info, self) .get_result(memory, dynamic_state, pipe_info, self)
.await? .await?

View File

@ -40,7 +40,7 @@ use tower_lsp::{
}; };
use crate::{ use crate::{
ast::types::{Value, VariableKind}, ast::types::{Expr, VariableKind},
executor::SourceRange, executor::SourceRange,
lsp::{backend::Backend as _, util::IntoDiagnostic}, lsp::{backend::Backend as _, util::IntoDiagnostic},
parser::PIPE_OPERATOR, parser::PIPE_OPERATOR,
@ -370,7 +370,7 @@ impl Backend {
crate::walk::Node::VariableDeclarator(variable) => { crate::walk::Node::VariableDeclarator(variable) => {
let sr: SourceRange = (&variable.id).into(); let sr: SourceRange = (&variable.id).into();
if sr.contains(source_range.start()) { if sr.contains(source_range.start()) {
if let Value::FunctionExpression(_) = &variable.init { if let Expr::FunctionExpression(_) = &variable.init {
let mut ti = token_index.lock().map_err(|_| anyhow::anyhow!("mutex"))?; let mut ti = token_index.lock().map_err(|_| anyhow::anyhow!("mutex"))?;
*ti = match self.get_semantic_token_type_index(&SemanticTokenType::FUNCTION) { *ti = match self.get_semantic_token_type_index(&SemanticTokenType::FUNCTION) {
Some(index) => index, Some(index) => index,

View File

@ -10,11 +10,11 @@ use winnow::{
use crate::{ use crate::{
ast::types::{ ast::types::{
ArrayExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem, CallExpression, CommentStyle, ArrayExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem, CallExpression, CommentStyle, Expr,
ExpressionStatement, FnArgPrimitive, FnArgType, FunctionExpression, Identifier, Literal, LiteralIdentifier, ExpressionStatement, FnArgPrimitive, FnArgType, FunctionExpression, Identifier, Literal, LiteralIdentifier,
LiteralValue, MemberExpression, MemberObject, NonCodeMeta, NonCodeNode, NonCodeValue, ObjectExpression, LiteralValue, MemberExpression, MemberObject, NonCodeMeta, NonCodeNode, NonCodeValue, ObjectExpression,
ObjectProperty, Parameter, PipeExpression, PipeSubstitution, Program, ReturnStatement, TagDeclarator, ObjectProperty, Parameter, PipeExpression, PipeSubstitution, Program, ReturnStatement, TagDeclarator,
UnaryExpression, UnaryOperator, Value, VariableDeclaration, VariableDeclarator, VariableKind, UnaryExpression, UnaryOperator, VariableDeclaration, VariableDeclarator, VariableKind,
}, },
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
executor::SourceRange, executor::SourceRange,
@ -136,7 +136,7 @@ fn non_code_node_no_leading_whitespace(i: TokenSlice) -> PResult<NonCodeNode> {
fn pipe_expression(i: TokenSlice) -> PResult<PipeExpression> { fn pipe_expression(i: TokenSlice) -> PResult<PipeExpression> {
let mut non_code_meta = NonCodeMeta::default(); let mut non_code_meta = NonCodeMeta::default();
let (head, noncode) = terminated( let (head, noncode) = terminated(
(value_but_not_pipe, preceded(whitespace, opt(non_code_node))), (expression_but_not_pipe, preceded(whitespace, opt(non_code_node))),
peek(pipe_surrounded_by_whitespace), peek(pipe_surrounded_by_whitespace),
) )
.context(expected("an expression, followed by the |> (pipe) operator")) .context(expected("an expression, followed by the |> (pipe) operator"))
@ -146,9 +146,9 @@ fn pipe_expression(i: TokenSlice) -> PResult<PipeExpression> {
} }
let mut values = vec![head]; let mut values = vec![head];
let value_surrounded_by_comments = ( let value_surrounded_by_comments = (
repeat(0.., preceded(opt(whitespace), non_code_node)), // Before the value repeat(0.., preceded(opt(whitespace), non_code_node)), // Before the expression.
preceded(opt(whitespace), fn_call), // The value preceded(opt(whitespace), fn_call), // The expression.
repeat(0.., noncode_just_after_code), // After the value repeat(0.., noncode_just_after_code), // After the expression.
); );
let tail: Vec<(Vec<_>, _, Vec<_>)> = repeat( let tail: Vec<(Vec<_>, _, Vec<_>)> = repeat(
1.., 1..,
@ -183,7 +183,7 @@ fn pipe_expression(i: TokenSlice) -> PResult<PipeExpression> {
max_noncode_end = nc.end.max(max_noncode_end); max_noncode_end = nc.end.max(max_noncode_end);
non_code_meta.insert(code_count, nc); non_code_meta.insert(code_count, nc);
} }
values.push(Value::CallExpression(Box::new(code))); values.push(Expr::CallExpression(Box::new(code)));
code_count += 1; code_count += 1;
for nc in noncode_after { for nc in noncode_after {
max_noncode_end = nc.end.max(max_noncode_end); max_noncode_end = nc.end.max(max_noncode_end);
@ -318,21 +318,21 @@ fn operand(i: TokenSlice) -> PResult<BinaryPart> {
let op = possible_operands let op = possible_operands
.try_map(|part| { .try_map(|part| {
let source_ranges = vec![SourceRange([part.start(), part.end()])]; let source_ranges = vec![SourceRange([part.start(), part.end()])];
let val = match part { let expr = match part {
// TODO: these should be valid operands eventually, // TODO: these should be valid operands eventually,
// users should be able to run "let x = f() + g()" // users should be able to run "let x = f() + g()"
// see https://github.com/KittyCAD/modeling-app/issues/783 // see https://github.com/KittyCAD/modeling-app/issues/783
Value::FunctionExpression(_) Expr::FunctionExpression(_)
| Value::PipeExpression(_) | Expr::PipeExpression(_)
| Value::PipeSubstitution(_) | Expr::PipeSubstitution(_)
| Value::ArrayExpression(_) | Expr::ArrayExpression(_)
| Value::ObjectExpression(_) => { | Expr::ObjectExpression(_) => {
return Err(KclError::Syntax(KclErrorDetails { return Err(KclError::Syntax(KclErrorDetails {
source_ranges, source_ranges,
message: TODO_783.to_owned(), message: TODO_783.to_owned(),
})) }))
} }
Value::None(_) => { Expr::None(_) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
source_ranges, source_ranges,
// TODO: Better error message here. // TODO: Better error message here.
@ -341,7 +341,7 @@ fn operand(i: TokenSlice) -> PResult<BinaryPart> {
message: "cannot use a KCL None value as an operand".to_owned(), message: "cannot use a KCL None value as an operand".to_owned(),
})); }));
} }
Value::TagDeclarator(_) => { Expr::TagDeclarator(_) => {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
source_ranges, source_ranges,
// TODO: Better error message here. // TODO: Better error message here.
@ -350,14 +350,14 @@ fn operand(i: TokenSlice) -> PResult<BinaryPart> {
message: "cannot use a KCL tag declaration as an operand".to_owned(), message: "cannot use a KCL tag declaration as an operand".to_owned(),
})); }));
} }
Value::UnaryExpression(x) => BinaryPart::UnaryExpression(x), Expr::UnaryExpression(x) => BinaryPart::UnaryExpression(x),
Value::Literal(x) => BinaryPart::Literal(x), Expr::Literal(x) => BinaryPart::Literal(x),
Value::Identifier(x) => BinaryPart::Identifier(x), Expr::Identifier(x) => BinaryPart::Identifier(x),
Value::BinaryExpression(x) => BinaryPart::BinaryExpression(x), Expr::BinaryExpression(x) => BinaryPart::BinaryExpression(x),
Value::CallExpression(x) => BinaryPart::CallExpression(x), Expr::CallExpression(x) => BinaryPart::CallExpression(x),
Value::MemberExpression(x) => BinaryPart::MemberExpression(x), Expr::MemberExpression(x) => BinaryPart::MemberExpression(x),
}; };
Ok(val) Ok(expr)
}) })
.context(expected("an operand (a value which can be used with an operator)")) .context(expected("an operand (a value which can be used with an operator)"))
.parse_next(i)?; .parse_next(i)?;
@ -452,7 +452,7 @@ fn equals(i: TokenSlice) -> PResult<Token> {
fn array(i: TokenSlice) -> PResult<ArrayExpression> { fn array(i: TokenSlice) -> PResult<ArrayExpression> {
let start = open_bracket(i)?.start; let start = open_bracket(i)?.start;
ignore_whitespace(i); ignore_whitespace(i);
let elements = alt((integer_range, separated(0.., value, comma_sep))) let elements = alt((integer_range, separated(0.., expression, comma_sep)))
.context(expected( .context(expected(
"array contents, either a numeric range (like 0..10) or a list of elements (like [1, 2, 3])", "array contents, either a numeric range (like 0..10) or a list of elements (like [1, 2, 3])",
)) ))
@ -468,14 +468,14 @@ fn array(i: TokenSlice) -> PResult<ArrayExpression> {
} }
/// Parse n..m into a vec of numbers [n, n+1, ..., m] /// Parse n..m into a vec of numbers [n, n+1, ..., m]
fn integer_range(i: TokenSlice) -> PResult<Vec<Value>> { fn integer_range(i: TokenSlice) -> PResult<Vec<Expr>> {
let (token0, floor) = integer.parse_next(i)?; let (token0, floor) = integer.parse_next(i)?;
double_period.parse_next(i)?; double_period.parse_next(i)?;
let (_token1, ceiling) = integer.parse_next(i)?; let (_token1, ceiling) = integer.parse_next(i)?;
Ok((floor..=ceiling) Ok((floor..=ceiling)
.map(|num| { .map(|num| {
let num = num as i64; let num = num as i64;
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: token0.start, start: token0.start,
end: token0.end, end: token0.end,
value: num.into(), value: num.into(),
@ -494,16 +494,16 @@ fn object_property(i: TokenSlice) -> PResult<ObjectProperty> {
)) ))
.parse_next(i)?; .parse_next(i)?;
ignore_whitespace(i); ignore_whitespace(i);
let val = value let expr = expression
.context(expected( .context(expected(
"the value which you're setting the property to, e.g. in 'height: 4', the value is 4", "the value which you're setting the property to, e.g. in 'height: 4', the value is 4",
)) ))
.parse_next(i)?; .parse_next(i)?;
Ok(ObjectProperty { Ok(ObjectProperty {
start: key.start, start: key.start,
end: val.end(), end: expr.end(),
key, key,
value: val, value: expr,
digest: None, digest: None,
}) })
} }
@ -727,7 +727,7 @@ fn body_items_within_function(i: TokenSlice) -> PResult<WithinFunction> {
non_code_node.map(WithinFunction::NonCode) non_code_node.map(WithinFunction::NonCode)
}, },
_ => _ =>
(expression.map(BodyItem::ExpressionStatement), opt(noncode_just_after_code)).map(WithinFunction::BodyItem), (expression_stmt.map(BodyItem::ExpressionStatement), opt(noncode_just_after_code)).map(WithinFunction::BodyItem),
} }
.context(expected("a function body items (functions are made up of variable declarations, expressions, and return statements, each of those is a possible body item")) .context(expected("a function body items (functions are made up of variable declarations, expressions, and return statements, each of those is a possible body item"))
.parse_next(i)?; .parse_next(i)?;
@ -894,7 +894,7 @@ pub fn return_stmt(i: TokenSlice) -> PResult<ReturnStatement> {
)) ))
.parse_next(i)?; .parse_next(i)?;
require_whitespace(i)?; require_whitespace(i)?;
let argument = value(i)?; let argument = expression(i)?;
Ok(ReturnStatement { Ok(ReturnStatement {
start, start,
end: argument.end(), end: argument.end(),
@ -903,62 +903,62 @@ pub fn return_stmt(i: TokenSlice) -> PResult<ReturnStatement> {
}) })
} }
/// Parse a KCL value /// Parse a KCL expression.
fn value(i: TokenSlice) -> PResult<Value> { fn expression(i: TokenSlice) -> PResult<Expr> {
alt(( alt((
pipe_expression.map(Box::new).map(Value::PipeExpression), pipe_expression.map(Box::new).map(Expr::PipeExpression),
value_but_not_pipe, expression_but_not_pipe,
)) ))
.context(expected("a KCL value")) .context(expected("a KCL value"))
.parse_next(i) .parse_next(i)
} }
fn value_but_not_pipe(i: TokenSlice) -> PResult<Value> { fn expression_but_not_pipe(i: TokenSlice) -> PResult<Expr> {
alt(( alt((
binary_expression.map(Box::new).map(Value::BinaryExpression), binary_expression.map(Box::new).map(Expr::BinaryExpression),
unary_expression.map(Box::new).map(Value::UnaryExpression), unary_expression.map(Box::new).map(Expr::UnaryExpression),
value_allowed_in_pipe_expr, expr_allowed_in_pipe_expr,
)) ))
.context(expected("a KCL value")) .context(expected("a KCL value"))
.parse_next(i) .parse_next(i)
} }
fn unnecessarily_bracketed(i: TokenSlice) -> PResult<Value> { fn unnecessarily_bracketed(i: TokenSlice) -> PResult<Expr> {
delimited( delimited(
terminated(open_paren, opt(whitespace)), terminated(open_paren, opt(whitespace)),
value, expression,
preceded(opt(whitespace), close_paren), preceded(opt(whitespace), close_paren),
) )
.parse_next(i) .parse_next(i)
} }
fn value_allowed_in_pipe_expr(i: TokenSlice) -> PResult<Value> { fn expr_allowed_in_pipe_expr(i: TokenSlice) -> PResult<Expr> {
alt(( alt((
member_expression.map(Box::new).map(Value::MemberExpression), member_expression.map(Box::new).map(Expr::MemberExpression),
bool_value.map(Box::new).map(Value::Literal), bool_value.map(Box::new).map(Expr::Literal),
tag.map(Box::new).map(Value::TagDeclarator), tag.map(Box::new).map(Expr::TagDeclarator),
literal.map(Box::new).map(Value::Literal), literal.map(Box::new).map(Expr::Literal),
fn_call.map(Box::new).map(Value::CallExpression), fn_call.map(Box::new).map(Expr::CallExpression),
identifier.map(Box::new).map(Value::Identifier), identifier.map(Box::new).map(Expr::Identifier),
array.map(Box::new).map(Value::ArrayExpression), array.map(Box::new).map(Expr::ArrayExpression),
object.map(Box::new).map(Value::ObjectExpression), object.map(Box::new).map(Expr::ObjectExpression),
pipe_sub.map(Box::new).map(Value::PipeSubstitution), pipe_sub.map(Box::new).map(Expr::PipeSubstitution),
function_expression.map(Box::new).map(Value::FunctionExpression), function_expression.map(Box::new).map(Expr::FunctionExpression),
unnecessarily_bracketed, unnecessarily_bracketed,
)) ))
.context(expected("a KCL value (but not a pipe expression)")) .context(expected("a KCL expression (but not a pipe expression)"))
.parse_next(i) .parse_next(i)
} }
fn possible_operands(i: TokenSlice) -> PResult<Value> { fn possible_operands(i: TokenSlice) -> PResult<Expr> {
alt(( alt((
unary_expression.map(Box::new).map(Value::UnaryExpression), unary_expression.map(Box::new).map(Expr::UnaryExpression),
bool_value.map(Box::new).map(Value::Literal), bool_value.map(Box::new).map(Expr::Literal),
member_expression.map(Box::new).map(Value::MemberExpression), member_expression.map(Box::new).map(Expr::MemberExpression),
literal.map(Box::new).map(Value::Literal), literal.map(Box::new).map(Expr::Literal),
fn_call.map(Box::new).map(Value::CallExpression), fn_call.map(Box::new).map(Expr::CallExpression),
identifier.map(Box::new).map(Value::Identifier), identifier.map(Box::new).map(Expr::Identifier),
binary_expr_in_parens.map(Box::new).map(Value::BinaryExpression), binary_expr_in_parens.map(Box::new).map(Expr::BinaryExpression),
unnecessarily_bracketed, unnecessarily_bracketed,
)) ))
.context(expected( .context(expected(
@ -1007,15 +1007,15 @@ fn declaration(i: TokenSlice) -> PResult<VariableDeclaration> {
let val = if kind == VariableKind::Fn { let val = if kind == VariableKind::Fn {
function_expression function_expression
.map(Box::new) .map(Box::new)
.map(Value::FunctionExpression) .map(Expr::FunctionExpression)
.context(expected("a KCL function expression, like () => { return 1 }")) .context(expected("a KCL function expression, like () => { return 1 }"))
.parse_next(i) .parse_next(i)
} else { } else {
value expression
.try_map(|val| { .try_map(|val| {
// Function bodies can be used if and only if declaring a function. // Function bodies can be used if and only if declaring a function.
// Check the 'if' direction: // Check the 'if' direction:
if matches!(val, Value::FunctionExpression(_)) { if matches!(val, Expr::FunctionExpression(_)) {
return Err(KclError::Syntax(KclErrorDetails { return Err(KclError::Syntax(KclErrorDetails {
source_ranges: vec![SourceRange([start, dec_end])], source_ranges: vec![SourceRange([start, dec_end])],
message: format!("Expected a `fn` variable kind, found: `{}`", kind), message: format!("Expected a `fn` variable kind, found: `{}`", kind),
@ -1218,9 +1218,9 @@ fn bracketed_section(i: TokenSlice) -> PResult<usize> {
Ok(tokens_examined) Ok(tokens_examined)
} }
/// Parse a KCL expression. /// Parse a KCL expression statement.
fn expression(i: TokenSlice) -> PResult<ExpressionStatement> { fn expression_stmt(i: TokenSlice) -> PResult<ExpressionStatement> {
let val = value let val = expression
.context(expected( .context(expected(
"an expression (i.e. a value, or an algorithm for calculating one), e.g. 'x + y' or '3' or 'width * 2'", "an expression (i.e. a value, or an algorithm for calculating one), e.g. 'x + y' or '3' or 'width * 2'",
)) ))
@ -1374,8 +1374,8 @@ fn comma_sep(i: TokenSlice) -> PResult<()> {
} }
/// Arguments are passed into a function. /// Arguments are passed into a function.
fn arguments(i: TokenSlice) -> PResult<Vec<Value>> { fn arguments(i: TokenSlice) -> PResult<Vec<Expr>> {
separated(0.., value, comma_sep) separated(0.., expression, comma_sep)
.context(expected("function arguments")) .context(expected("function arguments"))
.parse_next(i) .parse_next(i)
} }
@ -1513,10 +1513,10 @@ fn fn_call(i: TokenSlice) -> PResult<CallExpression> {
}; };
match spec_arg.type_.as_ref() { match spec_arg.type_.as_ref() {
"TagDeclarator" => match &arg { "TagDeclarator" => match &arg {
Value::Identifier(_) => { Expr::Identifier(_) => {
// These are fine since we want someone to be able to map a variable to a tag declarator. // These are fine since we want someone to be able to map a variable to a tag declarator.
} }
Value::TagDeclarator(tag) => { Expr::TagDeclarator(tag) => {
tag.clone() tag.clone()
.into_valid_binding_name() .into_valid_binding_name()
.map_err(|e| ErrMode::Cut(ContextError::from(e)))?; .map_err(|e| ErrMode::Cut(ContextError::from(e)))?;
@ -1532,8 +1532,8 @@ fn fn_call(i: TokenSlice) -> PResult<CallExpression> {
} }
}, },
"TagIdentifier" => match &arg { "TagIdentifier" => match &arg {
Value::Identifier(_) => {} Expr::Identifier(_) => {}
Value::MemberExpression(_) => {} Expr::MemberExpression(_) => {}
e => { e => {
return Err(ErrMode::Cut( return Err(ErrMode::Cut(
KclError::Syntax(KclErrorDetails { KclError::Syntax(KclErrorDetails {
@ -1564,7 +1564,7 @@ mod tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use super::*; use super::*;
use crate::ast::types::{BodyItem, Value, VariableKind}; use crate::ast::types::{BodyItem, Expr, VariableKind};
#[test] #[test]
fn parse_args() { fn parse_args() {
@ -1680,7 +1680,7 @@ const mySk1 = startSketchAt([0, 0])"#;
panic!("expected vardec"); panic!("expected vardec");
}; };
let val = item.declarations.remove(0).init; let val = item.declarations.remove(0).init;
let Value::PipeExpression(pipe) = val else { let Expr::PipeExpression(pipe) = val else {
panic!("expected pipe"); panic!("expected pipe");
}; };
let mut noncode = pipe.non_code_meta; let mut noncode = pipe.non_code_meta;
@ -1727,7 +1727,7 @@ const mySk1 = startSketchAt([0, 0])"#;
body: vec![BodyItem::ReturnStatement(ReturnStatement { body: vec![BodyItem::ReturnStatement(ReturnStatement {
start: 25, start: 25,
end: 33, end: 33,
argument: Value::Literal(Box::new(Literal { argument: Expr::Literal(Box::new(Literal {
start: 32, start: 32,
end: 33, end: 33,
value: 2u32.into(), value: 2u32.into(),
@ -1873,7 +1873,7 @@ const mySk1 = startSketchAt([0, 0])"#;
"sqrt(distance * p * FOS * 6 / ( sigmaAllow * width ))", "sqrt(distance * p * FOS * 6 / ( sigmaAllow * width ))",
] { ] {
let tokens = crate::token::lexer(input).unwrap(); let tokens = crate::token::lexer(input).unwrap();
let _actual = match value.parse(&tokens) { let _actual = match expression.parse(&tokens) {
Ok(x) => x, Ok(x) => x,
Err(e) => panic!("{e:?}"), Err(e) => panic!("{e:?}"),
}; };
@ -1919,7 +1919,7 @@ const mySk1 = startSketchAt([0, 0])"#;
Err(e) => panic!("Could not parse test {i}: {e:#?}"), Err(e) => panic!("Could not parse test {i}: {e:#?}"),
Ok(a) => a, Ok(a) => a,
}; };
let Value::BinaryExpression(_expr) = actual.declarations.remove(0).init else { let Expr::BinaryExpression(_expr) = actual.declarations.remove(0).init else {
panic!( panic!(
"Expected test {i} to be a binary expression but it wasn't, it was {:?}", "Expected test {i} to be a binary expression but it wasn't, it was {:?}",
actual.declarations[0] actual.declarations[0]
@ -2247,7 +2247,7 @@ const mySk1 = startSketchAt([0, 0])"#;
assert_eq!(actual.declarations.len(), 1); assert_eq!(actual.declarations.len(), 1);
let decl = actual.declarations.pop().unwrap(); let decl = actual.declarations.pop().unwrap();
assert_eq!(decl.id.name, "myVar"); assert_eq!(decl.id.name, "myVar");
let Value::Literal(value) = decl.init else { let Expr::Literal(value) = decl.init else {
panic!("value should be a literal") panic!("value should be a literal")
}; };
assert_eq!(value.end, test.len()); assert_eq!(value.end, test.len());
@ -2282,7 +2282,7 @@ const mySk1 = startSketchAt([0, 0])"#;
let expected = vec![BodyItem::ExpressionStatement(ExpressionStatement { let expected = vec![BodyItem::ExpressionStatement(ExpressionStatement {
start: 0, start: 0,
end: 7, end: 7,
expression: Value::BinaryExpression(Box::new(expr)), expression: Expr::BinaryExpression(Box::new(expr)),
digest: None, digest: None,
})]; })];
assert_eq!(expected, actual); assert_eq!(expected, actual);
@ -2377,7 +2377,7 @@ const mySk1 = startSketchAt([0, 0])"#;
body: vec![BodyItem::ExpressionStatement(ExpressionStatement { body: vec![BodyItem::ExpressionStatement(ExpressionStatement {
start: 0, start: 0,
end: 4, end: 4,
expression: Value::BinaryExpression(Box::new(BinaryExpression { expression: Expr::BinaryExpression(Box::new(BinaryExpression {
start: 0, start: 0,
end: 4, end: 4,
left: BinaryPart::Literal(Box::new(Literal { left: BinaryPart::Literal(Box::new(Literal {
@ -2774,81 +2774,81 @@ e
name: "myArray".to_string(), name: "myArray".to_string(),
digest: None, digest: None,
}, },
init: Value::ArrayExpression(Box::new(ArrayExpression { init: Expr::ArrayExpression(Box::new(ArrayExpression {
start: 16, start: 16,
end: 23, end: 23,
elements: vec![ elements: vec![
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 0u32.into(), value: 0u32.into(),
raw: "0".to_string(), raw: "0".to_string(),
digest: None, digest: None,
})), })),
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 1u32.into(), value: 1u32.into(),
raw: "1".to_string(), raw: "1".to_string(),
digest: None, digest: None,
})), })),
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 2u32.into(), value: 2u32.into(),
raw: "2".to_string(), raw: "2".to_string(),
digest: None, digest: None,
})), })),
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 3u32.into(), value: 3u32.into(),
raw: "3".to_string(), raw: "3".to_string(),
digest: None, digest: None,
})), })),
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 4u32.into(), value: 4u32.into(),
raw: "4".to_string(), raw: "4".to_string(),
digest: None, digest: None,
})), })),
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 5u32.into(), value: 5u32.into(),
raw: "5".to_string(), raw: "5".to_string(),
digest: None, digest: None,
})), })),
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 6u32.into(), value: 6u32.into(),
raw: "6".to_string(), raw: "6".to_string(),
digest: None, digest: None,
})), })),
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 7u32.into(), value: 7u32.into(),
raw: "7".to_string(), raw: "7".to_string(),
digest: None, digest: None,
})), })),
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 8u32.into(), value: 8u32.into(),
raw: "8".to_string(), raw: "8".to_string(),
digest: None, digest: None,
})), })),
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 9u32.into(), value: 9u32.into(),
raw: "9".to_string(), raw: "9".to_string(),
digest: None, digest: None,
})), })),
Value::Literal(Box::new(Literal { Expr::Literal(Box::new(Literal {
start: 17, start: 17,
end: 18, end: 18,
value: 10u32.into(), value: 10u32.into(),

View File

@ -4,7 +4,7 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
ast::types::{BodyItem, FunctionExpression, Program, Value}, ast::types::{BodyItem, Expr, FunctionExpression, Program},
docs::{StdLibFn, StdLibFnData}, docs::{StdLibFn, StdLibFnData},
token::lexer, token::lexer,
}; };
@ -89,7 +89,7 @@ pub fn extract_function(source: &str) -> Option<(Program, Box<FunctionExpression
let BodyItem::ExpressionStatement(expr) = src.body.last()? else { let BodyItem::ExpressionStatement(expr) = src.body.last()? else {
panic!("expected expression statement"); panic!("expected expression statement");
}; };
let Value::FunctionExpression(function) = expr.expression.clone() else { let Expr::FunctionExpression(function) = expr.expression.clone() else {
panic!("expected function expr"); panic!("expected function expr");
}; };
Some((src, function)) Some((src, function))

View File

@ -2,8 +2,8 @@ use anyhow::Result;
use crate::{ use crate::{
ast::types::{ ast::types::{
BinaryPart, BodyItem, LiteralIdentifier, MemberExpression, MemberObject, ObjectExpression, ObjectProperty, BinaryPart, BodyItem, Expr, LiteralIdentifier, MemberExpression, MemberObject, ObjectExpression,
Parameter, Program, UnaryExpression, Value, VariableDeclarator, ObjectProperty, Parameter, Program, UnaryExpression, VariableDeclarator,
}, },
walk::Node, walk::Node,
}; };
@ -108,20 +108,20 @@ where
} }
} }
fn walk_value<'a, WalkT>(node: &'a Value, f: &WalkT) -> Result<bool> fn walk_value<'a, WalkT>(node: &'a Expr, f: &WalkT) -> Result<bool>
where where
WalkT: Walker<'a>, WalkT: Walker<'a>,
{ {
match node { match node {
Value::Literal(lit) => f.walk(lit.as_ref().into()), Expr::Literal(lit) => f.walk(lit.as_ref().into()),
Value::TagDeclarator(tag) => f.walk(tag.as_ref().into()), Expr::TagDeclarator(tag) => f.walk(tag.as_ref().into()),
Value::Identifier(id) => { Expr::Identifier(id) => {
// sometimes there's a bare Identifier without a Value::Identifier. // sometimes there's a bare Identifier without a Value::Identifier.
f.walk(id.as_ref().into()) f.walk(id.as_ref().into())
} }
Value::BinaryExpression(be) => { Expr::BinaryExpression(be) => {
if !f.walk(be.as_ref().into())? { if !f.walk(be.as_ref().into())? {
return Ok(false); return Ok(false);
} }
@ -130,7 +130,7 @@ where
} }
walk_binary_part(&be.right, f) walk_binary_part(&be.right, f)
} }
Value::FunctionExpression(fe) => { Expr::FunctionExpression(fe) => {
if !f.walk(fe.as_ref().into())? { if !f.walk(fe.as_ref().into())? {
return Ok(false); return Ok(false);
} }
@ -142,7 +142,7 @@ where
} }
walk(&fe.body, f) walk(&fe.body, f)
} }
Value::CallExpression(ce) => { Expr::CallExpression(ce) => {
if !f.walk(ce.as_ref().into())? { if !f.walk(ce.as_ref().into())? {
return Ok(false); return Ok(false);
} }
@ -157,7 +157,7 @@ where
} }
Ok(true) Ok(true)
} }
Value::PipeExpression(pe) => { Expr::PipeExpression(pe) => {
if !f.walk(pe.as_ref().into())? { if !f.walk(pe.as_ref().into())? {
return Ok(false); return Ok(false);
} }
@ -169,8 +169,8 @@ where
} }
Ok(true) Ok(true)
} }
Value::PipeSubstitution(ps) => f.walk(ps.as_ref().into()), Expr::PipeSubstitution(ps) => f.walk(ps.as_ref().into()),
Value::ArrayExpression(ae) => { Expr::ArrayExpression(ae) => {
if !f.walk(ae.as_ref().into())? { if !f.walk(ae.as_ref().into())? {
return Ok(false); return Ok(false);
} }
@ -181,10 +181,10 @@ where
} }
Ok(true) Ok(true)
} }
Value::ObjectExpression(oe) => walk_object_expression(oe, f), Expr::ObjectExpression(oe) => walk_object_expression(oe, f),
Value::MemberExpression(me) => walk_member_expression(me, f), Expr::MemberExpression(me) => walk_member_expression(me, f),
Value::UnaryExpression(ue) => walk_unary_expression(ue, f), Expr::UnaryExpression(ue) => walk_unary_expression(ue, f),
Value::None(_) => Ok(true), Expr::None(_) => Ok(true),
} }
} }