Compare commits

..

3 Commits

Author SHA1 Message Date
9f45252522 cli: don't re-implement stuff 2025-11-07 21:10:25 -08:00
bae0da31c2 globals accepts {} too 2025-11-07 21:05:42 -08:00
4258503c0e shrimp cli wants the prelude too 2025-11-07 20:50:48 -08:00
4 changed files with 25 additions and 46 deletions

View File

@ -1,50 +1,14 @@
#!/usr/bin/env bun
import { Compiler } from '../src/compiler/compiler'
import { colors, globals } from '../src/prelude'
import { parser } from '../src/parser/shrimp'
import { colors } from '../src/prelude'
import { treeToString } from '../src/utils/tree'
import { VM, fromValue, bytecodeToString } from 'reefvm'
import { runFile, compileFile, parseCode } from '../src'
import { bytecodeToString } from 'reefvm'
import { readFileSync, writeFileSync, mkdirSync } from 'fs'
import { randomUUID } from 'crypto'
import { spawn } from 'child_process'
import { join } from 'path'
async function runFile(filePath: string) {
try {
const code = readFileSync(filePath, 'utf-8')
const compiler = new Compiler(code, Object.keys(globals))
const vm = new VM(compiler.bytecode, globals)
await vm.run()
return vm.stack.length ? fromValue(vm.stack[vm.stack.length - 1]) : null
} catch (error: any) {
console.error(`${colors.red}Error:${colors.reset} ${error.message}`)
process.exit(1)
}
}
async function compileFile(filePath: string) {
try {
const code = readFileSync(filePath, 'utf-8')
const compiler = new Compiler(code)
return bytecodeToString(compiler.bytecode)
} catch (error: any) {
console.error(`${colors.red}Error:${colors.reset} ${error.message}`)
process.exit(1)
}
}
async function parseFile(filePath: string) {
try {
const code = readFileSync(filePath, 'utf-8')
const tree = parser.parse(code)
return treeToString(tree, code)
} catch (error: any) {
console.error(`${colors.red}Error:${colors.reset} ${error.message}`)
process.exit(1)
}
}
function showHelp() {
console.log(`${colors.bright}${colors.magenta}🦐 Shrimp${colors.reset} is a scripting language in a shell.
@ -112,7 +76,7 @@ async function main() {
console.log(`${colors.bright}usage: shrimp bytecode <file>${colors.reset}`)
process.exit(1)
}
console.log(await compileFile(file))
console.log(bytecodeToString(compileFile(file)))
return
}
@ -122,7 +86,8 @@ async function main() {
console.log(`${colors.bright}usage: shrimp parse <file>${colors.reset}`)
process.exit(1)
}
console.log(await parseFile(file))
const input = readFileSync(file, 'utf-8')
console.log(treeToString(parseCode(input), input))
return
}

View File

@ -58,9 +58,9 @@ export class Compiler {
bytecode: Bytecode
pipeCounter = 0
constructor(public input: string, globals?: string[]) {
constructor(public input: string, globals?: string[] | Record<string, any>) {
try {
if (globals) setGlobals(globals)
if (globals) setGlobals(Array.isArray(globals) ? globals : Object.keys(globals))
const cst = parser.parse(input)
const errors = checkTreeForErrors(cst)

View File

@ -1,6 +1,9 @@
import { readFileSync } from 'fs'
import { glob, readFileSync } from 'fs'
import { VM, fromValue, type Bytecode } from 'reefvm'
import { type Tree } from '@lezer/common'
import { Compiler } from '#compiler/compiler'
import { parser } from '#parser/shrimp'
import { setGlobals } from '#parser/tokenizer'
import { globals as shrimpGlobals, colors } from '#prelude'
export { Compiler } from '#compiler/compiler'
@ -70,4 +73,15 @@ export function compileCode(code: string, globals?: Record<string, any>): Byteco
const globalNames = [...Object.keys(shrimpGlobals), ...(globals ? Object.keys(globals) : [])]
const compiler = new Compiler(code, globalNames)
return compiler.bytecode
}
export function parseFile(path: string, globals?: Record<string, any>): Tree {
const code = readFileSync(path, 'utf-8')
return parseCode(code, globals)
}
export function parseCode(code: string, globals?: Record<string, any>): Tree {
const globalNames = [...Object.keys(shrimpGlobals), ...(globals ? Object.keys(globals) : [])]
setGlobals(globalNames)
return parser.parse(code)
}

View File

@ -8,9 +8,9 @@ export function specializeKeyword(ident: string) {
// tell the dotGet searcher about builtin globals
export const globals: string[] = []
export const setGlobals = (newGlobals: string[]) => {
export const setGlobals = (newGlobals: string[] | Record<string, any>) => {
globals.length = 0
globals.push(...newGlobals)
globals.push(...(Array.isArray(newGlobals) ? newGlobals : Object.keys(newGlobals)))
}
// The only chars that can't be words are whitespace, apostrophes, closing parens, and EOF.