@@ -14,6 +14,7 @@ import polymod.hscript._internal.PolymodClassDeclEx.PolymodStaticClassReference;
14
14
*/
15
15
@:access (polymod.hscript._internal. PolymodScriptClass )
16
16
@:access (polymod.hscript._internal. PolymodAbstractScriptClass )
17
+ @:access (polymod.hscript._internal. PolymodEnum )
17
18
class PolymodInterpEx extends Interp
18
19
{
19
20
var targetCls : Class <Dynamic >;
@@ -194,6 +195,53 @@ class PolymodInterpEx extends Interp
194
195
return _scriptClassDescriptors .get (name );
195
196
}
196
197
198
+ private static var _scriptEnumDescriptors : Map <String , PolymodEnumDeclEx > = new Map <String , PolymodEnumDeclEx >();
199
+
200
+ private static function registerScriptEnum (e : PolymodEnumDeclEx )
201
+ {
202
+ var name = e .name ;
203
+ if (e .pkg != null )
204
+ {
205
+ name = e .pkg .join (" ." ) + " ." + name ;
206
+ }
207
+
208
+ if (_scriptEnumDescriptors .exists (name )) {
209
+ Polymod .error (SCRIPT_ENUM_ALREADY_REGISTERED , ' An enum with the fully qualified name " $name " has already been defined. Please change the enum name to ensure a unique name.' );
210
+ return ;
211
+ } else {
212
+ Polymod .debug (' Registering enum $name ' );
213
+ _scriptEnumDescriptors .set (name , e );
214
+ }
215
+ }
216
+
217
+ public function clearScriptEnumDescriptors (): Void {
218
+ // Clear the script enum descriptors.
219
+ _scriptEnumDescriptors .clear ();
220
+
221
+ // Also destroy local variable scope.
222
+ this .resetVariables ();
223
+ }
224
+
225
+ private static function validateImports (): Void
226
+ {
227
+ for (cls in _scriptClassDescriptors )
228
+ {
229
+ var clsPath = cls .pkg != null ? (cls .pkg .join (" ." ) + " ." ) : " " ;
230
+ clsPath + = cls .name ;
231
+
232
+ for (key => imp in cls .importsToValidate )
233
+ {
234
+ if (_scriptEnumDescriptors .exists (imp .fullPath ))
235
+ {
236
+ cls .imports .set (key , imp );
237
+ continue ;
238
+ }
239
+
240
+ Polymod .error (SCRIPT_CLASS_MODULE_NOT_FOUND , ' Could not import ${imp .fullPath }' , clsPath );
241
+ }
242
+ }
243
+ }
244
+
197
245
override function setVar (id : String , v : Dynamic )
198
246
{
199
247
if (_proxy != null && _proxy .superClass != null )
@@ -463,6 +511,89 @@ class PolymodInterpEx extends Interp
463
511
// If there is a try/catch block, the error will be caught.
464
512
// If there is no try/catch block, the error will be reported.
465
513
errorEx (EScriptThrow (str ));
514
+
515
+ // Enums
516
+ case EField (e ,f ):
517
+ var name = getIdent (e );
518
+ name = getClassDecl ().imports .get (name )?. fullPath ?? name ;
519
+ if (name != null && _scriptEnumDescriptors .exists (name ))
520
+ {
521
+ return new PolymodEnum (_scriptEnumDescriptors .get (name ), f , []);
522
+ }
523
+ case ECall (e ,params ):
524
+ var args = new Array ();
525
+ for (p in params )
526
+ args .push (expr (p ));
527
+
528
+ switch (Tools .expr (e )) {
529
+ case EField (e ,f ):
530
+ var name = getIdent (e );
531
+ name = getClassDecl ().imports .get (name )?. fullPath ?? name ;
532
+ if (name != null && _scriptEnumDescriptors .exists (name ))
533
+ {
534
+ return new PolymodEnum (_scriptEnumDescriptors .get (name ), f , args );
535
+ }
536
+ default :
537
+ }
538
+ case ESwitch (e , cases , def ):
539
+ var val : Dynamic = expr (e );
540
+
541
+ if (Std .isOfType (val , PolymodEnum ))
542
+ {
543
+ var old : Int = declared .length ;
544
+ var match = false ;
545
+ for (c in cases )
546
+ {
547
+ for (v in c .values )
548
+ {
549
+ switch (Tools .expr (v ))
550
+ {
551
+ case ECall (e , params ):
552
+ switch (Tools .expr (e ))
553
+ {
554
+ case EField (_ , f ):
555
+ if (val ._value == f )
556
+ {
557
+ for (i => p in params )
558
+ {
559
+ switch (Tools .expr (p ))
560
+ {
561
+ case EIdent (n ):
562
+ declared .push ({
563
+ n : n ,
564
+ old : {r : locals .get (n )}
565
+ });
566
+ locals .set (n , {r : val ._args [i ]});
567
+ default :
568
+ }
569
+ }
570
+ match = true ;
571
+ break ;
572
+ }
573
+ default :
574
+ }
575
+ case EField (_ , f ):
576
+ if (val ._value == f )
577
+ {
578
+ match = true ;
579
+ break ;
580
+ }
581
+ default :
582
+ }
583
+ }
584
+ if (match )
585
+ {
586
+ val = expr (c .expr );
587
+ break ;
588
+ }
589
+ }
590
+ if (! match )
591
+ {
592
+ val = def == null ? null : expr (def );
593
+ }
594
+ restore (old );
595
+ return val ;
596
+ }
466
597
default :
467
598
// Do nothing.
468
599
}
@@ -601,6 +732,21 @@ class PolymodInterpEx extends Interp
601
732
return a ;
602
733
}
603
734
735
+ function getIdent (e : Expr ): Null <String > {
736
+ #if hscriptPos
737
+ switch (e .e )
738
+ {
739
+ #else
740
+ switch (e )
741
+ {
742
+ #end
743
+ case EIdent (v ):
744
+ return v ;
745
+ default :
746
+ return null ;
747
+ }
748
+ }
749
+
604
750
override function makeIterator (v : Dynamic ): Iterator <Dynamic >
605
751
{
606
752
if (v .iterator != null )
@@ -1255,6 +1401,7 @@ class PolymodInterpEx extends Interp
1255
1401
{
1256
1402
var pkg : Array <String > = null ;
1257
1403
var imports : Map <String , PolymodClassImport > = [];
1404
+ var importsToValidate : Map <String , PolymodClassImport > = [];
1258
1405
1259
1406
for (importPath in PolymodScriptClass .defaultImports .keys ())
1260
1407
{
@@ -1306,6 +1453,8 @@ class PolymodInterpEx extends Interp
1306
1453
importedClass .cls = PolymodScriptClass .abstractClassImpls .get (importedClass .fullPath );
1307
1454
trace (' RESOLVED ABSTRACT CLASS ${importedClass .fullPath } -> ${Type .getClassName (importedClass .cls )}' );
1308
1455
trace (Type .getClassFields (importedClass .cls ));
1456
+ } else if (_scriptEnumDescriptors .exists (importedClass .fullPath )) {
1457
+ // do nothing
1309
1458
} else {
1310
1459
var resultCls : Class <Dynamic > = Type .resolveClass (importedClass .fullPath );
1311
1460
@@ -1316,7 +1465,9 @@ class PolymodInterpEx extends Interp
1316
1465
1317
1466
// If the class is still not found, skip this import entirely.
1318
1467
if (resultCls == null && resultEnm == null ) {
1319
- Polymod .error (SCRIPT_CLASS_MODULE_NOT_FOUND , ' Could not import class ${importedClass .fullPath }' , origin );
1468
+ // Polymod.error(SCRIPT_CLASS_MODULE_NOT_FOUND, 'Could not import class ${importedClass.fullPath}', origin);
1469
+ // this could be a scripted class or enum that hasn't been registered yet
1470
+ importsToValidate .set (importedClass .name , importedClass );
1320
1471
continue ;
1321
1472
} else if (resultCls != null ) {
1322
1473
importedClass .cls = resultCls ;
@@ -1372,6 +1523,7 @@ class PolymodInterpEx extends Interp
1372
1523
1373
1524
var classDecl : PolymodClassDeclEx = {
1374
1525
imports : imports ,
1526
+ importsToValidate : importsToValidate ,
1375
1527
pkg : pkg ,
1376
1528
name : c .name ,
1377
1529
params : c .params ,
@@ -1384,6 +1536,25 @@ class PolymodInterpEx extends Interp
1384
1536
staticFields : staticFields ,
1385
1537
};
1386
1538
registerScriptClass (classDecl );
1539
+ case DEnum (e ):
1540
+ if (pkg != null )
1541
+ {
1542
+ imports .set (e .name , {
1543
+ name : e .name ,
1544
+ pkg : pkg ,
1545
+ fullPath : pkg .join (" ." ) + " ." + e .name ,
1546
+ cls : null ,
1547
+ enm : null ,
1548
+ });
1549
+ }
1550
+
1551
+ var enumDecl : PolymodEnumDeclEx = {
1552
+ pkg : pkg ,
1553
+ name : e .name ,
1554
+ fields : e .fields ,
1555
+ };
1556
+
1557
+ registerScriptEnum (enumDecl );
1387
1558
case DTypedef (_ ):
1388
1559
}
1389
1560
}
0 commit comments