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