rip-lang 3.1.1 → 3.2.0

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
@@ -11,7 +11,7 @@
11
11
  <p align="center">
12
12
  <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.1.0-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
- <a href="#"><img src="https://img.shields.io/badge/tests-1073%2F1073-brightgreen.svg" alt="Tests"></a>
14
+ <a href="#"><img src="https://img.shields.io/badge/tests-1130%2F1130-brightgreen.svg" alt="Tests"></a>
15
15
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
16
16
  </p>
17
17
 
@@ -40,6 +40,7 @@ get '/users/:id' -> # RESTful API endpoint, comma-less
40
40
  - **Modern output** — ES2022 with native classes, `?.`, `??`, modules
41
41
  - **New operators** — `!`, `!?`, `//`, `%%`, `=~`, `.new()`, and more
42
42
  - **Reactive operators** — `:=`, `~=`, `~>` as language syntax
43
+ - **Optional types** — `::` annotations, `::=` aliases, `.d.ts` emission
43
44
  - **Zero dependencies** — everything included, even the parser generator
44
45
  - **Self-hosting** — `bun run parser` rebuilds the compiler from source
45
46
 
@@ -137,6 +138,27 @@ State, computed values, and effects as language operators:
137
138
 
138
139
  ---
139
140
 
141
+ ### Types (Optional)
142
+
143
+ Type annotations are erased at compile time — zero runtime cost:
144
+
145
+ ```coffee
146
+ def greet(name:: string):: string # Typed function
147
+ "Hello, #{name}!"
148
+
149
+ User ::= type # Structural type
150
+ id: number
151
+ name: string
152
+
153
+ enum HttpCode # Runtime enum
154
+ ok = 200
155
+ notFound = 404
156
+ ```
157
+
158
+ Compiles to `.js` (types erased) + `.d.ts` (types preserved) — full IDE support via TypeScript Language Server. See [docs/RIP-TYPES.md](docs/RIP-TYPES.md).
159
+
160
+ ---
161
+
140
162
  ## Operators
141
163
 
142
164
  | Operator | Example | What it does |
package/bin/rip CHANGED
@@ -25,6 +25,7 @@ Usage:
25
25
 
26
26
  Options:
27
27
  -c, --compile Show compiled JavaScript output
28
+ -d, --dts Generate .d.ts type declaration file
28
29
  -h, --help Show this help message
29
30
  -o, --output <file> Write JavaScript to file
30
31
  -q, --quiet Suppress headers
@@ -44,6 +45,8 @@ Examples:
44
45
  rip -t example.rip # Show ONLY tokens
45
46
  rip -s -c example.rip # Show s-expressions AND JavaScript
46
47
  rip -s -t -c example.rip # Show everything (full debug mode)
48
+ rip -d example.rip # Generate example.d.ts
49
+ rip -cd example.rip # Compile JS and generate .d.ts
47
50
  rip -q -c example.rip # Just the JS, no headers (for piping)
48
51
  rip -w # Launch browser REPL (auto-opens)
49
52
  echo 'x = 1 + 2' | rip -c # Compile from stdin
@@ -142,12 +145,14 @@ async function main() {
142
145
  const showTokens = ripOptions.includes('-t') || ripOptions.includes('--tokens');
143
146
  const showSExpr = ripOptions.includes('-s') || ripOptions.includes('--sexpr');
144
147
  const showCompiled = ripOptions.includes('-c') || ripOptions.includes('--compile');
148
+ const generateDts = ripOptions.includes('-d') || ripOptions.includes('--dts');
145
149
  const quiet = ripOptions.includes('-q') || ripOptions.includes('--quiet');
146
150
 
147
151
  const options = {
148
152
  showTokens,
149
153
  showSExpr,
150
- quiet
154
+ quiet,
155
+ types: generateDts ? 'emit' : undefined
151
156
  };
152
157
 
153
158
  // Find input file and output file from ripOptions only
@@ -162,7 +167,7 @@ async function main() {
162
167
  }
163
168
 
164
169
  // If .rip file without compile flags → execute instead of compile
165
- const hasCompileFlag = showCompiled || showTokens || showSExpr || outputFile;
170
+ const hasCompileFlag = showCompiled || showTokens || showSExpr || generateDts || outputFile;
166
171
  if (inputFile && inputFile.endsWith('.rip') && !hasCompileFlag) {
167
172
  // Check if file exists
168
173
  if (!existsSync(inputFile)) {
@@ -255,6 +260,23 @@ async function main() {
255
260
  }
256
261
  console.log(result.code);
257
262
  }
263
+
264
+ // Write .d.ts file
265
+ if (generateDts && result.dts) {
266
+ if (inputFile) {
267
+ let dtsFile = inputFile.replace(/\.rip$/, '.d.ts');
268
+ writeFileSync(dtsFile, result.dts, 'utf-8');
269
+ if (!options.quiet) {
270
+ console.log(`Generated ${dtsFile}`);
271
+ }
272
+ } else {
273
+ // stdin — print .d.ts to stdout
274
+ if (!options.quiet) {
275
+ console.log(`// == Type declarations == //\n`);
276
+ }
277
+ console.log(result.dts);
278
+ }
279
+ }
258
280
  } catch (error) {
259
281
  console.error('Compilation Error:', error.message);
260
282
  if (error.stack) {
@@ -90,18 +90,22 @@ console.log(code);
90
90
  ## The Pipeline
91
91
 
92
92
  ```
93
- Source Code → Lexer → Parser → S-Expressions → Codegen → JavaScript
94
- (1,542) (352) (simple arrays) (3,148) (ES2022)
93
+ Source Code → Lexer → emitTypes → Parser → S-Expressions → Codegen → JavaScript
94
+ (1,866) (types.js) (356) (simple arrays) (3,219) (ES2022)
95
+
96
+ file.d.ts (when types: "emit")
95
97
  ```
96
98
 
97
99
  ## Key Files
98
100
 
99
101
  | File | Purpose | Lines | Modify? |
100
102
  |------|---------|-------|---------|
101
- | `src/lexer.js` | Lexer + Rewriter | 1,542 | Yes |
102
- | `src/compiler.js` | Compiler + Code Generator | 3,148 | Yes |
103
- | `src/parser.js` | Generated parser | 352 | No (auto-gen) |
104
- | `src/grammar/grammar.rip` | Grammar specification | 887 | Yes (carefully) |
103
+ | `src/lexer.js` | Lexer + Rewriter | 1,866 | Yes |
104
+ | `src/compiler.js` | Compiler + Code Generator | 3,219 | Yes |
105
+ | `src/types.js` | Type System (lexer sidecar) | 718 | Yes |
106
+ | `src/components.js` | Component System (compiler sidecar) | ~1,240 | Yes |
107
+ | `src/parser.js` | Generated parser | 356 | No (auto-gen) |
108
+ | `src/grammar/grammar.rip` | Grammar specification | 934 | Yes (carefully) |
105
109
  | `src/grammar/solar.rip` | Parser generator | 1,001 | No |
106
110
 
107
111
  ## Example Flow
@@ -240,6 +244,12 @@ S-expressions are simple arrays that serve as Rip's intermediate representation
240
244
  ['class', name, parent?, ...members]
241
245
  ```
242
246
 
247
+ ### Types
248
+ ```javascript
249
+ ['enum', name, body] // Enum declaration (runtime JS)
250
+ // Type aliases, interfaces → handled by rewriter, never reach parser
251
+ ```
252
+
243
253
  ### Ranges & Slicing
244
254
  ```javascript
245
255
  ['..', from, to] // Inclusive range
@@ -558,7 +568,6 @@ bun src/compare-compilers.js
558
568
 
559
569
  # 9. Future Work
560
570
 
561
- - `::` token for type annotations (see `docs/RIP-TYPES.md`)
562
571
  - Comment preservation for source maps
563
572
  - Parser update to read `.data` directly instead of `new String()` properties
564
573
  - Once parser supports `.data`, the `meta()`/`str()` helpers become trivial to update
@@ -567,8 +576,9 @@ bun src/compare-compilers.js
567
576
 
568
577
  **See Also:**
569
578
  - [RIP-LANG.md](RIP-LANG.md) — Language reference
579
+ - [RIP-TYPES.md](RIP-TYPES.md) — Type system specification
570
580
  - [RIP-REACTIVITY.md](RIP-REACTIVITY.md) — Reactivity deep dive
571
581
 
572
582
  ---
573
583
 
574
- *Rip 3.0 — 1,073 tests passing — Zero dependencies — Self-hosting — ~7,700 LOC*
584
+ *Rip 3.0 — 1,130 tests passing — Zero dependencies — Self-hosting — ~8,800 LOC*
package/docs/RIP-LANG.md CHANGED
@@ -17,9 +17,10 @@ Rip is a modern reactive language that compiles to ES2022 JavaScript. It combine
17
17
  9. [Regex Features](#9-regex-features)
18
18
  10. [Server-Side Development](#10-server-side-development)
19
19
  11. [CLI Tools & Scripts](#11-cli-tools--scripts)
20
- 12. [JavaScript Interop](#12-javascript-interop)
21
- 13. [Common Patterns](#13-common-patterns)
22
- 14. [Quick Reference](#14-quick-reference)
20
+ 12. [Types](#12-types)
21
+ 13. [JavaScript Interop](#13-javascript-interop)
22
+ 14. [Common Patterns](#14-common-patterns)
23
+ 15. [Quick Reference](#15-quick-reference)
23
24
 
24
25
  ---
25
26
 
@@ -924,7 +925,41 @@ for filename in files
924
925
 
925
926
  ---
926
927
 
927
- # 12. JavaScript Interop
928
+ # 12. Types
929
+
930
+ Rip supports an optional, compile-time-only type system. Types are erased from
931
+ `.js` output and preserved in `.d.ts` declaration files.
932
+
933
+ ```coffee
934
+ # Type annotations (::)
935
+ count:: number = 0
936
+ def greet(name:: string):: string
937
+ "Hello, #{name}!"
938
+
939
+ # Type aliases (::=)
940
+ ID ::= number
941
+ User ::= type
942
+ id: number
943
+ name: string
944
+
945
+ # Interfaces
946
+ interface Animal
947
+ name: string
948
+
949
+ # Enums (emit runtime JS)
950
+ enum HttpCode
951
+ ok = 200
952
+ notFound = 404
953
+ ```
954
+
955
+ Types use `=>` for function type arrows and `->` for code arrows. This
956
+ disambiguates type expressions from function bodies cleanly.
957
+
958
+ For the complete type system specification, see [RIP-TYPES.md](RIP-TYPES.md).
959
+
960
+ ---
961
+
962
+ # 13. JavaScript Interop
928
963
 
929
964
  ```coffee
930
965
  # Import any npm package
@@ -954,7 +989,7 @@ const { code } = compile('x = 42');
954
989
 
955
990
  ---
956
991
 
957
- # 13. Common Patterns
992
+ # 14. Common Patterns
958
993
 
959
994
  ## Error Handling
960
995
 
@@ -1036,7 +1071,7 @@ class EventEmitter
1036
1071
 
1037
1072
  ---
1038
1073
 
1039
- # 14. Quick Reference
1074
+ # 15. Quick Reference
1040
1075
 
1041
1076
  ## Syntax Cheat Sheet
1042
1077
 
@@ -286,3 +286,24 @@ Rip's reactivity system:
286
286
  ✅ **Extra utilities** — `.lock()`, `.read()`, `.kill()` that others lack <br>
287
287
 
288
288
  **On par with Vue/Solid. Better than React. A fraction of the size.**
289
+
290
+ ---
291
+
292
+ ## Types and Reactivity
293
+
294
+ Reactive operators work with Rip's optional type system:
295
+
296
+ ```coffee
297
+ count:: number := 0 # Typed state
298
+ doubled:: number ~= count * 2 # Typed computed
299
+ ```
300
+
301
+ Type annotations are erased from `.js` output. In `.d.ts` output, reactive
302
+ state emits `Signal<T>` and computed values emit `Computed<T>`:
303
+
304
+ ```ts
305
+ declare const count: Signal<number>;
306
+ declare const doubled: Computed<number>;
307
+ ```
308
+
309
+ See [RIP-TYPES.md](RIP-TYPES.md) for the complete type system specification.