rip-lang 3.13.124 → 3.13.126

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.
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rip-lang",
3
- "version": "3.13.124",
3
+ "version": "3.13.126",
4
4
  "description": "A modern language that compiles to JavaScript",
5
5
  "type": "module",
6
6
  "main": "src/compiler.js",
package/src/compiler.js CHANGED
@@ -2709,11 +2709,11 @@ export class CodeGenerator {
2709
2709
  generateSwitchCaseBody(body, context) {
2710
2710
  let code = '';
2711
2711
  let hasFlow = this.hasExplicitControlFlow(body);
2712
+ let stmts = this.unwrapBlock(body);
2712
2713
  if (hasFlow) {
2713
- for (let s of this.unwrapBlock(body)) code += this.indent() + this.generate(s, 'statement') + ';\n';
2714
+ for (let s of stmts) code += this.indent() + this.generate(s, 'statement') + ';\n';
2714
2715
  } else if (context === 'value') {
2715
2716
  if (this.is(body, 'block') && body.length > 2) {
2716
- let stmts = body.slice(1);
2717
2717
  for (let i = 0; i < stmts.length; i++) {
2718
2718
  if (i === stmts.length - 1) code += this.indent() + `return ${this.generate(stmts[i], 'value')};\n`;
2719
2719
  else code += this.indent() + this.generate(stmts[i], 'statement') + ';\n';
@@ -2722,8 +2722,13 @@ export class CodeGenerator {
2722
2722
  code += this.indent() + `return ${this.extractExpression(body)};\n`;
2723
2723
  }
2724
2724
  } else {
2725
- if (this.is(body, 'block') && body.length > 1) {
2726
- for (let s of body.slice(1)) code += this.indent() + this.generate(s, 'statement') + ';\n';
2725
+ if (stmts.length === 1 && this.is(stmts[0], 'if') && !this.hasStatementInBranch(stmts[0]) && !this.hasNestedMultiStatement(stmts[0])) {
2726
+ let [_, condition, thenBranch, ...elseBranches] = stmts[0];
2727
+ let thenExpr = this.extractExpression(this.unwrapIfBranch(thenBranch));
2728
+ let elseExpr = this.buildTernaryChain(elseBranches);
2729
+ code += this.indent() + `(${this.unwrap(this.generate(condition, 'value'))} ? ${thenExpr} : ${elseExpr});\n`;
2730
+ } else if (this.is(body, 'block') && body.length > 1) {
2731
+ for (let s of stmts) code += this.indent() + this.generate(s, 'statement') + ';\n';
2727
2732
  } else {
2728
2733
  code += this.indent() + this.generate(body, 'statement') + ';\n';
2729
2734
  }
package/src/components.js CHANGED
@@ -236,18 +236,20 @@ export function installComponentSupport(CodeGenerator, Lexer) {
236
236
  if (!inRender) return 1;
237
237
 
238
238
  // ─────────────────────────────────────────────────────────────────────
239
- // Expression output: = expr → text node (stamp .text, skip tag detection)
239
+ // Expression output: = expr → synthetic text node __text__(expr)
240
240
  // ─────────────────────────────────────────────────────────────────────
241
241
  if (tag === '=' && i > 0) {
242
242
  let prev = tokens[i - 1][0];
243
243
  if (prev === 'TERMINATOR' || prev === 'INDENT' || prev === 'RENDER') {
244
- tokens.splice(i, 1);
245
- if (tokens[i] && tokens[i][0] === 'IDENTIFIER') {
246
- let val = tokens[i][1];
247
- if (typeof val === 'string') { val = new String(val); tokens[i][1] = val; }
248
- val.text = true;
249
- }
250
- return 0;
244
+ const textToken = gen('IDENTIFIER', '__text__', token);
245
+ const callStart = gen('CALL_START', '(', token);
246
+ tokens.splice(i, 1, textToken, callStart);
247
+ this.detectEnd(i + 2,
248
+ (t) => t[0] === 'TERMINATOR' || t[0] === 'OUTDENT',
249
+ (t, j) => tokens.splice(j, 0, gen('CALL_END', ')', t)),
250
+ { returnOnNegativeLevel: true }
251
+ );
252
+ return 2;
251
253
  }
252
254
  }
253
255
 
@@ -432,7 +434,8 @@ export function installComponentSupport(CodeGenerator, Lexer) {
432
434
 
433
435
  let isTemplateElement = false;
434
436
  let prevTag = i > 0 ? tokens[i - 1][0] : null;
435
- let isAfterControlFlow = prevTag === 'IF' || prevTag === 'UNLESS' || prevTag === 'WHILE' || prevTag === 'UNTIL' || prevTag === 'WHEN';
437
+ let isAfterControlFlow = prevTag === 'IF' || prevTag === 'UNLESS' || prevTag === 'WHILE' || prevTag === 'UNTIL' || prevTag === 'WHEN' ||
438
+ prevTag === 'FORIN' || prevTag === 'FOROF' || prevTag === 'FORAS' || prevTag === 'FORASAWAIT' || prevTag === 'BY';
436
439
 
437
440
  // Detect __clsx CALL_END early — OUTDENT tokens inside multi-line .()
438
441
  // args prevent startsWithTag from seeing the template tag, so we check
@@ -1604,6 +1607,20 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1604
1607
  return this.generateTemplateLoop(sexpr);
1605
1608
  }
1606
1609
 
1610
+ // Synthetic text node inserted by rewriteRender for `= expr`
1611
+ if (headStr === '__text__') {
1612
+ const expr = rest[0] ?? 'undefined';
1613
+ const textVar = this.newTextVar();
1614
+ const exprCode = this.generateInComponent(expr, 'value');
1615
+ if (this.hasReactiveDeps(expr)) {
1616
+ this._createLines.push(`${textVar} = document.createTextNode('');`);
1617
+ this._pushEffect(`${textVar}.data = String(${exprCode});`);
1618
+ } else {
1619
+ this._createLines.push(`${textVar} = document.createTextNode(String(${exprCode}));`);
1620
+ }
1621
+ return textVar;
1622
+ }
1623
+
1607
1624
  // General expression (computed value, function call, binary op, etc.)
1608
1625
  const textVar = this.newTextVar();
1609
1626
  const exprCode = this.generateInComponent(sexpr, 'value');
package/src/lexer.js CHANGED
@@ -1476,7 +1476,8 @@ export class Lexer {
1476
1476
  [indent, outdent] = this.makeIndentation();
1477
1477
  if (tag === 'THEN') indent.fromThen = true;
1478
1478
  tokens.splice(i + 1, 0, indent);
1479
- this.detectEnd(i + 2, condition, action);
1479
+ if (tag === 'THEN' && this.singleLineOwner(i) === 'LEADING_WHEN') this.detectWhenThenEnd(i + 2, condition, action);
1480
+ else this.detectEnd(i + 2, condition, action);
1480
1481
  if (tag === 'THEN') tokens.splice(i, 1);
1481
1482
  return 1;
1482
1483
  }
@@ -1485,6 +1486,35 @@ export class Lexer {
1485
1486
  });
1486
1487
  }
1487
1488
 
1489
+ singleLineOwner(i) {
1490
+ let starters = new Set(['LEADING_WHEN', 'IF', 'POST_IF', 'UNLESS', 'POST_UNLESS', 'ELSE', 'CATCH', 'TRY', 'FINALLY', '->', '=>']);
1491
+ for (let j = i - 1; j >= 0; j--) {
1492
+ let token = this.tokens[j];
1493
+ let tag = token?.[0];
1494
+ if (starters.has(tag)) return tag;
1495
+ if (LINE_BREAK.has(tag) || token?.newLine) return null;
1496
+ }
1497
+ return null;
1498
+ }
1499
+
1500
+ detectWhenThenEnd(i, condition, action) {
1501
+ let levels = 0;
1502
+ let nestedInlineBranches = 0;
1503
+ while (i < this.tokens.length) {
1504
+ let token = this.tokens[i];
1505
+ let tag = token[0];
1506
+ if (levels === 0) {
1507
+ if (tag === 'THEN' && this.singleLineOwner(i) !== 'LEADING_WHEN') nestedInlineBranches++;
1508
+ else if (tag === 'ELSE' && nestedInlineBranches > 0) nestedInlineBranches--;
1509
+ else if (condition.call(this, token, i)) return action.call(this, token, i);
1510
+ }
1511
+ if (EXPRESSION_START.has(tag)) levels++;
1512
+ if (EXPRESSION_END.has(tag)) levels--;
1513
+ if (levels < 0) return action.call(this, token, i);
1514
+ i++;
1515
+ }
1516
+ }
1517
+
1488
1518
  tagPostfixConditionals() {
1489
1519
  let original = null;
1490
1520