@algosail/lang 0.2.9 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/cli/sail.js +151 -0
- package/cli/typecheck.js +0 -0
- package/package.json +4 -4
- package/example/tictactoe.sail +0 -0
package/README.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Sail language tooling. Re-exports parser and typecheck.
|
|
4
4
|
|
|
5
|
+
## CLI
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
sail check <file.sail> # Typecheck
|
|
9
|
+
sail compile <file.sail> [options] # Compile to JS
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Options for `compile`: `--out <file.js>`, `--no-source-map`, `-` (stdout).
|
|
13
|
+
|
|
5
14
|
## Exports
|
|
6
15
|
|
|
7
16
|
```javascript
|
package/cli/sail.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Sail CLI — sail check | sail compile
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const args = process.argv.slice(2)
|
|
8
|
+
const cmd = args[0]
|
|
9
|
+
|
|
10
|
+
if (!cmd || cmd === '-h' || cmd === '--help') {
|
|
11
|
+
console.log(`sail - Sail language tooling
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
sail check <file.sail> Typecheck a Sail file
|
|
15
|
+
sail compile <file.sail> Compile Sail to JavaScript
|
|
16
|
+
|
|
17
|
+
Options for compile:
|
|
18
|
+
--out <file.js> Output path (default: input.js)
|
|
19
|
+
--no-source-map Disable source map generation
|
|
20
|
+
- Write to stdout
|
|
21
|
+
|
|
22
|
+
Examples:
|
|
23
|
+
sail check main.sail
|
|
24
|
+
sail compile main.sail --out dist/main.js
|
|
25
|
+
sail compile main.sail -
|
|
26
|
+
`)
|
|
27
|
+
process.exit(cmd === '-h' || cmd === '--help' ? 0 : 1)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const rest = args.slice(1)
|
|
31
|
+
|
|
32
|
+
if (cmd === 'check') {
|
|
33
|
+
await runCheck(rest)
|
|
34
|
+
} else if (cmd === 'compile') {
|
|
35
|
+
await runCompile(rest)
|
|
36
|
+
} else {
|
|
37
|
+
console.error(`sail: unknown command '${cmd}'. Use 'sail check' or 'sail compile'.`)
|
|
38
|
+
process.exit(1)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function runCheck(args) {
|
|
42
|
+
const filePath = args.find((a) => !a.startsWith('-'))
|
|
43
|
+
if (!filePath) {
|
|
44
|
+
console.error('Usage: sail check <path-to-file.sail>')
|
|
45
|
+
process.exit(1)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { createParser } = await import('@algosail/parser')
|
|
49
|
+
const { typecheck } = await import('@algosail/typecheck')
|
|
50
|
+
const { readFile } = await import('node:fs/promises')
|
|
51
|
+
const { pathToFileURL } = await import('node:url')
|
|
52
|
+
const { resolve } = await import('node:path')
|
|
53
|
+
const { formatError } = await import('@algosail/compiler/lib/formatError.js')
|
|
54
|
+
const { addErrorHints } = await import('@algosail/compiler/lib/errorHints.js')
|
|
55
|
+
|
|
56
|
+
const absPath = resolve(process.cwd(), filePath)
|
|
57
|
+
const uri = pathToFileURL(absPath).href
|
|
58
|
+
|
|
59
|
+
let text
|
|
60
|
+
try {
|
|
61
|
+
text = await readFile(absPath, 'utf8')
|
|
62
|
+
} catch (err) {
|
|
63
|
+
console.error(`sail check: cannot read ${filePath}: ${err.message}`)
|
|
64
|
+
process.exit(1)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const parser = await createParser()
|
|
68
|
+
const result = await parser.parseSail(uri, text)
|
|
69
|
+
const parseErrors = (result.errors ?? []).map((e) => ({
|
|
70
|
+
message: e.type === 'error' ? `Parse error: ${e.text}` : `Parse error: missing ${e.text}`,
|
|
71
|
+
startPosition: e.startPosition,
|
|
72
|
+
uri,
|
|
73
|
+
}))
|
|
74
|
+
const typeErrors = typecheck(result).map((e) => {
|
|
75
|
+
const hint = addErrorHints(e)
|
|
76
|
+
return { ...e, uri, ...(hint && { hint }) }
|
|
77
|
+
})
|
|
78
|
+
const errors = [...parseErrors, ...typeErrors]
|
|
79
|
+
|
|
80
|
+
if (errors.length > 0) {
|
|
81
|
+
for (const err of errors) {
|
|
82
|
+
console.error(formatError({ ...err, uri }, uri))
|
|
83
|
+
}
|
|
84
|
+
process.exit(1)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function runCompile(args) {
|
|
89
|
+
let inputPath = null
|
|
90
|
+
let outPath = null
|
|
91
|
+
|
|
92
|
+
for (let i = 0; i < args.length; i++) {
|
|
93
|
+
if (args[i] === '--out' && args[i + 1]) {
|
|
94
|
+
outPath = args[i + 1]
|
|
95
|
+
i++
|
|
96
|
+
} else if (!args[i].startsWith('-')) {
|
|
97
|
+
inputPath = args[i]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!inputPath) {
|
|
102
|
+
console.error('Usage: sail compile <input.sail> [--out <output.js>] [--no-source-map]')
|
|
103
|
+
process.exit(1)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const { compile } = await import('@algosail/compiler')
|
|
107
|
+
const { formatError } = await import('@algosail/compiler/lib/formatError.js')
|
|
108
|
+
const { readFile, writeFile } = await import('node:fs/promises')
|
|
109
|
+
const { dirname, resolve, basename } = await import('node:path')
|
|
110
|
+
const { pathToFileURL } = await import('node:url')
|
|
111
|
+
|
|
112
|
+
const absPath = resolve(process.cwd(), inputPath)
|
|
113
|
+
const uri = pathToFileURL(absPath).href
|
|
114
|
+
|
|
115
|
+
let source
|
|
116
|
+
try {
|
|
117
|
+
source = await readFile(absPath, 'utf8')
|
|
118
|
+
} catch (err) {
|
|
119
|
+
console.error(`sail compile: cannot read ${inputPath}: ${err.message}`)
|
|
120
|
+
process.exit(1)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const outputPath = outPath ?? inputPath.replace(/\.sail$/, '.js')
|
|
124
|
+
const compileOpts = {
|
|
125
|
+
outPath: outputPath !== '-' ? dirname(resolve(process.cwd(), outputPath)) : dirname(absPath),
|
|
126
|
+
sourceMap: outputPath !== '-' && !args.includes('--no-source-map'),
|
|
127
|
+
outFile: outputPath !== '-' ? resolve(process.cwd(), outputPath) : null,
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const result = await compile(uri, source, compileOpts)
|
|
131
|
+
|
|
132
|
+
if (result.errors.length > 0) {
|
|
133
|
+
for (const err of result.errors) {
|
|
134
|
+
console.error(formatError({ ...err, uri }, uri))
|
|
135
|
+
}
|
|
136
|
+
process.exit(1)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (outputPath === '-') {
|
|
140
|
+
process.stdout.write(result.js)
|
|
141
|
+
} else {
|
|
142
|
+
let js = result.js
|
|
143
|
+
if (result.sourceMap) {
|
|
144
|
+
const mapPath = outputPath + '.map'
|
|
145
|
+
await writeFile(mapPath, result.sourceMap, 'utf8')
|
|
146
|
+
js += `\n//# sourceMappingURL=${basename(mapPath)}`
|
|
147
|
+
}
|
|
148
|
+
await writeFile(outputPath, js, 'utf8')
|
|
149
|
+
console.log(`Compiled to ${outputPath}`)
|
|
150
|
+
}
|
|
151
|
+
}
|
package/cli/typecheck.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@algosail/lang",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"sail
|
|
7
|
+
"sail": "cli/sail.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "brittle \"test/**/*.test.js\""
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@algosail/builtins": "^0.0.6",
|
|
17
17
|
"@algosail/compiler": "^0.0.2",
|
|
18
|
-
"@algosail/parser": "^0.1.
|
|
19
|
-
"@algosail/typecheck": "^0.1.
|
|
18
|
+
"@algosail/parser": "^0.1.2",
|
|
19
|
+
"@algosail/typecheck": "^0.1.2"
|
|
20
20
|
}
|
|
21
21
|
}
|
package/example/tictactoe.sail
DELETED
|
File without changes
|