rip-lang 3.14.4 → 3.15.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.
package/src/compiler.js CHANGED
@@ -11,8 +11,12 @@
11
11
  import { Lexer } from './lexer.js';
12
12
  import { parser } from './parser.js';
13
13
  import { installComponentSupport } from './components.js';
14
- import { emitTypes, emitEnum } from './types.js';
15
- import { installSchemaSupport } from './schema.js';
14
+ // Type emission is CLI/editor-only. types-emit.js registers itself via
15
+ // setTypesEmitter() at module load. The browser never imports types-emit,
16
+ // so _typesEmitter stays null and .d.ts output is silently skipped.
17
+ let _typesEmitter = null;
18
+ export function setTypesEmitter(fn) { _typesEmitter = fn; }
19
+ import { installSchemaSupport } from '@rip-lang/schema';
16
20
  import { SourceMapGenerator } from './sourcemaps.js';
17
21
  import { RipError, toRipError } from './error.js';
18
22
 
@@ -1472,7 +1476,7 @@ export class CodeEmitter {
1472
1476
  let stmts = body.slice(1);
1473
1477
  this.indentLevel++;
1474
1478
  let lines = [];
1475
- if (!noVar) lines.push(`${itemVarPattern} = ${iterCode}[${idxName}];`);
1479
+ if (!noVar) lines.push(`let ${itemVarPattern} = ${iterCode}[${idxName}];`);
1476
1480
  if (guard) {
1477
1481
  lines.push(`if (${this.emit(guard, 'value')}) {`);
1478
1482
  this.indentLevel++;
@@ -1492,8 +1496,8 @@ export class CodeEmitter {
1492
1496
  : loopHeader + `{ ${this.emit(body, 'statement')}; }`;
1493
1497
  }
1494
1498
  return guard
1495
- ? loopHeader + `{ ${itemVarPattern} = ${iterCode}[${idxName}]; if (${this.emit(guard, 'value')}) ${this.emit(body, 'statement')}; }`
1496
- : loopHeader + `{ ${itemVarPattern} = ${iterCode}[${idxName}]; ${this.emit(body, 'statement')}; }`;
1499
+ ? loopHeader + `{ let ${itemVarPattern} = ${iterCode}[${idxName}]; if (${this.emit(guard, 'value')}) ${this.emit(body, 'statement')}; }`
1500
+ : loopHeader + `{ let ${itemVarPattern} = ${iterCode}[${idxName}]; ${this.emit(body, 'statement')}; }`;
1497
1501
  }
1498
1502
 
1499
1503
  // Index variable → traditional for loop
@@ -1503,7 +1507,7 @@ export class CodeEmitter {
1503
1507
  if (this.is(body, 'block')) {
1504
1508
  code += '{\n';
1505
1509
  this.indentLevel++;
1506
- code += this.indent() + `${itemVarPattern} = ${iterCode}[${indexVar}];\n`;
1510
+ code += this.indent() + `let ${itemVarPattern} = ${iterCode}[${indexVar}];\n`;
1507
1511
  if (guard) {
1508
1512
  code += this.indent() + `if (${this.unwrap(this.emit(guard, 'value'))}) {\n`;
1509
1513
  this.indentLevel++;
@@ -1517,8 +1521,8 @@ export class CodeEmitter {
1517
1521
  code += this.indent() + '}';
1518
1522
  } else {
1519
1523
  code += guard
1520
- ? `{ ${itemVarPattern} = ${iterCode}[${indexVar}]; if (${this.unwrap(this.emit(guard, 'value'))}) ${this.emit(body, 'statement')}; }`
1521
- : `{ ${itemVarPattern} = ${iterCode}[${indexVar}]; ${this.emit(body, 'statement')}; }`;
1524
+ ? `{ let ${itemVarPattern} = ${iterCode}[${indexVar}]; if (${this.unwrap(this.emit(guard, 'value'))}) ${this.emit(body, 'statement')}; }`
1525
+ : `{ let ${itemVarPattern} = ${iterCode}[${indexVar}]; ${this.emit(body, 'statement')}; }`;
1522
1526
  }
1523
1527
  return code;
1524
1528
  }
@@ -1542,8 +1546,7 @@ export class CodeEmitter {
1542
1546
  }
1543
1547
 
1544
1548
  // Default: for-of
1545
- let bind = noVar ? 'let ' : '';
1546
- let code = `for (${bind}${itemVarPattern} of ${this.emit(iterable, 'value')}) `;
1549
+ let code = `for (let ${itemVarPattern} of ${this.emit(iterable, 'value')}) `;
1547
1550
  code += guard ? this.emitLoopBodyWithGuard(body, guard) : this.emitLoopBody(body);
1548
1551
  return code;
1549
1552
  }
@@ -1558,7 +1561,7 @@ export class CodeEmitter {
1558
1561
 
1559
1562
  let [keyVar, valueVar] = Array.isArray(vars) ? vars : [vars];
1560
1563
  let objCode = this.emit(obj, 'value');
1561
- let code = `for (${keyVar} in ${objCode}) `;
1564
+ let code = `for (let ${keyVar} in ${objCode}) `;
1562
1565
 
1563
1566
  if (own && !valueVar && !guard) {
1564
1567
  if (this.is(body, 'block')) {
@@ -1576,7 +1579,7 @@ export class CodeEmitter {
1576
1579
  this.indentLevel++;
1577
1580
  let lines = [];
1578
1581
  if (own) lines.push(`if (!Object.hasOwn(${objCode}, ${keyVar})) continue;`);
1579
- lines.push(`${valueVar} = ${objCode}[${keyVar}];`);
1582
+ lines.push(`let ${valueVar} = ${objCode}[${keyVar}];`);
1580
1583
  if (guard) {
1581
1584
  lines.push(`if (${this.emit(guard, 'value')}) {`);
1582
1585
  this.indentLevel++;
@@ -1591,7 +1594,7 @@ export class CodeEmitter {
1591
1594
  }
1592
1595
  let inline = '';
1593
1596
  if (own) inline += `if (!Object.hasOwn(${objCode}, ${keyVar})) continue; `;
1594
- inline += `${valueVar} = ${objCode}[${keyVar}]; `;
1597
+ inline += `let ${valueVar} = ${objCode}[${keyVar}]; `;
1595
1598
  if (guard) inline += `if (${this.emit(guard, 'value')}) `;
1596
1599
  inline += `${this.emit(body, 'statement')};`;
1597
1600
  return code + `{ ${inline} }`;
@@ -1638,7 +1641,7 @@ export class CodeEmitter {
1638
1641
  itemVarPattern = this.emitDestructuringPattern(firstVar);
1639
1642
  else itemVarPattern = firstVar;
1640
1643
 
1641
- let code = `for ${awaitKw}(${itemVarPattern} of ${iterCode}) `;
1644
+ let code = `for ${awaitKw}(let ${itemVarPattern} of ${iterCode}) `;
1642
1645
 
1643
1646
  if (needsTempVar && destructStmts.length > 0) {
1644
1647
  let stmts = this.unwrapBlock(body);
@@ -2012,17 +2015,16 @@ export class CodeEmitter {
2012
2015
  let header = isNeg
2013
2016
  ? `for (let ${idxN} = ${ic}.length - 1; ${idxN} >= 0; ${update})`
2014
2017
  : `for (let ${idxN} = 0; ${idxN} < ${ic}.length; ${update})`;
2015
- return { header, setup: noVar ? null : `${ivp} = ${ic}[${idxN}];` };
2018
+ return { header, setup: noVar ? null : `let ${ivp} = ${ic}[${idxN}];` };
2016
2019
  }
2017
2020
  if (indexVar) {
2018
2021
  let ic = this.emit(iterable, 'value');
2019
2022
  return {
2020
2023
  header: `for (let ${indexVar} = 0; ${indexVar} < ${ic}.length; ${indexVar}++)`,
2021
- setup: `${ivp} = ${ic}[${indexVar}];`,
2024
+ setup: `let ${ivp} = ${ic}[${indexVar}];`,
2022
2025
  };
2023
2026
  }
2024
- let bind = noVar ? 'let ' : '';
2025
- return { header: `for (${bind}${ivp} of ${this.emit(iterable, 'value')})`, setup: null };
2027
+ return { header: `for (let ${ivp} of ${this.emit(iterable, 'value')})`, setup: null };
2026
2028
  }
2027
2029
 
2028
2030
  // Shared: parse a for-of (object) iterator and return { header, own, vv, oc, kvp }.
@@ -2032,7 +2034,7 @@ export class CodeEmitter {
2032
2034
  let kvp = (this.is(kv, 'array') || this.is(kv, 'object'))
2033
2035
  ? this.emitDestructuringPattern(kv) : kv;
2034
2036
  let oc = this.emit(iterable, 'value');
2035
- return { header: `for (${kvp} in ${oc})`, own, vv, oc, kvp };
2037
+ return { header: `for (let ${kvp} in ${oc})`, own, vv, oc, kvp };
2036
2038
  }
2037
2039
 
2038
2040
  // Shared: parse a for-as (iterator) spec and return { header }.
@@ -2041,13 +2043,28 @@ export class CodeEmitter {
2041
2043
  let [fv] = va;
2042
2044
  let ivp = (this.is(fv, 'array') || this.is(fv, 'object'))
2043
2045
  ? this.emitDestructuringPattern(fv) : fv;
2044
- return { header: `for ${isAwait ? 'await ' : ''}(${ivp} of ${this.emit(iterable, 'value')})` };
2046
+ return { header: `for ${isAwait ? 'await ' : ''}(let ${ivp} of ${this.emit(iterable, 'value')})` };
2045
2047
  }
2046
2048
 
2047
2049
  emitComprehension(head, rest, context) {
2048
2050
  let [expr, iterators, guards] = rest;
2049
2051
  if (context === 'statement') return this.emitComprehensionAsLoop(expr, iterators, guards);
2050
- if (this.comprehensionTarget) return this.emitComprehensionWithTarget(expr, iterators, guards, this.comprehensionTarget);
2052
+ if (this.comprehensionTarget) {
2053
+ // Consume-and-clear: the auto-return-loop logic sets comprehensionTarget
2054
+ // expecting ONE consumer (the direct value-context comprehension being
2055
+ // routed to the named target). Without clearing here, nested
2056
+ // comprehensions inside this comprehension's body (call args, RHS
2057
+ // expressions) would inherit the target and skip their own IIFE,
2058
+ // producing malformed JS or wrong semantics. The body's own emit calls
2059
+ // see comprehensionTarget = null and correctly produce IIFEs.
2060
+ let target = this.comprehensionTarget;
2061
+ this.comprehensionTarget = null;
2062
+ try {
2063
+ return this.emitComprehensionWithTarget(expr, iterators, guards, target);
2064
+ } finally {
2065
+ this.comprehensionTarget = target;
2066
+ }
2067
+ }
2051
2068
 
2052
2069
  // Enclosed: expr, iterators (iterable expressions), guards
2053
2070
  let hasAwait = this.containsAwait(expr) || iterators.some(i => this.containsAwait(i)) || guards.some(g => this.containsAwait(g));
@@ -2068,7 +2085,7 @@ export class CodeEmitter {
2068
2085
  code += this.indent() + header + ' {\n';
2069
2086
  this.indentLevel++;
2070
2087
  if (own) code += this.indent() + `if (!Object.hasOwn(${oc}, ${kvp})) continue;\n`;
2071
- if (vv) code += this.indent() + `${vv} = ${oc}[${kvp}];\n`;
2088
+ if (vv) code += this.indent() + `let ${vv} = ${oc}[${kvp}];\n`;
2072
2089
  } else if (iterType === 'for-as') {
2073
2090
  let { header } = this._forAsHeader(vars, iterable, iter[3]);
2074
2091
  code += this.indent() + header + ' {\n';
@@ -2132,10 +2149,10 @@ export class CodeEmitter {
2132
2149
  if (iterType === 'for-of') {
2133
2150
  let [kv, vv] = vars;
2134
2151
  let oc = this.emit(iterable, 'value');
2135
- code += this.indent() + `for (${kv} in ${oc}) {\n`;
2152
+ code += this.indent() + `for (let ${kv} in ${oc}) {\n`;
2136
2153
  this.indentLevel++;
2137
2154
  if (own) code += this.indent() + `if (!Object.hasOwn(${oc}, ${kv})) continue;\n`;
2138
- if (vv) code += this.indent() + `${vv} = ${oc}[${kv}];\n`;
2155
+ if (vv) code += this.indent() + `let ${vv} = ${oc}[${kv}];\n`;
2139
2156
  }
2140
2157
  }
2141
2158
  for (let guard of guards) { code += this.indent() + `if (${this.emit(guard, 'value')}) {\n`; this.indentLevel++; }
@@ -2616,6 +2633,21 @@ export class CodeEmitter {
2616
2633
  code += this.indent() + this.addSemicolon(stmt, this.emit(stmt, 'statement')) + '\n';
2617
2634
  return;
2618
2635
  }
2636
+ // Auto-return-loop: only for-in/for-of/for-as auto-collect into
2637
+ // _result, because emitForIn/emitForOf/emitForAs at value-context
2638
+ // wrap themselves in a comprehension that consumes
2639
+ // comprehensionTarget. `loop` and `while` have no such wrapping —
2640
+ // emitLoop/emitWhile just emit `while(...) { body }` and any
2641
+ // comprehensionTarget set here would LEAK into nested
2642
+ // expression-context comprehensions inside the body (causing
2643
+ // them to be routed to the wrong target and skip their own
2644
+ // IIFE). Loops with explicit `return X` inside their body
2645
+ // already work correctly; emit them as plain statements.
2646
+ let isCollectibleLoop = h === 'for-in' || h === 'for-of' || h === 'for-as';
2647
+ if (!isCollectibleLoop) {
2648
+ code += this.indent() + this.addSemicolon(stmt, this.emit(stmt, 'statement')) + '\n';
2649
+ return;
2650
+ }
2619
2651
  code += this.indent() + 'const _result = [];\n';
2620
2652
  this.comprehensionTarget = '_result';
2621
2653
  let saved = this._skipCompTargetInit;
@@ -2792,7 +2824,7 @@ export class CodeEmitter {
2792
2824
  code += this.indent() + header + ' {\n';
2793
2825
  this.indentLevel++;
2794
2826
  if (own) code += this.indent() + `if (!Object.hasOwn(${oc}, ${kvp})) continue;\n`;
2795
- if (vv) code += this.indent() + `${vv} = ${oc}[${kvp}];\n`;
2827
+ if (vv) code += this.indent() + `let ${vv} = ${oc}[${kvp}];\n`;
2796
2828
  if (guards?.length > 0) { code += this.indent() + `if (${guards.map(g => this.emit(g, 'value')).join(' && ')}) {\n`; this.indentLevel++; }
2797
2829
  emitBody();
2798
2830
  if (guards?.length > 0) { this.indentLevel--; code += this.indent() + '}\n'; }
@@ -2864,7 +2896,7 @@ export class CodeEmitter {
2864
2896
  code += header + ' {\n';
2865
2897
  this.indentLevel++;
2866
2898
  if (own) code += this.indent() + `if (!Object.hasOwn(${oc}, ${kvp})) continue;\n`;
2867
- if (vv) code += this.indent() + `${vv} = ${oc}[${kvp}];\n`;
2899
+ if (vv) code += this.indent() + `let ${vv} = ${oc}[${kvp}];\n`;
2868
2900
  emitBody();
2869
2901
  this.indentLevel--;
2870
2902
  code += this.indent() + '}';
@@ -3691,7 +3723,7 @@ export class Compiler {
3691
3723
 
3692
3724
  // If only terminators remain (type-only source), emit types and return early
3693
3725
  if (tokens.every(t => t[0] === 'TERMINATOR')) {
3694
- if (typeTokens) dts = emitTypes(typeTokens, ['program'], source);
3726
+ if (typeTokens && _typesEmitter) dts = _typesEmitter(typeTokens, ['program'], source);
3695
3727
  return { tokens, sexpr: ['program'], code: '', dts, data: dataSection, reactiveVars: {} };
3696
3728
  }
3697
3729
 
@@ -3761,6 +3793,11 @@ export class Compiler {
3761
3793
  skipDataPart: this.options.skipDataPart,
3762
3794
  stubComponents: this.options.stubComponents,
3763
3795
  reactiveVars: this.options.reactiveVars,
3796
+ // Schema runtime mode: 'browser' / 'validate' / 'server' / 'migration'.
3797
+ // Default 'migration' covers the common case (CLI, server, tests) where
3798
+ // the user might call any schema feature including .toSQL(). The browser
3799
+ // bundle build script overrides to 'browser' for size reduction.
3800
+ schemaMode: this.options.schemaMode,
3764
3801
  sourceMap,
3765
3802
  });
3766
3803
  let code = generator.compile(sexpr);
@@ -3768,15 +3805,28 @@ export class Compiler {
3768
3805
  let map = sourceMap ? sourceMap.toJSON() : null;
3769
3806
  let reverseMap = sourceMap ? sourceMap.toReverseMap() : null;
3770
3807
  if (map && this.options.sourceMap === 'inline') {
3771
- let b64 = typeof Buffer !== 'undefined' ? Buffer.from(map).toString('base64') : btoa(map);
3808
+ // map is already a JSON string (sourceMaps.toJSON() stringifies). UTF-8
3809
+ // safe encode: btoa() only handles Latin-1, so pre-encode non-ASCII via
3810
+ // TextEncoder before base64 in browsers. Bun's Buffer handles utf-8
3811
+ // directly. Source files containing emoji, em-dashes, accented chars,
3812
+ // etc. would otherwise break with `Failed to execute 'btoa'`.
3813
+ let b64;
3814
+ if (typeof Buffer !== 'undefined') {
3815
+ b64 = Buffer.from(map, 'utf8').toString('base64');
3816
+ } else {
3817
+ const bytes = new TextEncoder().encode(map);
3818
+ let bin = '';
3819
+ for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
3820
+ b64 = btoa(bin);
3821
+ }
3772
3822
  code += `\n//# sourceMappingURL=data:application/json;base64,${b64}`;
3773
3823
  } else if (map && this.options.filename) {
3774
3824
  code += `\n//# sourceMappingURL=${this.options.filename}.js.map`;
3775
3825
  }
3776
3826
 
3777
3827
  // Step 5: Emit .d.ts from annotated tokens + parsed s-expression
3778
- if (typeTokens) {
3779
- dts = emitTypes(typeTokens, sexpr, source);
3828
+ if (typeTokens && _typesEmitter) {
3829
+ dts = _typesEmitter(typeTokens, sexpr, source);
3780
3830
  }
3781
3831
 
3782
3832
  return { tokens, sexpr, code, dts, map, reverseMap, data: dataSection, reactiveVars: generator.reactiveVars };
@@ -3793,10 +3843,36 @@ export class Compiler {
3793
3843
  installComponentSupport(CodeEmitter, Lexer);
3794
3844
 
3795
3845
  // =============================================================================
3796
- // Type Support (enum generator)
3846
+ // Enum Codegen (CodeEmitter method)
3797
3847
  // =============================================================================
3848
+ // `enum` blocks compile to a runtime JavaScript object that maps both
3849
+ // forward (key → value) and reverse (value → key). This is real codegen,
3850
+ // not type machinery, so it lives with the rest of the emitter dispatch.
3851
+
3852
+ CodeEmitter.prototype.emitEnum = function emitEnum(head, rest, context) {
3853
+ let [name, body] = rest;
3854
+ let enumName = name?.valueOf?.() ?? name;
3855
+
3856
+ let pairs = [];
3857
+ if (Array.isArray(body)) {
3858
+ let items = body[0] === 'block' ? body.slice(1) : [body];
3859
+ for (let item of items) {
3860
+ if (Array.isArray(item)) {
3861
+ if (item[0]?.valueOf?.() === '=') {
3862
+ let key = item[1]?.valueOf?.() ?? item[1];
3863
+ let val = item[2]?.valueOf?.() ?? item[2];
3864
+ pairs.push([key, val]);
3865
+ }
3866
+ }
3867
+ }
3868
+ }
3869
+
3870
+ if (pairs.length === 0) return `const ${enumName} = {}`;
3798
3871
 
3799
- CodeEmitter.prototype.emitEnum = emitEnum;
3872
+ let forward = pairs.map(([k, v]) => `${k}: ${v}`).join(', ');
3873
+ let reverse = pairs.map(([k, v]) => `${v}: "${k}"`).join(', ');
3874
+ return `const ${enumName} = {${forward}, ${reverse}}`;
3875
+ };
3800
3876
 
3801
3877
  // =============================================================================
3802
3878
  // Schema Support (prototype installation)
@@ -808,7 +808,7 @@ grammar =
808
808
  # Schema
809
809
  # ============================================================================
810
810
  # `schema [:kind] INDENT ... OUTDENT` is parsed entirely by the schema
811
- # sub-parser at lexer-rewrite time (src/schema.js). The rewriter emits
811
+ # sub-parser at lexer-rewrite time (packages/schema/src/schema.js). The rewriter emits
812
812
  # a synthetic SCHEMA_BODY token whose .data carries the full descriptor
813
813
  # (kind, entries, per-entry loc). The main grammar only sees these two
814
814
  # terminals, which keeps schema body syntax (`name! type`, `@directive`,
@@ -154,7 +154,6 @@ class Generator
154
154
  for handle in handles
155
155
  [symbols, action, precedence] = @_parseHandle handle
156
156
 
157
- # Add symbols to grammar
158
157
  addSymbol symbol for symbol in symbols
159
158
 
160
159
  # Process semantic actions
package/src/lexer.js CHANGED
@@ -40,7 +40,7 @@
40
40
  // ==========================================================================
41
41
 
42
42
  import { installTypeSupport } from './types.js';
43
- import { installSchemaSupport } from './schema.js';
43
+ import { installSchemaSupport } from '@rip-lang/schema';
44
44
 
45
45
  // ==========================================================================
46
46
  // Token Category Sets
@@ -174,6 +174,15 @@ let TAGGABLE = new Set(['IDENTIFIER', 'PROPERTY', ')', 'CALL_END', ']', 'INDEX_E
174
174
  // Control flow tokens that don't end implicit calls/objects
175
175
  let CONTROL_IN_IMPLICIT = new Set(['IF', 'TRY', 'FINALLY', 'CATCH', 'CLASS', 'SWITCH', 'COMPONENT', 'FOR']);
176
176
 
177
+ // Tokens that complete an expression value. Used to detect postfix-position
178
+ // for keywords that exist in both prefix and postfix forms (FOR has no
179
+ // dedicated POST_FOR token like POST_IF, so we infer it from context).
180
+ let VALUE_END_TAGS = new Set([
181
+ 'IDENTIFIER', 'PROPERTY', 'NUMBER', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END',
182
+ ')', 'CALL_END', ']', 'INDEX_END', '}', 'MAP_END', 'PICK_END',
183
+ 'BOOL', 'NULL', 'UNDEFINED', 'INFINITY', 'NAN', 'SUPER', 'THIS', '@', 'SYMBOL',
184
+ ]);
185
+
177
186
  // Single-liner keywords that get implicit INDENT/OUTDENT
178
187
  let SINGLE_LINERS = new Set(['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN']);
179
188
 
@@ -1782,8 +1791,21 @@ export class Lexer {
1782
1791
  i += 1;
1783
1792
  };
1784
1793
 
1785
- // Don't end implicit on INDENT for control flow inside implicit
1786
- if ((inImplicitCall() || inImplicitObject()) && CONTROL_IN_IMPLICIT.has(tag)) {
1794
+ // Don't end implicit on INDENT for control flow inside implicit.
1795
+ //
1796
+ // Special case: FOR is the only entry in CONTROL_IN_IMPLICIT that can
1797
+ // appear in postfix position (no POST_FOR token exists, unlike
1798
+ // POST_IF / POST_UNLESS). When FOR follows a value-completing token
1799
+ // on the same line (e.g. `addSymbol s for s in xs`), it's a postfix
1800
+ // comprehension that should END the implicit call so the comprehension
1801
+ // wraps the call rather than becoming the call's argument. Detect
1802
+ // postfix FOR by: not at the start of a new line, AND the previous
1803
+ // token is a value-completing token (IDENTIFIER, ), ], literal, etc.).
1804
+ // Prefix FOR (after `:`, `=`, `->`, comma, etc.) keeps the existing
1805
+ // CONTROL behaviour. Falling through lets the IMPLICIT_END handler
1806
+ // below close the implicit call.
1807
+ let isPostfixFor = tag === 'FOR' && !token.newLine && VALUE_END_TAGS.has(prevTag);
1808
+ if ((inImplicitCall() || inImplicitObject()) && CONTROL_IN_IMPLICIT.has(tag) && !isPostfixFor) {
1787
1809
  stack.push(['CONTROL', i, {ours: true}]);
1788
1810
  return forward(1);
1789
1811
  }
package/src/parser.js CHANGED
@@ -256,16 +256,16 @@ const parserInstance = {
256
256
  }
257
257
  },
258
258
  parse(input) {
259
- let EOF, TERROR, action, errStr, expected, len, lex, lexer, loc, locs, newState, p, parseTable, preErrorSymbol, r, recovering, rv, sharedState, state, stk, symbol, tokenLen, tokenLine, tokenLoc, tokenText, vals;
259
+ let EOF, TERROR, action, errStr, expected, k, len, lex, lexer, loc, locs, newState, p, parseTable, preErrorSymbol, r, recovering, rv, sharedState, state, stk, symbol, tokenLen, tokenLine, tokenLoc, tokenText, v, vals;
260
260
  [stk, vals, locs] = [[0], [null], []];
261
261
  [parseTable, tokenText, tokenLine, tokenLen, recovering] = [this.parseTable, "", 0, 0, 0];
262
262
  [TERROR, EOF] = [2, 1];
263
263
  lexer = Object.create(this.lexer);
264
264
  sharedState = { ctx: {} };
265
- for (const k in this.ctx) {
265
+ for (let k in this.ctx) {
266
266
  if (!Object.hasOwn(this.ctx, k))
267
267
  continue;
268
- const v = this.ctx[k];
268
+ let v = this.ctx[k];
269
269
  sharedState.ctx[k] = v;
270
270
  }
271
271
  lexer.setInput(input, sharedState.ctx);
@@ -294,7 +294,7 @@ const parserInstance = {
294
294
  if (!recovering)
295
295
  expected = (() => {
296
296
  const result = [];
297
- for (const p in parseTable[state]) {
297
+ for (let p in parseTable[state]) {
298
298
  if (!Object.hasOwn(parseTable[state], p))
299
299
  continue;
300
300
  if (this.tokenNames[p] && p > TERROR)
package/src/typecheck.js CHANGED
@@ -11,8 +11,9 @@
11
11
  // type errors mapped back to Rip source positions.
12
12
 
13
13
  import { Compiler, getStdlibCode } from './compiler.js';
14
- import { INTRINSIC_TYPE_DECLS, INTRINSIC_FN_DECL, ARIA_TYPE_DECLS, SIGNAL_INTERFACE, SIGNAL_FN, COMPUTED_INTERFACE, COMPUTED_FN, EFFECT_FN } from './types.js';
15
- import { hasSchemas } from './schema.js';
14
+ import { INTRINSIC_TYPE_DECLS, INTRINSIC_FN_DECL, ARIA_TYPE_DECLS, SIGNAL_INTERFACE, SIGNAL_FN, COMPUTED_INTERFACE, COMPUTED_FN, EFFECT_FN } from './types-emit.js';
15
+ import { hasSchemas } from '@rip-lang/schema';
16
+ import '@rip-lang/schema/loader-server'; // registers full schema runtime provider
16
17
  import { createRequire } from 'module';
17
18
  import { readFileSync, existsSync, readdirSync } from 'fs';
18
19
  import { resolve, relative, dirname } from 'path';