import -> use
This commit is contained in:
parent
ef20c67e61
commit
23642d3da1
16
bin/shrimp
16
bin/shrimp
|
|
@ -25,9 +25,9 @@ ${colors.bright}Commands:${colors.reset}
|
|||
${colors.cyan}version${colors.reset} Print version
|
||||
|
||||
${colors.bright}Options:${colors.reset}
|
||||
${colors.cyan}eval -I${colors.reset} ${colors.yellow}<module>${colors.reset} Import module (can be repeated)
|
||||
Example: shrimp -I math -e 'random | echo'
|
||||
Example: shrimp -Imath -Istr -e 'random | echo'`)
|
||||
${colors.cyan}eval -U${colors.reset} ${colors.yellow}<module>${colors.reset} Use module (can be repeated)
|
||||
Example: shrimp -U math -e 'random | echo'
|
||||
Example: shrimp -Umath -Ustr -e 'random | echo'`)
|
||||
}
|
||||
|
||||
function showVersion() {
|
||||
|
|
@ -51,22 +51,22 @@ async function main() {
|
|||
return
|
||||
}
|
||||
|
||||
// Parse -I flags for imports (supports both "-I math" and "-Imath")
|
||||
// Parse -U flags for use (supports both "-U math" and "-Umath")
|
||||
const imports: string[] = []
|
||||
|
||||
while (args.length > 0) {
|
||||
const arg = args[0]
|
||||
|
||||
if (arg === '-I') {
|
||||
// "-I math" format
|
||||
if (arg === '-U') {
|
||||
// "-U math" format
|
||||
if (args.length < 2) {
|
||||
console.log(`${colors.bright}error: -I requires a module name${colors.reset}`)
|
||||
process.exit(1)
|
||||
}
|
||||
imports.push(args[1])
|
||||
args = args.slice(2)
|
||||
} else if (arg.startsWith('-I')) {
|
||||
// "-Imath" format
|
||||
} else if (arg.startsWith('-U')) {
|
||||
// "-Umath" format
|
||||
const moduleName = arg.slice(2)
|
||||
if (!moduleName) {
|
||||
console.log(`${colors.bright}error: -I requires a module name${colors.reset}`)
|
||||
|
|
|
|||
|
|
@ -496,29 +496,29 @@ describe('Compound assignment operators', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('import', () => {
|
||||
test('imports single dict', () => {
|
||||
expect(`import str; starts-with? abc a`).toEvaluateTo(true)
|
||||
describe('use', () => {
|
||||
test('uses single dict', () => {
|
||||
expect(`use str; starts-with? abc a`).toEvaluateTo(true)
|
||||
})
|
||||
|
||||
test('imports multiple dicts', () => {
|
||||
expect(`import str math list; map [1 2 3] do x: x * 2 end`).toEvaluateTo([2, 4, 6])
|
||||
test('uses multiple dicts', () => {
|
||||
expect(`use str math list; map [1 2 3] do x: x * 2 end`).toEvaluateTo([2, 4, 6])
|
||||
})
|
||||
|
||||
test('imports non-prelude dicts', () => {
|
||||
test('uses non-prelude dicts', () => {
|
||||
expect(`
|
||||
abc = [a=true b=yes c=si]
|
||||
import abc
|
||||
use abc
|
||||
abc.b
|
||||
`).toEvaluateTo('yes')
|
||||
})
|
||||
|
||||
test('can specify imports', () => {
|
||||
expect(`import str only=ends-with?; ref ends-with? | function?`).toEvaluateTo(true)
|
||||
expect(`import str only=ends-with?; ref starts-with? | function?`).toEvaluateTo(false)
|
||||
test('can specify uses', () => {
|
||||
expect(`use str only=ends-with?; ref ends-with? | function?`).toEvaluateTo(true)
|
||||
expect(`use str only=ends-with?; ref starts-with? | function?`).toEvaluateTo(false)
|
||||
expect(`
|
||||
abc = [a=true b=yes c=si]
|
||||
import abc only=[a c]
|
||||
use abc only=[a c]
|
||||
[a c]
|
||||
`).toEvaluateTo([true, 'si'])
|
||||
})
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export type NodeType =
|
|||
| 'Star'
|
||||
| 'Slash'
|
||||
|
||||
| 'Import'
|
||||
| 'Use'
|
||||
| 'Do'
|
||||
| 'Underscore'
|
||||
| 'colon'
|
||||
|
|
@ -290,7 +290,7 @@ class SyntaxNodeType {
|
|||
case 'Slash':
|
||||
return term.Slash
|
||||
|
||||
case 'Import':
|
||||
case 'Use':
|
||||
return term.Import
|
||||
|
||||
case 'Do':
|
||||
|
|
|
|||
|
|
@ -216,8 +216,8 @@ export class Parser {
|
|||
if (this.is($T.Keyword, 'throw'))
|
||||
return this.throw()
|
||||
|
||||
if (this.is($T.Keyword, 'import'))
|
||||
return this.import()
|
||||
if (this.is($T.Keyword, 'use'))
|
||||
return this.use()
|
||||
|
||||
return this.expect($T.Keyword, 'if/while/do/import') as never
|
||||
}
|
||||
|
|
@ -705,27 +705,6 @@ export class Parser {
|
|||
return node.push(this.keyword('end'))
|
||||
}
|
||||
|
||||
import(): SyntaxNode {
|
||||
const keyword = this.keyword('import')
|
||||
|
||||
const args: SyntaxNode[] = []
|
||||
while (!this.isExprEnd()) {
|
||||
if (this.is($T.NamedArgPrefix)) {
|
||||
const prefix = SyntaxNode.from(this.next())
|
||||
const val = this.value()
|
||||
const arg = new SyntaxNode('NamedArg', prefix.from, val.to)
|
||||
arg.push(prefix, val)
|
||||
args.push(arg)
|
||||
} else {
|
||||
args.push(this.identifier())
|
||||
}
|
||||
}
|
||||
|
||||
const node = new SyntaxNode('Import', keyword.from, args.at(-1)!.to)
|
||||
node.add(keyword)
|
||||
return node.push(...args)
|
||||
}
|
||||
|
||||
// if, while, do, etc
|
||||
keyword(name: string): SyntaxNode {
|
||||
const node = SyntaxNode.from(this.expect($T.Keyword, name))
|
||||
|
|
@ -834,6 +813,27 @@ export class Parser {
|
|||
return node.push(end)
|
||||
}
|
||||
|
||||
use(): SyntaxNode {
|
||||
const keyword = this.keyword('use')
|
||||
|
||||
const args: SyntaxNode[] = []
|
||||
while (!this.isExprEnd()) {
|
||||
if (this.is($T.NamedArgPrefix)) {
|
||||
const prefix = SyntaxNode.from(this.next())
|
||||
const val = this.value()
|
||||
const arg = new SyntaxNode('NamedArg', prefix.from, val.to)
|
||||
arg.push(prefix, val)
|
||||
args.push(arg)
|
||||
} else {
|
||||
args.push(this.identifier())
|
||||
}
|
||||
}
|
||||
|
||||
const node = new SyntaxNode('Use', keyword.from, args.at(-1)!.to)
|
||||
node.add(keyword)
|
||||
return node.push(...args)
|
||||
}
|
||||
|
||||
// while test: blah end
|
||||
while(): SyntaxNode {
|
||||
const keyword = this.keyword('while')
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ describe('operators', () => {
|
|||
|
||||
describe('keywords', () => {
|
||||
test('keywords', () => {
|
||||
expect(`import`).toMatchToken('Keyword', 'import')
|
||||
expect(`use`).toMatchToken('Keyword', 'use')
|
||||
|
||||
expect(`end`).toMatchToken('Keyword', 'end')
|
||||
expect(`do`).toMatchToken('Keyword', 'do')
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@ import { expect, describe, test } from 'bun:test'
|
|||
|
||||
import '../shrimp.grammar' // Importing this so changes cause it to retest!
|
||||
|
||||
describe('import', () => {
|
||||
test('parses single import', () => {
|
||||
expect(`import str`).toMatchTree(`
|
||||
Import
|
||||
keyword import
|
||||
describe('use', () => {
|
||||
test('parses single use', () => {
|
||||
expect(`use str`).toMatchTree(`
|
||||
Use
|
||||
keyword use
|
||||
Identifier str
|
||||
`)
|
||||
})
|
||||
|
||||
test('parses multiple imports', () => {
|
||||
expect(`import str math list`).toMatchTree(`
|
||||
Import
|
||||
keyword import
|
||||
test('parses multiple uses', () => {
|
||||
expect(`use str math list`).toMatchTree(`
|
||||
Use
|
||||
keyword use
|
||||
Identifier str
|
||||
Identifier math
|
||||
Identifier list
|
||||
|
|
@ -22,9 +22,9 @@ describe('import', () => {
|
|||
})
|
||||
|
||||
test('parses named args', () => {
|
||||
expect(`import str only=ends-with?`).toMatchTree(`
|
||||
Import
|
||||
keyword import
|
||||
expect(`use str only=ends-with?`).toMatchTree(`
|
||||
Use
|
||||
keyword use
|
||||
Identifier str
|
||||
NamedArg
|
||||
NamedArgPrefix only=
|
||||
|
|
@ -93,7 +93,7 @@ const operators = new Set([
|
|||
])
|
||||
|
||||
const keywords = new Set([
|
||||
'import',
|
||||
'use',
|
||||
'end',
|
||||
'do',
|
||||
'if',
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user