Fix them tests

This commit is contained in:
Corey Johnson 2025-11-05 12:40:31 -08:00
parent f57b1c985e
commit 653ff5df10
5 changed files with 60 additions and 26 deletions

View File

@ -75,6 +75,7 @@ export class Compiler {
if (DEBUG) { if (DEBUG) {
const bytecodeString = bytecodeToString(this.bytecode) const bytecodeString = bytecodeToString(this.bytecode)
console.log(`\n🤖 bytecode:\n----------------\n${bytecodeString}\n\n`) console.log(`\n🤖 bytecode:\n----------------\n${bytecodeString}\n\n`)
console.log(`\n🤖 bytecode:\n----------------\n${this.instructions}\n\n`)
} }
} catch (error) { } catch (error) {
if (error instanceof CompilerError) { if (error instanceof CompilerError) {
@ -281,13 +282,27 @@ export class Compiler {
const opValue = input.slice(operator.from, operator.to) const opValue = input.slice(operator.from, operator.to)
switch (opValue) { switch (opValue) {
case '+=': instructions.push(['ADD']); break case '+=':
case '-=': instructions.push(['SUB']); break instructions.push(['ADD'])
case '*=': instructions.push(['MUL']); break break
case '/=': instructions.push(['DIV']); break case '-=':
case '%=': instructions.push(['MOD']); break instructions.push(['SUB'])
break
case '*=':
instructions.push(['MUL'])
break
case '/=':
instructions.push(['DIV'])
break
case '%=':
instructions.push(['MOD'])
break
default: 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) // DUP and store (same as regular assignment)
@ -305,10 +320,8 @@ export class Compiler {
} }
case terms.FunctionDef: { case terms.FunctionDef: {
const { paramNames, bodyNodes, catchVariable, catchBody, finallyBody } = getFunctionDefParts( const { paramNames, bodyNodes, catchVariable, catchBody, finallyBody } =
node, getFunctionDefParts(node, input)
input
)
const instructions: ProgramItem[] = [] const instructions: ProgramItem[] = []
const functionLabel: Label = `.func_${this.fnLabelCount++}` const functionLabel: Label = `.func_${this.fnLabelCount++}`
const afterLabel: Label = `.after_${functionLabel}` const afterLabel: Label = `.after_${functionLabel}`
@ -331,7 +344,13 @@ export class Compiler {
if (catchVariable || finallyBody) { if (catchVariable || finallyBody) {
// If function has catch or finally, wrap body in try/catch/finally // If function has catch or finally, wrap body in try/catch/finally
instructions.push( instructions.push(
...this.#compileTryCatchFinally(compileFunctionBody, catchVariable, catchBody, finallyBody, input) ...this.#compileTryCatchFinally(
compileFunctionBody,
catchVariable,
catchBody,
finallyBody,
input
)
) )
} else { } else {
instructions.push(...compileFunctionBody()) instructions.push(...compileFunctionBody())
@ -414,8 +433,9 @@ export class Compiler {
instructions.push(['JUMP', afterLabel]) instructions.push(['JUMP', afterLabel])
instructions.push([`${fnLabel}:`]) instructions.push([`${fnLabel}:`])
instructions.push( instructions.push(
...block.filter(x => x.type.name !== 'keyword') ...block
.map(x => this.#compileNode(x!, input)) .filter((x) => x.type.name !== 'keyword')
.map((x) => this.#compileNode(x!, input))
.flat() .flat()
) )
instructions.push(['RETURN']) instructions.push(['RETURN'])
@ -435,15 +455,16 @@ export class Compiler {
body = [ body = [
...body.slice(0, startSlice), ...body.slice(0, startSlice),
['MAKE_FUNCTION', [], fnLabel], ['MAKE_FUNCTION', [], fnLabel],
...body.slice(startSlice) ...body.slice(startSlice),
] ]
// @ts-ignore // @ts-ignore
body[body.length - 3]![1] += 1 body[body.length - 3]![1] += 1
instructions.push(...body) instructions.push(...body)
} else { } else {
throw new Error(`FunctionCallWithBlock: Expected FunctionCallOrIdentifier or FunctionCall`) throw new Error(
`FunctionCallWithBlock: Expected FunctionCallOrIdentifier or FunctionCall`
)
} }
return instructions return instructions
@ -636,13 +657,13 @@ export class Compiler {
} }
case terms.Array: { 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. // 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 // = 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 // and check for arrays that look like `[ = ]` to interpret them as
// empty dicts // empty dicts
if (children.length === 1 && children[0]!.name === 'Word') { if (children.length === 1 && children[0]!.type.id === terms.Word) {
const child = children[0]! const child = children[0]!
if (input.slice(child.from, child.to) === '=') { if (input.slice(child.from, child.to) === '=') {
return [['MAKE_DICT', 0]] return [['MAKE_DICT', 0]]
@ -655,7 +676,7 @@ export class Compiler {
} }
case terms.Dict: { case terms.Dict: {
const children = getAllChildren(node) const children = getAllChildren(node).filter((n) => n.type.id !== terms.Comment)
const instructions: ProgramItem[] = [] const instructions: ProgramItem[] = []
children.forEach((node) => { children.forEach((node) => {
@ -691,6 +712,10 @@ export class Compiler {
return instructions return instructions
} }
case terms.Comment: {
return [] // ignore comments
}
default: default:
throw new CompilerError( throw new CompilerError(
`Compiler doesn't know how to handle a "${node.type.name}" node.`, `Compiler doesn't know how to handle a "${node.type.name}" node.`,

View File

@ -304,9 +304,12 @@ describe('default params', () => {
}) })
test.skip('dict default', () => { test.skip('dict default', () => {
expect('make-person = do person=[name=Bob age=60]: person end; make-person') expect('make-person = do person=[name=Bob age=60]: person end; make-person').toEvaluateTo({
.toEvaluateTo({ name: 'Bob', age: 60 }) name: 'Bob',
expect('make-person = do person=[name=Bob age=60]: person end; make-person [name=Jon age=21]') age: 60,
.toEvaluateTo({ name: 'Jon', age: 21 }) })
expect(
'make-person = do person=[name=Bob age=60]: person end; make-person [name=Jon age=21]'
).toEvaluateTo({ name: 'Jon', age: 21 })
}) })
}) })

View File

@ -66,8 +66,8 @@ describe('array literals', () => {
}) })
test('comments within arrays', () => { test('comments within arrays', () => {
expect(`[1 # first expect(`[1
2 # second 2
]`).toEvaluateTo([1, 2]) ]`).toEvaluateTo([1, 2])
}) })

View File

@ -150,8 +150,11 @@ describe('array literals', () => {
2 # second 2 # second
]`).toMatchTree(` ]`).toMatchTree(`
Array Array
Comment # something...
Number 1 Number 1
Comment # first
Number 2 Number 2
Comment # second
`) `)
}) })
@ -397,12 +400,15 @@ c=3]`).toMatchTree(`
c=3 c=3
]`).toMatchTree(` ]`).toMatchTree(`
Dict Dict
Comment # something...
NamedArg NamedArg
NamedArgPrefix a= NamedArgPrefix a=
Number 1 Number 1
Comment # first
NamedArg NamedArg
NamedArgPrefix b= NamedArgPrefix b=
Number 2 Number 2
Comment # second
NamedArg NamedArg
NamedArgPrefix c= NamedArgPrefix c=
Number 3 Number 3

Binary file not shown.