Skip to content

Commit

Permalink
Merge branch 'main' into tag-as-top-level
Browse files Browse the repository at this point in the history
  • Loading branch information
jessfraz authored Jun 25, 2024
2 parents 64ec1df + 24516cd commit c9b4702
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 36 deletions.
53 changes: 52 additions & 1 deletion src/lang/queryAst.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { parse, recast, initPromise } from './wasm'
import { parse, recast, initPromise, PathToNode } from './wasm'
import {
findAllPreviousVariables,
isNodeSafeToReplace,
Expand All @@ -9,6 +9,7 @@ import {
findUsesOfTagInPipe,
hasSketchPipeBeenExtruded,
hasExtrudableGeometry,
traverse,
} from './queryAst'
import { enginelessExecutor } from '../lib/testHelpers'
import {
Expand Down Expand Up @@ -539,3 +540,53 @@ const extrude001 = extrude(10, sketch001)
expect(extrudable).toBeFalsy()
})
})

describe.only('Testing traverse and pathToNode', () => {
it.each([
['basic', '2.73'],
[
'very nested, array, object, callExpression, array, memberExpression',
'.yo',
],
])('testing %s', async (testName, literalOfInterest) => {
const code = `const myVar = 5
const sketch001 = startSketchOn('XZ')
|> startProfileAt([3.29, 7.86], %)
|> line([2.48, 2.44], %)
|> line([-3.86, -2.73], %)
|> line([-17.67, 0.85], %)
|> close(%)
const bing = { yo: 55 }
const myNestedVar = [
{
prop: line([bing.yo, 21], sketch001)
}
]
`
const ast = parse(code)
if (err(ast)) throw ast
let pathToNode: PathToNode = []
traverse(ast, {
enter: (node, path) => {
if (
node.type === 'Literal' &&
String(node.value) === literalOfInterest
) {
pathToNode = path
} else if (
node.type === 'Identifier' &&
literalOfInterest.includes(node.name)
) {
pathToNode = path
}
},
})

const literalIndex = code.indexOf(literalOfInterest)
const pathToNode2 = getNodePathFromSourceRange(ast, [
literalIndex + 2,
literalIndex + 2,
])
expect(pathToNode).toEqual(pathToNode2)
})
})
119 changes: 85 additions & 34 deletions src/lang/queryAst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,18 @@ function moreNodePathFromSourceRange(
}
}
}
if (_node.type === 'MemberExpression' && isInRange) {
const { object, property } = _node
if (object.start <= start && object.end >= end) {
path.push(['object', 'MemberExpression'])
return moreNodePathFromSourceRange(object, sourceRange, path)
}
if (property.start <= start && property.end >= end) {
path.push(['property', 'MemberExpression'])
return moreNodePathFromSourceRange(property, sourceRange, path)
}
return path
}
if (_node.type === 'PipeSubstitution' && isInRange) return path
console.error('not implemented: ' + node.type)
return path
Expand Down Expand Up @@ -307,48 +319,87 @@ type KCLNode =
| ReturnStatement

export function traverse(
node: KCLNode,
node: KCLNode | Program,
option: {
enter?: (node: KCLNode) => void
enter?: (node: KCLNode, pathToNode: PathToNode) => void
leave?: (node: KCLNode) => void
}
},
pathToNode: PathToNode = []
) {
option?.enter?.(node)
const _traverse = (node: KCLNode) => traverse(node, option)

if (node.type === 'VariableDeclaration') {
node.declarations.forEach(_traverse)
} else if (node.type === 'VariableDeclarator') {
_traverse(node.init)
} else if (node.type === 'PipeExpression') {
node.body.forEach(_traverse)
} else if (node.type === 'CallExpression') {
_traverse(node.callee)
node.arguments.forEach(_traverse)
} else if (node.type === 'BinaryExpression') {
_traverse(node.left)
_traverse(node.right)
} else if (node.type === 'Identifier') {
const _node = node as KCLNode
option?.enter?.(_node, pathToNode)
const _traverse = (node: KCLNode, pathToNode: PathToNode) =>
traverse(node, option, pathToNode)

if (_node.type === 'VariableDeclaration') {
_node.declarations.forEach((declaration, index) =>
_traverse(declaration, [
...pathToNode,
['declarations', 'VariableDeclaration'],
[index, 'index'],
])
)
} else if (_node.type === 'VariableDeclarator') {
_traverse(_node.init, [...pathToNode, ['init', '']])
} else if (_node.type === 'PipeExpression') {
_node.body.forEach((expression, index) =>
_traverse(expression, [
...pathToNode,
['body', 'PipeExpression'],
[index, 'index'],
])
)
} else if (_node.type === 'CallExpression') {
_traverse(_node.callee, [...pathToNode, ['callee', 'CallExpression']])
_node.arguments.forEach((arg, index) =>
_traverse(arg, [
...pathToNode,
['arguments', 'CallExpression'],
[index, 'index'],
])
)
} else if (_node.type === 'BinaryExpression') {
_traverse(_node.left, [...pathToNode, ['left', 'BinaryExpression']])
_traverse(_node.right, [...pathToNode, ['right', 'BinaryExpression']])
} else if (_node.type === 'Identifier') {
// do nothing
} else if (node.type === 'Literal') {
} else if (_node.type === 'Literal') {
// do nothing
} else if (node.type === 'ArrayExpression') {
node.elements.forEach(_traverse)
} else if (node.type === 'ObjectExpression') {
node.properties.forEach(({ key, value }) => {
_traverse(key)
_traverse(value)
} else if (_node.type === 'ArrayExpression') {
_node.elements.forEach((el, index) =>
_traverse(el, [
...pathToNode,
['elements', 'ArrayExpression'],
[index, 'index'],
])
)
} else if (_node.type === 'ObjectExpression') {
_node.properties.forEach(({ key, value }, index) => {
_traverse(key, [
...pathToNode,
['properties', 'ObjectExpression'],
[index, 'index'],
['key', 'Property'],
])
_traverse(value, [
...pathToNode,
['properties', 'ObjectExpression'],
[index, 'index'],
['value', 'Property'],
])
})
} else if (node.type === 'UnaryExpression') {
_traverse(node.argument)
} else if (node.type === 'MemberExpression') {
} else if (_node.type === 'UnaryExpression') {
_traverse(_node.argument, [...pathToNode, ['argument', 'UnaryExpression']])
} else if (_node.type === 'MemberExpression') {
// hmm this smell
_traverse(node.object)
_traverse(node.property)
} else if ('body' in node && Array.isArray(node.body)) {
node.body.forEach(_traverse)
_traverse(_node.object, [...pathToNode, ['object', 'MemberExpression']])
_traverse(_node.property, [...pathToNode, ['property', 'MemberExpression']])
} else if ('body' in _node && Array.isArray(_node.body)) {
_node.body.forEach((expression, index) =>
_traverse(expression, [...pathToNode, ['body', ''], [index, 'index']])
)
}
option?.leave?.(node)
option?.leave?.(_node)
}

export interface PrevVariable<T> {
Expand Down
52 changes: 51 additions & 1 deletion src/wasm-lib/kcl/src/ast/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2101,7 +2101,7 @@ impl ObjectExpression {
format!(
"{}: {}",
prop.key.name,
prop.value.recast(options, indentation_level + 1, is_in_pipe)
prop.value.recast(options, indentation_level + 1, is_in_pipe).trim()
)
})
.collect::<Vec<String>>()
Expand Down Expand Up @@ -3748,6 +3748,56 @@ const outsideRevolve = startSketchOn('XZ')
);
}

#[test]
fn test_recast_fn_in_object() {
let some_program_string = r#"const bing = { yo: 55 }
const myNestedVar = [{ prop: callExp(bing.yo) }]
"#;
let tokens = crate::token::lexer(some_program_string).unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();

let recasted = program.recast(&Default::default(), 0);
assert_eq!(recasted, some_program_string);
}

#[test]
fn test_recast_fn_in_array() {
let some_program_string = r#"const bing = { yo: 55 }
const myNestedVar = [callExp(bing.yo)]
"#;
let tokens = crate::token::lexer(some_program_string).unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();

let recasted = program.recast(&Default::default(), 0);
assert_eq!(recasted, some_program_string);
}

#[test]
fn test_recast_object_fn_in_array_weird_bracket() {
let some_program_string = r#"const bing = { yo: 55 }
const myNestedVar = [
{
prop: line([bing.yo, 21], sketch001)
}
]
"#;
let tokens = crate::token::lexer(some_program_string).unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();

let recasted = program.recast(&Default::default(), 0);
assert_eq!(
recasted,
r#"const bing = { yo: 55 }
const myNestedVar = [
{ prop: line([bing.yo, 21], sketch001) }
]
"#
);
}

#[test]
fn test_recast_empty_file() {
let some_program_string = r#""#;
Expand Down

0 comments on commit c9b4702

Please sign in to comment.