rip-lang 3.13.78 → 3.13.80
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/README.md +1 -1
- package/package.json +5 -2
- package/src/compiler.js +16 -2
- package/src/components.js +84 -39
- package/src/typecheck.js +2 -0
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-3.13.
|
|
12
|
+
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.13.80-blue.svg" alt="Version"></a>
|
|
13
13
|
<a href="#zero-dependencies"><img src="https://img.shields.io/badge/dependencies-ZERO-brightgreen.svg" alt="Dependencies"></a>
|
|
14
14
|
<a href="#"><img src="https://img.shields.io/badge/tests-1%2C436%2F1%2C436-brightgreen.svg" alt="Tests"></a>
|
|
15
15
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rip-lang",
|
|
3
|
-
"version": "3.13.
|
|
3
|
+
"version": "3.13.80",
|
|
4
4
|
"description": "A modern language that compiles to JavaScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/compiler.js",
|
|
@@ -66,5 +66,8 @@
|
|
|
66
66
|
},
|
|
67
67
|
"homepage": "https://github.com/shreeve/rip-lang#readme",
|
|
68
68
|
"author": "Steve Shreeve <steve.shreeve@gmail.com>",
|
|
69
|
-
"license": "MIT"
|
|
69
|
+
"license": "MIT",
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"typescript": "5.9.3"
|
|
72
|
+
}
|
|
70
73
|
}
|
package/src/compiler.js
CHANGED
|
@@ -297,6 +297,11 @@ export class CodeGenerator {
|
|
|
297
297
|
if (entry.loc) {
|
|
298
298
|
this.sourceMap.addMapping(lineOffset, 0, entry.loc.r, entry.loc.c);
|
|
299
299
|
}
|
|
300
|
+
if (entry.subLocs) {
|
|
301
|
+
for (const { lineOffset: lo, loc } of entry.subLocs) {
|
|
302
|
+
if (loc) this.sourceMap.addMapping(lineOffset + lo, 0, loc.r, loc.c);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
300
305
|
lineOffset += entry.code.split('\n').length;
|
|
301
306
|
}
|
|
302
307
|
}
|
|
@@ -619,7 +624,12 @@ export class CodeGenerator {
|
|
|
619
624
|
if (!blockStmts.includes(h) || !generated.endsWith('}')) generated += ';';
|
|
620
625
|
}
|
|
621
626
|
let loc = Array.isArray(stmt) ? stmt.loc : null;
|
|
622
|
-
|
|
627
|
+
let entry = { code: generated, loc };
|
|
628
|
+
if (this._pendingComponentLineLocs) {
|
|
629
|
+
entry.subLocs = this._pendingComponentLineLocs;
|
|
630
|
+
this._pendingComponentLineLocs = null;
|
|
631
|
+
}
|
|
632
|
+
return entry;
|
|
623
633
|
});
|
|
624
634
|
let statementsCode = stmtEntries.map(e => e.code).join('\n');
|
|
625
635
|
|
|
@@ -3397,10 +3407,14 @@ declare function __computed<T>(fn: () => T): Computed<T>;
|
|
|
3397
3407
|
declare function __effect(fn: () => void | (() => void)): () => void;
|
|
3398
3408
|
declare function __batch<T>(fn: () => T): T;
|
|
3399
3409
|
declare function __readonly<T>(v: T): Readonly<{ value: T }>;
|
|
3410
|
+
declare function __pushComponent(component: any): any;
|
|
3411
|
+
declare function __popComponent(prev: any): void;
|
|
3412
|
+
declare function __handleComponentError(error: any, component: any): void;
|
|
3413
|
+
declare function __clsx(...args: any[]): string;
|
|
3400
3414
|
declare function setContext(key: string, value: any): void;
|
|
3401
3415
|
declare function getContext(key: string): any;
|
|
3402
3416
|
declare function hasContext(key: string): boolean;
|
|
3403
|
-
declare class __Component { constructor(props?: any); [key: string]: any; }
|
|
3417
|
+
declare class __Component { constructor(props?: any); _create?(): any; _setup?(): void; _root?: any; _children?: any[]; [key: string]: any; }
|
|
3404
3418
|
`;
|
|
3405
3419
|
}
|
|
3406
3420
|
|
package/src/components.js
CHANGED
|
@@ -107,6 +107,16 @@ function isPublicProp(target) {
|
|
|
107
107
|
return Array.isArray(target) && target[0] === '.' && target[1] === 'this';
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Extract type annotation from s-expression target node.
|
|
112
|
+
* Type annotations are stored as .type on String objects by the type rewriter.
|
|
113
|
+
*/
|
|
114
|
+
function getMemberType(target) {
|
|
115
|
+
if (target instanceof String && target.type) return target.type;
|
|
116
|
+
if (Array.isArray(target) && target[2] instanceof String && target[2].type) return target[2].type;
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
110
120
|
// ============================================================================
|
|
111
121
|
// Prototype Installation
|
|
112
122
|
// ============================================================================
|
|
@@ -703,35 +713,35 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
703
713
|
} else if (op === 'state') {
|
|
704
714
|
const varName = getMemberName(stmt[1]);
|
|
705
715
|
if (varName) {
|
|
706
|
-
stateVars.push({ name: varName, value: stmt[2], isPublic: isPublicProp(stmt[1]) });
|
|
716
|
+
stateVars.push({ name: varName, value: stmt[2], isPublic: isPublicProp(stmt[1]), type: getMemberType(stmt[1]), loc: stmt.loc });
|
|
707
717
|
memberNames.add(varName);
|
|
708
718
|
reactiveMembers.add(varName);
|
|
709
719
|
}
|
|
710
720
|
} else if (op === 'computed') {
|
|
711
721
|
const varName = getMemberName(stmt[1]);
|
|
712
722
|
if (varName) {
|
|
713
|
-
derivedVars.push({ name: varName, expr: stmt[2] });
|
|
723
|
+
derivedVars.push({ name: varName, expr: stmt[2], loc: stmt.loc });
|
|
714
724
|
memberNames.add(varName);
|
|
715
725
|
reactiveMembers.add(varName);
|
|
716
726
|
}
|
|
717
727
|
} else if (op === 'readonly') {
|
|
718
728
|
const varName = getMemberName(stmt[1]);
|
|
719
729
|
if (varName) {
|
|
720
|
-
readonlyVars.push({ name: varName, value: stmt[2], isPublic: isPublicProp(stmt[1]) });
|
|
730
|
+
readonlyVars.push({ name: varName, value: stmt[2], isPublic: isPublicProp(stmt[1]), type: getMemberType(stmt[1]), loc: stmt.loc });
|
|
721
731
|
memberNames.add(varName);
|
|
722
732
|
}
|
|
723
733
|
} else if (op === '=') {
|
|
724
734
|
const varName = getMemberName(stmt[1]);
|
|
725
735
|
if (varName) {
|
|
726
736
|
if (LIFECYCLE_HOOKS.has(varName)) {
|
|
727
|
-
lifecycleHooks.push({ name: varName, value: stmt[2] });
|
|
737
|
+
lifecycleHooks.push({ name: varName, value: stmt[2], loc: stmt.loc });
|
|
728
738
|
} else {
|
|
729
739
|
const val = stmt[2];
|
|
730
740
|
if (Array.isArray(val) && (val[0] === '->' || val[0] === '=>')) {
|
|
731
|
-
methods.push({ name: varName, func: val });
|
|
741
|
+
methods.push({ name: varName, func: val, loc: stmt.loc });
|
|
732
742
|
memberNames.add(varName);
|
|
733
743
|
} else {
|
|
734
|
-
stateVars.push({ name: varName, value: val, isPublic: isPublicProp(stmt[1]) });
|
|
744
|
+
stateVars.push({ name: varName, value: val, isPublic: isPublicProp(stmt[1]), loc: stmt.loc });
|
|
735
745
|
memberNames.add(varName);
|
|
736
746
|
reactiveMembers.add(varName);
|
|
737
747
|
}
|
|
@@ -747,9 +757,9 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
747
757
|
if (!Array.isArray(pair)) continue;
|
|
748
758
|
const [methodName, funcDef] = pair;
|
|
749
759
|
if (typeof methodName === 'string' && LIFECYCLE_HOOKS.has(methodName)) {
|
|
750
|
-
lifecycleHooks.push({ name: methodName, value: funcDef });
|
|
760
|
+
lifecycleHooks.push({ name: methodName, value: funcDef, loc: pair.loc });
|
|
751
761
|
} else if (typeof methodName === 'string') {
|
|
752
|
-
methods.push({ name: methodName, func: funcDef });
|
|
762
|
+
methods.push({ name: methodName, func: funcDef, loc: pair.loc });
|
|
753
763
|
memberNames.add(methodName);
|
|
754
764
|
}
|
|
755
765
|
}
|
|
@@ -773,49 +783,76 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
773
783
|
this._autoEventHandlers = autoEventHandlers.size > 0 ? autoEventHandlers : null;
|
|
774
784
|
|
|
775
785
|
const lines = [];
|
|
786
|
+
const lineLocs = [];
|
|
776
787
|
let blockFactoriesCode = '';
|
|
777
788
|
|
|
778
|
-
|
|
789
|
+
let totalLines = 0;
|
|
790
|
+
const pushLine = (line, loc) => {
|
|
791
|
+
if (loc) lineLocs.push({ lineOffset: totalLines, loc });
|
|
792
|
+
lines.push(line);
|
|
793
|
+
totalLines += line.split('\n').length;
|
|
794
|
+
};
|
|
795
|
+
const pushPlain = (line) => {
|
|
796
|
+
lines.push(line);
|
|
797
|
+
totalLines += line.split('\n').length;
|
|
798
|
+
};
|
|
799
|
+
|
|
800
|
+
pushPlain('class extends __Component {');
|
|
779
801
|
|
|
780
802
|
// --- Init (called by __Component constructor) ---
|
|
781
|
-
|
|
803
|
+
if (this.options.lspMode) {
|
|
804
|
+
const typedProps = [];
|
|
805
|
+
for (const v of [...readonlyVars, ...stateVars]) {
|
|
806
|
+
if (v.isPublic) {
|
|
807
|
+
const t = v.type || 'any';
|
|
808
|
+
typedProps.push(`${v.name}?: ${t}`);
|
|
809
|
+
typedProps.push(`__bind_${v.name}__?: ${t}`);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
const propsType = typedProps.length > 0
|
|
813
|
+
? `{ ${typedProps.join(', ')}, [key: string]: any }`
|
|
814
|
+
: 'any';
|
|
815
|
+
pushPlain(` _init(props: ${propsType}) {`);
|
|
816
|
+
} else {
|
|
817
|
+
pushPlain(' _init(props) {');
|
|
818
|
+
}
|
|
782
819
|
|
|
783
820
|
// Constants (readonly)
|
|
784
|
-
for (const { name, value, isPublic } of readonlyVars) {
|
|
821
|
+
for (const { name, value, isPublic, loc } of readonlyVars) {
|
|
785
822
|
const val = this.generateInComponent(value, 'value');
|
|
786
|
-
|
|
823
|
+
pushLine(isPublic
|
|
787
824
|
? ` this.${name} = props.${name} ?? ${val};`
|
|
788
|
-
: ` this.${name} = ${val}
|
|
825
|
+
: ` this.${name} = ${val};`, loc);
|
|
789
826
|
}
|
|
790
827
|
|
|
791
828
|
// Accepted vars (from ancestor context via getContext)
|
|
792
829
|
for (const name of acceptedVars) {
|
|
793
|
-
|
|
830
|
+
pushPlain(` this.${name} = getContext('${name}');`);
|
|
794
831
|
}
|
|
795
832
|
|
|
796
833
|
// State variables (__state handles signal passthrough)
|
|
797
|
-
for (const { name, value, isPublic } of stateVars) {
|
|
834
|
+
for (const { name, value, isPublic, loc } of stateVars) {
|
|
798
835
|
const val = this.generateInComponent(value, 'value');
|
|
799
|
-
|
|
836
|
+
pushLine(isPublic
|
|
800
837
|
? ` this.${name} = __state(props.__bind_${name}__ ?? props.${name} ?? ${val});`
|
|
801
|
-
: ` this.${name} = __state(${val})
|
|
838
|
+
: ` this.${name} = __state(${val});`, loc);
|
|
802
839
|
}
|
|
803
840
|
|
|
804
841
|
// Computed (derived)
|
|
805
|
-
for (const { name, expr } of derivedVars) {
|
|
842
|
+
for (const { name, expr, loc } of derivedVars) {
|
|
806
843
|
if (this.is(expr, 'block')) {
|
|
807
844
|
const transformed = this.transformComponentMembers(expr);
|
|
808
845
|
const body = this.generateFunctionBody(transformed);
|
|
809
|
-
|
|
846
|
+
pushLine(` this.${name} = __computed(() => ${body});`, loc);
|
|
810
847
|
} else {
|
|
811
848
|
const val = this.generateInComponent(expr, 'value');
|
|
812
|
-
|
|
849
|
+
pushLine(` this.${name} = __computed(() => ${val});`, loc);
|
|
813
850
|
}
|
|
814
851
|
}
|
|
815
852
|
|
|
816
853
|
// Offered vars (share with descendants via setContext — after all members are initialized)
|
|
817
854
|
for (const name of offeredVars) {
|
|
818
|
-
|
|
855
|
+
pushPlain(` setContext('${name}', this.${name});`);
|
|
819
856
|
}
|
|
820
857
|
|
|
821
858
|
// Effects
|
|
@@ -825,73 +862,81 @@ export function installComponentSupport(CodeGenerator, Lexer) {
|
|
|
825
862
|
if (this.is(effectBody, 'block')) {
|
|
826
863
|
const transformed = this.transformComponentMembers(effectBody);
|
|
827
864
|
const body = this.generateFunctionBody(transformed, [], true);
|
|
828
|
-
|
|
865
|
+
pushLine(` __effect(${isAsync}() => ${body});`, effect.loc);
|
|
829
866
|
} else {
|
|
830
867
|
const effectCode = this.generateInComponent(effectBody, 'value');
|
|
831
|
-
|
|
868
|
+
pushLine(` __effect(${isAsync}() => { ${effectCode}; });`, effect.loc);
|
|
832
869
|
}
|
|
833
870
|
}
|
|
834
871
|
|
|
835
|
-
|
|
872
|
+
pushPlain(' }');
|
|
836
873
|
|
|
837
874
|
// --- Methods ---
|
|
838
|
-
for (const { name, func } of methods) {
|
|
875
|
+
for (const { name, func, loc } of methods) {
|
|
839
876
|
if (Array.isArray(func) && (func[0] === '->' || func[0] === '=>')) {
|
|
840
877
|
const [, params, methodBody] = func;
|
|
841
878
|
const paramStr = Array.isArray(params) ? params.map(p => this.formatParam(p)).join(', ') : '';
|
|
842
879
|
const transformed = this.reactiveMembers ? this.transformComponentMembers(methodBody) : methodBody;
|
|
843
880
|
const isAsync = this.containsAwait(methodBody);
|
|
844
881
|
const bodyCode = this.generateFunctionBody(transformed, params || []);
|
|
845
|
-
|
|
882
|
+
pushLine(` ${isAsync ? 'async ' : ''}${name}(${paramStr}) ${bodyCode}`, loc);
|
|
846
883
|
}
|
|
847
884
|
}
|
|
848
885
|
|
|
849
886
|
// --- Lifecycle hooks ---
|
|
850
|
-
for (const { name, value } of lifecycleHooks) {
|
|
887
|
+
for (const { name, value, loc } of lifecycleHooks) {
|
|
851
888
|
if (Array.isArray(value) && (value[0] === '->' || value[0] === '=>')) {
|
|
852
889
|
const [, params, hookBody] = value;
|
|
853
890
|
const paramStr = Array.isArray(params) ? params.map(p => this.formatParam(p)).join(', ') : '';
|
|
854
891
|
const transformed = this.reactiveMembers ? this.transformComponentMembers(hookBody) : hookBody;
|
|
855
892
|
const isAsync = this.containsAwait(hookBody);
|
|
856
893
|
const bodyCode = this.generateFunctionBody(transformed, params || []);
|
|
857
|
-
|
|
894
|
+
pushLine(` ${isAsync ? 'async ' : ''}${name}(${paramStr}) ${bodyCode}`, loc);
|
|
858
895
|
}
|
|
859
896
|
}
|
|
860
897
|
|
|
861
898
|
// --- Render block (fine-grained) ---
|
|
862
|
-
if (renderBlock
|
|
899
|
+
if (renderBlock) {
|
|
863
900
|
const renderBody = renderBlock[1];
|
|
864
901
|
const result = this.buildRender(renderBody);
|
|
865
902
|
|
|
866
|
-
if (result.blockFactories.length > 0) {
|
|
903
|
+
if (!this.options.lspMode && result.blockFactories.length > 0) {
|
|
867
904
|
blockFactoriesCode = result.blockFactories.join('\n\n') + '\n\n';
|
|
868
905
|
}
|
|
869
906
|
|
|
870
|
-
|
|
907
|
+
pushLine(' _create() {', renderBlock.loc);
|
|
871
908
|
for (const line of result.createLines) {
|
|
872
|
-
|
|
909
|
+
pushPlain(` ${line}`);
|
|
873
910
|
}
|
|
874
|
-
|
|
875
|
-
|
|
911
|
+
pushPlain(` return ${result.rootVar};`);
|
|
912
|
+
pushPlain(' }');
|
|
876
913
|
|
|
877
|
-
if (result.setupLines.length > 0) {
|
|
878
|
-
|
|
914
|
+
if (!this.options.lspMode && result.setupLines.length > 0) {
|
|
915
|
+
pushPlain(' _setup() {');
|
|
879
916
|
for (const line of result.setupLines) {
|
|
880
|
-
|
|
917
|
+
pushPlain(` ${line}`);
|
|
881
918
|
}
|
|
882
|
-
|
|
919
|
+
pushPlain(' }');
|
|
883
920
|
}
|
|
884
921
|
}
|
|
885
922
|
|
|
886
|
-
|
|
923
|
+
pushPlain('}');
|
|
887
924
|
|
|
888
925
|
// Restore context
|
|
889
926
|
this.componentMembers = prevComponentMembers;
|
|
890
927
|
this.reactiveMembers = prevReactiveMembers;
|
|
891
928
|
this._autoEventHandlers = prevAutoEventHandlers;
|
|
892
929
|
|
|
930
|
+
// Store line-level source mappings for the parent statement entry
|
|
931
|
+
if (lineLocs.length > 0) {
|
|
932
|
+
this._pendingComponentLineLocs = lineLocs;
|
|
933
|
+
}
|
|
934
|
+
|
|
893
935
|
// If block factories exist, wrap in IIFE so they're in scope
|
|
894
936
|
if (blockFactoriesCode) {
|
|
937
|
+
// Adjust lineOffsets for the IIFE wrapper + block factories prefix
|
|
938
|
+
const prefixLines = blockFactoriesCode.split('\n').length;
|
|
939
|
+
for (const entry of lineLocs) entry.lineOffset += prefixLines;
|
|
895
940
|
return `(() => {\n${blockFactoriesCode}return ${lines.join('\n')};\n})()`;
|
|
896
941
|
}
|
|
897
942
|
|
package/src/typecheck.js
CHANGED
|
@@ -41,6 +41,8 @@ export const SKIP_CODES = new Set([
|
|
|
41
41
|
2307, // Cannot find module
|
|
42
42
|
2393, // Duplicate function implementation
|
|
43
43
|
2451, // Cannot redeclare block-scoped variable
|
|
44
|
+
2554, // Expected N arguments but got M (generated event handler wrappers pass event arg)
|
|
45
|
+
7006, // Parameter implicitly has 'any' type (generated event callback params)
|
|
44
46
|
1064, // Return type of async function must be Promise
|
|
45
47
|
2582, // Cannot find name 'test' (test runner globals)
|
|
46
48
|
2593, // Cannot find name 'describe' (test runner globals)
|