Files
modeling-app/src/lang/executor.test.ts

206 lines
5.2 KiB
TypeScript
Raw Normal View History

2022-11-26 08:34:23 +11:00
import fs from 'node:fs'
2022-11-14 14:04:23 +11:00
2022-11-26 08:34:23 +11:00
import { abstractSyntaxTree } from './abstractSyntaxTree'
import { lexer } from './tokeniser'
import { executor, ProgramMemory } from './executor'
2022-12-06 05:40:05 +11:00
import { Transform, SketchGeo } from './sketch'
2022-11-14 14:04:23 +11:00
2022-11-26 08:34:23 +11:00
describe('test', () => {
it('test assigning two variables, the second summing with the first', () => {
2022-11-14 14:04:23 +11:00
const code = `const myVar = 5
2022-11-26 08:34:23 +11:00
const newVar = myVar + 1`
const { root } = exe(code)
expect(root.myVar).toBe(5)
expect(root.newVar).toBe(6)
})
it('test assigning a var with a string', () => {
const code = `const myVar = "a str"`
const { root } = exe(code)
expect(root.myVar).toBe('a str')
})
it('test assigning a var by cont concatenating two strings string', () => {
const code = fs.readFileSync(
2022-11-26 08:34:23 +11:00
'./src/lang/testExamples/variableDeclaration.cado',
'utf-8'
)
const { root } = exe(code)
expect(root.myVar).toBe('a str another str')
})
it('test with function call', () => {
2022-11-14 14:04:23 +11:00
const code = `
const myVar = "hello"
2022-11-26 08:34:23 +11:00
log(5, myVar)`
2022-11-14 14:04:23 +11:00
const programMemoryOverride = {
log: jest.fn(),
2022-11-26 08:34:23 +11:00
}
const { root } = executor(abstractSyntaxTree(lexer(code)), {
root: programMemoryOverride,
_sketch: [],
2022-11-26 08:34:23 +11:00
})
expect(root.myVar).toBe('hello')
expect(programMemoryOverride.log).toHaveBeenCalledWith(5, 'hello')
})
it('fn funcN = () => {}', () => {
const { root } = exe(
[
2022-11-26 08:34:23 +11:00
'fn funcN = (a, b) => {',
' return a + b',
'}',
'const theVar = 60',
'const magicNum = funcN(9, theVar)',
].join('\n')
)
expect(root.theVar).toBe(60)
expect(root.magicNum).toBe(69)
})
it('sketch declaration', () => {
let code = `sketch mySketch {
path myPath = lineTo(0,1)
lineTo(1,1)
path rightPath = lineTo(1,0)
close()
}
2022-11-21 09:16:24 +11:00
show(mySketch)
2022-11-26 08:34:23 +11:00
`
const { root, return: _return } = exe(code)
expect(
2022-12-06 05:40:05 +11:00
root.mySketch.sketch.map(
({ previousPath, firstPath, geo, ...rest }: any) => rest
)
).toEqual([
2022-11-26 21:03:38 +11:00
{ type: 'base', from: [0, 0], sourceRange: [0, 0] },
2022-11-26 08:34:23 +11:00
{ type: 'toPoint', to: [0, 1], sourceRange: [25, 45], name: 'myPath' },
{ type: 'toPoint', to: [1, 1], sourceRange: [48, 59] },
{ type: 'toPoint', to: [1, 0], sourceRange: [67, 90], name: 'rightPath' },
{
2022-11-26 08:34:23 +11:00
type: 'close',
sourceRange: [93, 100],
},
2022-11-26 08:34:23 +11:00
])
2022-12-06 05:40:05 +11:00
expect(root.mySketch.sketch[0]).toEqual(root.mySketch.sketch[4].firstPath)
2022-11-21 09:16:24 +11:00
// hmm not sure what handle the "show" function
expect(_return).toEqual([
{
2022-11-26 08:34:23 +11:00
type: 'Identifier',
2022-11-21 09:16:24 +11:00
start: 108,
end: 116,
2022-11-26 08:34:23 +11:00
name: 'mySketch',
2022-11-21 09:16:24 +11:00
},
2022-11-26 08:34:23 +11:00
])
})
it('pipe binary expression into call expression', () => {
const code = [
'fn myFn = (a) => { return a + 1 }',
'const myVar = 5 + 1 |> myFn(%)',
].join('\n')
const { root } = exe(code)
expect(root.myVar).toBe(7)
})
2022-12-04 08:16:04 +11:00
it('rotated sketch', () => {
const code = [
'sketch mySk1 {',
' lineTo(1,1)',
' path myPath = lineTo(0, 1)',
' lineTo(1,1)',
'}',
'const rotated = rx(90, mySk1)',
// 'show(mySk1)',
].join('\n')
const { root } = exe(code)
2022-12-06 05:40:05 +11:00
expect(root.mySk1.sketch).toHaveLength(4)
2022-12-04 08:16:04 +11:00
expect(root?.rotated?.type).toBe('transform')
})
it('execute pipe sketch into call expression', () => {
const code = [
'sketch mySk1 {',
' lineTo(1,1)',
' path myPath = lineTo(0, 1)',
' lineTo(1,1)',
'} |> rx(90, %)',
].join('\n')
const { root } = exe(code)
const striptVersion = removeGeoFromSketch(root.mySk1)
expect(striptVersion).toEqual({
2022-12-06 05:40:05 +11:00
type: 'sketchGeo',
2022-12-04 08:16:04 +11:00
sketch: [
{
type: 'base',
from: [0, 0],
sourceRange: [0, 0],
},
{
type: 'toPoint',
to: [1, 1],
sourceRange: [17, 28],
},
{
type: 'toPoint',
to: [0, 1],
sourceRange: [36, 57],
name: 'myPath',
},
{
type: 'toPoint',
to: [1, 1],
sourceRange: [60, 71],
},
],
2022-12-06 05:40:05 +11:00
sourceRange: [13, 73],
2022-12-04 08:16:04 +11:00
})
2022-12-06 05:40:05 +11:00
// old expect
// expect(striptVersion).toEqual({
// type: 'transform',
// rotation: [1.5707963267948966, 0, 0],
// transform: [0, 0, 0],
// sketch: [
// {
// type: 'base',
// from: [0, 0],
// sourceRange: [0, 0],
// },
// {
// type: 'toPoint',
// to: [1, 1],
// sourceRange: [17, 28],
// },
// {
// type: 'toPoint',
// to: [0, 1],
// sourceRange: [36, 57],
// name: 'myPath',
// },
// {
// type: 'toPoint',
// to: [1, 1],
// sourceRange: [60, 71],
// },
// ],
// sourceRange: [77, 86],
// })
2022-12-04 08:16:04 +11:00
})
2022-11-26 08:34:23 +11:00
})
2022-11-14 14:04:23 +11:00
// helpers
function exe(
code: string,
programMemory: ProgramMemory = { root: {}, _sketch: [] }
) {
2022-11-26 08:34:23 +11:00
const tokens = lexer(code)
const ast = abstractSyntaxTree(tokens)
return executor(ast, programMemory)
}
2022-12-04 08:16:04 +11:00
2022-12-06 05:40:05 +11:00
function removeGeoFromSketch(sketch: Transform | SketchGeo): any {
if (sketch.type !== 'sketchGeo') {
2022-12-04 08:16:04 +11:00
return removeGeoFromSketch(sketch.sketch)
}
return {
...sketch,
sketch: sketch.sketch.map(({ geo, previousPath, ...rest }: any) => rest),
}
}