2023-02-01 07:30:55 +11:00
|
|
|
import { recast } from './recast'
|
2022-11-26 19:03:09 +11:00
|
|
|
import { Program, abstractSyntaxTree } from './abstractSyntaxTree'
|
|
|
|
import { lexer, Token } from './tokeniser'
|
|
|
|
import fs from 'node:fs'
|
2022-11-26 08:00:18 +11:00
|
|
|
|
2022-11-26 08:31:10 +11:00
|
|
|
describe('recast', () => {
|
|
|
|
it('recasts a simple program', () => {
|
|
|
|
const code = '1 + 2'
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code)
|
|
|
|
})
|
|
|
|
it('variable declaration', () => {
|
|
|
|
const code = 'const myVar = 5'
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code)
|
|
|
|
})
|
|
|
|
it("variable declaration that's binary with string", () => {
|
|
|
|
const code = "const myVar = 5 + 'yo'"
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code)
|
|
|
|
const codeWithOtherQuotes = 'const myVar = 5 + "yo"'
|
|
|
|
const { ast: ast2 } = code2ast(codeWithOtherQuotes)
|
|
|
|
expect(recast(ast2)).toBe(codeWithOtherQuotes)
|
|
|
|
})
|
2022-11-26 19:03:09 +11:00
|
|
|
it('test assigning two variables, the second summing with the first', () => {
|
|
|
|
const code = `const myVar = 5
|
|
|
|
const newVar = myVar + 1`
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code)
|
|
|
|
})
|
|
|
|
it('test assigning a var by cont concatenating two strings string', () => {
|
|
|
|
const code = fs.readFileSync(
|
|
|
|
'./src/lang/testExamples/variableDeclaration.cado',
|
|
|
|
'utf-8'
|
|
|
|
)
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
|
|
|
it('test with function call', () => {
|
|
|
|
const code = `
|
|
|
|
const myVar = "hello"
|
|
|
|
log(5, myVar)`
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
2023-02-01 07:30:55 +11:00
|
|
|
expect(recasted).toBe(code)
|
2022-11-26 19:03:09 +11:00
|
|
|
})
|
|
|
|
it('function declaration with call', () => {
|
2022-11-27 14:07:03 +11:00
|
|
|
const code = [
|
|
|
|
'fn funcN = (a, b) => {',
|
|
|
|
' return a + b',
|
|
|
|
'}',
|
|
|
|
'const theVar = 60',
|
|
|
|
'const magicNum = funcN(9, theVar)',
|
|
|
|
].join('\n')
|
2022-11-26 19:03:09 +11:00
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
2023-02-01 07:30:55 +11:00
|
|
|
expect(recasted).toBe(code)
|
2022-11-26 19:03:09 +11:00
|
|
|
})
|
|
|
|
it('sketch declaration', () => {
|
|
|
|
let code = `sketch mySketch {
|
|
|
|
path myPath = lineTo(0, 1)
|
|
|
|
lineTo(1, 1)
|
|
|
|
path rightPath = lineTo(1, 0)
|
|
|
|
close()
|
|
|
|
}
|
|
|
|
show(mySketch)
|
|
|
|
`
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
2022-12-04 13:10:26 +11:00
|
|
|
it('sketch piped into callExpression', () => {
|
|
|
|
const code = [
|
|
|
|
'sketch mySk1 {',
|
|
|
|
' lineTo(1, 1)',
|
|
|
|
' path myPath = lineTo(0, 1)',
|
|
|
|
' lineTo(1, 1)',
|
|
|
|
'}',
|
|
|
|
' |> rx(90, %)',
|
|
|
|
].join('\n')
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
|
|
|
it('recast BinaryExpression piped into CallExpression', () => {
|
|
|
|
const code = [
|
|
|
|
'fn myFn = (a) => {',
|
|
|
|
' return a + 1',
|
|
|
|
'}',
|
|
|
|
'const myVar = 5 + 1',
|
|
|
|
' |> myFn(%)',
|
|
|
|
].join('\n')
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
2023-02-01 07:30:55 +11:00
|
|
|
expect(recasted).toBe(code)
|
2022-12-04 13:10:26 +11:00
|
|
|
})
|
2023-01-21 21:23:01 +11:00
|
|
|
it('recast nested binary expression', () => {
|
|
|
|
const code = ['const myVar = 1 + 2 * 5'].join('\n')
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
|
|
|
it('recast nested binary expression with parans', () => {
|
|
|
|
const code = ['const myVar = 1 + (1 + 2) * 5'].join('\n')
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
|
|
|
it('unnecessary paran wrap will be remove', () => {
|
|
|
|
const code = ['const myVar = 1 + (2 * 5)'].join('\n')
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.replace('(', '').replace(')', ''))
|
|
|
|
})
|
|
|
|
it('complex nested binary expression', () => {
|
|
|
|
const code = ['1 * ((2 + 3) / 4 + 5)'].join('\n')
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
|
|
|
it('multiplied paren expressions', () => {
|
|
|
|
const code = ['3 + (1 + 2) * (3 + 4)'].join('\n')
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
2022-12-30 21:53:50 +11:00
|
|
|
it('recast array declaration', () => {
|
|
|
|
const code = ['const three = 3', "const yo = [1, '2', three, 4 + 5]"].join(
|
|
|
|
'\n'
|
|
|
|
)
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
|
|
|
it('recast long array declaration', () => {
|
|
|
|
const code = [
|
|
|
|
'const three = 3',
|
|
|
|
'const yo = [',
|
|
|
|
' 1,',
|
|
|
|
" '2',",
|
|
|
|
' three,',
|
|
|
|
' 4 + 5,',
|
|
|
|
" 'hey oooooo really long long long'",
|
|
|
|
']',
|
|
|
|
].join('\n')
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
2023-01-01 21:48:30 +11:00
|
|
|
it('recast long object exectution', () => {
|
|
|
|
const code = `const three = 3
|
|
|
|
const yo = {
|
|
|
|
aStr: 'str',
|
|
|
|
anum: 2,
|
|
|
|
identifier: three,
|
|
|
|
binExp: 4 + 5
|
|
|
|
}`
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
|
|
|
it('recast short object exectution', () => {
|
|
|
|
const code = `const yo = { key: 'val' }`
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
2023-01-03 19:41:27 +11:00
|
|
|
it('recast object execution with member expression', () => {
|
|
|
|
const code = `const yo = { a: { b: { c: '123' } } }
|
|
|
|
const key = 'c'
|
|
|
|
const myVar = yo.a['b'][key]
|
|
|
|
const key2 = 'b'
|
|
|
|
const myVar2 = yo['a'][key2].c`
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code.trim())
|
|
|
|
})
|
2023-02-01 07:30:55 +11:00
|
|
|
})
|
|
|
|
|
|
|
|
describe('testing recasting with comments and whitespace', () => {
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
it('code with comments', () => {
|
|
|
|
const code = `
|
|
|
|
const yo = { a: { b: { c: '123' } } }
|
|
|
|
// this is a comment
|
|
|
|
const key = 'c'`
|
|
|
|
|
2023-02-01 07:30:55 +11:00
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
|
2023-02-01 07:30:55 +11:00
|
|
|
expect(recasted).toBe(code)
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
})
|
2023-02-01 07:30:55 +11:00
|
|
|
it('code with comment and extra lines', () => {
|
|
|
|
const code = `
|
|
|
|
const yo = 'c' /* this is
|
|
|
|
a
|
|
|
|
comment */
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
|
2023-02-01 07:30:55 +11:00
|
|
|
const yo = 'bing'`
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code)
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
})
|
2023-02-01 07:30:55 +11:00
|
|
|
it('comments at the start and end', () => {
|
|
|
|
const code = `
|
|
|
|
// this is a comment
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
|
|
|
|
const yo = { a: { b: { c: '123' } } }
|
|
|
|
const key = 'c'
|
|
|
|
|
2023-02-01 07:30:55 +11:00
|
|
|
// this is also a comment`
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code)
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
})
|
2023-02-01 07:30:55 +11:00
|
|
|
it('comments in a fn block', () => {
|
|
|
|
const code = `
|
|
|
|
const myFn = () => {
|
|
|
|
// this is a comment
|
|
|
|
const yo = { a: { b: { c: '123' } } } /* block
|
|
|
|
comment */
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
|
2023-02-01 07:30:55 +11:00
|
|
|
const key = 'c'
|
|
|
|
// this is also a comment
|
|
|
|
}`
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code)
|
|
|
|
})
|
|
|
|
it('comments in a sketch block', () => {
|
|
|
|
const code = `
|
|
|
|
sketch mySketch { /* comment at start */
|
|
|
|
// comment at start more
|
|
|
|
path myPath = lineTo(0, 1) /* comment here with
|
|
|
|
some whitespace below */
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
|
|
|
|
|
2023-02-01 07:30:55 +11:00
|
|
|
lineTo(1, 1)
|
|
|
|
/* comment before declaration*/path rightPath = lineTo(1, 0)
|
|
|
|
close()
|
|
|
|
// comment at end
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
|
|
|
|
}`
|
2023-02-01 07:30:55 +11:00
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code)
|
2023-01-24 21:09:00 +11:00
|
|
|
})
|
2023-02-01 07:30:55 +11:00
|
|
|
it('comments in a pipe expression', () => {
|
|
|
|
const code = [
|
|
|
|
'sketch mySk1 {',
|
|
|
|
' lineTo(1, 1)',
|
|
|
|
' path myPath = lineTo(0, 1)',
|
|
|
|
' lineTo(1, 1)',
|
|
|
|
'}',
|
|
|
|
' // a comment',
|
|
|
|
' |> rx(90, %)',
|
|
|
|
].join('\n')
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code)
|
|
|
|
})
|
|
|
|
it('comments sprinkled in all over the place', () => {
|
|
|
|
const code = `
|
|
|
|
/* comment at start */
|
2023-01-24 21:09:00 +11:00
|
|
|
|
2023-02-01 07:30:55 +11:00
|
|
|
sketch mySk1 {
|
|
|
|
lineTo(1, 1)
|
|
|
|
// comment here
|
|
|
|
path myPath = lineTo(0, 1)
|
|
|
|
lineTo(1, 1) /* and
|
|
|
|
here
|
|
|
|
*/
|
2023-01-24 21:09:00 +11:00
|
|
|
}
|
2023-02-01 07:30:55 +11:00
|
|
|
// a comment between pipe expression statements
|
2023-01-24 21:09:00 +11:00
|
|
|
|> rx(90, %)
|
2023-02-01 07:30:55 +11:00
|
|
|
// and another with just white space between others below
|
|
|
|
|> ry(45, %)
|
2023-01-24 21:09:00 +11:00
|
|
|
|
|
|
|
|
2023-02-01 07:30:55 +11:00
|
|
|
|> rx(45, %)
|
|
|
|
/*
|
|
|
|
one more for good measure
|
|
|
|
*/`
|
|
|
|
const { ast } = code2ast(code)
|
|
|
|
const recasted = recast(ast)
|
|
|
|
expect(recasted).toBe(code)
|
Add the ability to recast comments and some whitespace (#10)
* Add the ability to recast comments and some whitespace
Currently because whitespace or anything that's not needed for execution is not stored in the AST, it's hard to respect things like user formatting when recasting.
I think having a by-default-opinioned formatter is a good thing, but where this becomes problematic is when users wants to simply leave a blank space between some lines for a bit of breathing room, a code paragraph if you will, but maybe more importantly comments have not been implemented for the same reason, there wasn't a way with the current setup to insert them back in.
In some ways the most straightforward way to do this is to put whitespace and comments into the AST. Even though they are not crucial for execution, code-gen/recasting needs to be a first-class citizen in this lang so that's probably the long-term solution. However I'm trying to draw inspiration from other languages, and since it's not the norm to put comments et-al into the AST I haven't done so.
Because whitespace is tokenised already if not transformed into the AST, there is somewhat of a map of these things without going back to source code, so atm I'm experimenting with using this to insert extra linebreaks and comments back in between statements. I think this is a good compromise for the time being for what is a nice to have feature atm.
Because it's only going to respect non-code parts in between statements this will mean that you can't format objects or function params how you like (but I think this is good to have an opinioned fmt out of the box) and comments like myFunctionCall('a', /* inline comment */ b) will not work either.
* clean up
2023-01-23 14:50:58 +11:00
|
|
|
})
|
2022-11-26 08:31:10 +11:00
|
|
|
})
|
2022-11-26 08:00:18 +11:00
|
|
|
|
|
|
|
// helpers
|
|
|
|
|
2022-11-26 08:31:10 +11:00
|
|
|
function code2ast(code: string): { ast: Program; tokens: Token[] } {
|
|
|
|
const tokens = lexer(code)
|
|
|
|
const ast = abstractSyntaxTree(tokens)
|
2022-11-26 08:00:18 +11:00
|
|
|
return {
|
|
|
|
ast,
|
2022-11-26 08:31:10 +11:00
|
|
|
tokens,
|
2022-11-26 08:00:18 +11:00
|
|
|
}
|
|
|
|
}
|