Add new query for getting available variables (#52)

* Add new query for getting available variables

* use array for findAllPreviousVariables
This commit is contained in:
Kurt Hutten
2023-03-10 08:35:30 +11:00
committed by GitHub
parent d729ae3990
commit 2bb987b3b5
3 changed files with 102 additions and 4 deletions

View File

@ -335,12 +335,21 @@ export function sketchOnExtrudedFace(
} }
} }
export const getLastIndex = (pathToNode: PathToNode): number => { export const getLastIndex = (pathToNode: PathToNode): number =>
splitPathAtLastIndex(pathToNode).index
export function splitPathAtLastIndex(pathToNode: PathToNode): {
path: PathToNode
index: number
} {
const last = pathToNode[pathToNode.length - 1] const last = pathToNode[pathToNode.length - 1]
if (typeof last === 'number') { if (typeof last === 'number') {
return last return {
path: pathToNode.slice(0, -1),
index: last,
}
} }
return getLastIndex(pathToNode.slice(0, -1)) return splitPathAtLastIndex(pathToNode.slice(0, -1))
} }
export function createLiteral(value: string | number): Literal { export function createLiteral(value: string | number): Literal {

48
src/lang/queryAst.test.ts Normal file
View File

@ -0,0 +1,48 @@
import { abstractSyntaxTree } from './abstractSyntaxTree'
import { findAllPreviousVariables } from './queryAst'
import { lexer } from './tokeniser'
import { initPromise } from './rust'
import { executor } from './executor'
beforeAll(() => initPromise)
describe('findAllPreviousVariables', () => {
it('should find all previous variables', () => {
const code = `const baseThick = 1
const armAngle = 60
const baseThickHalf = baseThick / 2
const halfArmAngle = armAngle / 2
const arrExpShouldNotBeIncluded = [1, 2, 3]
const objExpShouldNotBeIncluded = { a: 1, b: 2, c: 3 }
const part001 = startSketchAt([0, 0])
|> yLineTo(1, %)
|> xLine(3.84, %) // selection-range-7ish-before-this
const variableBelowShouldNotBeIncluded = 3
show(part001)`
const rangeStart = code.indexOf('// selection-range-7ish-before-this') - 7
const ast = abstractSyntaxTree(lexer(code))
const programMemory = executor(ast)
const { variables, bodyPath, insertIndex } = findAllPreviousVariables(
ast,
programMemory,
[rangeStart, rangeStart]
)
expect(variables).toEqual([
{ key: 'baseThick', value: 1 },
{ key: 'armAngle', value: 60 },
{ key: 'baseThickHalf', value: 0.5 },
{ key: 'halfArmAngle', value: 30 },
// no arrExpShouldNotBeIncluded, variableBelowShouldNotBeIncluded etc
])
// there are 4 number variables and 2 non-number variables before the sketch var
// ∴ the insert index should be 6
expect(insertIndex).toEqual(6)
expect(bodyPath).toEqual(['body'])
})
})

View File

@ -1,6 +1,7 @@
import { PathToNode } from './executor' import { PathToNode, ProgramMemory } from './executor'
import { Range } from '../useStore' import { Range } from '../useStore'
import { Program } from './abstractSyntaxTree' import { Program } from './abstractSyntaxTree'
import { splitPathAtLastIndex } from './modifyAst'
export function getNodeFromPath<T>( export function getNodeFromPath<T>(
node: Program, node: Program,
@ -133,3 +134,43 @@ export function getNodePathFromSourceRange(
} }
return path return path
} }
interface PrevVariable<T> {
key: string
value: T
}
export function findAllPreviousVariables(
ast: Program,
programMemory: ProgramMemory,
sourceRange: Range,
type: 'number' | 'string' = 'number'
): {
variables: PrevVariable<typeof type extends 'number' ? number : string>[]
bodyPath: PathToNode
insertIndex: number
} {
const path = getNodePathFromSourceRange(ast, sourceRange)
const { path: pathToDec } = getNodeFromPath(ast, path, 'VariableDeclaration')
const { index: insertIndex, path: bodyPath } = splitPathAtLastIndex(pathToDec)
const { node: bodyItems } = getNodeFromPath<Program['body']>(ast, bodyPath)
const variables: PrevVariable<any>[] = []
bodyItems.forEach((item) => {
if (item.type !== 'VariableDeclaration' || item.end > sourceRange[0]) return
const varName = item.declarations[0].id.name
const varValue = programMemory?.root[varName]
if (typeof varValue?.value !== type) return
variables.push({
key: varName,
value: varValue.value,
})
})
return {
insertIndex,
bodyPath: bodyPath,
variables,
}
}