rip-lang 1.0.0 → 1.1.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.
@@ -31,7 +31,7 @@ echo 'your code' | ./bin/rip -s # S-expressions (parser)
31
31
  echo 'your code' | ./bin/rip -c # JavaScript (codegen)
32
32
 
33
33
  # Run tests
34
- bun run test # All 854 tests
34
+ bun run test # All tests
35
35
  bun test/runner.js test/rip/FILE.rip # Specific file
36
36
  bun --no-cache test/runner.js test/rip # Clear Bun cache
37
37
 
@@ -47,13 +47,13 @@ bun run parser # Regenerates src/parser.js from grammar.rip
47
47
  ```bash
48
48
  gh issue list
49
49
  git branch -a
50
- cat ISSUE-*.md # Handoff docs for complex issues
50
+ cat ISSUE-*.md # Handoff docs for complex issues (if any exist)
51
51
  ```
52
52
 
53
- **If resuming Issue #11 (nested comprehension IIFEs):**
54
- - Read `ISSUE-11.md` for complete analysis
55
- - Branch: `fix/nested-comprehension-context`
56
- - See "Recommended Approach" section
53
+ **If resuming an existing issue:**
54
+ - Read any `ISSUE-*.md` handoff documentation
55
+ - Check for an existing feature branch
56
+ - Review the analysis and recommended approach
57
57
 
58
58
  ---
59
59
 
@@ -114,11 +114,11 @@ fail "name", "invalid syntax"
114
114
  test/rip/
115
115
  ├── assignment.rip (43 tests)
116
116
  ├── async.rip (29 tests)
117
- ├── comprehensions.rip (24 tests) ← Nested comprehension tests here
117
+ ├── comprehensions.rip (24 tests)
118
118
  ├── functions.rip (71 tests)
119
119
  ├── loops.rip (25 tests)
120
120
  ... 15 more files
121
- Total: 854 tests (100% passing)
121
+ Total: 850+ tests (100% passing)
122
122
  ```
123
123
 
124
124
  ### Test-Driven Development
@@ -174,7 +174,7 @@ bun run test
174
174
  ### Modify Parser Runtime Behavior
175
175
 
176
176
  ```bash
177
- # Example: Improve error messages (Issue #7)
177
+ # Example: Improve error messages or parser behavior
178
178
 
179
179
  # 1. Edit solar.rip (NOT parser.js!)
180
180
  vim src/grammar/solar.rip
@@ -351,21 +351,22 @@ gh pr merge <number> --squash --delete-branch
351
351
  ## 🎯 Current Project Status
352
352
 
353
353
  **Version:** 1.0.0
354
- **Tests:** 854/854 passing (100%)
354
+ **Tests:** 854+ passing (100%)
355
355
  **Status:** Production-ready, actively maintained
356
356
 
357
- **Recent Achievements:**
358
- - ✅ Postfix comprehensions with `by` step (Issue #1)
359
- - Parser error locations (Issue #7)
360
- - Range loops without variable (Issue #9)
361
- - bar.coffee compiles successfully
362
- - 48% smaller output than CoffeeScript
363
-
364
- **Open Issues:**
365
- - Issue #11: Nested comprehension IIFEs (in progress, see ISSUE-11.md)
357
+ **Check current status:**
358
+ ```bash
359
+ gh issue list # See open issues
360
+ git branch -a # See active branches
361
+ bun run test # Verify test count and status
362
+ cat README.md | grep "Tests:" # Current test count
363
+ ```
366
364
 
367
- **Active Branches:**
368
- - `fix/nested-comprehension-context` - Issue #11 work
365
+ **Key achievements:**
366
+ - Full CoffeeScript compatibility
367
+ - ✅ 48% smaller output than CoffeeScript
368
+ - ✅ Comprehensive test coverage
369
+ - ✅ Production-ready compiler
369
370
 
370
371
  ---
371
372
 
@@ -379,7 +380,7 @@ gh pr merge <number> --squash --delete-branch
379
380
 
380
381
  **Technical Reference:**
381
382
  - `docs/CODEGEN.md` - All 110+ node types
382
- - `docs/COMPREHENSIONS.md` - Context rules (CRITICAL for Issue #11!)
383
+ - `docs/COMPREHENSIONS.md` - Context rules for comprehensions
383
384
  - `docs/SOLAR.md` - Parser generator guide
384
385
  - `docs/STRING.md` - String metadata
385
386
  - `docs/REGEX-PLUS.md` - Ruby-style regex
@@ -391,7 +392,7 @@ gh pr merge <number> --squash --delete-branch
391
392
 
392
393
  ## 🎨 Code Style Principles
393
394
 
394
- From today's session:
395
+ Follow these principles:
395
396
 
396
397
  1. **Keep it clean** - No ugly hacks, readable code
397
398
  2. **Keep it simple** - S-expressions over complex AST
@@ -413,16 +414,21 @@ case '+': return this.buildBinaryExpression(rest[0], rest[1], '+', {precedence:
413
414
 
414
415
  ---
415
416
 
416
- ## 🏆 Session History
417
+ ## 🏆 Workflow Example
417
418
 
418
- **Today (2025-10-31):** Completed 5 full GitHub workflows
419
- - Issue #1/PR #2: Postfix `by` step support
420
- - Issue #3/PR #4: Refactor step handling
421
- - Issue #5/PR #6: Comprehension context fix
422
- - Issue #7+#9/PR #10: Parser errors + range loops
423
- - Issue #11: Analysis complete, implementation pending
419
+ **Complete workflow for any issue:**
420
+ 1. Identify the bug or feature need
421
+ 2. Create issue via `gh issue create`
422
+ 3. Create feature branch
423
+ 4. Write failing tests
424
+ 5. Implement the fix
425
+ 6. Verify all tests pass
426
+ 7. Build browser bundle (if needed)
427
+ 8. Commit with `Fixes #N` reference
428
+ 9. Create PR with `gh pr create`
429
+ 10. Merge with `gh pr merge --squash --delete-branch`
424
430
 
425
- **All issues auto-closed via `Fixes #N` in PR descriptions!**
431
+ **All issues auto-close via `Fixes #N` in PR descriptions!**
426
432
 
427
433
  ---
428
434
 
@@ -513,7 +519,7 @@ git commit -m "fix bug" # WRONG - didn't run tests!
513
519
 
514
520
  ### ✅ Always Test First
515
521
  ```bash
516
- bun run test # MUST be 854/854 passing
522
+ bun run test # MUST be 100% passing
517
523
  git commit
518
524
  ```
519
525
 
@@ -526,7 +532,7 @@ git commit -m "Fix comprehension bug" # WRONG - issue won't auto-close!
526
532
  ```bash
527
533
  git commit -m "Fix: Description
528
534
 
529
- Fixes #11 # RIGHT - auto-closes issue!
535
+ Fixes #N # RIGHT - auto-closes issue!
530
536
  "
531
537
  ```
532
538
 
@@ -538,7 +544,7 @@ git commit anyway # WRONG!
538
544
 
539
545
  ### ✅ Keep 100% Pass Rate
540
546
  ```bash
541
- bun run test # Must be 854/854 passing
547
+ bun run test # Must be 100% passing
542
548
  # If tests fail, fix them or revert your change
543
549
  ```
544
550
 
@@ -595,12 +601,11 @@ Context-aware generation = smarter, more efficient code!
595
601
 
596
602
  **When you need deep knowledge:**
597
603
 
598
- ### For Comprehension Work (Issue #11)
604
+ ### For Comprehension Work
599
605
  1. `docs/COMPREHENSIONS.md` - Complete context rules
600
- 2. `ISSUE-11.md` - Nested IIFE problem analysis
601
- 3. `test/rip/comprehensions.rip` - All test cases
602
- 4. `src/codegen.js:2025-2230` - Comprehension IIFE generation
603
- 5. `src/codegen.js:4080-4250` - Plain loop generation
606
+ 2. `test/rip/comprehensions.rip` - All test cases
607
+ 3. Search `src/codegen.js` for `case 'comprehension':` - IIFE generation
608
+ 4. Search `src/codegen.js` for `case 'for-in':` - Plain loop generation
604
609
 
605
610
  ### For Grammar Work
606
611
  1. `docs/SOLAR.md` - Parser generator guide
@@ -614,24 +619,24 @@ Context-aware generation = smarter, more efficient code!
614
619
 
615
620
  ---
616
621
 
617
- ## 🎯 Your First Task
622
+ ## 🎯 Getting Started
618
623
 
619
624
  **Start here:**
620
625
 
621
- 1. ✅ Read AGENT.md (you're ready after this!)
626
+ 1. ✅ Read `AGENT.md` (you're ready after this!)
622
627
  2. ✅ Run `bun run test` (verify everything passes)
623
628
  3. ✅ Check `gh issue list` (see what's open)
624
- 4. ✅ If Issue #11 exists, read `ISSUE-11.md`
625
- 5. ✅ Create branch: `git checkout fix/nested-comprehension-context`
626
- 6. ✅ Implement Solution B from ISSUE-11.md
627
- 7. ✅ Follow the workflow in `docs/WORKFLOW.md`
629
+ 4. ✅ If handoff docs exist, read any `ISSUE-*.md` files
630
+ 5. ✅ Create appropriate branch: `git checkout -b fix/descriptive-name`
631
+ 6. ✅ Follow the test-driven workflow
632
+ 7. ✅ Reference `docs/WORKFLOW.md` for the complete process
628
633
 
629
634
  ---
630
635
 
631
636
  ## 🌟 Success Criteria
632
637
 
633
638
  **Before committing:**
634
- - ✅ All tests pass (854/854 or higher)
639
+ - ✅ All tests pass (100% pass rate)
635
640
  - ✅ Code follows existing patterns
636
641
  - ✅ Documentation updated
637
642
  - ✅ Browser bundle rebuilt (if codegen changed)
@@ -649,9 +654,9 @@ Context-aware generation = smarter, more efficient code!
649
654
 
650
655
  **Resources available:**
651
656
  1. Read the docs (comprehensive!)
652
- 2. Check closed PRs (#2, #4, #6, #10) for examples
657
+ 2. Check closed PRs for workflow examples: `gh pr list --state closed`
653
658
  3. Review test files for patterns
654
- 4. Use debug flags extensively
659
+ 4. Use debug flags extensively (`-t`, `-s`, `-c`)
655
660
 
656
661
  **The docs are excellent** - trust them! Everything you need is documented.
657
662
 
@@ -665,9 +670,9 @@ Context-aware generation = smarter, more efficient code!
665
670
  > - Keep the IR simple (s-expressions)
666
671
  > - Keep the pipeline clear (lex → parse → generate)
667
672
  > - Keep the code minimal (pattern matching)
668
- > - Test everything (854/854 tests passing)
673
+ > - Test everything (100% tests passing)
669
674
 
670
- **From today's session:**
675
+ **Core practices:**
671
676
 
672
677
  > Follow the workflow.
673
678
  > Write tests first.
@@ -53,7 +53,7 @@ body:
53
53
  options:
54
54
  - Blocking migration
55
55
  - High - affects many files
56
- - Medium - affects some files
56
+ - Medium - affects some files
57
57
  - Low - easy to work around
58
58
  validations:
59
59
  required: false
@@ -83,4 +83,3 @@ body:
83
83
  required: true
84
84
  - label: I've tested with the latest version of Rip
85
85
  required: false
86
-
@@ -6,4 +6,3 @@ contact_links:
6
6
  - name: 💬 Discussions
7
7
  url: https://github.com/shreeve/rip-lang/discussions
8
8
  about: Ask questions, share ideas, and discuss Rip with the community
9
-
@@ -52,4 +52,3 @@ body:
52
52
  - label: docs/COMPREHENSIONS.md
53
53
  - label: docs/SOLAR.md
54
54
  - label: Other docs in docs/ folder
55
-
@@ -22,8 +22,8 @@
22
22
 
23
23
  <!-- List the specific changes -->
24
24
 
25
- -
26
- -
25
+ -
26
+ -
27
27
 
28
28
  ## Testing
29
29
 
@@ -81,4 +81,3 @@
81
81
  ## Additional Notes
82
82
 
83
83
  <!-- Any other context, concerns, or discussion points -->
84
-
package/CHANGELOG.md ADDED
@@ -0,0 +1,82 @@
1
+ # Changelog
2
+
3
+ All notable changes to Rip will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.1.1] - 2025-11-01
9
+
10
+ ### Fixed
11
+ - **Browser REPL launcher (`rip -w`)** - Port fallback now works correctly
12
+ - Fixed `ReferenceError: assignedPort is not defined`
13
+ - Server tries port 3000, falls back to OS-assigned port if busy
14
+ - Browser opens with correct port automatically
15
+ - Works when installed globally via `npm install -g rip-lang` or `bun install -g rip-lang`
16
+
17
+ ### Changed
18
+ - Refactored serve.js to eliminate code duplication
19
+ - Improved port detection by parsing server output
20
+
21
+ ## [1.1.0] - 2025-11-01
22
+
23
+ ### Added
24
+ - **Beautiful s-expression formatter** - Canonical format with proper indentation
25
+ - Deployed in CLI (`-s` flag), browser REPL, and as standalone utility
26
+ - 80% more compact than JSON, fully parenthesized
27
+ - Heregex patterns collapsed to single line
28
+ - Meta-circular: Rip code formatting Rip's data structures!
29
+ - **Script execution** - `rip script.rip` now executes directly (no explicit `bun` needed)
30
+ - Auto-detects .rip files and uses Bun loader
31
+ - Passes arguments correctly
32
+ - Shebang support: `#!/usr/bin/env rip`
33
+ - **Browser REPL launcher** - `rip -w` starts local server and opens browser
34
+ - One-command workflow
35
+ - Works offline with local changes
36
+ - Cross-platform (macOS, Windows, Linux)
37
+ - **Resizable REPL panes** - Drag slider between Rip source and JavaScript output
38
+ - **Local time display** - Build timestamp shown in user's timezone
39
+ - **Friendly error messages** - Clear "File not found" instead of stack traces
40
+
41
+ ### Fixed
42
+ - **Postfix `by` step in comprehensions** - `for i in [0..10] by 2` now works
43
+ - **Nested IIFE elimination** - Major code generation optimization (37% smaller)
44
+ - **Throw in expressions** - Properly wrapped in IIFE
45
+ - **Rest parameters in middle position** - Both functions and array destructuring
46
+ - `def fn(first, ...middle, last)` works
47
+ - `[first, ...middle, last] = arr` works
48
+ - **Parser error messages** - Now show line and column numbers
49
+ - **Range loops without variable** - `for [1..10]` optimization
50
+ - **Comprehension context detection** - Smart IIFE vs plain loop decisions
51
+ - **Step handling refactoring** - Unified logic, 37% code reduction
52
+ - **Global installation** - `rip -w` works correctly when installed via npm/bun
53
+
54
+ ### Changed
55
+ - Version bumped to 1.1.0
56
+ - Test count: 843 → 864 (+21 tests, all passing)
57
+ - Documentation updated throughout
58
+ - Package.json prepared for NPM publishing
59
+
60
+ ### Documentation
61
+ - Complete GitHub workflow system (issues, PRs, templates)
62
+ - AI agent onboarding guide
63
+ - CONTRIBUTING.md with real examples
64
+ - Updated README, AGENT.md, COFFEESCRIPT-COMPARISON.md
65
+ - All stats current (864 tests)
66
+
67
+ ### Infrastructure
68
+ - 10 complete GitHub workflows (issue → branch → test → fix → PR → merge)
69
+ - Comprehensive test coverage (100% passing)
70
+ - Ready for NPM publish
71
+
72
+ ## [1.0.0] - 2025-10-31
73
+
74
+ ### Initial Release
75
+ - Complete Rip language compiler
76
+ - CoffeeScript-inspired syntax with modern ES2022 output
77
+ - Zero dependencies (includes SLR(1) parser generator)
78
+ - Self-hosting capability
79
+ - 843/843 tests passing
80
+ - Terminal REPL
81
+ - Browser bundle (43KB brotli-compressed)
82
+ - Complete documentation
package/CONTRIBUTING.md CHANGED
@@ -316,7 +316,7 @@ All tests passing: X/Y (100%)
316
316
  ## Getting Help
317
317
 
318
318
  - Read [AGENT.md](AGENT.md) for AI assistant guide
319
- - Check [docs/](docs/) for detailed documentation
319
+ - Check [docs/](docs/) for detailed documentation
320
320
  - Open a [Question issue](https://github.com/shreeve/rip-lang/issues/new/choose)
321
321
  - Look at existing tests in `test/rip/` for examples
322
322
  - Review closed PRs for workflow examples
@@ -328,4 +328,3 @@ Open an issue or discussion. We're happy to help!
328
328
  ---
329
329
 
330
330
  **Philosophy:** Keep it simple. Keep it tested. Keep it elegant. ✨
331
-
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-1.0.0-blue.svg" alt="Version"></a>
12
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-1.1.1-blue.svg" alt="Version"></a>
13
13
  <a href="#es2022-target"><img src="https://img.shields.io/badge/target-ES2022-blue.svg" alt="Target"></a>
14
14
  <a href="#current-status"><img src="https://img.shields.io/badge/tests-864%2F864-brightgreen.svg" alt="Tests"></a>
15
15
  <a href="#current-status"><img src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg" alt="Coverage"></a>
@@ -1123,7 +1123,7 @@ for (let i = 0; i < obj.length; i += 2) {
1123
1123
 
1124
1124
  ## Current Status
1125
1125
 
1126
- **Version:** 1.0.0 - **STABLE RELEASE!** 🎉
1126
+ **Version:** 1.1.0 - **ENHANCED RELEASE!** 🎉
1127
1127
 
1128
1128
  **⚡ NEW: DUAL SYNTAX SUPPORT - CoffeeScript Compatibility!**
1129
1129
 
package/bin/rip CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
3
  import { readFileSync, writeFileSync, existsSync } from 'fs';
4
- import { execSync } from 'child_process';
4
+ import { execSync, spawn } from 'child_process';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { dirname, join } from 'path';
7
7
  import { Compiler } from '../src/compiler.js';
@@ -32,9 +32,11 @@ Options:
32
32
  -s, --sexpr Show s-expressions
33
33
  -t, --tokens Show token stream
34
34
  -v, --version Show version number
35
+ -w, --web Launch browser REPL (auto-shutdown server)
35
36
 
36
37
  Examples:
37
- rip # Interactive REPL
38
+ rip # Interactive REPL (terminal)
39
+ rip -w # Launch browser REPL (auto-opens)
38
40
  rip script.rip # Execute script (auto-detects .rip)
39
41
  rip script.rip arg1 arg2 # Execute with arguments
40
42
  rip -c example.rip # Compile to stdout
@@ -62,6 +64,45 @@ async function main() {
62
64
  process.exit(0);
63
65
  }
64
66
 
67
+ // Launch local browser REPL (starts server + opens browser)
68
+ if (args.includes('-w') || args.includes('--web')) {
69
+ console.log('🚀 Starting Rip browser REPL...\n');
70
+
71
+ // Start the server and capture output to get the actual port
72
+ const servePath = join(__dirname, '../scripts/serve.js');
73
+ const serverProcess = spawn('bun', [servePath], {
74
+ stdio: ['inherit', 'pipe', 'inherit'],
75
+ detached: false
76
+ });
77
+
78
+ let actualPort = null;
79
+
80
+ // Capture server output and extract port
81
+ serverProcess.stdout.on('data', (data) => {
82
+ const output = data.toString();
83
+ process.stdout.write(output);
84
+
85
+ // Parse port from "Server running at http://localhost:PORT"
86
+ if (!actualPort) {
87
+ const match = output.match(/localhost:(\d+)/);
88
+ if (match) {
89
+ actualPort = match[1];
90
+
91
+ // Open browser once we know the port
92
+ setTimeout(() => {
93
+ const openCmd = process.platform === 'darwin' ? 'open' :
94
+ process.platform === 'win32' ? 'start' : 'xdg-open';
95
+ execSync(`${openCmd} http://localhost:${actualPort}/`);
96
+ console.log('\n📱 Press Ctrl+C to stop server\n');
97
+ }, 300);
98
+ }
99
+ }
100
+ });
101
+
102
+ // Keep server running (don't exit)
103
+ return;
104
+ }
105
+
65
106
  // Check if REPL should be started
66
107
  // Launch REPL if: no args AND stdin is a TTY (not piped), OR explicit -r flag
67
108
  const isTTY = process.stdin.isTTY;
@@ -6736,7 +6736,7 @@ function compileToJS(source, options = {}) {
6736
6736
  }
6737
6737
  // src/browser.js
6738
6738
  var VERSION = "1.0.0";
6739
- var BUILD_DATE = "2025-11-01@05:15:36GMT";
6739
+ var BUILD_DATE = "2025-11-01@08:21:02GMT";
6740
6740
  var dedent = (s) => {
6741
6741
  const m = s.match(/^[ \t]*(?=\S)/gm);
6742
6742
  const i = Math.min(...(m || []).map((x) => x.length));
@@ -239,4 +239,4 @@ _setDataSection();
239
239
  function _setDataSection() {
240
240
  DATA = ${JSON.stringify(U)};
241
241
  }`;F.push(J),A=F.join(`
242
- `)}return{tokens:E,sexpr:R,code:A,data:U}}compileToJS(Y){return this.compile(Y).code}compileToSExpr(Y){return this.compile(Y).sexpr}}function o2(Y,U={}){return new N1(U).compile(Y)}function K1(Y,U={}){return new N1(U).compileToJS(Y)}var G3="1.0.0",Z3="2025-11-01@05:15:36GMT",t2=(Y)=>{let U=Y.match(/^[ \t]*(?=\S)/gm),M=Math.min(...(U||[]).map((_)=>_.length));return Y.replace(RegExp(`^[ ]{${M}}`,"gm"),"").trim()};async function v2(){let Y=document.querySelectorAll('script[type="text/rip"]');for(let U of Y){if(U.hasAttribute("data-rip-processed"))continue;try{let M=t2(U.textContent),_=K1(M);(0,eval)(_),U.setAttribute("data-rip-processed","true")}catch(M){console.error("Error compiling Rip script:",M),console.error("Script content:",U.textContent)}}}if(typeof document!=="undefined")if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",v2);else v2();function e2(Y){try{let M=K1(Y).replace(/^let\s+[^;]+;\s*\n\s*/m,"");M=M.replace(/^const\s+/gm,"var ");let _=(0,eval)(M);if(_!==void 0)globalThis._=_;return _}catch(U){console.error("Rip compilation error:",U.message);return}}if(typeof globalThis!=="undefined")globalThis.rip=e2;export{e2 as rip,v2 as processRipScripts,R1 as parser,K1 as compileToJS,o2 as compile,G3 as VERSION,x1 as Lexer,N1 as Compiler,A1 as CodeGenerator,Z3 as BUILD_DATE};
242
+ `)}return{tokens:E,sexpr:R,code:A,data:U}}compileToJS(Y){return this.compile(Y).code}compileToSExpr(Y){return this.compile(Y).sexpr}}function o2(Y,U={}){return new N1(U).compile(Y)}function K1(Y,U={}){return new N1(U).compileToJS(Y)}var G3="1.0.0",Z3="2025-11-01@08:21:02GMT",t2=(Y)=>{let U=Y.match(/^[ \t]*(?=\S)/gm),M=Math.min(...(U||[]).map((_)=>_.length));return Y.replace(RegExp(`^[ ]{${M}}`,"gm"),"").trim()};async function v2(){let Y=document.querySelectorAll('script[type="text/rip"]');for(let U of Y){if(U.hasAttribute("data-rip-processed"))continue;try{let M=t2(U.textContent),_=K1(M);(0,eval)(_),U.setAttribute("data-rip-processed","true")}catch(M){console.error("Error compiling Rip script:",M),console.error("Script content:",U.textContent)}}}if(typeof document!=="undefined")if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",v2);else v2();function e2(Y){try{let M=K1(Y).replace(/^let\s+[^;]+;\s*\n\s*/m,"");M=M.replace(/^const\s+/gm,"var ");let _=(0,eval)(M);if(_!==void 0)globalThis._=_;return _}catch(U){console.error("Rip compilation error:",U.message);return}}if(typeof globalThis!=="undefined")globalThis.rip=e2;export{e2 as rip,v2 as processRipScripts,R1 as parser,K1 as compileToJS,o2 as compile,G3 as VERSION,x1 as Lexer,N1 as Compiler,A1 as CodeGenerator,Z3 as BUILD_DATE};
Binary file
Binary file
package/docs/index.html CHANGED
@@ -58,8 +58,8 @@
58
58
  <p class="note">If not redirected, <a href="repl.html">click here</a></p>
59
59
  </div>
60
60
  <script>
61
- // Immediate redirect to REPL
62
- window.location.href = 'repl.html';
61
+ // Immediate redirect to REPL (preserve query params)
62
+ window.location.href = 'repl.html' + window.location.search;
63
63
  </script>
64
64
  </body>
65
65
  </html>
package/docs/repl.html CHANGED
@@ -4,6 +4,7 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Rip REPL - Interactive Browser Environment</title>
7
+ <link rel="icon" href="data:,">
7
8
  <style>
8
9
  * {
9
10
  margin: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rip-lang",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "A lightweight scripting language that compiles to modern JavaScript",
5
5
  "type": "module",
6
6
  "main": "src/compiler.js",
package/scripts/serve.js CHANGED
@@ -1,10 +1,17 @@
1
1
  #!/usr/bin/env bun
2
2
  // Simple static file server with brotli support
3
3
  import { readFileSync, existsSync } from 'fs';
4
- import { join, extname } from 'path';
4
+ import { join, extname, dirname } from 'path';
5
+ import { fileURLToPath } from 'url';
5
6
 
6
- const PORT = 3000;
7
- const ROOT = 'docs';
7
+ // Get the directory where this script lives
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+
11
+ // Serve from docs/ relative to script location (works when globally installed)
12
+ const ROOT = process.env.SERVE_DIR || join(__dirname, '../docs');
13
+ // Try port 3000 first, fallback to 0 (OS-assigned)
14
+ const PORT = process.env.PORT || 3000;
8
15
 
9
16
  const MIME_TYPES = {
10
17
  '.html': 'text/html; charset=utf-8',
@@ -17,55 +24,67 @@ const MIME_TYPES = {
17
24
  '.ico': 'image/x-icon'
18
25
  };
19
26
 
20
- Bun.serve({
21
- port: PORT,
22
-
23
- fetch(req) {
24
- const url = new URL(req.url);
25
- let pathname = url.pathname;
26
-
27
- // Default to index.html for directory requests
28
- if (pathname.endsWith('/')) {
29
- pathname += 'index.html';
30
- }
27
+ // Request handler for serving files
28
+ function handleRequest(req) {
29
+ const url = new URL(req.url);
30
+ let pathname = url.pathname;
31
31
 
32
- const filePath = join(ROOT, pathname);
33
- const ext = extname(pathname);
34
- const acceptEncoding = req.headers.get('accept-encoding') || '';
32
+ // Default to index.html for directory requests
33
+ if (pathname.endsWith('/')) {
34
+ pathname += 'index.html';
35
+ }
35
36
 
36
- // Check for brotli compressed version (.br)
37
- if (acceptEncoding.includes('br') && existsSync(filePath + '.br')) {
38
- try {
39
- const compressed = readFileSync(filePath + '.br');
40
- return new Response(compressed, {
41
- headers: {
42
- 'Content-Type': MIME_TYPES[ext] || 'application/octet-stream',
43
- 'Content-Encoding': 'br',
44
- 'Cache-Control': 'public, max-age=31536000'
45
- }
46
- });
47
- } catch (e) {
48
- // Fall through to regular file
49
- }
50
- }
37
+ const filePath = join(ROOT, pathname);
38
+ const ext = extname(pathname);
39
+ const acceptEncoding = req.headers.get('accept-encoding') || '';
51
40
 
52
- // Serve regular file
41
+ // Check for brotli compressed version (.br)
42
+ if (acceptEncoding.includes('br') && existsSync(filePath + '.br')) {
53
43
  try {
54
- const file = readFileSync(filePath);
55
- return new Response(file, {
44
+ const compressed = readFileSync(filePath + '.br');
45
+ return new Response(compressed, {
56
46
  headers: {
57
- 'Content-Type': MIME_TYPES[ext] || 'application/octet-stream'
47
+ 'Content-Type': MIME_TYPES[ext] || 'application/octet-stream',
48
+ 'Content-Encoding': 'br',
49
+ 'Cache-Control': 'public, max-age=31536000'
58
50
  }
59
51
  });
60
52
  } catch (e) {
61
- return new Response('404 Not Found', { status: 404 });
53
+ // Fall through to regular file
62
54
  }
63
55
  }
64
- });
65
56
 
66
- console.log(`🚀 Server running at http://localhost:${PORT}`);
57
+ // Serve regular file
58
+ try {
59
+ const file = readFileSync(filePath);
60
+ return new Response(file, {
61
+ headers: {
62
+ 'Content-Type': MIME_TYPES[ext] || 'application/octet-stream'
63
+ }
64
+ });
65
+ } catch (e) {
66
+ return new Response('404 Not Found', { status: 404 });
67
+ }
68
+ }
69
+
70
+ // Try to start server on preferred port, fallback to OS-assigned port
71
+ let server;
72
+ try {
73
+ server = Bun.serve({ port: PORT, fetch: handleRequest });
74
+ } catch (err) {
75
+ if (err.code === 'EADDRINUSE') {
76
+ // Port in use, let OS assign one
77
+ server = Bun.serve({ port: 0, fetch: handleRequest });
78
+ } else {
79
+ throw err;
80
+ }
81
+ }
82
+
83
+ const actualPort = server.port;
84
+
85
+ console.log(`🚀 Server running at http://localhost:${actualPort}`);
67
86
  console.log(`📁 Serving from: ${ROOT}/`);
68
87
  console.log(`🗜️ Brotli compression: enabled`);
69
88
  console.log('');
70
- console.log(`✨ Rip REPL: http://localhost:${PORT}/`);
71
- console.log(`📚 Examples: http://localhost:${PORT}/examples/`);
89
+ console.log(`✨ Rip REPL: http://localhost:${actualPort}/`);
90
+ console.log(`📚 Examples: http://localhost:${actualPort}/examples/`);
@@ -816,7 +816,7 @@ class Generator
816
816
  text = if hash.text then " near '#{hash.text}'" else ''
817
817
  location = "line #{line}, column #{col}"
818
818
  message = "Parse error at #{location}#{token}#{text}: #{str}"
819
-
819
+
820
820
  error = new Error message
821
821
  error.hash = hash
822
822
  throw error