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) {
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.`,

View File

@ -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 })
})
})
})

View File

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

View File

@ -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

Binary file not shown.