Add comments to the tree #24
|
|
@ -75,6 +75,7 @@ export class Compiler {
|
|||
if (DEBUG) {
|
||||
const bytecodeString = bytecodeToString(this.bytecode)
|
||||
console.log(`\n🤖 bytecode:\n----------------\n${bytecodeString}\n\n`)
|
||||
console.log(`\n🤖 bytecode:\n----------------\n${this.instructions}\n\n`)
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof CompilerError) {
|
||||
|
|
@ -281,13 +282,27 @@ export class Compiler {
|
|||
|
||||
const opValue = input.slice(operator.from, operator.to)
|
||||
switch (opValue) {
|
||||
case '+=': instructions.push(['ADD']); break
|
||||
case '-=': instructions.push(['SUB']); break
|
||||
case '*=': instructions.push(['MUL']); break
|
||||
case '/=': instructions.push(['DIV']); break
|
||||
case '%=': instructions.push(['MOD']); break
|
||||
case '+=':
|
||||
instructions.push(['ADD'])
|
||||
break
|
||||
case '-=':
|
||||
instructions.push(['SUB'])
|
||||
break
|
||||
case '*=':
|
||||
instructions.push(['MUL'])
|
||||
break
|
||||
case '/=':
|
||||
instructions.push(['DIV'])
|
||||
break
|
||||
case '%=':
|
||||
instructions.push(['MOD'])
|
||||
break
|
||||
default:
|
||||
throw new CompilerError(`Unknown compound operator: ${opValue}`, operator.from, operator.to)
|
||||
throw new CompilerError(
|
||||
`Unknown compound operator: ${opValue}`,
|
||||
operator.from,
|
||||
operator.to
|
||||
)
|
||||
}
|
||||
|
||||
// DUP and store (same as regular assignment)
|
||||
|
|
@ -305,10 +320,8 @@ export class Compiler {
|
|||
}
|
||||
|
||||
case terms.FunctionDef: {
|
||||
const { paramNames, bodyNodes, catchVariable, catchBody, finallyBody } = getFunctionDefParts(
|
||||
node,
|
||||
input
|
||||
)
|
||||
const { paramNames, bodyNodes, catchVariable, catchBody, finallyBody } =
|
||||
getFunctionDefParts(node, input)
|
||||
const instructions: ProgramItem[] = []
|
||||
const functionLabel: Label = `.func_${this.fnLabelCount++}`
|
||||
const afterLabel: Label = `.after_${functionLabel}`
|
||||
|
|
@ -331,7 +344,13 @@ export class Compiler {
|
|||
if (catchVariable || finallyBody) {
|
||||
// If function has catch or finally, wrap body in try/catch/finally
|
||||
instructions.push(
|
||||
...this.#compileTryCatchFinally(compileFunctionBody, catchVariable, catchBody, finallyBody, input)
|
||||
...this.#compileTryCatchFinally(
|
||||
compileFunctionBody,
|
||||
catchVariable,
|
||||
catchBody,
|
||||
finallyBody,
|
||||
input
|
||||
)
|
||||
)
|
||||
} else {
|
||||
instructions.push(...compileFunctionBody())
|
||||
|
|
@ -414,8 +433,9 @@ export class Compiler {
|
|||
instructions.push(['JUMP', afterLabel])
|
||||
instructions.push([`${fnLabel}:`])
|
||||
instructions.push(
|
||||
...block.filter(x => x.type.name !== 'keyword')
|
||||
.map(x => this.#compileNode(x!, input))
|
||||
...block
|
||||
.filter((x) => x.type.name !== 'keyword')
|
||||
.map((x) => this.#compileNode(x!, input))
|
||||
.flat()
|
||||
)
|
||||
instructions.push(['RETURN'])
|
||||
|
|
@ -435,15 +455,16 @@ export class Compiler {
|
|||
body = [
|
||||
...body.slice(0, startSlice),
|
||||
['MAKE_FUNCTION', [], fnLabel],
|
||||
...body.slice(startSlice)
|
||||
...body.slice(startSlice),
|
||||
]
|
||||
|
||||
// @ts-ignore
|
||||
body[body.length - 3]![1] += 1
|
||||
instructions.push(...body)
|
||||
|
||||
} else {
|
||||
throw new Error(`FunctionCallWithBlock: Expected FunctionCallOrIdentifier or FunctionCall`)
|
||||
throw new Error(
|
||||
`FunctionCallWithBlock: Expected FunctionCallOrIdentifier or FunctionCall`
|
||||
)
|
||||
}
|
||||
|
||||
return instructions
|
||||
|
|
@ -636,13 +657,13 @@ export class Compiler {
|
|||
}
|
||||
|
||||
case terms.Array: {
|
||||
const children = getAllChildren(node)
|
||||
const children = getAllChildren(node).filter((n) => n.type.id !== terms.Comment)
|
||||
|
|
||||
|
||||
// We can easily parse [=] as an empty dict, but `[ = ]` is tougher.
|
||||
// = can be a valid word, and is also valid inside words, so for now we cheat
|
||||
// and check for arrays that look like `[ = ]` to interpret them as
|
||||
// empty dicts
|
||||
if (children.length === 1 && children[0]!.name === 'Word') {
|
||||
if (children.length === 1 && children[0]!.type.id === terms.Word) {
|
||||
const child = children[0]!
|
||||
if (input.slice(child.from, child.to) === '=') {
|
||||
return [['MAKE_DICT', 0]]
|
||||
|
|
@ -655,7 +676,7 @@ export class Compiler {
|
|||
}
|
||||
|
||||
case terms.Dict: {
|
||||
const children = getAllChildren(node)
|
||||
const children = getAllChildren(node).filter((n) => n.type.id !== terms.Comment)
|
||||
const instructions: ProgramItem[] = []
|
||||
|
||||
children.forEach((node) => {
|
||||
|
|
@ -691,6 +712,10 @@ export class Compiler {
|
|||
return instructions
|
||||
}
|
||||
|
||||
case terms.Comment: {
|
||||
return [] // ignore comments
|
||||
}
|
||||
|
||||
default:
|
||||
throw new CompilerError(
|
||||
`Compiler doesn't know how to handle a "${node.type.name}" node.`,
|
||||
|
|
|
|||
|
|
@ -304,9 +304,12 @@ describe('default params', () => {
|
|||
})
|
||||
|
||||
test.skip('dict default', () => {
|
||||
expect('make-person = do person=[name=Bob age=60]: person end; make-person')
|
||||
.toEvaluateTo({ name: 'Bob', age: 60 })
|
||||
expect('make-person = do person=[name=Bob age=60]: person end; make-person [name=Jon age=21]')
|
||||
.toEvaluateTo({ name: 'Jon', age: 21 })
|
||||
expect('make-person = do person=[name=Bob age=60]: person end; make-person').toEvaluateTo({
|
||||
name: 'Bob',
|
||||
age: 60,
|
||||
})
|
||||
expect(
|
||||
'make-person = do person=[name=Bob age=60]: person end; make-person [name=Jon age=21]'
|
||||
).toEvaluateTo({ name: 'Jon', age: 21 })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ describe('array literals', () => {
|
|||
})
|
||||
|
||||
test('comments within arrays', () => {
|
||||
expect(`[1 # first
|
||||
2 # second
|
||||
expect(`[1
|
||||
2
|
||||
]`).toEvaluateTo([1, 2])
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -150,8 +150,11 @@ describe('array literals', () => {
|
|||
2 # second
|
||||
]`).toMatchTree(`
|
||||
Array
|
||||
Comment # something...
|
||||
Number 1
|
||||
Comment # first
|
||||
Number 2
|
||||
Comment # second
|
||||
`)
|
||||
})
|
||||
|
||||
|
|
@ -397,12 +400,15 @@ c=3]`).toMatchTree(`
|
|||
c=3
|
||||
]`).toMatchTree(`
|
||||
Dict
|
||||
Comment # something...
|
||||
NamedArg
|
||||
NamedArgPrefix a=
|
||||
Number 1
|
||||
Comment # first
|
||||
NamedArg
|
||||
NamedArgPrefix b=
|
||||
Number 2
|
||||
Comment # second
|
||||
NamedArg
|
||||
NamedArgPrefix c=
|
||||
Number 3
|
||||
|
|
|
|||
BIN
vscode-extension/shrimp-0.0.1.vsix
Normal file
BIN
vscode-extension/shrimp-0.0.1.vsix
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user
Maybe put the filter in getAllChildren() so we won't have to worry about it?
YES