code-the-jewels 0.1.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.
Files changed (60) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/PROMPTS/01-build-v0.1.md +10 -0
  3. package/README.md +186 -0
  4. package/dist/ast.d.ts +143 -0
  5. package/dist/ast.js +2 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +145 -0
  8. package/dist/diagnostics.d.ts +7 -0
  9. package/dist/diagnostics.js +16 -0
  10. package/dist/generator.d.ts +11 -0
  11. package/dist/generator.js +126 -0
  12. package/dist/index.d.ts +7 -0
  13. package/dist/index.js +15 -0
  14. package/dist/lexer.d.ts +18 -0
  15. package/dist/lexer.js +210 -0
  16. package/dist/parser.d.ts +40 -0
  17. package/dist/parser.js +394 -0
  18. package/dist/repl.d.ts +1 -0
  19. package/dist/repl.js +132 -0
  20. package/dist/runtime/atl-data.d.ts +4 -0
  21. package/dist/runtime/atl-data.js +18 -0
  22. package/dist/runtime/atl-flow.d.ts +1 -0
  23. package/dist/runtime/atl-flow.js +5 -0
  24. package/dist/runtime/bk-parse.d.ts +3 -0
  25. package/dist/runtime/bk-parse.js +9 -0
  26. package/dist/runtime/bk-text.d.ts +5 -0
  27. package/dist/runtime/bk-text.js +13 -0
  28. package/dist/runtime/rtj-core.d.ts +1 -0
  29. package/dist/runtime/rtj-core.js +51 -0
  30. package/dist/semantic.d.ts +11 -0
  31. package/dist/semantic.js +153 -0
  32. package/dist/tests/basic.test.d.ts +1 -0
  33. package/dist/tests/basic.test.js +69 -0
  34. package/dist/token.d.ts +56 -0
  35. package/dist/token.js +77 -0
  36. package/examples/cities.rtj +11 -0
  37. package/examples/count-words.rtj +12 -0
  38. package/examples/duo.rtj +12 -0
  39. package/examples/hello.rtj +1 -0
  40. package/examples/pipes.rtj +6 -0
  41. package/package.json +22 -0
  42. package/public/_redirects +1 -0
  43. package/public/index.html +559 -0
  44. package/src/ast.ts +189 -0
  45. package/src/cli.ts +120 -0
  46. package/src/diagnostics.ts +15 -0
  47. package/src/generator.ts +129 -0
  48. package/src/index.ts +7 -0
  49. package/src/lexer.ts +208 -0
  50. package/src/parser.ts +461 -0
  51. package/src/repl.ts +105 -0
  52. package/src/runtime/atl-data.ts +11 -0
  53. package/src/runtime/atl-flow.ts +1 -0
  54. package/src/runtime/bk-parse.ts +3 -0
  55. package/src/runtime/bk-text.ts +5 -0
  56. package/src/runtime/rtj-core.ts +21 -0
  57. package/src/semantic.ts +144 -0
  58. package/src/tests/basic.test.ts +74 -0
  59. package/src/token.ts +85 -0
  60. package/tsconfig.json +15 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "mcp__claude_ai_Notion__notion-fetch"
5
+ ]
6
+ }
7
+ }
@@ -0,0 +1,10 @@
1
+ # Prompt 01: Build Code The Jewels v0.1 (Full Implementation)
2
+
3
+ Source: Notion page 32f4cf98-04bf-81ac-a19d-c05270b747a6
4
+
5
+ Built the complete v0.1 transpiler from scratch:
6
+ - Lexer, Parser (recursive descent), AST, Semantic analysis, JS code generator
7
+ - Runtime standard library: bk:text, bk:parse, atl:data, atl:flow
8
+ - CLI with run/compile/check/repl commands
9
+ - Pipe operator (|>) and duo blocks (mike/el dual pipelines)
10
+ - 5 example programs, all passing acceptance criteria
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # Code The Jewels
2
+
3
+ > :point_right:{:gem:}.rtj
4
+
5
+ A programming language built the way Run The Jewels makes music. Two cities. Two voices. One compiler.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install -g code-the-jewels
11
+ ```
12
+
13
+ Or from source:
14
+
15
+ ```bash
16
+ git clone https://github.com/everettsteele/code-the-jewels.git
17
+ cd code-the-jewels
18
+ npm install
19
+ npm run build
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ Create `hello.rtj`:
25
+
26
+ ```
27
+ talk "code the jewels"
28
+ ```
29
+
30
+ Run it:
31
+
32
+ ```bash
33
+ rtj run hello.rtj
34
+ ```
35
+
36
+ Output: `code the jewels`
37
+
38
+ A duo block:
39
+
40
+ ```
41
+ feature words from "bk:parse"
42
+ feature count from "atl:data"
43
+
44
+ jewel line = "walking in the snow"
45
+
46
+ jewel wordCount = duo(line) {
47
+ mike: words
48
+ el: count
49
+ }
50
+
51
+ talk wordCount
52
+ ```
53
+
54
+ Output: `4`
55
+
56
+ ## Keywords
57
+
58
+ Every keyword traces back to RTJ.
59
+
60
+ | Keyword | Purpose | JS Equivalent | Origin |
61
+ |------------|--------------------------------|------------------------|---------------------------------------------|
62
+ | `jewel` | Declare a variable | `const` | The jewel. The core unit. |
63
+ | `verse` | Declare a function | `function` | A verse. A block of bars. |
64
+ | `send` | Return a value | `return` | Send it back. |
65
+ | `talk` | Print to console | `console.log` | "Talk to Me", RTJ3 |
66
+ | `ifwild` | Conditional | `if` | "if wild" check before you move |
67
+ | `elsewild` | Else branch | `else` | The other path |
68
+ | `run` | Loop over a collection | `for...of` | Run it. |
69
+ | `in` | Iterator keyword | `of` | Run x in y |
70
+ | `feature` | Import from standard library | destructured `require` | A feature. A guest appearance. |
71
+ | `from` | Import source | module path | Where the feature comes from |
72
+ | `yank` | Throw an error | `throw` | Yank the chain. Pull the plug. |
73
+ | `duo` | Dual pipeline block | (custom) | "yankee and the brave (ep. 4)", RTJ4 |
74
+ | `mike` | First pipeline in a duo block | (custom) | Killer Mike. Atlanta. |
75
+ | `el` | Second pipeline in a duo block | (custom) | El-P. Brooklyn. |
76
+
77
+ ## Pipe Operator
78
+
79
+ The pipe operator `|>` passes the jewel from one function to the next. Left to right. No nesting.
80
+
81
+ ```
82
+ feature trim, upper from "bk:text"
83
+
84
+ jewel line = " code the jewels "
85
+ jewel clean = line |> trim |> upper
86
+
87
+ talk clean
88
+ // Output: CODE THE JEWELS
89
+ ```
90
+
91
+ `a |> f |> g` compiles to `g(f(a))`. Each step takes the previous result as its argument.
92
+
93
+ ## duo()
94
+
95
+ Named after "yankee and the brave (ep. 4)" from RTJ4. A duo block splits processing into two named pipelines.
96
+
97
+ `mike` runs first (Atlanta). `el` responds (Brooklyn). Both branches are required. A duo without both is just a solo.
98
+
99
+ ```
100
+ feature trim from "bk:text"
101
+ feature words from "bk:parse"
102
+ feature count from "atl:data"
103
+
104
+ jewel bars = " rtj from atlanta to brooklyn "
105
+
106
+ jewel total = duo(bars) {
107
+ mike: trim |> words
108
+ el: count
109
+ }
110
+
111
+ talk total
112
+ // Output: 5
113
+ ```
114
+
115
+ Compiles to: `el(mike(input))`. The mike pipeline feeds into the el pipeline. Two passes, one result.
116
+
117
+ ## Standard Library
118
+
119
+ The standard library is split by city. `bk:` is Brooklyn (El-P's borough). `atl:` is Atlanta (Killer Mike's city).
120
+
121
+ ### bk:text
122
+ String operations: `trim`, `upper`, `lower`, `split`, `join`
123
+
124
+ ### bk:parse
125
+ Text parsing: `words`, `lines`, `chars`
126
+
127
+ ### atl:data
128
+ Data operations: `count`, `countBy`, `first`, `last`
129
+
130
+ ### atl:flow
131
+ Control flow: `identity`
132
+
133
+ ## Compiler Stages
134
+
135
+ The compiler runs in stages. Each one has a name.
136
+
137
+ 1. **The Fist (El)** / Lexer. Breaks source into tokens.
138
+ 2. **The Hands** / Parser. Shapes tokens into an AST.
139
+ 3. **Mike Pass** / Semantic analysis. Walks the tree, checks scope, validates imports.
140
+ 4. **El Pass** / Optimization. (Reserved for v0.2.)
141
+ 5. **The Gun (Mike)** / Code generator. Fires the AST into JavaScript.
142
+ 6. **Jewel Box** / Output. The final `.js` file, ready to run.
143
+
144
+ ## CLI Commands
145
+
146
+ ```bash
147
+ # Run a .rtj file
148
+ rtj run <file.rtj>
149
+
150
+ # Compile to JavaScript
151
+ rtj compile <file.rtj>
152
+
153
+ # Check for errors (parse + semantic only)
154
+ rtj check <file.rtj>
155
+
156
+ # Start interactive REPL
157
+ rtj repl
158
+ ```
159
+
160
+ ## Version Naming
161
+
162
+ Each major version is named after an RTJ album.
163
+
164
+ | Version | Codename | Album |
165
+ |---------|-----------------------------|-------|
166
+ | v0.1 | RTJ0 "The Self-Titled Era" | Run The Jewels (2013) |
167
+ | v0.2 | RTJ2 "The Meow Era" | Run The Jewels 2 (2014) |
168
+ | v0.3 | RTJ3 "Talk to Me" | Run The Jewels 3 (2016) |
169
+ | v0.4 | RTJ4 "The Brave Era" | RTJ4 (2020) |
170
+
171
+ ## Examples
172
+
173
+ See the `examples/` directory:
174
+ - `hello.rtj` - Hello world
175
+ - `pipes.rtj` - Pipe operator
176
+ - `duo.rtj` - Duo blocks
177
+ - `cities.rtj` - Functions and arrays
178
+ - `count-words.rtj` - Word frequency counting
179
+
180
+ ## Links
181
+
182
+ [codethejewels.com](http://codethejewels.com)
183
+
184
+ ## License
185
+
186
+ MIT. Free, like every RTJ album. Part of [Meridian](https://neverstill.llc).
package/dist/ast.d.ts ADDED
@@ -0,0 +1,143 @@
1
+ export interface Location {
2
+ line: number;
3
+ column: number;
4
+ }
5
+ export type Statement = VarDecl | FunctionDecl | ReturnStmt | TalkStmt | IfStmt | LoopStmt | ImportStmt | ThrowStmt | ExpressionStmt | BlockStmt;
6
+ export type Expression = Identifier | StringLiteral | NumberLiteral | BooleanLiteral | NullLiteral | ArrayLiteral | ObjectLiteral | BinaryExpr | UnaryExpr | CallExpr | MemberExpr | PipeExpr | DuoExpr;
7
+ export interface Program {
8
+ type: 'Program';
9
+ body: Statement[];
10
+ }
11
+ export interface VarDecl {
12
+ type: 'VarDecl';
13
+ name: string;
14
+ init: Expression;
15
+ loc: Location;
16
+ }
17
+ export interface FunctionDecl {
18
+ type: 'FunctionDecl';
19
+ name: string;
20
+ params: string[];
21
+ body: BlockStmt;
22
+ loc: Location;
23
+ }
24
+ export interface ReturnStmt {
25
+ type: 'ReturnStmt';
26
+ value?: Expression;
27
+ loc: Location;
28
+ }
29
+ export interface TalkStmt {
30
+ type: 'TalkStmt';
31
+ value: Expression;
32
+ loc: Location;
33
+ }
34
+ export interface IfStmt {
35
+ type: 'IfStmt';
36
+ condition: Expression;
37
+ consequent: BlockStmt;
38
+ alternate?: BlockStmt;
39
+ loc: Location;
40
+ }
41
+ export interface LoopStmt {
42
+ type: 'LoopStmt';
43
+ variable: string;
44
+ iterable: Expression;
45
+ body: BlockStmt;
46
+ loc: Location;
47
+ }
48
+ export interface ImportStmt {
49
+ type: 'ImportStmt';
50
+ names: string[];
51
+ source: string;
52
+ loc: Location;
53
+ }
54
+ export interface ThrowStmt {
55
+ type: 'ThrowStmt';
56
+ value: Expression;
57
+ loc: Location;
58
+ }
59
+ export interface ExpressionStmt {
60
+ type: 'ExpressionStmt';
61
+ expr: Expression;
62
+ loc: Location;
63
+ }
64
+ export interface BlockStmt {
65
+ type: 'BlockStmt';
66
+ body: Statement[];
67
+ loc: Location;
68
+ }
69
+ export interface Identifier {
70
+ type: 'Identifier';
71
+ name: string;
72
+ loc: Location;
73
+ }
74
+ export interface StringLiteral {
75
+ type: 'StringLiteral';
76
+ value: string;
77
+ loc: Location;
78
+ }
79
+ export interface NumberLiteral {
80
+ type: 'NumberLiteral';
81
+ value: number;
82
+ loc: Location;
83
+ }
84
+ export interface BooleanLiteral {
85
+ type: 'BooleanLiteral';
86
+ value: boolean;
87
+ loc: Location;
88
+ }
89
+ export interface NullLiteral {
90
+ type: 'NullLiteral';
91
+ loc: Location;
92
+ }
93
+ export interface ArrayLiteral {
94
+ type: 'ArrayLiteral';
95
+ elements: Expression[];
96
+ loc: Location;
97
+ }
98
+ export interface ObjectLiteral {
99
+ type: 'ObjectLiteral';
100
+ pairs: {
101
+ key: string;
102
+ value: Expression;
103
+ }[];
104
+ loc: Location;
105
+ }
106
+ export interface BinaryExpr {
107
+ type: 'BinaryExpr';
108
+ op: string;
109
+ left: Expression;
110
+ right: Expression;
111
+ loc: Location;
112
+ }
113
+ export interface UnaryExpr {
114
+ type: 'UnaryExpr';
115
+ op: string;
116
+ operand: Expression;
117
+ loc: Location;
118
+ }
119
+ export interface CallExpr {
120
+ type: 'CallExpr';
121
+ callee: Expression;
122
+ args: Expression[];
123
+ loc: Location;
124
+ }
125
+ export interface MemberExpr {
126
+ type: 'MemberExpr';
127
+ object: Expression;
128
+ property: Expression;
129
+ computed: boolean;
130
+ loc: Location;
131
+ }
132
+ export interface PipeExpr {
133
+ type: 'PipeExpr';
134
+ steps: Expression[];
135
+ loc: Location;
136
+ }
137
+ export interface DuoExpr {
138
+ type: 'DuoExpr';
139
+ input: Expression;
140
+ mikePipeline: Expression[];
141
+ elPipeline: Expression[];
142
+ loc: Location;
143
+ }
package/dist/ast.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const os = __importStar(require("os"));
40
+ const lexer_1 = require("./lexer");
41
+ const parser_1 = require("./parser");
42
+ const semantic_1 = require("./semantic");
43
+ const generator_1 = require("./generator");
44
+ const diagnostics_1 = require("./diagnostics");
45
+ const repl_1 = require("./repl");
46
+ function compile(source) {
47
+ const lexer = new lexer_1.Lexer(source);
48
+ const tokens = lexer.tokenize();
49
+ const parser = new parser_1.Parser(tokens);
50
+ const ast = parser.parse();
51
+ const semantic = new semantic_1.Semantic();
52
+ semantic.analyze(ast);
53
+ const gen = new generator_1.Generator();
54
+ return gen.generate(ast);
55
+ }
56
+ function resolveRuntimePath() {
57
+ // When running from dist/, runtime is at dist/runtime/rtj-core.js
58
+ // When running via ts-node, runtime is at src/runtime/rtj-core.ts
59
+ const distRuntime = path.join(__dirname, 'runtime', 'rtj-core');
60
+ return distRuntime;
61
+ }
62
+ function run(filePath) {
63
+ const absPath = path.resolve(filePath);
64
+ if (!fs.existsSync(absPath)) {
65
+ console.error(`File not found: ${absPath}`);
66
+ process.exit(1);
67
+ }
68
+ const source = fs.readFileSync(absPath, 'utf-8');
69
+ let js = compile(source);
70
+ // Replace the generic runtime require with the actual path
71
+ const runtimePath = resolveRuntimePath().replace(/\\/g, '/');
72
+ js = js.replace('const __rtj = require("./runtime/rtj-core");', `const __rtj = require("${runtimePath}");`);
73
+ // Write to temp file and execute
74
+ const tmpFile = path.join(os.tmpdir(), `rtj_${Date.now()}_${Math.random().toString(36).slice(2)}.js`);
75
+ fs.writeFileSync(tmpFile, js, 'utf-8');
76
+ try {
77
+ require(tmpFile);
78
+ }
79
+ finally {
80
+ fs.unlinkSync(tmpFile);
81
+ }
82
+ }
83
+ function compileToFile(filePath) {
84
+ const absPath = path.resolve(filePath);
85
+ if (!fs.existsSync(absPath)) {
86
+ console.error(`File not found: ${absPath}`);
87
+ process.exit(1);
88
+ }
89
+ const source = fs.readFileSync(absPath, 'utf-8');
90
+ const js = compile(source);
91
+ const outPath = absPath.replace(/\.rtj$/, '.js');
92
+ fs.writeFileSync(outPath, js, 'utf-8');
93
+ }
94
+ function check(filePath) {
95
+ const absPath = path.resolve(filePath);
96
+ if (!fs.existsSync(absPath)) {
97
+ console.error(`File not found: ${absPath}`);
98
+ process.exit(1);
99
+ }
100
+ const source = fs.readFileSync(absPath, 'utf-8');
101
+ compile(source); // throws on error
102
+ }
103
+ const [, , command, ...args] = process.argv;
104
+ try {
105
+ switch (command) {
106
+ case 'run': {
107
+ if (!args[0]) {
108
+ console.error('Usage: rtj run <file.rtj>');
109
+ process.exit(1);
110
+ }
111
+ run(args[0]);
112
+ break;
113
+ }
114
+ case 'compile': {
115
+ if (!args[0]) {
116
+ console.error('Usage: rtj compile <file.rtj>');
117
+ process.exit(1);
118
+ }
119
+ compileToFile(args[0]);
120
+ break;
121
+ }
122
+ case 'check': {
123
+ if (!args[0]) {
124
+ console.error('Usage: rtj check <file.rtj>');
125
+ process.exit(1);
126
+ }
127
+ check(args[0]);
128
+ break;
129
+ }
130
+ case 'repl': {
131
+ (0, repl_1.startRepl)();
132
+ break;
133
+ }
134
+ default: {
135
+ console.log('Usage: rtj <run|compile|check|repl> [file]');
136
+ }
137
+ }
138
+ }
139
+ catch (err) {
140
+ if (err instanceof diagnostics_1.RTJError) {
141
+ console.error(err.format());
142
+ process.exit(1);
143
+ }
144
+ throw err;
145
+ }
@@ -0,0 +1,7 @@
1
+ export declare class RTJError extends Error {
2
+ kind: 'SyntaxError' | 'NameError' | 'ImportError' | 'DuoError' | 'RuntimeError';
3
+ line?: number | undefined;
4
+ column?: number | undefined;
5
+ constructor(kind: 'SyntaxError' | 'NameError' | 'ImportError' | 'DuoError' | 'RuntimeError', message: string, line?: number | undefined, column?: number | undefined);
6
+ format(): string;
7
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RTJError = void 0;
4
+ class RTJError extends Error {
5
+ constructor(kind, message, line, column) {
6
+ super(message);
7
+ this.kind = kind;
8
+ this.line = line;
9
+ this.column = column;
10
+ }
11
+ format() {
12
+ const loc = this.line ? ` near line ${this.line}` : '';
13
+ return `${this.kind}: ${this.message}${loc}`;
14
+ }
15
+ }
16
+ exports.RTJError = RTJError;
@@ -0,0 +1,11 @@
1
+ import { Program } from './ast';
2
+ export declare class Generator {
3
+ private indent;
4
+ generate(program: Program): string;
5
+ private pad;
6
+ private genStatement;
7
+ private genBlock;
8
+ private genExpression;
9
+ private flattenPipe;
10
+ private flattenPipeFromStrings;
11
+ }
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Generator = void 0;
4
+ class Generator {
5
+ constructor() {
6
+ this.indent = 0;
7
+ }
8
+ generate(program) {
9
+ const lines = [
10
+ '"use strict";',
11
+ 'const __rtj = require("./runtime/rtj-core");',
12
+ 'const __modules = __rtj.modules;',
13
+ '',
14
+ ];
15
+ for (const stmt of program.body) {
16
+ lines.push(this.genStatement(stmt));
17
+ }
18
+ return lines.join('\n') + '\n';
19
+ }
20
+ pad() {
21
+ return ' '.repeat(this.indent);
22
+ }
23
+ genStatement(stmt) {
24
+ switch (stmt.type) {
25
+ case 'VarDecl':
26
+ return `${this.pad()}const ${stmt.name} = ${this.genExpression(stmt.init)};`;
27
+ case 'FunctionDecl': {
28
+ const params = stmt.params.join(', ');
29
+ const body = this.genBlock(stmt.body);
30
+ return `${this.pad()}function ${stmt.name}(${params}) ${body}`;
31
+ }
32
+ case 'ReturnStmt':
33
+ return stmt.value
34
+ ? `${this.pad()}return ${this.genExpression(stmt.value)};`
35
+ : `${this.pad()}return;`;
36
+ case 'TalkStmt':
37
+ return `${this.pad()}__rtj.talk(${this.genExpression(stmt.value)});`;
38
+ case 'IfStmt': {
39
+ let result = `${this.pad()}if (${this.genExpression(stmt.condition)}) ${this.genBlock(stmt.consequent)}`;
40
+ if (stmt.alternate) {
41
+ result += ` else ${this.genBlock(stmt.alternate)}`;
42
+ }
43
+ return result;
44
+ }
45
+ case 'LoopStmt':
46
+ return `${this.pad()}for (const ${stmt.variable} of ${this.genExpression(stmt.iterable)}) ${this.genBlock(stmt.body)}`;
47
+ case 'ImportStmt': {
48
+ const names = stmt.names.join(', ');
49
+ return `${this.pad()}const { ${names} } = __modules["${stmt.source}"];`;
50
+ }
51
+ case 'ThrowStmt':
52
+ return `${this.pad()}throw new Error(${this.genExpression(stmt.value)});`;
53
+ case 'ExpressionStmt':
54
+ return `${this.pad()}${this.genExpression(stmt.expr)};`;
55
+ case 'BlockStmt':
56
+ return this.genBlock(stmt);
57
+ }
58
+ }
59
+ genBlock(block) {
60
+ const lines = ['{'];
61
+ this.indent++;
62
+ for (const stmt of block.body) {
63
+ lines.push(this.genStatement(stmt));
64
+ }
65
+ this.indent--;
66
+ lines.push(`${this.pad()}}`);
67
+ return lines.join('\n');
68
+ }
69
+ genExpression(expr) {
70
+ switch (expr.type) {
71
+ case 'Identifier':
72
+ return expr.name;
73
+ case 'StringLiteral':
74
+ return JSON.stringify(expr.value);
75
+ case 'NumberLiteral':
76
+ return String(expr.value);
77
+ case 'BooleanLiteral':
78
+ return String(expr.value);
79
+ case 'NullLiteral':
80
+ return 'null';
81
+ case 'ArrayLiteral':
82
+ return `[${expr.elements.map(e => this.genExpression(e)).join(', ')}]`;
83
+ case 'ObjectLiteral': {
84
+ const pairs = expr.pairs.map(p => `${JSON.stringify(p.key)}: ${this.genExpression(p.value)}`);
85
+ return `{ ${pairs.join(', ')} }`;
86
+ }
87
+ case 'BinaryExpr':
88
+ return `(${this.genExpression(expr.left)} ${expr.op} ${this.genExpression(expr.right)})`;
89
+ case 'UnaryExpr':
90
+ return `(${expr.op}${this.genExpression(expr.operand)})`;
91
+ case 'CallExpr': {
92
+ const callee = this.genExpression(expr.callee);
93
+ const args = expr.args.map(a => this.genExpression(a)).join(', ');
94
+ return `${callee}(${args})`;
95
+ }
96
+ case 'MemberExpr':
97
+ if (expr.computed) {
98
+ return `${this.genExpression(expr.object)}[${this.genExpression(expr.property)}]`;
99
+ }
100
+ return `${this.genExpression(expr.object)}.${this.genExpression(expr.property)}`;
101
+ case 'PipeExpr':
102
+ return this.flattenPipe(expr.steps);
103
+ case 'DuoExpr': {
104
+ const allSteps = [...expr.mikePipeline, ...expr.elPipeline];
105
+ const initial = this.genExpression(expr.input);
106
+ return this.flattenPipeFromStrings(initial, allSteps);
107
+ }
108
+ }
109
+ }
110
+ flattenPipe(steps) {
111
+ if (steps.length === 0)
112
+ return '';
113
+ if (steps.length === 1)
114
+ return this.genExpression(steps[0]);
115
+ const initial = this.genExpression(steps[0]);
116
+ return this.flattenPipeFromStrings(initial, steps.slice(1));
117
+ }
118
+ flattenPipeFromStrings(initial, fns) {
119
+ let result = initial;
120
+ for (const fn of fns) {
121
+ result = `${this.genExpression(fn)}(${result})`;
122
+ }
123
+ return result;
124
+ }
125
+ }
126
+ exports.Generator = Generator;
@@ -0,0 +1,7 @@
1
+ export { Lexer } from './lexer';
2
+ export { Parser } from './parser';
3
+ export { Semantic } from './semantic';
4
+ export { Generator } from './generator';
5
+ export { RTJError } from './diagnostics';
6
+ export { TokenType } from './token';
7
+ export type { Token } from './token';
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenType = exports.RTJError = exports.Generator = exports.Semantic = exports.Parser = exports.Lexer = void 0;
4
+ var lexer_1 = require("./lexer");
5
+ Object.defineProperty(exports, "Lexer", { enumerable: true, get: function () { return lexer_1.Lexer; } });
6
+ var parser_1 = require("./parser");
7
+ Object.defineProperty(exports, "Parser", { enumerable: true, get: function () { return parser_1.Parser; } });
8
+ var semantic_1 = require("./semantic");
9
+ Object.defineProperty(exports, "Semantic", { enumerable: true, get: function () { return semantic_1.Semantic; } });
10
+ var generator_1 = require("./generator");
11
+ Object.defineProperty(exports, "Generator", { enumerable: true, get: function () { return generator_1.Generator; } });
12
+ var diagnostics_1 = require("./diagnostics");
13
+ Object.defineProperty(exports, "RTJError", { enumerable: true, get: function () { return diagnostics_1.RTJError; } });
14
+ var token_1 = require("./token");
15
+ Object.defineProperty(exports, "TokenType", { enumerable: true, get: function () { return token_1.TokenType; } });