use module

This commit is contained in:
Chris Wanstrath 2025-10-26 13:13:53 -07:00 committed by Chris Wanstrath
parent 67a98837ed
commit af7f389a04
2 changed files with 59 additions and 7 deletions

View File

@ -1,7 +1,12 @@
// The prelude creates all the builtin Shrimp functions. // The prelude creates all the builtin Shrimp functions.
import { resolve, parse } from 'path'
import { readFileSync } from 'fs' import { readFileSync } from 'fs'
import { VM, isValue, toValue, type Value, extractParamInfo, isWrapped, getOriginalFunction } from 'reefvm' import { Compiler } from '#compiler/compiler'
import {
VM, Scope, toValue, type Value,
extractParamInfo, isWrapped, getOriginalFunction,
} from 'reefvm'
export const colors = { export const colors = {
reset: '\x1b[0m', reset: '\x1b[0m',
@ -16,7 +21,7 @@ export const colors = {
pink: '\x1b[38;2;255;105;180m' pink: '\x1b[38;2;255;105;180m'
} }
export const nativeFunctions = { export const globalFunctions = {
// hello // hello
echo: (...args: any[]) => { echo: (...args: any[]) => {
console.log(...args.map(a => { console.log(...args.map(a => {
@ -73,14 +78,33 @@ export const nativeFunctions = {
}, },
// modules // modules
use: function (this: VM, path: string) { use: async function (this: VM, path: string) {
const file = readFileSync(path + '.sh') const scope = this.scope
const pc = this.pc
const fullPath = resolve(path) + '.sh'
const code = readFileSync(fullPath, 'utf-8')
this.pc = this.instructions.length
this.scope = new Scope(scope)
const compiled = new Compiler(code)
this.appendBytecode(compiled.bytecode)
await this.continue()
const module: Map<string, Value> = new Map
for (const [name, value] of this.scope.locals.entries())
module.set(name, value)
this.scope = scope
this.pc = pc
this.stopped = false
this.scope.set(parse(fullPath).name, { type: 'dict', value: module })
} }
} }
export function formatValue(value: Value | any, inner = false): string { export function formatValue(value: Value, inner = false): string {
if (!isValue(value)) value = toValue(value)
switch (value.type) { switch (value.type) {
case 'string': case 'string':
return `${colors.green}'${value.value.replaceAll("'", "\\'")}${colors.green}'${colors.reset}` return `${colors.green}'${value.value.replaceAll("'", "\\'")}${colors.green}'${colors.reset}`

View File

@ -0,0 +1,28 @@
import { expect, describe, test } from 'bun:test'
import { globalFunctions } from '#prelude'
describe('use', () => {
test(`imports all a file's functions`, async () => {
expect(`
use ./src/prelude/tests/math
dbl = math | at double
dbl 4
`).toEvaluateTo(8, globalFunctions)
expect(`
use ./src/prelude/tests/math
math | at pi
`).toEvaluateTo(3.14, globalFunctions)
expect(`
use ./src/prelude/tests/math
math | at 🥧
`).toEvaluateTo(3.14159265359, globalFunctions)
expect(`
use ./src/prelude/tests/math
call = do x y: x y end
call (math | at add1) 5
`).toEvaluateTo(6, globalFunctions)
})
})