rip-lang 3.14.3 → 3.14.4

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.14.3",
3
+ "version": "3.14.4",
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
@@ -2611,8 +2611,24 @@ export class CodeEmitter {
2611
2611
  }
2612
2612
  }
2613
2613
 
2614
+ if (!isConstructor && !sideEffectOnly && isLast && loopStmts.includes(h)) {
2615
+ if (this.containsYield(stmt)) {
2616
+ code += this.indent() + this.addSemicolon(stmt, this.emit(stmt, 'statement')) + '\n';
2617
+ return;
2618
+ }
2619
+ code += this.indent() + 'const _result = [];\n';
2620
+ this.comprehensionTarget = '_result';
2621
+ let saved = this._skipCompTargetInit;
2622
+ this._skipCompTargetInit = true;
2623
+ code += this.emit(stmt, 'value');
2624
+ this._skipCompTargetInit = saved;
2625
+ this.comprehensionTarget = null;
2626
+ code += this.indent() + 'return _result;\n';
2627
+ return;
2628
+ }
2629
+
2614
2630
  let needsReturn = !isConstructor && !sideEffectOnly && isLast &&
2615
- !noRetStmts.includes(h) && !loopStmts.includes(h) &&
2631
+ !noRetStmts.includes(h) &&
2616
2632
  !this.hasExplicitControlFlow(stmt);
2617
2633
  let ctx = needsReturn ? 'value' : 'statement';
2618
2634
  let sc = this.emit(stmt, ctx);
@@ -2727,28 +2743,80 @@ export class CodeEmitter {
2727
2743
 
2728
2744
  emitComprehensionWithTarget(expr, iterators, guards, targetVar) {
2729
2745
  let code = '';
2730
- code += this.indent() + `${targetVar} = [];\n`;
2731
- let unwrappedExpr = (this.is(expr, 'block') && expr.length === 2) ? expr[1] : expr;
2746
+ if (!this._skipCompTargetInit) code += this.indent() + `${targetVar} = [];\n`;
2747
+
2748
+ let hasCtrl = (node) => {
2749
+ if (typeof node === 'string' && (node === 'break' || node === 'continue')) return true;
2750
+ if (!Array.isArray(node)) return false;
2751
+ if (['break', 'continue', 'return', 'throw'].includes(node[0])) return true;
2752
+ if (node[0] === 'if') return node.slice(1).some(hasCtrl);
2753
+ return node.some(hasCtrl);
2754
+ };
2755
+
2756
+ let emitBody = () => {
2757
+ let loopTypes = ['for-in', 'for-of', 'for-as', 'while', 'loop'];
2758
+ if (this.is(expr, 'block')) {
2759
+ for (let i = 0; i < expr.length - 1; i++) {
2760
+ let s = expr[i + 1], isLast = i === expr.length - 2;
2761
+ if (!isLast || hasCtrl(s) || (Array.isArray(s) && loopTypes.includes(s[0]))) {
2762
+ code += this.indent() + this.emit(s, 'statement') + ';\n';
2763
+ } else {
2764
+ code += this.indent() + `${targetVar}.push(${this.emit(s, 'value')});\n`;
2765
+ }
2766
+ }
2767
+ } else if (hasCtrl(expr)) {
2768
+ code += this.indent() + this.emit(expr, 'statement') + ';\n';
2769
+ } else {
2770
+ code += this.indent() + `${targetVar}.push(${this.emit(expr, 'value')});\n`;
2771
+ }
2772
+ };
2732
2773
 
2733
2774
  if (iterators.length === 1) {
2734
2775
  let [iterType, vars, iterable, stepOrOwn] = iterators[0];
2776
+
2735
2777
  if (iterType === 'for-in') {
2736
2778
  let { header, setup } = this._forInHeader(vars, iterable, stepOrOwn);
2737
2779
  code += this.indent() + header + ' {\n';
2738
2780
  this.indentLevel++;
2739
2781
  if (setup) code += this.indent() + setup + '\n';
2740
- if (guards && guards.length > 0) {
2741
- code += this.indent() + `if (${guards.map(g => this.emit(g, 'value')).join(' && ')}) {\n`;
2742
- this.indentLevel++;
2743
- }
2744
- code += this.indent() + `${targetVar}.push(${this.unwrap(this.emit(unwrappedExpr, 'value'))});\n`;
2745
- if (guards && guards.length > 0) { this.indentLevel--; code += this.indent() + '}\n'; }
2782
+ if (guards?.length > 0) { code += this.indent() + `if (${guards.map(g => this.emit(g, 'value')).join(' && ')}) {\n`; this.indentLevel++; }
2783
+ emitBody();
2784
+ if (guards?.length > 0) { this.indentLevel--; code += this.indent() + '}\n'; }
2785
+ this.indentLevel--;
2786
+ code += this.indent() + '}\n';
2787
+ return code;
2788
+ }
2789
+
2790
+ if (iterType === 'for-of') {
2791
+ let { header, own, vv, oc, kvp } = this._forOfHeader(vars, iterable, stepOrOwn);
2792
+ code += this.indent() + header + ' {\n';
2793
+ this.indentLevel++;
2794
+ if (own) code += this.indent() + `if (!Object.hasOwn(${oc}, ${kvp})) continue;\n`;
2795
+ if (vv) code += this.indent() + `${vv} = ${oc}[${kvp}];\n`;
2796
+ if (guards?.length > 0) { code += this.indent() + `if (${guards.map(g => this.emit(g, 'value')).join(' && ')}) {\n`; this.indentLevel++; }
2797
+ emitBody();
2798
+ if (guards?.length > 0) { this.indentLevel--; code += this.indent() + '}\n'; }
2799
+ this.indentLevel--;
2800
+ code += this.indent() + '}\n';
2801
+ return code;
2802
+ }
2803
+
2804
+ if (iterType === 'for-as') {
2805
+ let { header } = this._forAsHeader(vars, iterable, stepOrOwn);
2806
+ code += this.indent() + header + ' {\n';
2807
+ this.indentLevel++;
2808
+ if (guards?.length > 0) { code += this.indent() + `if (${guards.map(g => this.emit(g, 'value')).join(' && ')}) {\n`; this.indentLevel++; }
2809
+ emitBody();
2810
+ if (guards?.length > 0) { this.indentLevel--; code += this.indent() + '}\n'; }
2746
2811
  this.indentLevel--;
2747
2812
  code += this.indent() + '}\n';
2748
2813
  return code;
2749
2814
  }
2750
2815
  }
2751
- return this.indent() + `${targetVar} = (() => { /* complex comprehension */ })();\n`;
2816
+
2817
+ code = '';
2818
+ code += this.indent() + `${targetVar} = ${this.emit(['comprehension', expr, iterators, guards || []], 'value')};\n`;
2819
+ return code;
2752
2820
  }
2753
2821
 
2754
2822
  emitComprehensionAsLoop(expr, iterators, guards) {
package/src/lexer.js CHANGED
@@ -172,7 +172,7 @@ let IMPLICIT_FUNC = new Set([
172
172
  let TAGGABLE = new Set(['IDENTIFIER', 'PROPERTY', ')', 'CALL_END', ']', 'INDEX_END']);
173
173
 
174
174
  // Control flow tokens that don't end implicit calls/objects
175
- let CONTROL_IN_IMPLICIT = new Set(['IF', 'TRY', 'FINALLY', 'CATCH', 'CLASS', 'SWITCH', 'COMPONENT']);
175
+ let CONTROL_IN_IMPLICIT = new Set(['IF', 'TRY', 'FINALLY', 'CATCH', 'CLASS', 'SWITCH', 'COMPONENT', 'FOR']);
176
176
 
177
177
  // Single-liner keywords that get implicit INDENT/OUTDENT
178
178
  let SINGLE_LINERS = new Set(['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN']);