hclang 0.5.14 → 0.15.1
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 +246 -25
- package/esm/_dnt.polyfills.js +144 -0
- package/esm/_dnt.shims.js +61 -0
- package/esm/cli/hc.js +159 -0
- package/esm/cli/prompt.js +58 -0
- package/esm/cli/resource-store.js +125 -0
- package/esm/cli/runfile.js +62 -0
- package/esm/deps/jsr.io/@nothing628/chalk/1.0.1/src/ansi-styles/index.js +209 -0
- package/esm/deps/jsr.io/@nothing628/chalk/1.0.1/src/mod.js +170 -0
- package/esm/deps/jsr.io/@nothing628/chalk/1.0.1/src/supports-color/index.js +155 -0
- package/esm/deps/jsr.io/@nothing628/chalk/1.0.1/src/utilities.js +32 -0
- package/esm/deps/jsr.io/@std/cli/1.0.32/parse_args.js +372 -0
- package/esm/lib/execute/eval-pipe.js +34 -0
- package/esm/lib/execute/hc-eval.js +233 -0
- package/esm/lib/execute/hc-log.js +46 -0
- package/esm/lib/execute/hc-test.js +220 -0
- package/esm/lib/execute/lex-pipe.js +94 -0
- package/esm/lib/execute/lex-run.js +134 -0
- package/esm/lib/execute/lex.js +170 -0
- package/esm/lib/execute/parse-pipe.js +113 -0
- package/esm/lib/execute/sigilizer.js +75 -0
- package/esm/lib/execute/syntax.js +79 -0
- package/esm/lib/execute/terminals.js +62 -0
- package/esm/lib/frames/atom-syntax.js +58 -0
- package/esm/lib/frames/bound-method.js +123 -0
- package/esm/lib/frames/context.js +41 -0
- package/esm/lib/frames/effect-marker.js +36 -0
- package/esm/lib/frames/evaluation-scope.js +389 -0
- package/esm/lib/frames/frame-alias.js +143 -0
- package/esm/lib/frames/frame-arg.js +149 -0
- package/esm/lib/frames/frame-array.js +129 -0
- package/esm/lib/frames/frame-atom.js +36 -0
- package/esm/lib/frames/frame-blob.js +181 -0
- package/esm/lib/frames/frame-bytes.js +176 -0
- package/esm/lib/frames/frame-comment.js +65 -0
- package/esm/lib/frames/frame-decimal.js +172 -0
- package/esm/lib/frames/frame-doc.js +114 -0
- package/esm/lib/frames/frame-expr.js +135 -0
- package/esm/lib/frames/frame-group.js +45 -0
- package/esm/lib/frames/frame-handle.js +132 -0
- package/esm/lib/frames/frame-int.js +208 -0
- package/esm/lib/frames/frame-lazy.js +138 -0
- package/esm/lib/frames/frame-list.js +145 -0
- package/esm/lib/frames/frame-match.js +9 -0
- package/esm/lib/frames/frame-name.js +132 -0
- package/esm/lib/frames/frame-note.js +132 -0
- package/esm/lib/frames/frame-number.js +101 -0
- package/esm/lib/frames/frame-numeric.js +217 -0
- package/esm/lib/frames/frame-rational.js +143 -0
- package/esm/lib/frames/frame-resource.js +154 -0
- package/esm/lib/frames/frame-schema.js +84 -0
- package/esm/lib/frames/frame-scope-anchor.js +169 -0
- package/esm/lib/frames/frame-sequence.js +102 -0
- package/esm/lib/frames/frame-string.js +185 -0
- package/esm/lib/frames/frame-symbol.js +426 -0
- package/esm/lib/frames/frame-text.js +32 -0
- package/esm/lib/frames/frame-type.js +41 -0
- package/esm/lib/frames/frame-typed-number.js +128 -0
- package/esm/lib/frames/frame-uri.js +128 -0
- package/esm/lib/frames/frame.js +457 -0
- package/esm/lib/frames/meta-frame.js +332 -0
- package/esm/lib/frames/resource-binding.js +11 -0
- package/esm/lib/frames/resource-reference.js +147 -0
- package/esm/lib/frames/resource-store.js +52 -0
- package/esm/lib/frames/schema-bit-matcher.js +153 -0
- package/esm/lib/frames/schema-compiler.js +7 -0
- package/esm/lib/frames/schema-matcher.js +49 -0
- package/esm/lib/frames/schema-structural-matcher.js +46 -0
- package/esm/lib/frames/stringify.js +32 -0
- package/esm/lib/frames.js +44 -0
- package/esm/lib/ops/conditionals.js +13 -0
- package/esm/lib/ops/frame-curry.js +52 -0
- package/esm/lib/ops/frame-ops.js +27 -0
- package/esm/lib/ops/iterators.js +36 -0
- package/esm/lib/ops/math.js +25 -0
- package/esm/lib/ops/type-operations.js +24 -0
- package/esm/lib/ops.js +31 -0
- package/esm/lib/scan.js +14 -0
- package/esm/lib/version.js +1 -0
- package/esm/package.json +3 -0
- package/package.json +19 -78
- package/lib/src/cli/hc.js +0 -40
- package/lib/src/cli/runfile.js +0 -28
- package/lib/src/execute/eval-pipe.js +0 -15
- package/lib/src/execute/evaluate.js +0 -10
- package/lib/src/execute/execute.js +0 -18
- package/lib/src/execute/frame-space.js +0 -17
- package/lib/src/execute/hc-eval.js +0 -105
- package/lib/src/execute/hc-log.js +0 -39
- package/lib/src/execute/hc-test.js +0 -44
- package/lib/src/execute/lex-bytes.js +0 -42
- package/lib/src/execute/lex-pipe.js +0 -63
- package/lib/src/execute/lex.js +0 -110
- package/lib/src/execute/lexer.js +0 -24
- package/lib/src/execute/parse-pipe.js +0 -55
- package/lib/src/execute/syntax.js +0 -36
- package/lib/src/execute/terminals.js +0 -54
- package/lib/src/execute.js +0 -3
- package/lib/src/frames/frame-alias.js +0 -45
- package/lib/src/frames/frame-arg.js +0 -62
- package/lib/src/frames/frame-array.js +0 -47
- package/lib/src/frames/frame-atom.js +0 -41
- package/lib/src/frames/frame-blob.js +0 -104
- package/lib/src/frames/frame-bytes.js +0 -31
- package/lib/src/frames/frame-comment.js +0 -28
- package/lib/src/frames/frame-doc.js +0 -19
- package/lib/src/frames/frame-expr.js +0 -34
- package/lib/src/frames/frame-group.js +0 -31
- package/lib/src/frames/frame-lazy.js +0 -39
- package/lib/src/frames/frame-list.js +0 -58
- package/lib/src/frames/frame-name.js +0 -29
- package/lib/src/frames/frame-note.js +0 -104
- package/lib/src/frames/frame-number.js +0 -88
- package/lib/src/frames/frame-schema.js +0 -47
- package/lib/src/frames/frame-string.js +0 -41
- package/lib/src/frames/frame-symbol.js +0 -82
- package/lib/src/frames/frame.js +0 -76
- package/lib/src/frames/meta-frame.js +0 -83
- package/lib/src/frames.js +0 -24
- package/lib/src/index.js +0 -5
- package/lib/src/maml/tag.js +0 -17
- package/lib/src/maml.js +0 -26
- package/lib/src/ops/conditionals.js +0 -14
- package/lib/src/ops/frame-curry.js +0 -17
- package/lib/src/ops/frame-ops.js +0 -24
- package/lib/src/ops/iterators.js +0 -28
- package/lib/src/ops/math.js +0 -68
- package/lib/src/ops.js +0 -24
- package/lib/src/version.js +0 -3
- package/lib/test/execute/eval-pipe-spec.js +0 -45
- package/lib/test/execute/evaluate-spec.js +0 -133
- package/lib/test/execute/execute-spec.js +0 -115
- package/lib/test/execute/hc-eval-spec.js +0 -68
- package/lib/test/execute/hc-test-spec.js +0 -53
- package/lib/test/execute/lex-pipe-spec.js +0 -25
- package/lib/test/execute/parse-spec.js +0 -67
- package/lib/test/execute/script-spec.js +0 -24
- package/lib/test/frames/frame-alias-spec.js +0 -36
- package/lib/test/frames/frame-arg-spec.js +0 -57
- package/lib/test/frames/frame-array-spec.js +0 -54
- package/lib/test/frames/frame-blob-spec.js +0 -56
- package/lib/test/frames/frame-bytes-spec.js +0 -16
- package/lib/test/frames/frame-comment-spec.js +0 -17
- package/lib/test/frames/frame-doc-spec.js +0 -17
- package/lib/test/frames/frame-expr-spec.js +0 -60
- package/lib/test/frames/frame-group-spec.js +0 -27
- package/lib/test/frames/frame-lazy-spec.js +0 -49
- package/lib/test/frames/frame-name-spec.js +0 -26
- package/lib/test/frames/frame-note-spec.js +0 -48
- package/lib/test/frames/frame-number-spec.js +0 -23
- package/lib/test/frames/frame-schema-spec.js +0 -54
- package/lib/test/frames/frame-spec.js +0 -31
- package/lib/test/frames/frame-string-spec.js +0 -43
- package/lib/test/frames/frame-symbol-spec.js +0 -64
- package/lib/test/frames/meta-frame-spec.js +0 -75
- package/lib/test/maml/maml-spec.js +0 -42
- package/lib/test/maml/tag-spec.js +0 -53
- package/lib/test/ops/iterators-spec.js +0 -70
package/README.md
CHANGED
|
@@ -1,50 +1,271 @@
|
|
|
1
|
-
#
|
|
2
|
-
version: 0.5.11
|
|
1
|
+
# Homoiconic C
|
|
3
2
|
|
|
4
|
-
[](https://jsr.io/@swanfactory/hclang)
|
|
4
|
+
[](https://jsr.io/@swanfactory/hclang)
|
|
5
|
+
|
|
6
|
+
A universal language for code and data.
|
|
5
7
|
|
|
6
8
|
## Introduction
|
|
7
9
|
|
|
8
|
-
[Homoiconic C](https://theswanfactory.wordpress.com/2016/12/20/homoiconic-c-a-universal-language-for-code-and-data/)
|
|
10
|
+
[Homoiconic C](https://theswanfactory.wordpress.com/2016/12/20/homoiconic-c-a-universal-language-for-code-and-data/)
|
|
11
|
+
(HC) is a single universal language for code and data. This monorepo contains
|
|
12
|
+
the first implementation of HC as an interpreter written in TypeScript running
|
|
13
|
+
on [Deno](https://deno.land/).
|
|
9
14
|
|
|
10
|
-
|
|
15
|
+
The repository includes several packages:
|
|
16
|
+
|
|
17
|
+
- **[@swanfactory/hclang](https://jsr.io/@swanfactory/hclang)** - Core library
|
|
18
|
+
published to JSR
|
|
19
|
+
- **CLI** - Interactive REPL and command-line tools
|
|
20
|
+
- **MAML** -
|
|
21
|
+
[_Multipurpose Abstract Markup Language_](https://theswanfactory.wordpress.com/2016/11/08/introducing-maml-a-draft-proposal-for-html6/),
|
|
22
|
+
a radically simple proposal for replacing web technologies (HTML, CSS,
|
|
23
|
+
JavaScript, SVG) with a single format based on HC
|
|
24
|
+
- **Web** - Web components and Fresh framework integration
|
|
25
|
+
|
|
26
|
+
HC can also be used to define easily-parseable variants of other common file
|
|
27
|
+
formats (e.g., HCSV, HCSON).
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### Try it Online
|
|
32
|
+
|
|
33
|
+
Visit [hclang.deno.dev](https://hclang.deno.dev) to try HC directly in your
|
|
34
|
+
browser with no installation required.
|
|
35
|
+
|
|
36
|
+
### Use as a Library
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Deno
|
|
40
|
+
deno add jsr:@swanfactory/hclang
|
|
11
41
|
|
|
42
|
+
# Node.js/npm
|
|
43
|
+
npx jsr add @swanfactory/hclang
|
|
12
44
|
```
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
45
|
+
|
|
46
|
+
Then in your code:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { execute } from "@swanfactory/hclang";
|
|
50
|
+
|
|
51
|
+
const result = execute("1 + 1");
|
|
52
|
+
console.log(result); // Output: '2'
|
|
16
53
|
```
|
|
17
|
-
This will launch the interpreter.
|
|
18
54
|
|
|
19
|
-
|
|
55
|
+
See the [library documentation](https://jsr.io/@swanfactory/hclang/doc) for more
|
|
56
|
+
details.
|
|
57
|
+
|
|
58
|
+
### Run the CLI
|
|
20
59
|
|
|
21
|
-
|
|
60
|
+
With Node.js 24 or newer, run the current CLI directly from npm. Deno is not
|
|
61
|
+
required:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Interactive REPL
|
|
65
|
+
npx hclang@latest
|
|
66
|
+
|
|
67
|
+
# Evaluate a file
|
|
68
|
+
npx hclang@latest path/to/program.hc
|
|
69
|
+
|
|
70
|
+
# Verify executable examples in an HC document
|
|
71
|
+
npx hclang@latest path/to/examples.hc --testdoc
|
|
22
72
|
```
|
|
23
|
-
|
|
73
|
+
|
|
74
|
+
From source:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git clone https://github.com/TheSwanFactory/hclang.git
|
|
78
|
+
cd hclang
|
|
79
|
+
deno task hc
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This will launch the interactive HC interpreter.
|
|
83
|
+
|
|
84
|
+
### Run Tests
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
deno task test
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
### Available Tasks
|
|
93
|
+
|
|
94
|
+
The root `deno.json` provides several tasks:
|
|
95
|
+
|
|
96
|
+
| Task | Description |
|
|
97
|
+
| ---------------------- | ------------------------------------------------- |
|
|
98
|
+
| `deno task hc` | Launch the HC REPL |
|
|
99
|
+
| `deno task setup` | Install pre-commit hooks |
|
|
100
|
+
| `deno task test` | Run all tests (setup, format, lint, and tests) |
|
|
101
|
+
| `deno task test:setup` | Run all pre-commit hooks on all files |
|
|
102
|
+
| `deno task test:cli` | Test CLI package |
|
|
103
|
+
| `deno task test:lib` | Test library package |
|
|
104
|
+
| `deno task test:maml` | Test MAML package |
|
|
105
|
+
| `deno task test:web` | Test web package |
|
|
106
|
+
| `deno task test:bs` | Test BitScheme documentation |
|
|
107
|
+
| `deno task test:doc` | Test HC documentation examples |
|
|
108
|
+
| `deno task build` | Build native, npm, and web artifacts |
|
|
109
|
+
| `deno task build:npm` | Generate the Node.js CLI package in `dist/npm` |
|
|
110
|
+
| `deno task test:npm` | Pack and smoke-test the CLI package through `npx` |
|
|
111
|
+
|
|
112
|
+
### BitScheme
|
|
113
|
+
|
|
114
|
+
[BitScheme](cli/hc/BitScheme.hc) is a specialized scripting language for
|
|
115
|
+
declaratively parsing, manipulating, and generating binary data. It includes
|
|
116
|
+
executable documentation that can be tested:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
deno task test:bs
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This runs the BitScheme interpreter on its own documentation, executing embedded
|
|
123
|
+
code examples and verifying outputs.
|
|
124
|
+
|
|
125
|
+
### Debug Mode
|
|
126
|
+
|
|
127
|
+
Enable verbose debugging output:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
export DEBUG=true
|
|
131
|
+
deno task hc
|
|
24
132
|
```
|
|
25
|
-
This will open the BitScheme.html file, and also run the documentation through the testdoc evaluator which will generate pass/fail messages.
|
|
26
133
|
|
|
27
134
|
## Development
|
|
28
135
|
|
|
29
|
-
|
|
136
|
+
### Setup
|
|
137
|
+
|
|
138
|
+
1. Clone the [GitHub repository](https://github.com/TheSwanFactory/hclang.git):
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
git clone https://github.com/TheSwanFactory/hclang.git
|
|
142
|
+
cd hclang
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
2. Install [Deno](https://github.com/denoland/deno):
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# macOS
|
|
149
|
+
brew install deno
|
|
150
|
+
|
|
151
|
+
# Other platforms: see https://deno.land/
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
3. (Optional) Install [pre-commit](https://pre-commit.com/) for automatic code
|
|
155
|
+
quality checks:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# macOS
|
|
159
|
+
brew install pre-commit
|
|
160
|
+
|
|
161
|
+
# Other platforms: pip install pre-commit
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Pre-commit hooks are automatically installed when you run `deno task test` or
|
|
165
|
+
manually with `deno task setup`.
|
|
166
|
+
|
|
167
|
+
4. Run tests:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
deno task test
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
This will automatically set up pre-commit hooks, format code, run linters,
|
|
174
|
+
and execute the test suite.
|
|
175
|
+
|
|
176
|
+
### Project Structure
|
|
177
|
+
|
|
178
|
+
This is a Deno workspace (monorepo) with the following packages:
|
|
179
|
+
|
|
180
|
+
```text
|
|
181
|
+
hclang/
|
|
182
|
+
├── cli/ # HC command-line interface & REPL
|
|
183
|
+
├── lib/ # Core library (published to JSR)
|
|
184
|
+
├── maml/ # MAML markup language
|
|
185
|
+
├── web/ # Web components
|
|
186
|
+
├── doc/ # Documentation and papers
|
|
187
|
+
└── deno.json # Workspace root configuration
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### VS Code Extension
|
|
191
|
+
|
|
192
|
+
The VS Code extension for HC is now included in this repository at
|
|
193
|
+
[vscode-extension/](vscode-extension/). It provides comprehensive syntax
|
|
194
|
+
highlighting for all HC language features based on the complete grammar
|
|
195
|
+
specification.
|
|
196
|
+
|
|
197
|
+
**Installation:**
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# Install from source
|
|
201
|
+
deno task vscode:install
|
|
202
|
+
|
|
203
|
+
# Or package for distribution
|
|
204
|
+
deno task vscode:package
|
|
205
|
+
|
|
206
|
+
# Or publish to marketplace
|
|
207
|
+
deno task vscode:publish
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
The extension recognizes `.hc` files and provides:
|
|
211
|
+
|
|
212
|
+
- Syntax highlighting for all HC elements (numbers, strings, identifiers,
|
|
213
|
+
operators, etc.)
|
|
214
|
+
- Smart bracket matching for `{}`, `[]`, `()`
|
|
215
|
+
- Auto-closing pairs
|
|
216
|
+
- Comment toggling with `#`
|
|
217
|
+
|
|
218
|
+
**Note:** The old standalone
|
|
219
|
+
[language-hclang](https://github.com/TheSwanFactory/language-hclang) repository
|
|
220
|
+
is now deprecated in favor of this integrated extension.
|
|
221
|
+
|
|
222
|
+
## Publishing
|
|
223
|
+
|
|
224
|
+
For maintainers publishing new versions:
|
|
225
|
+
|
|
226
|
+
1. Ensure all tests pass:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
deno task test
|
|
230
|
+
```
|
|
30
231
|
|
|
31
|
-
2.
|
|
232
|
+
2. Update version everywhere:
|
|
32
233
|
|
|
33
|
-
|
|
234
|
+
```bash
|
|
235
|
+
deno task bump
|
|
236
|
+
```
|
|
34
237
|
|
|
35
|
-
|
|
36
|
-
|
|
238
|
+
This updates `deno.json`, `lib/version.ts`, and all workspace package
|
|
239
|
+
versions, then commits the changes.
|
|
37
240
|
|
|
38
|
-
|
|
241
|
+
3. Merge the PR to the `master` branch.
|
|
39
242
|
|
|
40
|
-
|
|
243
|
+
GitHub Actions compares the version in `deno.json` with the version before
|
|
244
|
+
the merge. When the version changed, it publishes the libraries to
|
|
245
|
+
[JSR](https://jsr.io/@swanfactory/hclang), publishes the exact `hclang`
|
|
246
|
+
tarball exercised through `npx`, and creates a GitHub Release tagged
|
|
247
|
+
`v<version>` with generated notes. Each registry is checked independently, so
|
|
248
|
+
a rerun resumes a partial release instead of retrying versions that are
|
|
249
|
+
already immutable. Merges without a version bump do not publish or create a
|
|
250
|
+
release; no manual tag is required.
|
|
41
251
|
|
|
42
|
-
|
|
252
|
+
npm publishing runs in the protected `npm-publish` GitHub environment using a
|
|
253
|
+
trusted publisher for the public `hclang` package. Its npm settings must
|
|
254
|
+
authorize the `TheSwanFactory/hclang` repository,
|
|
255
|
+
`.github/workflows/deno.js.yml`, the `npm-publish` environment, and direct
|
|
256
|
+
`npm publish` before merging a release bump. The build/PR job has no OIDC
|
|
257
|
+
token permission.
|
|
43
258
|
|
|
44
|
-
|
|
259
|
+
## Links
|
|
45
260
|
|
|
46
|
-
|
|
261
|
+
- **JSR Package**: [@swanfactory/hclang](https://jsr.io/@swanfactory/hclang)
|
|
262
|
+
- **Documentation**: [JSR Docs](https://jsr.io/@swanfactory/hclang/doc)
|
|
263
|
+
- **GitHub**: [TheSwanFactory/hclang](https://github.com/TheSwanFactory/hclang)
|
|
264
|
+
- **Blog**:
|
|
265
|
+
[Homoiconic C Introduction](https://theswanfactory.wordpress.com/2016/12/20/homoiconic-c-a-universal-language-for-code-and-data/)
|
|
266
|
+
- **MAML**:
|
|
267
|
+
[HTML6 Proposal](https://theswanfactory.wordpress.com/2016/11/08/introducing-maml-a-draft-proposal-for-html6/)
|
|
47
268
|
|
|
48
|
-
|
|
269
|
+
## License
|
|
49
270
|
|
|
50
|
-
|
|
271
|
+
MIT
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on [import-meta-ponyfill](https://github.com/gaubee/import-meta-ponyfill),
|
|
3
|
+
* but instead of using npm to install additional dependencies,
|
|
4
|
+
* this approach manually consolidates cjs/mjs/d.ts into a single file.
|
|
5
|
+
*
|
|
6
|
+
* Note that this code might be imported multiple times
|
|
7
|
+
* (for example, both dnt.test.polyfills.ts and dnt.polyfills.ts contain this code;
|
|
8
|
+
* or Node.js might dynamically clear the cache and then force a require).
|
|
9
|
+
* Therefore, it's important to avoid redundant writes to global objects.
|
|
10
|
+
* Additionally, consider that commonjs is used alongside esm,
|
|
11
|
+
* so the two ponyfill functions are stored independently in two separate global objects.
|
|
12
|
+
*/
|
|
13
|
+
//@ts-ignore
|
|
14
|
+
import { createRequire } from "node:module";
|
|
15
|
+
//@ts-ignore
|
|
16
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
17
|
+
//@ts-ignore
|
|
18
|
+
import { dirname } from "node:path";
|
|
19
|
+
const defineGlobalPonyfill = (symbolFor, fn) => {
|
|
20
|
+
if (!Reflect.has(globalThis, Symbol.for(symbolFor))) {
|
|
21
|
+
Object.defineProperty(globalThis, Symbol.for(symbolFor), {
|
|
22
|
+
configurable: true,
|
|
23
|
+
get() {
|
|
24
|
+
return fn;
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export let import_meta_ponyfill_commonjs = (Reflect.get(globalThis, Symbol.for("import-meta-ponyfill-commonjs")) ??
|
|
30
|
+
(() => {
|
|
31
|
+
const moduleImportMetaWM = new WeakMap();
|
|
32
|
+
return (require, module) => {
|
|
33
|
+
let importMetaCache = moduleImportMetaWM.get(module);
|
|
34
|
+
if (importMetaCache == null) {
|
|
35
|
+
const importMeta = Object.assign(Object.create(null), {
|
|
36
|
+
url: pathToFileURL(module.filename).href,
|
|
37
|
+
main: require.main == module,
|
|
38
|
+
resolve: (specifier, parentURL = importMeta.url) => {
|
|
39
|
+
return pathToFileURL((importMeta.url === parentURL
|
|
40
|
+
? require
|
|
41
|
+
: createRequire(parentURL))
|
|
42
|
+
.resolve(specifier)).href;
|
|
43
|
+
},
|
|
44
|
+
filename: module.filename,
|
|
45
|
+
dirname: module.path,
|
|
46
|
+
});
|
|
47
|
+
moduleImportMetaWM.set(module, importMeta);
|
|
48
|
+
importMetaCache = importMeta;
|
|
49
|
+
}
|
|
50
|
+
return importMetaCache;
|
|
51
|
+
};
|
|
52
|
+
})());
|
|
53
|
+
defineGlobalPonyfill("import-meta-ponyfill-commonjs", import_meta_ponyfill_commonjs);
|
|
54
|
+
export let import_meta_ponyfill_esmodule = (Reflect.get(globalThis, Symbol.for("import-meta-ponyfill-esmodule")) ??
|
|
55
|
+
((importMeta) => {
|
|
56
|
+
const resolveFunStr = String(importMeta.resolve);
|
|
57
|
+
const shimWs = new WeakSet();
|
|
58
|
+
//@ts-ignore
|
|
59
|
+
const mainUrl = ("file:///" + process.argv[1].replace(/\\/g, "/"))
|
|
60
|
+
.replace(/\/{3,}/, "///");
|
|
61
|
+
const commonShim = (importMeta) => {
|
|
62
|
+
if (typeof importMeta.main !== "boolean") {
|
|
63
|
+
importMeta.main = importMeta.url === mainUrl;
|
|
64
|
+
}
|
|
65
|
+
if (typeof importMeta.filename !== "string") {
|
|
66
|
+
importMeta.filename = fileURLToPath(importMeta.url);
|
|
67
|
+
importMeta.dirname = dirname(importMeta.filename);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
if (
|
|
71
|
+
// v16.2.0+, v14.18.0+: Add support for WHATWG URL object to parentURL parameter.
|
|
72
|
+
resolveFunStr === "undefined" ||
|
|
73
|
+
// v20.0.0+, v18.19.0+"" This API now returns a string synchronously instead of a Promise.
|
|
74
|
+
resolveFunStr.startsWith("async")
|
|
75
|
+
// enable by --experimental-import-meta-resolve flag
|
|
76
|
+
) {
|
|
77
|
+
import_meta_ponyfill_esmodule = (importMeta) => {
|
|
78
|
+
if (!shimWs.has(importMeta)) {
|
|
79
|
+
shimWs.add(importMeta);
|
|
80
|
+
const importMetaUrlRequire = {
|
|
81
|
+
url: importMeta.url,
|
|
82
|
+
require: createRequire(importMeta.url),
|
|
83
|
+
};
|
|
84
|
+
// note: the parameter types must be explicitly annotated because
|
|
85
|
+
// `@types/node` also declares `ImportMeta.resolve`, which makes
|
|
86
|
+
// the contextual type an overload set that provides no inference
|
|
87
|
+
importMeta.resolve = function resolve(specifier, parentURL = importMeta.url) {
|
|
88
|
+
return pathToFileURL((importMetaUrlRequire.url === parentURL
|
|
89
|
+
? importMetaUrlRequire.require
|
|
90
|
+
: createRequire(parentURL)).resolve(specifier)).href;
|
|
91
|
+
};
|
|
92
|
+
commonShim(importMeta);
|
|
93
|
+
}
|
|
94
|
+
return importMeta;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
/// native support
|
|
99
|
+
import_meta_ponyfill_esmodule = (importMeta) => {
|
|
100
|
+
if (!shimWs.has(importMeta)) {
|
|
101
|
+
shimWs.add(importMeta);
|
|
102
|
+
commonShim(importMeta);
|
|
103
|
+
}
|
|
104
|
+
return importMeta;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return import_meta_ponyfill_esmodule(importMeta);
|
|
108
|
+
}));
|
|
109
|
+
defineGlobalPonyfill("import-meta-ponyfill-esmodule", import_meta_ponyfill_esmodule);
|
|
110
|
+
export let import_meta_ponyfill = ((...args) => {
|
|
111
|
+
const _MODULE = (() => {
|
|
112
|
+
if (typeof require === "function" && typeof module === "object") {
|
|
113
|
+
return "commonjs";
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// eval("typeof import.meta");
|
|
117
|
+
return "esmodule";
|
|
118
|
+
}
|
|
119
|
+
})();
|
|
120
|
+
if (_MODULE === "commonjs") {
|
|
121
|
+
//@ts-ignore
|
|
122
|
+
import_meta_ponyfill = (r, m) => import_meta_ponyfill_commonjs(r, m);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
//@ts-ignore
|
|
126
|
+
import_meta_ponyfill = (im) => import_meta_ponyfill_esmodule(im);
|
|
127
|
+
}
|
|
128
|
+
//@ts-ignore
|
|
129
|
+
return import_meta_ponyfill(...args);
|
|
130
|
+
});
|
|
131
|
+
// https://github.com/tc39/proposal-accessible-object-hasownproperty/blob/main/polyfill.js
|
|
132
|
+
if (!Object.hasOwn) {
|
|
133
|
+
Object.defineProperty(Object, "hasOwn", {
|
|
134
|
+
value: function (object, property) {
|
|
135
|
+
if (object == null) {
|
|
136
|
+
throw new TypeError("Cannot convert undefined or null to object");
|
|
137
|
+
}
|
|
138
|
+
return Object.prototype.hasOwnProperty.call(Object(object), property);
|
|
139
|
+
},
|
|
140
|
+
configurable: true,
|
|
141
|
+
enumerable: false,
|
|
142
|
+
writable: true,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Deno } from "@deno/shim-deno";
|
|
2
|
+
export { Deno } from "@deno/shim-deno";
|
|
3
|
+
const dntGlobals = {
|
|
4
|
+
Deno,
|
|
5
|
+
};
|
|
6
|
+
export const dntGlobalThis = createMergeProxy(globalThis, dntGlobals);
|
|
7
|
+
function createMergeProxy(baseObj, extObj) {
|
|
8
|
+
return new Proxy(baseObj, {
|
|
9
|
+
get(_target, prop, _receiver) {
|
|
10
|
+
if (prop in extObj) {
|
|
11
|
+
return extObj[prop];
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
return baseObj[prop];
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
set(_target, prop, value) {
|
|
18
|
+
if (prop in extObj) {
|
|
19
|
+
delete extObj[prop];
|
|
20
|
+
}
|
|
21
|
+
baseObj[prop] = value;
|
|
22
|
+
return true;
|
|
23
|
+
},
|
|
24
|
+
deleteProperty(_target, prop) {
|
|
25
|
+
let success = false;
|
|
26
|
+
if (prop in extObj) {
|
|
27
|
+
delete extObj[prop];
|
|
28
|
+
success = true;
|
|
29
|
+
}
|
|
30
|
+
if (prop in baseObj) {
|
|
31
|
+
delete baseObj[prop];
|
|
32
|
+
success = true;
|
|
33
|
+
}
|
|
34
|
+
return success;
|
|
35
|
+
},
|
|
36
|
+
ownKeys(_target) {
|
|
37
|
+
const baseKeys = Reflect.ownKeys(baseObj);
|
|
38
|
+
const extKeys = Reflect.ownKeys(extObj);
|
|
39
|
+
const extKeysSet = new Set(extKeys);
|
|
40
|
+
return [...baseKeys.filter((k) => !extKeysSet.has(k)), ...extKeys];
|
|
41
|
+
},
|
|
42
|
+
defineProperty(_target, prop, desc) {
|
|
43
|
+
if (prop in extObj) {
|
|
44
|
+
delete extObj[prop];
|
|
45
|
+
}
|
|
46
|
+
Reflect.defineProperty(baseObj, prop, desc);
|
|
47
|
+
return true;
|
|
48
|
+
},
|
|
49
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
50
|
+
if (prop in extObj) {
|
|
51
|
+
return Reflect.getOwnPropertyDescriptor(extObj, prop);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return Reflect.getOwnPropertyDescriptor(baseObj, prop);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
has(_target, prop) {
|
|
58
|
+
return prop in extObj || prop in baseObj;
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
package/esm/cli/hc.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "../_dnt.polyfills.js";
|
|
3
|
+
import * as dntShim from "../_dnt.shims.js";
|
|
4
|
+
import { HCEval, make_context } from "../lib/execute/hc-eval.js";
|
|
5
|
+
import { HCLog } from "../lib/execute/hc-log.js";
|
|
6
|
+
import { HCTest } from "../lib/execute/hc-test.js";
|
|
7
|
+
import { parseArgs } from "../deps/jsr.io/@std/cli/1.0.32/parse_args.js";
|
|
8
|
+
import { runfile } from "./runfile.js";
|
|
9
|
+
import { Prompt } from "./prompt.js";
|
|
10
|
+
import { DenoFileStore } from "./resource-store.js";
|
|
11
|
+
import { Frame, FrameResource, RESOURCE_ROOT_KEY, } from "../lib/frames.js";
|
|
12
|
+
/**
|
|
13
|
+
* @module hc
|
|
14
|
+
*
|
|
15
|
+
* This is the main entry point for the hc command-line interface (CLI).
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* aliases to short form of command-line interface (CLI) options.
|
|
19
|
+
*/
|
|
20
|
+
const aliases = {
|
|
21
|
+
e: "evaluate",
|
|
22
|
+
h: "help",
|
|
23
|
+
i: "interactive",
|
|
24
|
+
t: "testdoc",
|
|
25
|
+
v: "verbose",
|
|
26
|
+
V: "version",
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Parses command-line arguments and returns the options.
|
|
30
|
+
*
|
|
31
|
+
* @param args - The array of command-line arguments (only).
|
|
32
|
+
* @returns The parsed options object.
|
|
33
|
+
*/
|
|
34
|
+
export function getOptions(args) {
|
|
35
|
+
return parseArgs(args, {
|
|
36
|
+
alias: aliases,
|
|
37
|
+
boolean: ["help", "interactive", "testdoc", "verbose", "version"],
|
|
38
|
+
string: ["evaluate"],
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Creates and returns an instance of `HCEval` initialized with the provided environment variables.
|
|
43
|
+
*
|
|
44
|
+
* The host namespace also carries this harness's root binding, so a resource
|
|
45
|
+
* identifier resolves against a fresh temp directory rather than against the
|
|
46
|
+
* working directory. That is a narrowing: the process still holds whatever the
|
|
47
|
+
* harness granted it, and the root binding is the ceiling the language enforces
|
|
48
|
+
* inside it.
|
|
49
|
+
*
|
|
50
|
+
* @param env - An object containing key-value pairs of environment variables.
|
|
51
|
+
* @param out - Optional output sink. Tests inject a capture frame; the CLI uses HCLog.
|
|
52
|
+
* @returns An instance of `HCEval` configured with the provided environment variables.
|
|
53
|
+
*/
|
|
54
|
+
export function getEval(env, out) {
|
|
55
|
+
const context = make_context(env);
|
|
56
|
+
const output = out ?? new HCLog(context);
|
|
57
|
+
return new HCEval(output, new Frame(), getHost(context));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Builds this harness's host namespace, root binding included.
|
|
61
|
+
*
|
|
62
|
+
* Exported so a test can run a source unit under the authority the CLI actually
|
|
63
|
+
* grants, rather than under an empty namespace that would make the resource
|
|
64
|
+
* primitive invisible.
|
|
65
|
+
*
|
|
66
|
+
* @param context - Host bindings, which are copied rather than adopted.
|
|
67
|
+
* @returns A frame reachable from HC source through `$$`.
|
|
68
|
+
*/
|
|
69
|
+
export function getHost(context = {}) {
|
|
70
|
+
// Copied, because a Frame adopts the Context object it is handed and the
|
|
71
|
+
// logger holds the same one: the root binding belongs to the host namespace
|
|
72
|
+
// and nowhere else.
|
|
73
|
+
const host = new Frame({ ...context });
|
|
74
|
+
host.set(RESOURCE_ROOT_KEY, FrameResource.root(new DenoFileStore()));
|
|
75
|
+
return host;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The main function for the CLI application.
|
|
79
|
+
*
|
|
80
|
+
* @param hc_eval - An instance of HCEval.
|
|
81
|
+
* @param options - The options object returned by the getOptions function.
|
|
82
|
+
*
|
|
83
|
+
* The function performs the following tasks:
|
|
84
|
+
* - Logs the options if the verbose flag is set.
|
|
85
|
+
* - Creates a context and output logger.
|
|
86
|
+
* - Initializes the HCEval instance.
|
|
87
|
+
* - If the testdoc option is set, initializes the HCTest instance and updates the HCEval instance.
|
|
88
|
+
* - If the evaluate option is set, evaluates the provided code.
|
|
89
|
+
* - Iterates over the files provided in the options and runs each file.
|
|
90
|
+
* - If the interactive option is set or no evaluation has been performed, starts the REPL.
|
|
91
|
+
*/
|
|
92
|
+
export async function main(hcEval, options) {
|
|
93
|
+
let evaluated = false;
|
|
94
|
+
let sourceStarted = false;
|
|
95
|
+
let lexicalComplete = true;
|
|
96
|
+
let test;
|
|
97
|
+
if (options.verbose) {
|
|
98
|
+
console.error("options", options);
|
|
99
|
+
}
|
|
100
|
+
if (options.testdoc) {
|
|
101
|
+
test = new HCTest(hcEval.out);
|
|
102
|
+
hcEval = hcEval.withOutput(test);
|
|
103
|
+
evaluated = true;
|
|
104
|
+
}
|
|
105
|
+
const finishSource = (evaluator) => {
|
|
106
|
+
const complete = evaluator.finish();
|
|
107
|
+
if (!complete) {
|
|
108
|
+
const reason = evaluator.error() ?? "incomplete lexical input";
|
|
109
|
+
console.error(`HCEval.finish.failed: ${reason}`);
|
|
110
|
+
}
|
|
111
|
+
return complete;
|
|
112
|
+
};
|
|
113
|
+
if (options.evaluate) {
|
|
114
|
+
sourceStarted = true;
|
|
115
|
+
hcEval.call(options.evaluate.toString());
|
|
116
|
+
evaluated = true;
|
|
117
|
+
lexicalComplete = finishSource(hcEval);
|
|
118
|
+
}
|
|
119
|
+
for (const file of options._) {
|
|
120
|
+
if (!lexicalComplete)
|
|
121
|
+
break;
|
|
122
|
+
if (typeof file !== "string") {
|
|
123
|
+
console.error("Invalid file argument", file);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (sourceStarted)
|
|
127
|
+
hcEval = hcEval.nextSourceUnit();
|
|
128
|
+
sourceStarted = true;
|
|
129
|
+
evaluated = await runfile(hcEval, file);
|
|
130
|
+
lexicalComplete = finishSource(hcEval);
|
|
131
|
+
}
|
|
132
|
+
if (lexicalComplete && (options.interactive || !evaluated)) {
|
|
133
|
+
if (sourceStarted)
|
|
134
|
+
hcEval = hcEval.nextSourceUnit();
|
|
135
|
+
sourceStarted = true;
|
|
136
|
+
if (hcEval.out instanceof HCLog)
|
|
137
|
+
hcEval.out.prompt = true;
|
|
138
|
+
await new Prompt(hcEval).repl();
|
|
139
|
+
lexicalComplete = finishSource(hcEval);
|
|
140
|
+
}
|
|
141
|
+
if (!sourceStarted) {
|
|
142
|
+
lexicalComplete = finishSource(hcEval);
|
|
143
|
+
}
|
|
144
|
+
if (test && lexicalComplete) {
|
|
145
|
+
test.finish();
|
|
146
|
+
}
|
|
147
|
+
return lexicalComplete ? test?.exitCode ?? 0 : 1;
|
|
148
|
+
}
|
|
149
|
+
if (globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).main) {
|
|
150
|
+
const env = dntShim.Deno.env.toObject();
|
|
151
|
+
const options = getOptions(dntShim.Deno.args);
|
|
152
|
+
const hc_eval = getEval(env);
|
|
153
|
+
main(hc_eval, options).then((exitCode) => {
|
|
154
|
+
dntShim.Deno.exit(exitCode);
|
|
155
|
+
}).catch((err) => {
|
|
156
|
+
console.error(err);
|
|
157
|
+
dntShim.Deno.exit(1);
|
|
158
|
+
});
|
|
159
|
+
}
|