tova 0.2.9 → 0.3.1
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/bin/tova.js +1404 -114
- package/package.json +3 -1
- package/src/analyzer/analyzer.js +882 -695
- package/src/analyzer/client-analyzer.js +191 -0
- package/src/analyzer/server-analyzer.js +467 -0
- package/src/analyzer/types.js +20 -4
- package/src/codegen/base-codegen.js +473 -111
- package/src/codegen/client-codegen.js +109 -46
- package/src/codegen/codegen.js +65 -5
- package/src/codegen/server-codegen.js +297 -38
- package/src/diagnostics/error-codes.js +255 -0
- package/src/diagnostics/formatter.js +150 -28
- package/src/docs/generator.js +390 -0
- package/src/lexer/lexer.js +306 -64
- package/src/lexer/tokens.js +19 -0
- package/src/lsp/server.js +935 -53
- package/src/parser/ast.js +81 -368
- package/src/parser/client-ast.js +138 -0
- package/src/parser/client-parser.js +504 -0
- package/src/parser/parser.js +492 -1056
- package/src/parser/server-ast.js +240 -0
- package/src/parser/server-parser.js +602 -0
- package/src/runtime/array-proto.js +32 -0
- package/src/runtime/embedded.js +1 -1
- package/src/runtime/reactivity.js +239 -42
- package/src/stdlib/advanced-collections.js +81 -0
- package/src/stdlib/inline.js +556 -13
- package/src/version.js +1 -1
package/src/parser/ast.js
CHANGED
|
@@ -77,9 +77,10 @@ export class LetDestructure {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
export class FunctionDeclaration {
|
|
80
|
-
constructor(name, params, body, returnType, loc, isAsync = false) {
|
|
80
|
+
constructor(name, params, body, returnType, loc, isAsync = false, typeParams = []) {
|
|
81
81
|
this.type = 'FunctionDeclaration';
|
|
82
82
|
this.name = name;
|
|
83
|
+
this.typeParams = typeParams; // Array of type parameter names (generics)
|
|
83
84
|
this.params = params; // Array of Parameter nodes
|
|
84
85
|
this.body = body; // BlockStatement or Expression (implicit return)
|
|
85
86
|
this.returnType = returnType; // optional type annotation
|
|
@@ -198,21 +199,34 @@ export class IfStatement {
|
|
|
198
199
|
}
|
|
199
200
|
|
|
200
201
|
export class ForStatement {
|
|
201
|
-
constructor(variable, iterable, body, elseBody, loc) {
|
|
202
|
+
constructor(variable, iterable, body, elseBody, loc, guard = null, label = null, isAsync = false) {
|
|
202
203
|
this.type = 'ForStatement';
|
|
203
204
|
this.variable = variable; // Identifier or destructure pattern
|
|
204
205
|
this.iterable = iterable; // Expression
|
|
205
206
|
this.body = body; // BlockStatement
|
|
206
207
|
this.elseBody = elseBody; // BlockStatement or null (for-else)
|
|
208
|
+
this.guard = guard; // Expression or null (when guard)
|
|
209
|
+
this.label = label; // string or null (for named loops)
|
|
210
|
+
this.isAsync = isAsync; // true for `async for x in stream`
|
|
207
211
|
this.loc = loc;
|
|
208
212
|
}
|
|
209
213
|
}
|
|
210
214
|
|
|
211
215
|
export class WhileStatement {
|
|
212
|
-
constructor(condition, body, loc) {
|
|
216
|
+
constructor(condition, body, loc, label = null) {
|
|
213
217
|
this.type = 'WhileStatement';
|
|
214
218
|
this.condition = condition;
|
|
215
219
|
this.body = body;
|
|
220
|
+
this.label = label; // string or null (for named loops)
|
|
221
|
+
this.loc = loc;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export class LoopStatement {
|
|
226
|
+
constructor(body, label, loc) {
|
|
227
|
+
this.type = 'LoopStatement';
|
|
228
|
+
this.body = body; // BlockStatement
|
|
229
|
+
this.label = label; // string or null (for named loops)
|
|
216
230
|
this.loc = loc;
|
|
217
231
|
}
|
|
218
232
|
}
|
|
@@ -240,15 +254,17 @@ export class TryCatchStatement {
|
|
|
240
254
|
}
|
|
241
255
|
|
|
242
256
|
export class BreakStatement {
|
|
243
|
-
constructor(loc) {
|
|
257
|
+
constructor(loc, label = null) {
|
|
244
258
|
this.type = 'BreakStatement';
|
|
259
|
+
this.label = label; // string or null (for named break)
|
|
245
260
|
this.loc = loc;
|
|
246
261
|
}
|
|
247
262
|
}
|
|
248
263
|
|
|
249
264
|
export class ContinueStatement {
|
|
250
|
-
constructor(loc) {
|
|
265
|
+
constructor(loc, label = null) {
|
|
251
266
|
this.type = 'ContinueStatement';
|
|
267
|
+
this.label = label; // string or null (for named continue)
|
|
252
268
|
this.loc = loc;
|
|
253
269
|
}
|
|
254
270
|
}
|
|
@@ -521,6 +537,16 @@ export class DictComprehension {
|
|
|
521
537
|
}
|
|
522
538
|
}
|
|
523
539
|
|
|
540
|
+
export class IsExpression {
|
|
541
|
+
constructor(value, typeName, negated, loc) {
|
|
542
|
+
this.type = 'IsExpression';
|
|
543
|
+
this.value = value;
|
|
544
|
+
this.typeName = typeName; // string: "String", "Int", "Nil", etc.
|
|
545
|
+
this.negated = negated; // true for "is not"
|
|
546
|
+
this.loc = loc;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
524
550
|
export class MembershipExpression {
|
|
525
551
|
constructor(value, collection, negated, loc) {
|
|
526
552
|
this.type = 'MembershipExpression';
|
|
@@ -630,368 +656,49 @@ export class RangePattern {
|
|
|
630
656
|
}
|
|
631
657
|
|
|
632
658
|
// ============================================================
|
|
633
|
-
// Client-specific nodes
|
|
659
|
+
// Client-specific nodes (lazy-loaded from client-ast.js, re-exported for backward compat)
|
|
634
660
|
// ============================================================
|
|
635
661
|
|
|
636
|
-
export
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
this.loc = loc;
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
export class ComputedDeclaration {
|
|
647
|
-
constructor(name, expression, loc) {
|
|
648
|
-
this.type = 'ComputedDeclaration';
|
|
649
|
-
this.name = name;
|
|
650
|
-
this.expression = expression;
|
|
651
|
-
this.loc = loc;
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
export class EffectDeclaration {
|
|
656
|
-
constructor(body, loc) {
|
|
657
|
-
this.type = 'EffectDeclaration';
|
|
658
|
-
this.body = body;
|
|
659
|
-
this.loc = loc;
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
export class ComponentDeclaration {
|
|
664
|
-
constructor(name, params, body, loc) {
|
|
665
|
-
this.type = 'ComponentDeclaration';
|
|
666
|
-
this.name = name;
|
|
667
|
-
this.params = params;
|
|
668
|
-
this.body = body; // Array of JSX elements and statements
|
|
669
|
-
this.loc = loc;
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
export class ComponentStyleBlock {
|
|
674
|
-
constructor(css, loc) {
|
|
675
|
-
this.type = 'ComponentStyleBlock';
|
|
676
|
-
this.css = css; // raw CSS string
|
|
677
|
-
this.loc = loc;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
export class StoreDeclaration {
|
|
682
|
-
constructor(name, body, loc) {
|
|
683
|
-
this.type = 'StoreDeclaration';
|
|
684
|
-
this.name = name; // e.g. "TodoStore"
|
|
685
|
-
this.body = body; // Array of StateDeclaration, ComputedDeclaration, FunctionDeclaration
|
|
686
|
-
this.loc = loc;
|
|
687
|
-
}
|
|
688
|
-
}
|
|
662
|
+
export {
|
|
663
|
+
StateDeclaration, ComputedDeclaration, EffectDeclaration,
|
|
664
|
+
ComponentDeclaration, ComponentStyleBlock, StoreDeclaration,
|
|
665
|
+
JSXElement, JSXAttribute, JSXSpreadAttribute, JSXFragment,
|
|
666
|
+
JSXText, JSXExpression, JSXFor, JSXIf,
|
|
667
|
+
} from './client-ast.js';
|
|
689
668
|
|
|
690
669
|
// ============================================================
|
|
691
|
-
//
|
|
670
|
+
// Server-specific nodes (lazy-loaded from server-ast.js, re-exported for backward compat)
|
|
692
671
|
// ============================================================
|
|
693
672
|
|
|
694
|
-
export
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
export class JSXAttribute {
|
|
706
|
-
constructor(name, value, loc) {
|
|
707
|
-
this.type = 'JSXAttribute';
|
|
708
|
-
this.name = name; // string (e.g., "class", "on:click")
|
|
709
|
-
this.value = value; // Expression or string
|
|
710
|
-
this.loc = loc;
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
export class JSXSpreadAttribute {
|
|
715
|
-
constructor(expression, loc) {
|
|
716
|
-
this.type = 'JSXSpreadAttribute';
|
|
717
|
-
this.expression = expression;
|
|
718
|
-
this.loc = loc;
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
export class JSXText {
|
|
723
|
-
constructor(value, loc) {
|
|
724
|
-
this.type = 'JSXText';
|
|
725
|
-
this.value = value;
|
|
726
|
-
this.loc = loc;
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
export class JSXExpression {
|
|
731
|
-
constructor(expression, loc) {
|
|
732
|
-
this.type = 'JSXExpression';
|
|
733
|
-
this.expression = expression;
|
|
734
|
-
this.loc = loc;
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
export class JSXFor {
|
|
739
|
-
constructor(variable, iterable, body, loc, keyExpr = null) {
|
|
740
|
-
this.type = 'JSXFor';
|
|
741
|
-
this.variable = variable;
|
|
742
|
-
this.iterable = iterable;
|
|
743
|
-
this.body = body;
|
|
744
|
-
this.keyExpr = keyExpr; // optional key expression for keyed reconciliation
|
|
745
|
-
this.loc = loc;
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
export class JSXIf {
|
|
750
|
-
constructor(condition, consequent, alternate, loc, alternates = []) {
|
|
751
|
-
this.type = 'JSXIf';
|
|
752
|
-
this.condition = condition;
|
|
753
|
-
this.consequent = consequent;
|
|
754
|
-
this.alternates = alternates; // Array of { condition, body } for elif chains
|
|
755
|
-
this.alternate = alternate; // else body (or null)
|
|
756
|
-
this.loc = loc;
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
// ============================================================
|
|
761
|
-
// Server-specific nodes
|
|
762
|
-
// ============================================================
|
|
763
|
-
|
|
764
|
-
export class RouteDeclaration {
|
|
765
|
-
constructor(method, path, handler, loc, decorators = []) {
|
|
766
|
-
this.type = 'RouteDeclaration';
|
|
767
|
-
this.method = method; // GET, POST, PUT, DELETE, PATCH
|
|
768
|
-
this.path = path; // string literal
|
|
769
|
-
this.handler = handler; // Identifier or FunctionDeclaration
|
|
770
|
-
this.decorators = decorators; // Array of { name, args } for "with auth, role("admin")"
|
|
771
|
-
this.loc = loc;
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
export class MiddlewareDeclaration {
|
|
776
|
-
constructor(name, params, body, loc) {
|
|
777
|
-
this.type = 'MiddlewareDeclaration';
|
|
778
|
-
this.name = name;
|
|
779
|
-
this.params = params; // Array of Parameter nodes (req, next)
|
|
780
|
-
this.body = body; // BlockStatement
|
|
781
|
-
this.loc = loc;
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
export class HealthCheckDeclaration {
|
|
786
|
-
constructor(path, loc) {
|
|
787
|
-
this.type = 'HealthCheckDeclaration';
|
|
788
|
-
this.path = path; // string literal, e.g. "/health"
|
|
789
|
-
this.loc = loc;
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
export class CorsDeclaration {
|
|
794
|
-
constructor(config, loc) {
|
|
795
|
-
this.type = 'CorsDeclaration';
|
|
796
|
-
this.config = config; // { origins: ArrayLiteral, methods: ArrayLiteral, headers: ArrayLiteral }
|
|
797
|
-
this.loc = loc;
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
export class ErrorHandlerDeclaration {
|
|
802
|
-
constructor(params, body, loc) {
|
|
803
|
-
this.type = 'ErrorHandlerDeclaration';
|
|
804
|
-
this.params = params; // Array of Parameter nodes (err, req)
|
|
805
|
-
this.body = body; // BlockStatement
|
|
806
|
-
this.loc = loc;
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
export class WebSocketDeclaration {
|
|
811
|
-
constructor(handlers, loc, config = null) {
|
|
812
|
-
this.type = 'WebSocketDeclaration';
|
|
813
|
-
this.handlers = handlers; // { on_open, on_message, on_close, on_error } — each is { params, body } or null
|
|
814
|
-
this.config = config; // { auth: expression } or null
|
|
815
|
-
this.loc = loc;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
export class StaticDeclaration {
|
|
820
|
-
constructor(path, dir, loc, fallback = null) {
|
|
821
|
-
this.type = 'StaticDeclaration';
|
|
822
|
-
this.path = path; // URL prefix, e.g. "/public"
|
|
823
|
-
this.dir = dir; // directory path, e.g. "./public"
|
|
824
|
-
this.fallback = fallback; // fallback file, e.g. "index.html"
|
|
825
|
-
this.loc = loc;
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
export class DiscoverDeclaration {
|
|
830
|
-
constructor(peerName, urlExpression, loc, config = null) {
|
|
831
|
-
this.type = 'DiscoverDeclaration';
|
|
832
|
-
this.peerName = peerName; // string — the peer server name
|
|
833
|
-
this.urlExpression = urlExpression; // Expression — the URL
|
|
834
|
-
this.config = config; // { threshold, timeout } or null
|
|
835
|
-
this.loc = loc;
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
export class AuthDeclaration {
|
|
840
|
-
constructor(config, loc) {
|
|
841
|
-
this.type = 'AuthDeclaration';
|
|
842
|
-
this.config = config; // { type, secret, ... } object config
|
|
843
|
-
this.loc = loc;
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
export class MaxBodyDeclaration {
|
|
848
|
-
constructor(limit, loc) {
|
|
849
|
-
this.type = 'MaxBodyDeclaration';
|
|
850
|
-
this.limit = limit; // Expression — max body size in bytes
|
|
851
|
-
this.loc = loc;
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
export class RouteGroupDeclaration {
|
|
856
|
-
constructor(prefix, body, loc) {
|
|
857
|
-
this.type = 'RouteGroupDeclaration';
|
|
858
|
-
this.prefix = prefix; // string — URL prefix, e.g. "/api/v1"
|
|
859
|
-
this.body = body; // Array of server statements
|
|
860
|
-
this.loc = loc;
|
|
861
|
-
}
|
|
862
|
-
}
|
|
673
|
+
export {
|
|
674
|
+
RouteDeclaration, MiddlewareDeclaration, HealthCheckDeclaration,
|
|
675
|
+
CorsDeclaration, ErrorHandlerDeclaration, WebSocketDeclaration,
|
|
676
|
+
StaticDeclaration, DiscoverDeclaration, AuthDeclaration,
|
|
677
|
+
MaxBodyDeclaration, RouteGroupDeclaration, RateLimitDeclaration,
|
|
678
|
+
LifecycleHookDeclaration, SubscribeDeclaration, EnvDeclaration,
|
|
679
|
+
ScheduleDeclaration, UploadDeclaration, SessionDeclaration,
|
|
680
|
+
DbDeclaration, TlsDeclaration, CompressionDeclaration,
|
|
681
|
+
BackgroundJobDeclaration, CacheDeclaration, SseDeclaration,
|
|
682
|
+
ModelDeclaration, AiConfigDeclaration,
|
|
683
|
+
} from './server-ast.js';
|
|
863
684
|
|
|
864
|
-
export class
|
|
865
|
-
constructor(
|
|
866
|
-
this.type = '
|
|
867
|
-
this.
|
|
868
|
-
this.
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
export class LifecycleHookDeclaration {
|
|
873
|
-
constructor(hook, params, body, loc) {
|
|
874
|
-
this.type = 'LifecycleHookDeclaration';
|
|
875
|
-
this.hook = hook; // "start" or "stop"
|
|
876
|
-
this.params = params;
|
|
877
|
-
this.body = body;
|
|
878
|
-
this.loc = loc;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
export class SubscribeDeclaration {
|
|
883
|
-
constructor(event, params, body, loc) {
|
|
884
|
-
this.type = 'SubscribeDeclaration';
|
|
885
|
-
this.event = event; // string — event name
|
|
886
|
-
this.params = params;
|
|
887
|
-
this.body = body;
|
|
888
|
-
this.loc = loc;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
export class EnvDeclaration {
|
|
893
|
-
constructor(name, typeAnnotation, defaultValue, loc) {
|
|
894
|
-
this.type = 'EnvDeclaration';
|
|
895
|
-
this.name = name;
|
|
896
|
-
this.typeAnnotation = typeAnnotation;
|
|
897
|
-
this.defaultValue = defaultValue;
|
|
898
|
-
this.loc = loc;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
export class ScheduleDeclaration {
|
|
903
|
-
constructor(pattern, name, params, body, loc) {
|
|
904
|
-
this.type = 'ScheduleDeclaration';
|
|
905
|
-
this.pattern = pattern; // string — interval or cron pattern
|
|
906
|
-
this.name = name; // optional function name
|
|
907
|
-
this.params = params;
|
|
908
|
-
this.body = body;
|
|
909
|
-
this.loc = loc;
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
export class UploadDeclaration {
|
|
914
|
-
constructor(config, loc) {
|
|
915
|
-
this.type = 'UploadDeclaration';
|
|
916
|
-
this.config = config; // { max_size, allowed_types, ... }
|
|
917
|
-
this.loc = loc;
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
export class SessionDeclaration {
|
|
922
|
-
constructor(config, loc) {
|
|
923
|
-
this.type = 'SessionDeclaration';
|
|
924
|
-
this.config = config; // { secret, max_age, cookie_name, ... }
|
|
925
|
-
this.loc = loc;
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
export class DbDeclaration {
|
|
930
|
-
constructor(config, loc) {
|
|
931
|
-
this.type = 'DbDeclaration';
|
|
932
|
-
this.config = config; // { path, wal, ... }
|
|
933
|
-
this.loc = loc;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
export class TlsDeclaration {
|
|
938
|
-
constructor(config, loc) {
|
|
939
|
-
this.type = 'TlsDeclaration';
|
|
940
|
-
this.config = config; // { cert, key, ... }
|
|
941
|
-
this.loc = loc;
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
export class CompressionDeclaration {
|
|
946
|
-
constructor(config, loc) {
|
|
947
|
-
this.type = 'CompressionDeclaration';
|
|
948
|
-
this.config = config; // { enabled, min_size, ... }
|
|
949
|
-
this.loc = loc;
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
export class BackgroundJobDeclaration {
|
|
954
|
-
constructor(name, params, body, loc) {
|
|
955
|
-
this.type = 'BackgroundJobDeclaration';
|
|
956
|
-
this.name = name;
|
|
957
|
-
this.params = params;
|
|
958
|
-
this.body = body;
|
|
959
|
-
this.loc = loc;
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
export class CacheDeclaration {
|
|
964
|
-
constructor(config, loc) {
|
|
965
|
-
this.type = 'CacheDeclaration';
|
|
966
|
-
this.config = config; // { max_age, stale_while_revalidate, ... }
|
|
967
|
-
this.loc = loc;
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
export class SseDeclaration {
|
|
972
|
-
constructor(path, params, body, loc) {
|
|
973
|
-
this.type = 'SseDeclaration';
|
|
974
|
-
this.path = path; // string — SSE endpoint path
|
|
975
|
-
this.params = params; // Array of Parameter nodes
|
|
976
|
-
this.body = body; // BlockStatement
|
|
977
|
-
this.loc = loc;
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
export class ModelDeclaration {
|
|
982
|
-
constructor(name, config, loc) {
|
|
983
|
-
this.type = 'ModelDeclaration';
|
|
984
|
-
this.name = name; // string — type name to generate CRUD for
|
|
985
|
-
this.config = config; // { table, timestamps, ... } or null
|
|
685
|
+
export class TestBlock {
|
|
686
|
+
constructor(name, body, loc, options = {}) {
|
|
687
|
+
this.type = 'TestBlock';
|
|
688
|
+
this.name = name; // optional string name
|
|
689
|
+
this.body = body; // Array of statements
|
|
690
|
+
this.timeout = options.timeout || null; // optional timeout in ms
|
|
691
|
+
this.beforeEach = options.beforeEach || null; // Array of statements or null
|
|
692
|
+
this.afterEach = options.afterEach || null; // Array of statements or null
|
|
986
693
|
this.loc = loc;
|
|
987
694
|
}
|
|
988
695
|
}
|
|
989
696
|
|
|
990
|
-
export class
|
|
697
|
+
export class BenchBlock {
|
|
991
698
|
constructor(name, body, loc) {
|
|
992
|
-
this.type = '
|
|
699
|
+
this.type = 'BenchBlock';
|
|
993
700
|
this.name = name; // optional string name
|
|
994
|
-
this.body = body; // Array of statements
|
|
701
|
+
this.body = body; // Array of statements (expressions to benchmark)
|
|
995
702
|
this.loc = loc;
|
|
996
703
|
}
|
|
997
704
|
}
|
|
@@ -1041,6 +748,14 @@ export class FunctionTypeAnnotation {
|
|
|
1041
748
|
}
|
|
1042
749
|
}
|
|
1043
750
|
|
|
751
|
+
export class UnionTypeAnnotation {
|
|
752
|
+
constructor(members, loc) {
|
|
753
|
+
this.type = 'UnionTypeAnnotation';
|
|
754
|
+
this.members = members; // Array of TypeAnnotation nodes
|
|
755
|
+
this.loc = loc;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
1044
759
|
// ============================================================
|
|
1045
760
|
// Impl blocks
|
|
1046
761
|
// ============================================================
|
|
@@ -1073,9 +788,10 @@ export class TraitDeclaration {
|
|
|
1073
788
|
// ============================================================
|
|
1074
789
|
|
|
1075
790
|
export class TypeAlias {
|
|
1076
|
-
constructor(name, typeExpr, loc) {
|
|
791
|
+
constructor(name, typeParams, typeExpr, loc) {
|
|
1077
792
|
this.type = 'TypeAlias';
|
|
1078
793
|
this.name = name;
|
|
794
|
+
this.typeParams = typeParams; // Array of type parameter names (for generics)
|
|
1079
795
|
this.typeExpr = typeExpr; // TypeAnnotation
|
|
1080
796
|
this.loc = loc;
|
|
1081
797
|
}
|
|
@@ -1085,6 +801,16 @@ export class TypeAlias {
|
|
|
1085
801
|
// Defer statement
|
|
1086
802
|
// ============================================================
|
|
1087
803
|
|
|
804
|
+
export class WithStatement {
|
|
805
|
+
constructor(expression, name, body, loc) {
|
|
806
|
+
this.type = 'WithStatement';
|
|
807
|
+
this.expression = expression; // resource expression
|
|
808
|
+
this.name = name; // binding name (string)
|
|
809
|
+
this.body = body; // BlockStatement
|
|
810
|
+
this.loc = loc;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
1088
814
|
export class DeferStatement {
|
|
1089
815
|
constructor(body, loc) {
|
|
1090
816
|
this.type = 'DeferStatement';
|
|
@@ -1212,19 +938,6 @@ export class RefreshPolicy {
|
|
|
1212
938
|
}
|
|
1213
939
|
}
|
|
1214
940
|
|
|
1215
|
-
// ============================================================
|
|
1216
|
-
// AI configuration
|
|
1217
|
-
// ============================================================
|
|
1218
|
-
|
|
1219
|
-
export class AiConfigDeclaration {
|
|
1220
|
-
constructor(name, config, loc) {
|
|
1221
|
-
this.type = 'AiConfigDeclaration';
|
|
1222
|
-
this.name = name; // optional string name (null for default)
|
|
1223
|
-
this.config = config; // key-value config object
|
|
1224
|
-
this.loc = loc;
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
941
|
// ============================================================
|
|
1229
942
|
// Refinement types
|
|
1230
943
|
// ============================================================
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Client-specific AST Node definitions for the Tova language
|
|
2
|
+
// Extracted from ast.js for lazy loading — only loaded when client { } blocks are used.
|
|
3
|
+
|
|
4
|
+
// ============================================================
|
|
5
|
+
// Client-specific nodes
|
|
6
|
+
// ============================================================
|
|
7
|
+
|
|
8
|
+
export class StateDeclaration {
|
|
9
|
+
constructor(name, typeAnnotation, initialValue, loc) {
|
|
10
|
+
this.type = 'StateDeclaration';
|
|
11
|
+
this.name = name;
|
|
12
|
+
this.typeAnnotation = typeAnnotation;
|
|
13
|
+
this.initialValue = initialValue;
|
|
14
|
+
this.loc = loc;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class ComputedDeclaration {
|
|
19
|
+
constructor(name, expression, loc) {
|
|
20
|
+
this.type = 'ComputedDeclaration';
|
|
21
|
+
this.name = name;
|
|
22
|
+
this.expression = expression;
|
|
23
|
+
this.loc = loc;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class EffectDeclaration {
|
|
28
|
+
constructor(body, loc) {
|
|
29
|
+
this.type = 'EffectDeclaration';
|
|
30
|
+
this.body = body;
|
|
31
|
+
this.loc = loc;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class ComponentDeclaration {
|
|
36
|
+
constructor(name, params, body, loc) {
|
|
37
|
+
this.type = 'ComponentDeclaration';
|
|
38
|
+
this.name = name;
|
|
39
|
+
this.params = params;
|
|
40
|
+
this.body = body; // Array of JSX elements and statements
|
|
41
|
+
this.loc = loc;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class ComponentStyleBlock {
|
|
46
|
+
constructor(css, loc) {
|
|
47
|
+
this.type = 'ComponentStyleBlock';
|
|
48
|
+
this.css = css; // raw CSS string
|
|
49
|
+
this.loc = loc;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export class StoreDeclaration {
|
|
54
|
+
constructor(name, body, loc) {
|
|
55
|
+
this.type = 'StoreDeclaration';
|
|
56
|
+
this.name = name; // e.g. "TodoStore"
|
|
57
|
+
this.body = body; // Array of StateDeclaration, ComputedDeclaration, FunctionDeclaration
|
|
58
|
+
this.loc = loc;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ============================================================
|
|
63
|
+
// JSX-like nodes
|
|
64
|
+
// ============================================================
|
|
65
|
+
|
|
66
|
+
export class JSXElement {
|
|
67
|
+
constructor(tag, attributes, children, selfClosing, loc) {
|
|
68
|
+
this.type = 'JSXElement';
|
|
69
|
+
this.tag = tag;
|
|
70
|
+
this.attributes = attributes; // Array of JSXAttribute
|
|
71
|
+
this.children = children; // Array of JSXElement, JSXText, JSXExpression
|
|
72
|
+
this.selfClosing = selfClosing;
|
|
73
|
+
this.loc = loc;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export class JSXAttribute {
|
|
78
|
+
constructor(name, value, loc) {
|
|
79
|
+
this.type = 'JSXAttribute';
|
|
80
|
+
this.name = name; // string (e.g., "class", "on:click")
|
|
81
|
+
this.value = value; // Expression or string
|
|
82
|
+
this.loc = loc;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export class JSXSpreadAttribute {
|
|
87
|
+
constructor(expression, loc) {
|
|
88
|
+
this.type = 'JSXSpreadAttribute';
|
|
89
|
+
this.expression = expression;
|
|
90
|
+
this.loc = loc;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export class JSXFragment {
|
|
95
|
+
constructor(children, loc) {
|
|
96
|
+
this.type = 'JSXFragment';
|
|
97
|
+
this.children = children; // Array of JSXElement, JSXText, JSXExpression, etc.
|
|
98
|
+
this.loc = loc;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export class JSXText {
|
|
103
|
+
constructor(value, loc) {
|
|
104
|
+
this.type = 'JSXText';
|
|
105
|
+
this.value = value;
|
|
106
|
+
this.loc = loc;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export class JSXExpression {
|
|
111
|
+
constructor(expression, loc) {
|
|
112
|
+
this.type = 'JSXExpression';
|
|
113
|
+
this.expression = expression;
|
|
114
|
+
this.loc = loc;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export class JSXFor {
|
|
119
|
+
constructor(variable, iterable, body, loc, keyExpr = null) {
|
|
120
|
+
this.type = 'JSXFor';
|
|
121
|
+
this.variable = variable;
|
|
122
|
+
this.iterable = iterable;
|
|
123
|
+
this.body = body;
|
|
124
|
+
this.keyExpr = keyExpr; // optional key expression for keyed reconciliation
|
|
125
|
+
this.loc = loc;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export class JSXIf {
|
|
130
|
+
constructor(condition, consequent, alternate, loc, alternates = []) {
|
|
131
|
+
this.type = 'JSXIf';
|
|
132
|
+
this.condition = condition;
|
|
133
|
+
this.consequent = consequent;
|
|
134
|
+
this.alternates = alternates; // Array of { condition, body } for elif chains
|
|
135
|
+
this.alternate = alternate; // else body (or null)
|
|
136
|
+
this.loc = loc;
|
|
137
|
+
}
|
|
138
|
+
}
|