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.
- package/.cursor/rules/rip-agent-onboarding.md +55 -50
- package/.github/ISSUE_TEMPLATE/coffeescript_compatibility.yml +1 -2
- package/.github/ISSUE_TEMPLATE/config.yml +0 -1
- package/.github/ISSUE_TEMPLATE/question.yml +0 -1
- package/.github/pull_request_template.md +2 -3
- package/CHANGELOG.md +82 -0
- package/CONTRIBUTING.md +1 -2
- package/README.md +2 -2
- package/bin/rip +43 -2
- package/docs/dist/rip.browser.js +1 -1
- package/docs/dist/rip.browser.min.js +1 -1
- package/docs/dist/rip.browser.min.js.br +0 -0
- package/docs/favicon.ico +0 -0
- package/docs/index.html +2 -2
- package/docs/repl.html +1 -0
- package/package.json +1 -1
- package/scripts/serve.js +60 -41
- package/src/grammar/solar.rip +1 -1
|
@@ -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
|
|
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
|
|
54
|
-
- Read `ISSUE
|
|
55
|
-
-
|
|
56
|
-
-
|
|
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)
|
|
117
|
+
├── comprehensions.rip (24 tests)
|
|
118
118
|
├── functions.rip (71 tests)
|
|
119
119
|
├── loops.rip (25 tests)
|
|
120
120
|
... 15 more files
|
|
121
|
-
Total:
|
|
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
|
|
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
|
|
354
|
+
**Tests:** 854+ passing (100%)
|
|
355
355
|
**Status:** Production-ready, actively maintained
|
|
356
356
|
|
|
357
|
-
**
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
-
**
|
|
368
|
-
-
|
|
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
|
|
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
|
-
|
|
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
|
-
## 🏆
|
|
417
|
+
## 🏆 Workflow Example
|
|
417
418
|
|
|
418
|
-
**
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
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-
|
|
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
|
|
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 #
|
|
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
|
|
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
|
|
604
|
+
### For Comprehension Work
|
|
599
605
|
1. `docs/COMPREHENSIONS.md` - Complete context rules
|
|
600
|
-
2. `
|
|
601
|
-
3. `
|
|
602
|
-
4. `src/codegen.js
|
|
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
|
-
## 🎯
|
|
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
|
|
625
|
-
5. ✅ Create branch: `git checkout fix/
|
|
626
|
-
6. ✅
|
|
627
|
-
7. ✅
|
|
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 (
|
|
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
|
|
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 (
|
|
673
|
+
> - Test everything (100% tests passing)
|
|
669
674
|
|
|
670
|
-
**
|
|
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
|
-
|
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.
|
|
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.
|
|
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;
|
package/docs/dist/rip.browser.js
CHANGED
|
@@ -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@
|
|
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@
|
|
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
|
package/docs/favicon.ico
ADDED
|
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
package/package.json
CHANGED
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
|
-
|
|
7
|
-
const
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
// Default to index.html for directory requests
|
|
33
|
+
if (pathname.endsWith('/')) {
|
|
34
|
+
pathname += 'index.html';
|
|
35
|
+
}
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
41
|
+
// Check for brotli compressed version (.br)
|
|
42
|
+
if (acceptEncoding.includes('br') && existsSync(filePath + '.br')) {
|
|
53
43
|
try {
|
|
54
|
-
const
|
|
55
|
-
return new Response(
|
|
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
|
-
|
|
53
|
+
// Fall through to regular file
|
|
62
54
|
}
|
|
63
55
|
}
|
|
64
|
-
});
|
|
65
56
|
|
|
66
|
-
|
|
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:${
|
|
71
|
-
console.log(`📚 Examples: http://localhost:${
|
|
89
|
+
console.log(`✨ Rip REPL: http://localhost:${actualPort}/`);
|
|
90
|
+
console.log(`📚 Examples: http://localhost:${actualPort}/examples/`);
|
package/src/grammar/solar.rip
CHANGED
|
@@ -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
|