Compare commits

...

2 Commits

Author SHA1 Message Date
88434a932a add ref for grabbing a function 2025-11-08 00:58:17 -08:00
409aa9c34e fix calling no-arg dotget functions 2025-11-08 00:17:08 -08:00
5 changed files with 42 additions and 3 deletions

View File

@ -62,7 +62,7 @@
"hono": ["hono@4.10.4", "", {}, "sha512-YG/fo7zlU3KwrBL5vDpWKisLYiM+nVstBQqfr7gCPbSYURnNEP9BDxEMz8KfsDR9JX0lJWDRNc6nXX31v7ZEyg=="], "hono": ["hono@4.10.4", "", {}, "sha512-YG/fo7zlU3KwrBL5vDpWKisLYiM+nVstBQqfr7gCPbSYURnNEP9BDxEMz8KfsDR9JX0lJWDRNc6nXX31v7ZEyg=="],
"reefvm": ["reefvm@git+https://git.nose.space/defunkt/reefvm#bffb83a5280a4d74e424c4e0f4fbd46f790227a3", { "peerDependencies": { "typescript": "^5" } }, "bffb83a5280a4d74e424c4e0f4fbd46f790227a3"], "reefvm": ["reefvm@git+https://git.nose.space/defunkt/reefvm#f439c25742ed69bb141e92f41eeab8bbfd6ac12c", { "peerDependencies": { "typescript": "^5" } }, "f439c25742ed69bb141e92f41eeab8bbfd6ac12c"],
"style-mod": ["style-mod@4.1.3", "", {}, "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ=="], "style-mod": ["style-mod@4.1.3", "", {}, "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ=="],

View File

@ -51,6 +51,7 @@ function processEscapeSeq(escapeSeq: string): string {
export class Compiler { export class Compiler {
instructions: ProgramItem[] = [] instructions: ProgramItem[] = []
labelCount = 0
fnLabelCount = 0 fnLabelCount = 0
ifLabelCount = 0 ifLabelCount = 0
tryLabelCount = 0 tryLabelCount = 0
@ -367,7 +368,29 @@ export class Compiler {
case terms.FunctionCallOrIdentifier: { case terms.FunctionCallOrIdentifier: {
if (node.firstChild?.type.id === terms.DotGet) { if (node.firstChild?.type.id === terms.DotGet) {
return this.#compileNode(node.firstChild, input) const instructions: ProgramItem[] = []
const callLabel = `.call_dotget_${++this.labelCount}`
const afterLabel = `.after_dotget_${++this.labelCount}`
instructions.push(...this.#compileNode(node.firstChild, input))
instructions.push(['DUP'])
instructions.push(['TYPE'])
instructions.push(['PUSH', 'function'])
instructions.push(['EQ'])
instructions.push(['JUMP_IF_TRUE', callLabel])
instructions.push(['DUP'])
instructions.push(['TYPE'])
instructions.push(['PUSH', 'native'])
instructions.push(['EQ'])
instructions.push(['JUMP_IF_TRUE', callLabel])
instructions.push(['JUMP', afterLabel])
instructions.push([`${callLabel}:`])
instructions.push(['PUSH', 0])
instructions.push(['PUSH', 0])
instructions.push(['CALL'])
instructions.push([`${afterLabel}:`])
return instructions
} }
return [['TRY_CALL', value]] return [['TRY_CALL', value]]

View File

@ -110,7 +110,10 @@ describe('compiler', () => {
}) })
test('function call with no args', () => { test('function call with no args', () => {
expect(`bloop = do: 'bloop' end; bloop`).toEvaluateTo('bloop') expect(`bloop = do: 'bleep' end; bloop`).toEvaluateTo('bleep')
expect(`bloop = [ go=do: 'bleep' end ]; bloop.go`).toEvaluateTo('bleep')
expect(`bloop = [ go=do: 'bleep' end ]; abc = do x: x end; abc (bloop.go)`).toEvaluateTo('bleep')
expect(`num = ((math.random) * 10 + 1) | math.floor; num >= 1 and num <= 10 `).toEvaluateTo(true)
}) })
test('function call with if statement and multiple expressions', () => { test('function call with if statement and multiple expressions', () => {

View File

@ -40,6 +40,7 @@ export const globals = {
'var?': function (this: VM, v: string) { 'var?': function (this: VM, v: string) {
return typeof v !== 'string' || this.scope.has(v) return typeof v !== 'string' || this.scope.has(v)
}, },
ref: (fn: Function) => fn,
// type predicates // type predicates
'string?': (v: any) => toValue(v).type === 'string', 'string?': (v: any) => toValue(v).type === 'string',

View File

@ -77,3 +77,15 @@ describe('introspection', () => {
await expect(`describe 'hello'`).toEvaluateTo("#<string: \u001b[32m'hello\u001b[32m'\u001b[0m>", globals) await expect(`describe 'hello'`).toEvaluateTo("#<string: \u001b[32m'hello\u001b[32m'\u001b[0m>", globals)
}) })
}) })
describe('ref', () => {
expect(`rnd = do x: true end; rnd | type`).toEvaluateTo('boolean')
expect(`rnd = do x: true end; ref rnd | type`).toEvaluateTo('function')
expect(`math.random | type`).toEvaluateTo('number')
expect(`ref math.random | type`).toEvaluateTo('native')
expect(`rnd = math.random; rnd | type`).toEvaluateTo('number')
expect(`rnd = ref math.random; rnd | type`).toEvaluateTo('number')
expect(`rnd = ref math.random; ref rnd | type`).toEvaluateTo('native')
})