rip-lang 3.13.129 → 3.13.131

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 CHANGED
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.13.129-blue.svg" alt="Version"></a>
12
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.13.130-blue.svg" alt="Version"></a>
13
13
  <a href="#zero-dependencies"><img src="https://img.shields.io/badge/dependencies-ZERO-brightgreen.svg" alt="Dependencies"></a>
14
14
  <a href="#"><img src="https://img.shields.io/badge/tests-1%2C436%2F1%2C436-brightgreen.svg" alt="Tests"></a>
15
15
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
@@ -410,16 +410,16 @@ Simple arrays (with `.loc`) instead of AST node classes. The compiler is self-ho
410
410
  | Component | File | Lines |
411
411
  |-----------|------|-------|
412
412
  | Lexer + Rewriter | `src/lexer.js` | 1,778 |
413
+ | Grammar | `src/grammar/grammar.rip` | 948 |
414
+ | Parser Generator | `src/grammar/solar.rip` | 929 |
415
+ | Parser (generated) | `src/parser.js` | 359 |
413
416
  | Compiler + Codegen | `src/compiler.js` | 3,334 |
414
- | Type System | `src/types.js` | 1,091 |
415
417
  | Component System | `src/components.js` | 2,026 |
418
+ | Browser Engine | `src/browser.js` | 194 |
416
419
  | Source Maps | `src/sourcemaps.js` | 189 |
420
+ | Type System | `src/types.js` | 1,091 |
417
421
  | Type Checking | `src/typecheck.js` | 442 |
418
- | Parser (generated) | `src/parser.js` | 359 |
419
- | Grammar | `src/grammar/grammar.rip` | 948 |
420
- | Parser Generator | `src/grammar/solar.rip` | 929 |
421
422
  | REPL | `src/repl.js` | 600 |
422
- | Browser Entry | `src/browser.js` | 194 |
423
423
  | **Total** | | **~11,890** |
424
424
 
425
425
  ---
package/bin/rip CHANGED
@@ -32,14 +32,6 @@ function getRepoRoot() {
32
32
  }
33
33
  }
34
34
 
35
- function getWorkspaceServerPath() {
36
- const repoRoot = getRepoRoot();
37
- if (!repoRoot) return null;
38
-
39
- const workspaceServerPath = join(repoRoot, 'packages', 'server', 'server.rip');
40
- return isFile(workspaceServerPath) ? workspaceServerPath : null;
41
- }
42
-
43
35
  function printHelp() {
44
36
  console.log(`
45
37
  Rip ${VERSION} - ${SUMMARY}
@@ -62,34 +54,28 @@ Options:
62
54
  --shadow Show virtual TypeScript content (what rip check sees)
63
55
 
64
56
  Subcommands:
65
- rip server [flags] [app] Start server (watches *.rip, HTTPS, mDNS)
66
57
  rip check [dir] Type-check all .rip files in directory
58
+ rip <name> [args] Run rip-<name> (repo bin/, node_modules, or PATH)
67
59
 
68
- Serve flags:
69
- --watch=<glob> Watch glob pattern (default: *.rip)
70
- --static Disable hot reload and file watching
71
- http HTTP-only mode (no HTTPS)
72
- http:<port> Set HTTP port
73
- w:<n> Worker count (auto, half, 2x, 3x, or number)
60
+ Packages:
61
+ rip server [flags] [app] Start server (run 'rip server -h' for details)
62
+ rip db DuckDB server
63
+ rip csv CSV parser
64
+ rip print Syntax-highlighted code printer
74
65
 
75
66
  Examples:
76
67
  rip # Interactive REPL (terminal)
77
68
  rip script.rip # Execute script directly
78
69
  rip script.rip arg1 arg2 # Execute with arguments
79
- rip server # Serve ./index.rip (watches *.rip)
80
- rip server http # Serve HTTP-only
81
- rip server myapp # Serve with mDNS name
70
+ rip server # Start server (watches *.rip, HTTPS, mDNS)
71
+ rip server -c # Validate server config
72
+ rip server -s # Stop running server
82
73
  rip -c example.rip # Compile and show JavaScript
83
74
  rip -o output.js example.rip # Compile and save to file
84
75
  rip -s example.rip # Show ONLY s-expressions
85
76
  rip -t example.rip # Show ONLY tokens
86
- rip -s -c example.rip # Show s-expressions AND JavaScript
87
- rip -s -t -c example.rip # Show everything (full debug mode)
88
77
  rip -d example.rip # Show type declarations
89
78
  rip -m example.rip # Compile with inline source map
90
- rip -cd example.rip # Show compiled JS and type declarations
91
- rip --shadow example.rip # Show shadow TypeScript (for type-check debugging)
92
- rip -q -c example.rip # Just the JS, no headers (for piping)
93
79
  echo 'p 1 + 2' | rip # Execute from stdin
94
80
  echo 'x = 1 + 2' | rip -c # Compile from stdin
95
81
 
@@ -141,7 +127,7 @@ async function main() {
141
127
  process.exit(0);
142
128
  }
143
129
 
144
- // --- Subcommands ---
130
+ // --- Built-in subcommands ---
145
131
 
146
132
  if (args[0] === 'check') {
147
133
  const { runCheck } = await import('../src/typecheck.js');
@@ -153,22 +139,48 @@ async function main() {
153
139
  process.exit(exitCode);
154
140
  }
155
141
 
156
- if (args[0] === 'server') {
157
- let serverPath;
158
- serverPath = getWorkspaceServerPath();
159
- if (!serverPath) {
160
- try {
161
- serverPath = fileURLToPath(import.meta.resolve('@rip-lang/server/server'));
162
- } catch {
163
- console.error('Error: @rip-lang/server is not installed.\n\n bun add @rip-lang/server\n');
164
- process.exit(1);
142
+ // --- Subcommand dispatch: rip <name> → rip-<name> ---
143
+
144
+ if (scriptFileIndex >= 0) {
145
+ const candidate = args[scriptFileIndex];
146
+ if (!candidate.startsWith('-') && !isFile(candidate)) {
147
+ const name = candidate;
148
+ const subArgs = args.slice(scriptFileIndex + 1);
149
+
150
+ const repoRoot = getRepoRoot();
151
+ if (repoRoot) {
152
+ // 1. Repo package: bin/rip-<name>
153
+ const repoPkg = join(repoRoot, 'bin', `rip-${name}`);
154
+ if (existsSync(repoPkg)) {
155
+ const r = spawnSync(repoPkg, subArgs, { stdio: 'inherit', env: process.env });
156
+ process.exit(r.status ?? 1);
157
+ }
158
+
159
+ // 2. Repo script: bin/<name>
160
+ const repoScript = join(repoRoot, 'bin', name);
161
+ if (existsSync(repoScript)) {
162
+ const r = spawnSync(repoScript, subArgs, { stdio: 'inherit', env: process.env });
163
+ process.exit(r.status ?? 1);
164
+ }
165
+
166
+ // 3. Local node_modules: node_modules/.bin/rip-<name>
167
+ const localBin = join(repoRoot, 'node_modules', '.bin', `rip-${name}`);
168
+ if (existsSync(localBin)) {
169
+ const r = spawnSync(localBin, subArgs, { stdio: 'inherit', env: process.env });
170
+ process.exit(r.status ?? 1);
171
+ }
165
172
  }
173
+
174
+ // 4. Global PATH: rip-<name>
175
+ const pathResult = spawnSync(`rip-${name}`, subArgs, { stdio: 'inherit', env: process.env });
176
+ if (pathResult.error?.code !== 'ENOENT') {
177
+ process.exit(pathResult.status ?? 1);
178
+ }
179
+
180
+ // 5. Not found
181
+ console.error(`rip: unknown command '${name}'\n\nRun 'rip --help' for usage.`);
182
+ process.exit(1);
166
183
  }
167
- const result = spawnSync('bun', ['--preload', loaderPath, serverPath, ...args.slice(1)], {
168
- stdio: 'inherit',
169
- env: process.env
170
- });
171
- process.exit(result.status ?? 1);
172
184
  }
173
185
 
174
186
  // --- REPL ---
@@ -256,20 +268,6 @@ async function main() {
256
268
  process.exit(exitCode);
257
269
  }
258
270
 
259
- // Fallback: look for bin/{command} in git repo root
260
- // Allows `rip migrate --status` to find and run {repo}/bin/migrate
261
- if (inputFile && !inputFile.startsWith('-') && !isFile(inputFile)) {
262
- try {
263
- const repoRoot = getRepoRoot();
264
- if (!repoRoot) throw new Error('No git repo root');
265
- const binScript = join(repoRoot, 'bin', inputFile);
266
- if (existsSync(binScript)) {
267
- const r = spawnSync(binScript, scriptArgs, { stdio: 'inherit', env: process.env });
268
- process.exit(r.status ?? 1);
269
- }
270
- } catch {}
271
- }
272
-
273
271
  // --- Compile (with flags) ---
274
272
 
275
273
  if (source === undefined) {
package/bin/rip-server ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { spawnSync } from 'child_process';
4
+ import { fileURLToPath } from 'url';
5
+ import { dirname, join } from 'path';
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const loaderPath = join(__dirname, '../rip-loader.js');
9
+ const serverPath = join(__dirname, '../packages/server/server.rip');
10
+
11
+ const nodeModules = join(__dirname, '..', '..');
12
+ if (!process.env.NODE_PATH?.split(':').includes(nodeModules)) {
13
+ process.env.NODE_PATH = [nodeModules, process.env.NODE_PATH].filter(Boolean).join(':');
14
+ }
15
+
16
+ const result = spawnSync('bun', ['--preload', loaderPath, serverPath, ...process.argv.slice(2)], {
17
+ stdio: 'inherit',
18
+ env: process.env
19
+ });
20
+ process.exit(result.status ?? 1);
package/docs/RIP-LANG.md CHANGED
@@ -108,6 +108,14 @@ user = {name: "Alice", age: 30}
108
108
  shorthand = {name, age} # Same as {name: name, age: age}
109
109
  config = {api.host: "localhost", api.port: 3000} # Dotted keys → flat string keys
110
110
 
111
+ # Map literals — real JavaScript Map with any key type
112
+ table = *{
113
+ /^NAME:/: [""]
114
+ "CHOOSE 1": [1]
115
+ true: "yes"
116
+ null: "nothing"
117
+ }
118
+
111
119
  # Ranges
112
120
  nums = [1..5] # [1, 2, 3, 4, 5]
113
121
  exclusive = [1...5] # [1, 2, 3, 4]
@@ -331,6 +339,7 @@ Multiple lines
331
339
  | `not in` | Not in | `x not in arr` | Negated membership test |
332
340
  | `not of` | Not of | `k not of obj` | Negated key existence |
333
341
  | `<=>` | Two-way bind | `value <=> name` | Bidirectional reactive binding (render blocks) |
342
+ | `*{ }` | Map literal | `*{/pat/: val}` | `new Map([[/pat/, val]])` |
334
343
 
335
344
  ## Assignment Operators
336
345
 
@@ -2075,6 +2084,9 @@ a ?? b # nullish coalescing
2075
2084
  # Word arrays
2076
2085
  %w[foo bar baz] # ["foo", "bar", "baz"] — Ruby-style word literal
2077
2086
 
2087
+ # Map literals — real Map with any key type
2088
+ *{ /regex/: val, "key": val, 42: val }
2089
+
2078
2090
  # Two-way binding (render blocks)
2079
2091
  input value <=> @name # bidirectional reactive binding
2080
2092
  Dialog open <=> @show # works with components too