2023-04-03 16:05:25 +10:00
|
|
|
import { Selection, TooTip } from '../useStore'
|
2023-01-06 09:29:26 +11:00
|
|
|
import {
|
|
|
|
Program,
|
|
|
|
CallExpression,
|
|
|
|
PipeExpression,
|
|
|
|
VariableDeclaration,
|
2023-02-12 10:56:45 +11:00
|
|
|
VariableDeclarator,
|
2023-01-06 09:29:26 +11:00
|
|
|
ExpressionStatement,
|
|
|
|
Value,
|
2023-02-12 10:56:45 +11:00
|
|
|
Literal,
|
|
|
|
PipeSubstitution,
|
|
|
|
Identifier,
|
|
|
|
ArrayExpression,
|
|
|
|
ObjectExpression,
|
2023-03-02 21:19:11 +11:00
|
|
|
UnaryExpression,
|
|
|
|
BinaryExpression,
|
2023-01-06 09:29:26 +11:00
|
|
|
} from './abstractSyntaxTree'
|
2023-04-01 16:47:00 +11:00
|
|
|
import {
|
|
|
|
findAllPreviousVariables,
|
|
|
|
getNodeFromPath,
|
|
|
|
getNodePathFromSourceRange,
|
|
|
|
isNodeSafeToReplace,
|
|
|
|
} from './queryAst'
|
2023-02-12 10:56:45 +11:00
|
|
|
import { PathToNode, ProgramMemory } from './executor'
|
2023-03-02 21:19:11 +11:00
|
|
|
import {
|
|
|
|
addTagForSketchOnFace,
|
|
|
|
getFirstArg,
|
|
|
|
createFirstArg,
|
|
|
|
} from './std/sketch'
|
2023-01-06 09:29:26 +11:00
|
|
|
|
|
|
|
export function addSketchTo(
|
|
|
|
node: Program,
|
|
|
|
axis: 'xy' | 'xz' | 'yz',
|
|
|
|
name = ''
|
2023-04-01 16:47:00 +11:00
|
|
|
): { modifiedAst: Program; id: string; pathToNode: PathToNode } {
|
2023-01-06 09:29:26 +11:00
|
|
|
const _node = { ...node }
|
|
|
|
const _name = name || findUniqueName(node, 'part')
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
const startSketchAt = createCallExpression('startSketchAt', [
|
2023-03-17 15:53:20 +11:00
|
|
|
createLiteral('default'),
|
2023-02-12 10:56:45 +11:00
|
|
|
])
|
|
|
|
const rotate = createCallExpression(axis === 'xz' ? 'rx' : 'ry', [
|
|
|
|
createLiteral(90),
|
|
|
|
createPipeSubstitution(),
|
|
|
|
])
|
2023-03-17 15:53:20 +11:00
|
|
|
const initialLineTo = createCallExpression('line', [
|
|
|
|
createLiteral('default'),
|
2023-02-12 10:56:45 +11:00
|
|
|
createPipeSubstitution(),
|
|
|
|
])
|
2023-01-06 09:29:26 +11:00
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
const pipeBody =
|
|
|
|
axis !== 'xy'
|
|
|
|
? [startSketchAt, rotate, initialLineTo]
|
|
|
|
: [startSketchAt, initialLineTo]
|
|
|
|
|
|
|
|
const variableDeclaration = createVariableDeclaration(
|
|
|
|
_name,
|
|
|
|
createPipeExpression(pipeBody)
|
|
|
|
)
|
2023-01-06 09:29:26 +11:00
|
|
|
|
|
|
|
const showCallIndex = getShowIndex(_node)
|
|
|
|
let sketchIndex = showCallIndex
|
|
|
|
if (showCallIndex === -1) {
|
2023-02-12 10:56:45 +11:00
|
|
|
_node.body = [...node.body, variableDeclaration]
|
2023-01-06 09:29:26 +11:00
|
|
|
sketchIndex = _node.body.length - 1
|
|
|
|
} else {
|
|
|
|
const newBody = [...node.body]
|
2023-02-12 10:56:45 +11:00
|
|
|
newBody.splice(showCallIndex, 0, variableDeclaration)
|
2023-01-06 09:29:26 +11:00
|
|
|
_node.body = newBody
|
|
|
|
}
|
2023-04-01 16:47:00 +11:00
|
|
|
let pathToNode: PathToNode = [
|
|
|
|
['body', ''],
|
|
|
|
[sketchIndex, 'index'],
|
|
|
|
['declarations', 'VariableDeclaration'],
|
|
|
|
['0', 'index'],
|
|
|
|
['init', 'VariableDeclarator'],
|
2023-01-06 09:29:26 +11:00
|
|
|
]
|
|
|
|
if (axis !== 'xy') {
|
2023-04-01 16:47:00 +11:00
|
|
|
pathToNode = [...pathToNode, ['body', ''], ['0', 'index']]
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst: addToShow(_node, _name),
|
|
|
|
id: _name,
|
|
|
|
pathToNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function findUniqueName(
|
2023-01-06 09:29:26 +11:00
|
|
|
ast: Program | string,
|
|
|
|
name: string,
|
2023-01-09 13:19:14 +11:00
|
|
|
pad = 3,
|
2023-01-06 09:29:26 +11:00
|
|
|
index = 1
|
|
|
|
): string {
|
|
|
|
let searchStr = ''
|
|
|
|
if (typeof ast === 'string') {
|
|
|
|
searchStr = ast
|
|
|
|
} else {
|
|
|
|
searchStr = JSON.stringify(ast)
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
const indexStr = `${index}`.padStart(pad, '0')
|
2023-01-06 09:29:26 +11:00
|
|
|
const newName = `${name}${indexStr}`
|
|
|
|
const isInString = searchStr.includes(newName)
|
|
|
|
if (!isInString) {
|
|
|
|
return newName
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
return findUniqueName(searchStr, name, pad, index + 1)
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
function addToShow(node: Program, name: string): Program {
|
|
|
|
const _node = { ...node }
|
|
|
|
const dumbyStartend = { start: 0, end: 0 }
|
|
|
|
const showCallIndex = getShowIndex(_node)
|
|
|
|
if (showCallIndex === -1) {
|
2023-03-02 21:19:11 +11:00
|
|
|
const showCall = createCallExpression('show', [createIdentifier(name)])
|
2023-01-06 09:29:26 +11:00
|
|
|
const showExpressionStatement: ExpressionStatement = {
|
|
|
|
type: 'ExpressionStatement',
|
|
|
|
...dumbyStartend,
|
|
|
|
expression: showCall,
|
|
|
|
}
|
|
|
|
_node.body = [..._node.body, showExpressionStatement]
|
|
|
|
return _node
|
|
|
|
}
|
|
|
|
const showCall = { ..._node.body[showCallIndex] } as ExpressionStatement
|
|
|
|
const showCallArgs = (showCall.expression as CallExpression).arguments
|
2023-03-02 21:19:11 +11:00
|
|
|
const newShowCallArgs: Value[] = [...showCallArgs, createIdentifier(name)]
|
|
|
|
const newShowExpression = createCallExpression('show', newShowCallArgs)
|
2023-01-06 09:29:26 +11:00
|
|
|
|
|
|
|
_node.body[showCallIndex] = {
|
|
|
|
...showCall,
|
|
|
|
expression: newShowExpression,
|
|
|
|
}
|
|
|
|
return _node
|
|
|
|
}
|
|
|
|
|
|
|
|
function getShowIndex(node: Program): number {
|
|
|
|
return node.body.findIndex(
|
|
|
|
(statement) =>
|
|
|
|
statement.type === 'ExpressionStatement' &&
|
|
|
|
statement.expression.type === 'CallExpression' &&
|
|
|
|
statement.expression.callee.type === 'Identifier' &&
|
|
|
|
statement.expression.callee.name === 'show'
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function mutateArrExp(
|
|
|
|
node: Value,
|
|
|
|
updateWith: ArrayExpression
|
|
|
|
): boolean {
|
|
|
|
if (node.type === 'ArrayExpression') {
|
|
|
|
node.elements.forEach((element, i) => {
|
|
|
|
if (element.type === 'Literal') {
|
|
|
|
node.elements[i] = updateWith.elements[i]
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return true
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
return false
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function mutateObjExpProp(
|
|
|
|
node: Value,
|
|
|
|
updateWith: Literal | ArrayExpression,
|
|
|
|
key: string
|
|
|
|
): boolean {
|
|
|
|
if (node.type === 'ObjectExpression') {
|
|
|
|
const keyIndex = node.properties.findIndex((a) => a.key.name === key)
|
|
|
|
if (keyIndex !== -1) {
|
|
|
|
if (
|
|
|
|
updateWith.type === 'Literal' &&
|
|
|
|
node.properties[keyIndex].value.type === 'Literal'
|
|
|
|
) {
|
|
|
|
node.properties[keyIndex].value = updateWith
|
|
|
|
return true
|
|
|
|
} else if (
|
|
|
|
node.properties[keyIndex].value.type === 'ArrayExpression' &&
|
|
|
|
updateWith.type === 'ArrayExpression'
|
|
|
|
) {
|
|
|
|
const arrExp = node.properties[keyIndex].value as ArrayExpression
|
|
|
|
arrExp.elements.forEach((element, i) => {
|
|
|
|
if (element.type === 'Literal') {
|
|
|
|
arrExp.elements[i] = updateWith.elements[i]
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
} else {
|
|
|
|
node.properties.push({
|
|
|
|
type: 'ObjectProperty',
|
|
|
|
key: createIdentifier(key),
|
|
|
|
value: updateWith,
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
})
|
|
|
|
}
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
return false
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
2023-01-06 12:45:34 +11:00
|
|
|
|
|
|
|
export function extrudeSketch(
|
|
|
|
node: Program,
|
2023-04-01 16:47:00 +11:00
|
|
|
pathToNode: PathToNode,
|
2023-01-06 12:45:34 +11:00
|
|
|
shouldPipe = true
|
2023-01-13 17:58:37 +11:00
|
|
|
): {
|
|
|
|
modifiedAst: Program
|
|
|
|
pathToNode: PathToNode
|
|
|
|
pathToExtrudeArg: PathToNode
|
|
|
|
} {
|
2023-01-06 12:45:34 +11:00
|
|
|
const _node = { ...node }
|
|
|
|
const dumbyStartend = { start: 0, end: 0 }
|
2023-02-12 10:56:45 +11:00
|
|
|
const { node: sketchExpression } = getNodeFromPath(
|
2023-01-06 12:45:34 +11:00
|
|
|
_node,
|
|
|
|
pathToNode,
|
2023-02-12 10:56:45 +11:00
|
|
|
'SketchExpression' // TODO fix this #25
|
2023-01-13 17:58:37 +11:00
|
|
|
)
|
2023-01-06 12:45:34 +11:00
|
|
|
|
|
|
|
// determine if sketchExpression is in a pipeExpression or not
|
2023-01-13 17:58:37 +11:00
|
|
|
const { node: pipeExpression } = getNodeFromPath<PipeExpression>(
|
2023-01-06 12:45:34 +11:00
|
|
|
_node,
|
|
|
|
pathToNode,
|
2023-01-13 17:58:37 +11:00
|
|
|
'PipeExpression'
|
|
|
|
)
|
|
|
|
const isInPipeExpression = pipeExpression.type === 'PipeExpression'
|
|
|
|
|
2023-04-01 16:47:00 +11:00
|
|
|
const { node: variableDeclorator, shallowPath: pathToDecleration } =
|
2023-01-13 17:58:37 +11:00
|
|
|
getNodeFromPath<VariableDeclarator>(_node, pathToNode, 'VariableDeclarator')
|
2023-01-06 12:45:34 +11:00
|
|
|
|
2023-03-02 21:19:11 +11:00
|
|
|
const extrudeCall = createCallExpression('extrude', [
|
|
|
|
createLiteral(4),
|
|
|
|
shouldPipe
|
|
|
|
? createPipeSubstitution()
|
2023-01-06 12:45:34 +11:00
|
|
|
: {
|
2023-03-02 21:19:11 +11:00
|
|
|
type: 'Identifier',
|
2023-01-06 12:45:34 +11:00
|
|
|
...dumbyStartend,
|
2023-03-02 21:19:11 +11:00
|
|
|
name: variableDeclorator.id.name,
|
|
|
|
},
|
|
|
|
])
|
|
|
|
|
|
|
|
if (shouldPipe) {
|
|
|
|
const pipeChain = createPipeExpression(
|
|
|
|
isInPipeExpression
|
|
|
|
? [...pipeExpression.body, extrudeCall]
|
|
|
|
: [sketchExpression as any, extrudeCall]
|
|
|
|
)
|
2023-01-06 12:45:34 +11:00
|
|
|
|
|
|
|
variableDeclorator.init = pipeChain
|
2023-04-01 16:47:00 +11:00
|
|
|
const pathToExtrudeArg: PathToNode = [
|
2023-01-13 17:58:37 +11:00
|
|
|
...pathToDecleration,
|
2023-04-01 16:47:00 +11:00
|
|
|
['init', 'VariableDeclarator'],
|
|
|
|
['body', ''],
|
|
|
|
[pipeChain.body.length - 1, 'index'],
|
|
|
|
['arguments', 'CallExpression'],
|
|
|
|
[0, 'index'],
|
2023-01-13 17:58:37 +11:00
|
|
|
]
|
2023-01-06 12:45:34 +11:00
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst: _node,
|
|
|
|
pathToNode,
|
2023-01-13 17:58:37 +11:00
|
|
|
pathToExtrudeArg,
|
2023-01-06 12:45:34 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
const name = findUniqueName(node, 'part')
|
2023-03-02 21:19:11 +11:00
|
|
|
const VariableDeclaration = createVariableDeclaration(name, extrudeCall)
|
2023-01-06 12:45:34 +11:00
|
|
|
const showCallIndex = getShowIndex(_node)
|
|
|
|
_node.body.splice(showCallIndex, 0, VariableDeclaration)
|
2023-04-01 16:47:00 +11:00
|
|
|
const pathToExtrudeArg: PathToNode = [
|
|
|
|
['body', ''],
|
|
|
|
[showCallIndex, 'index'],
|
|
|
|
['declarations', 'VariableDeclaration'],
|
|
|
|
[0, 'index'],
|
|
|
|
['init', 'VariableDeclarator'],
|
|
|
|
['arguments', 'CallExpression'],
|
|
|
|
[0, 'index'],
|
2023-01-13 17:58:37 +11:00
|
|
|
]
|
2023-01-06 12:45:34 +11:00
|
|
|
return {
|
|
|
|
modifiedAst: addToShow(_node, name),
|
2023-04-01 16:47:00 +11:00
|
|
|
pathToNode: [...pathToNode.slice(0, -1), [showCallIndex, 'index']],
|
2023-01-13 17:58:37 +11:00
|
|
|
pathToExtrudeArg,
|
2023-01-06 12:45:34 +11:00
|
|
|
}
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
|
|
|
|
export function sketchOnExtrudedFace(
|
|
|
|
node: Program,
|
2023-04-01 16:47:00 +11:00
|
|
|
pathToNode: PathToNode,
|
2023-02-12 10:56:45 +11:00
|
|
|
programMemory: ProgramMemory
|
2023-04-01 16:47:00 +11:00
|
|
|
): { modifiedAst: Program; pathToNode: PathToNode } {
|
2023-02-12 10:56:45 +11:00
|
|
|
let _node = { ...node }
|
2023-01-09 13:19:14 +11:00
|
|
|
const newSketchName = findUniqueName(node, 'part')
|
2023-04-01 16:47:00 +11:00
|
|
|
const { node: oldSketchNode, shallowPath: pathToOldSketch } =
|
2023-02-12 10:56:45 +11:00
|
|
|
getNodeFromPath<VariableDeclarator>(
|
|
|
|
_node,
|
|
|
|
pathToNode,
|
|
|
|
'VariableDeclarator',
|
|
|
|
true
|
|
|
|
)
|
|
|
|
const oldSketchName = oldSketchNode.id.name
|
|
|
|
const { node: expression } = getNodeFromPath<CallExpression>(
|
2023-01-10 15:40:34 +11:00
|
|
|
_node,
|
|
|
|
pathToNode,
|
2023-02-12 10:56:45 +11:00
|
|
|
'CallExpression'
|
|
|
|
)
|
2023-01-09 13:19:14 +11:00
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
const { modifiedAst, tag } = addTagForSketchOnFace(
|
|
|
|
{
|
|
|
|
previousProgramMemory: programMemory,
|
2023-01-13 17:58:37 +11:00
|
|
|
pathToNode,
|
2023-02-12 10:56:45 +11:00
|
|
|
node: _node,
|
|
|
|
},
|
|
|
|
expression.callee.name
|
|
|
|
)
|
|
|
|
_node = modifiedAst
|
|
|
|
|
|
|
|
const newSketch = createVariableDeclaration(
|
|
|
|
newSketchName,
|
|
|
|
createPipeExpression([
|
|
|
|
createCallExpression('startSketchAt', [
|
|
|
|
createArrayExpression([createLiteral(0), createLiteral(0)]),
|
|
|
|
]),
|
|
|
|
createCallExpression('lineTo', [
|
|
|
|
createArrayExpression([createLiteral(1), createLiteral(1)]),
|
|
|
|
createPipeSubstitution(),
|
|
|
|
]),
|
|
|
|
createCallExpression('transform', [
|
|
|
|
createCallExpression('getExtrudeWallTransform', [
|
|
|
|
createLiteral(tag),
|
|
|
|
createIdentifier(oldSketchName),
|
|
|
|
]),
|
|
|
|
createPipeSubstitution(),
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
'const'
|
|
|
|
)
|
|
|
|
const expressionIndex = getLastIndex(pathToOldSketch)
|
|
|
|
_node.body.splice(expressionIndex + 1, 0, newSketch)
|
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst: addToShow(_node, newSketchName),
|
2023-04-01 16:47:00 +11:00
|
|
|
pathToNode: [...pathToNode.slice(0, -1), [expressionIndex, 'index']],
|
2023-02-12 10:56:45 +11:00
|
|
|
}
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
|
2023-03-10 08:35:30 +11:00
|
|
|
export const getLastIndex = (pathToNode: PathToNode): number =>
|
|
|
|
splitPathAtLastIndex(pathToNode).index
|
|
|
|
|
|
|
|
export function splitPathAtLastIndex(pathToNode: PathToNode): {
|
|
|
|
path: PathToNode
|
|
|
|
index: number
|
|
|
|
} {
|
2023-02-12 10:56:45 +11:00
|
|
|
const last = pathToNode[pathToNode.length - 1]
|
2023-04-01 16:47:00 +11:00
|
|
|
if (last && typeof last[0] === 'number') {
|
2023-03-10 08:35:30 +11:00
|
|
|
return {
|
|
|
|
path: pathToNode.slice(0, -1),
|
2023-04-01 16:47:00 +11:00
|
|
|
index: last[0],
|
2023-03-10 08:35:30 +11:00
|
|
|
}
|
2023-03-21 19:02:18 +11:00
|
|
|
} else if (pathToNode.length === 0) {
|
|
|
|
return {
|
|
|
|
path: [],
|
|
|
|
index: -1,
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
2023-03-10 08:35:30 +11:00
|
|
|
return splitPathAtLastIndex(pathToNode.slice(0, -1))
|
2023-02-12 10:56:45 +11:00
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
|
2023-04-01 16:47:00 +11:00
|
|
|
export function splitPathAtPipeExpression(pathToNode: PathToNode): {
|
|
|
|
path: PathToNode
|
|
|
|
index: number
|
|
|
|
} {
|
|
|
|
const last = pathToNode[pathToNode.length - 1]
|
|
|
|
|
|
|
|
if (
|
|
|
|
last &&
|
|
|
|
last[1] === 'index' &&
|
|
|
|
pathToNode?.[pathToNode.length - 2]?.[1] === 'PipeExpression' &&
|
|
|
|
typeof last[0] === 'number'
|
|
|
|
) {
|
|
|
|
return {
|
|
|
|
path: pathToNode.slice(0, -1),
|
|
|
|
index: last[0],
|
|
|
|
}
|
|
|
|
} else if (pathToNode.length === 0) {
|
|
|
|
return {
|
|
|
|
path: [],
|
|
|
|
index: -1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return splitPathAtPipeExpression(pathToNode.slice(0, -1))
|
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function createLiteral(value: string | number): Literal {
|
|
|
|
return {
|
|
|
|
type: 'Literal',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
value,
|
|
|
|
raw: `${value}`,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createIdentifier(name: string): Identifier {
|
|
|
|
return {
|
|
|
|
type: 'Identifier',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createPipeSubstitution(): PipeSubstitution {
|
|
|
|
return {
|
|
|
|
type: 'PipeSubstitution',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createCallExpression(
|
|
|
|
name: string,
|
|
|
|
args: CallExpression['arguments']
|
|
|
|
): CallExpression {
|
|
|
|
return {
|
|
|
|
type: 'CallExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
callee: {
|
|
|
|
type: 'Identifier',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
name,
|
|
|
|
},
|
|
|
|
optional: false,
|
|
|
|
arguments: args,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createArrayExpression(
|
|
|
|
elements: ArrayExpression['elements']
|
|
|
|
): ArrayExpression {
|
|
|
|
return {
|
|
|
|
type: 'ArrayExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
elements,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createPipeExpression(
|
|
|
|
body: PipeExpression['body']
|
|
|
|
): PipeExpression {
|
|
|
|
return {
|
2023-01-09 13:19:14 +11:00
|
|
|
type: 'PipeExpression',
|
2023-02-12 10:56:45 +11:00
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
body,
|
2023-02-01 07:30:55 +11:00
|
|
|
nonCodeMeta: {},
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
export function createVariableDeclaration(
|
|
|
|
varName: string,
|
|
|
|
init: VariableDeclarator['init'],
|
|
|
|
kind: VariableDeclaration['kind'] = 'const'
|
|
|
|
): VariableDeclaration {
|
|
|
|
return {
|
2023-01-09 13:19:14 +11:00
|
|
|
type: 'VariableDeclaration',
|
2023-02-12 10:56:45 +11:00
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2023-01-09 13:19:14 +11:00
|
|
|
declarations: [
|
|
|
|
{
|
|
|
|
type: 'VariableDeclarator',
|
2023-02-12 10:56:45 +11:00
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
id: createIdentifier(varName),
|
|
|
|
init,
|
2023-01-09 13:19:14 +11:00
|
|
|
},
|
|
|
|
],
|
2023-02-12 10:56:45 +11:00
|
|
|
kind,
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function createObjectExpression(properties: {
|
|
|
|
[key: string]: Value
|
|
|
|
}): ObjectExpression {
|
|
|
|
return {
|
|
|
|
type: 'ObjectExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
properties: Object.entries(properties).map(([key, value]) => ({
|
|
|
|
type: 'ObjectProperty',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
key: createIdentifier(key),
|
|
|
|
value,
|
|
|
|
})),
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
|
|
|
}
|
2023-03-02 21:19:11 +11:00
|
|
|
|
|
|
|
export function createUnaryExpression(
|
|
|
|
argument: UnaryExpression['argument'],
|
|
|
|
operator: UnaryExpression['operator'] = '-'
|
|
|
|
): UnaryExpression {
|
|
|
|
return {
|
|
|
|
type: 'UnaryExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
operator,
|
|
|
|
argument,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createBinaryExpression([left, operator, right]: [
|
|
|
|
BinaryExpression['left'],
|
|
|
|
BinaryExpression['operator'],
|
|
|
|
BinaryExpression['right']
|
|
|
|
]): BinaryExpression {
|
|
|
|
return {
|
|
|
|
type: 'BinaryExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
operator,
|
|
|
|
left,
|
|
|
|
right,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-02 17:20:11 +10:00
|
|
|
export function createBinaryExpressionWithUnary([left, right]: [
|
|
|
|
BinaryExpression['left'],
|
|
|
|
BinaryExpression['right']
|
|
|
|
]): BinaryExpression {
|
|
|
|
if (right.type === 'UnaryExpression' && right.operator === '-')
|
|
|
|
return createBinaryExpression([left, '-', right.argument])
|
|
|
|
return createBinaryExpression([left, '+', right])
|
|
|
|
}
|
|
|
|
|
2023-03-02 21:19:11 +11:00
|
|
|
export function giveSketchFnCallTag(
|
|
|
|
ast: Program,
|
2023-04-03 16:05:25 +10:00
|
|
|
range: Selection['range'],
|
2023-03-07 15:45:59 +11:00
|
|
|
tag?: string
|
2023-04-14 07:49:36 +10:00
|
|
|
): {
|
|
|
|
modifiedAst: Program
|
|
|
|
tag: string
|
|
|
|
isTagExisting: boolean
|
|
|
|
pathToNode: PathToNode
|
|
|
|
} {
|
|
|
|
const path = getNodePathFromSourceRange(ast, range)
|
2023-03-02 21:19:11 +11:00
|
|
|
const { node: primaryCallExp } = getNodeFromPath<CallExpression>(
|
|
|
|
ast,
|
2023-04-14 07:49:36 +10:00
|
|
|
path,
|
2023-04-01 16:47:00 +11:00
|
|
|
'CallExpression'
|
2023-03-02 21:19:11 +11:00
|
|
|
)
|
|
|
|
const firstArg = getFirstArg(primaryCallExp)
|
2023-03-07 15:45:59 +11:00
|
|
|
const isTagExisting = !!firstArg.tag
|
2023-03-02 21:19:11 +11:00
|
|
|
const tagValue = (firstArg.tag ||
|
2023-03-07 15:45:59 +11:00
|
|
|
createLiteral(tag || findUniqueName(ast, 'seg', 2))) as Literal
|
2023-03-02 21:19:11 +11:00
|
|
|
const tagStr = String(tagValue.value)
|
|
|
|
const newFirstArg = createFirstArg(
|
|
|
|
primaryCallExp.callee.name as TooTip,
|
|
|
|
firstArg.val,
|
|
|
|
tagValue
|
|
|
|
)
|
|
|
|
primaryCallExp.arguments[0] = newFirstArg
|
|
|
|
return {
|
|
|
|
modifiedAst: ast,
|
|
|
|
tag: tagStr,
|
2023-03-07 15:45:59 +11:00
|
|
|
isTagExisting,
|
2023-04-14 07:49:36 +10:00
|
|
|
pathToNode: path,
|
2023-03-02 21:19:11 +11:00
|
|
|
}
|
|
|
|
}
|
2023-04-01 16:47:00 +11:00
|
|
|
|
|
|
|
export function moveValueIntoNewVariable(
|
|
|
|
ast: Program,
|
|
|
|
programMemory: ProgramMemory,
|
2023-04-03 16:05:25 +10:00
|
|
|
sourceRange: Selection['range'],
|
2023-04-01 16:47:00 +11:00
|
|
|
variableName: string
|
|
|
|
): {
|
|
|
|
modifiedAst: Program
|
|
|
|
} {
|
|
|
|
const { isSafe, value, replacer } = isNodeSafeToReplace(ast, sourceRange)
|
|
|
|
if (!isSafe || value.type === 'Identifier') return { modifiedAst: ast }
|
|
|
|
|
|
|
|
const { insertIndex } = findAllPreviousVariables(
|
|
|
|
ast,
|
|
|
|
programMemory,
|
|
|
|
sourceRange
|
|
|
|
)
|
|
|
|
let _node = JSON.parse(JSON.stringify(ast))
|
|
|
|
_node = replacer(_node, variableName).modifiedAst
|
|
|
|
_node.body.splice(
|
|
|
|
insertIndex,
|
|
|
|
0,
|
|
|
|
createVariableDeclaration(variableName, value)
|
|
|
|
)
|
|
|
|
return { modifiedAst: _node }
|
|
|
|
}
|