17
17
*******************************************************************************/
18
18
package org .rascalmpl .interpreter .env ;
19
19
20
+ import java .util .ArrayList ;
20
21
import java .util .Collection ;
21
22
import java .util .Collections ;
22
23
import java .util .HashMap ;
23
24
import java .util .HashSet ;
25
+ import java .util .Iterator ;
24
26
import java .util .LinkedHashSet ;
25
27
import java .util .LinkedList ;
26
28
import java .util .List ;
27
29
import java .util .Map ;
30
+ import java .util .Map .Entry ;
31
+ import java .util .Optional ;
28
32
import java .util .Set ;
29
33
import java .util .function .Predicate ;
30
34
67
71
*/
68
72
public class ModuleEnvironment extends Environment {
69
73
protected final GlobalEnvironment heap ;
70
- protected Set <String > importedModules ;
74
+ /** Map of imported modules to resolved ModuleEnvironments, will only be empty in case of a module was in a cycle or got reloaded and failed during the reload. use {@link #importedModulesResolved} to lazily resolve the modules. */
75
+ protected Map <String , Optional <ModuleEnvironment >> importedModules ;
71
76
protected Set <String > extended ;
72
77
protected TypeStore typeStore ;
73
78
protected Set <IValue > productions ;
@@ -79,6 +84,7 @@ public class ModuleEnvironment extends Environment {
79
84
private String deprecated ;
80
85
protected Map <String , AbstractFunction > resourceImporters ;
81
86
protected Map <Type , Set <GenericKeywordParameters >> cachedGeneralKeywordParameters ;
87
+ protected Map <String , List <AbstractFunction >> cachedPublicFunctions ;
82
88
83
89
protected static final TypeFactory TF = TypeFactory .getInstance ();
84
90
@@ -87,7 +93,7 @@ public class ModuleEnvironment extends Environment {
87
93
public ModuleEnvironment (String name , GlobalEnvironment heap ) {
88
94
super (ValueFactoryFactory .getValueFactory ().sourceLocation (URIUtil .assumeCorrect ("main" , name , "" )), name );
89
95
this .heap = heap ;
90
- this .importedModules = new HashSet < String >();
96
+ this .importedModules = new HashMap < >();
91
97
this .concreteSyntaxTypes = new HashMap <String , NonTerminalType >();
92
98
this .productions = new HashSet <IValue >();
93
99
this .generalKeywordParameters = new HashMap <Type ,List <KeywordFormal >>();
@@ -97,6 +103,7 @@ public ModuleEnvironment(String name, GlobalEnvironment heap) {
97
103
this .bootstrap = false ;
98
104
this .resourceImporters = new HashMap <String , AbstractFunction >();
99
105
this .cachedGeneralKeywordParameters = null ;
106
+ this .cachedPublicFunctions = null ;
100
107
}
101
108
102
109
/**
@@ -116,13 +123,14 @@ protected ModuleEnvironment(ModuleEnvironment env) {
116
123
this .bootstrap = env .bootstrap ;
117
124
this .resourceImporters = env .resourceImporters ;
118
125
this .cachedGeneralKeywordParameters = null ;
126
+ this .cachedPublicFunctions = null ;
119
127
this .deprecated = env .deprecated ;
120
128
}
121
129
122
130
@ Override
123
131
public void reset () {
124
132
super .reset ();
125
- this .importedModules = new HashSet <>();
133
+ this .importedModules = new HashMap <>();
126
134
this .concreteSyntaxTypes = new HashMap <>();
127
135
this .typeStore = new TypeStore ();
128
136
this .productions = new HashSet <IValue >();
@@ -133,6 +141,13 @@ public void reset() {
133
141
this .deprecated = null ;
134
142
this .generalKeywordParameters = new HashMap <>();
135
143
this .cachedGeneralKeywordParameters = null ;
144
+ this .cachedPublicFunctions = null ;
145
+ }
146
+
147
+ public void clearLookupCaches () {
148
+ importedModules .replaceAll ((k , v ) -> Optional .empty ());
149
+ cachedGeneralKeywordParameters = null ;
150
+ cachedPublicFunctions = null ;
136
151
}
137
152
138
153
public void extend (ModuleEnvironment other ) {
@@ -142,9 +157,9 @@ public void extend(ModuleEnvironment other) {
142
157
// so that types become available
143
158
if (other .importedModules != null ) {
144
159
if (this .importedModules == null ) {
145
- this .importedModules = new HashSet < String >();
160
+ this .importedModules = new HashMap < >();
146
161
}
147
- this .importedModules .addAll (other .importedModules );
162
+ this .importedModules .putAll (other .importedModules );
148
163
}
149
164
150
165
if (other .concreteSyntaxTypes != null ) {
@@ -294,7 +309,7 @@ public IMap getSyntaxDefinition() {
294
309
result .put (VF .string (m ), t );
295
310
}else if (m .equals (getName ())) { // This is the root scope.
296
311
ISetWriter importWriter = VF .setWriter ();
297
- for (String impname : importedModules ){
312
+ for (String impname : importedModules . keySet () ){
298
313
if (!done .contains (impname )) todo .add (impname );
299
314
300
315
importWriter .insert (VF .string (impname ));
@@ -327,15 +342,25 @@ public boolean isModuleEnvironment() {
327
342
328
343
public void addImport (String name , ModuleEnvironment env ) {
329
344
assert heap .getModule (name ).equals (env );
330
- importedModules .add (name );
345
+ importedModules .put (name , Optional . ofNullable ( env ) );
331
346
typeStore .importStore (env .typeStore );
347
+ this .cachedGeneralKeywordParameters = null ;
348
+ this .cachedPublicFunctions = null ;
349
+ }
350
+
351
+ void removeModule (String name ) {
352
+ importedModules .computeIfPresent (name , (k , v ) -> Optional .empty ());
353
+ this .cachedGeneralKeywordParameters = null ;
354
+ this .cachedPublicFunctions = null ;
332
355
}
333
356
334
357
public void addExtend (String name ) {
335
358
if (extended == null ) {
336
359
extended = new HashSet <String >();
337
360
}
338
361
extended .add (name );
362
+ this .cachedGeneralKeywordParameters = null ;
363
+ this .cachedPublicFunctions = null ;
339
364
}
340
365
341
366
public List <AbstractFunction > getTests () {
@@ -356,7 +381,7 @@ public List<AbstractFunction> getTests() {
356
381
357
382
@ Override
358
383
public Set <String > getImports () {
359
- return Collections .unmodifiableSet (importedModules );
384
+ return Collections .unmodifiableSet (importedModules . keySet () );
360
385
}
361
386
362
387
public Set <String > getImportsTransitive () {
@@ -384,18 +409,18 @@ public Set<String> getImportsTransitive() {
384
409
}
385
410
386
411
public void unImport (String moduleName ) {
387
- if (importedModules .remove (moduleName )) {
388
- ModuleEnvironment old = heap .getModule (moduleName );
389
- if (old != null ) {
390
- typeStore .unimportStores (new TypeStore [] { old .getStore () });
391
- }
412
+ var old = importedModules .remove (moduleName );
413
+ if (old != null && old .isPresent ()) {
414
+ typeStore .unimportStores (old .get ().getStore ());
392
415
}
393
416
cachedGeneralKeywordParameters = null ;
417
+ cachedPublicFunctions = null ;
394
418
}
395
419
396
420
public void unExtend (String moduleName ) {
397
421
extended .remove (moduleName );
398
422
cachedGeneralKeywordParameters = null ;
423
+ cachedPublicFunctions = null ;
399
424
}
400
425
401
426
@ Override
@@ -447,6 +472,7 @@ public Result<IValue> getVariable(QualifiedName name) {
447
472
448
473
return getFrameVariable (cons );
449
474
}
475
+
450
476
451
477
@ Override
452
478
public void storeVariable (String name , Result <IValue > value ) {
@@ -461,8 +487,7 @@ public void storeVariable(String name, Result<IValue> value) {
461
487
super .storeVariable (name , value );
462
488
}
463
489
else {
464
- for (String i : importedModules ) {
465
- ModuleEnvironment module = heap .getModule (i );
490
+ for (ModuleEnvironment module : importedModulesResolved ) {
466
491
result = module .getLocalPublicVariable (name );
467
492
468
493
if (result != null ) {
@@ -483,8 +508,7 @@ public org.rascalmpl.interpreter.result.Result<IValue> getSimpleVariable(String
483
508
return var ;
484
509
}
485
510
486
- for (String moduleName : importedModules ) {
487
- ModuleEnvironment mod = getImport (moduleName );
511
+ for (ModuleEnvironment mod : importedModulesResolved ) {
488
512
489
513
if (mod != null ) {
490
514
var = mod .getLocalPublicVariable (name );
@@ -511,8 +535,7 @@ protected Map<String,Result<IValue>> getVariableDefiningEnvironment(String name)
511
535
}
512
536
}
513
537
514
- for (String moduleName : importedModules ) {
515
- ModuleEnvironment mod = getImport (moduleName );
538
+ for (ModuleEnvironment mod : importedModulesResolved ) {
516
539
Result <IValue > r = null ;
517
540
if (mod != null && mod .variableEnvironment != null )
518
541
r = mod .variableEnvironment .get (name );
@@ -527,32 +550,36 @@ protected Map<String,Result<IValue>> getVariableDefiningEnvironment(String name)
527
550
528
551
@ Override
529
552
public void getAllFunctions (String name , List <AbstractFunction > collection ) {
530
- super .getAllFunctions (name , collection );
531
-
532
- for (String moduleName : importedModules ) {
533
- ModuleEnvironment mod = getImport (moduleName );
553
+ collection .addAll (lookupCachedFunctions (name ));
554
+ }
555
+
556
+ private List <AbstractFunction > lookupCachedFunctions (String name ) {
557
+ if (cachedPublicFunctions == null ) {
558
+ cachedPublicFunctions = io .usethesource .capsule .Map .Transient .of ();
559
+ }
560
+ return cachedPublicFunctions .computeIfAbsent (name , n -> {
561
+ var result = new ArrayList <AbstractFunction >();
562
+ super .getAllFunctions (n , result );
534
563
535
- if (mod != null ) {
536
- mod .getLocalPublicFunctions (name , collection );
564
+ for (ModuleEnvironment mod : importedModulesResolved ) {
565
+
566
+ if (mod != null ) {
567
+ mod .getLocalPublicFunctions (n , result );
568
+ }
537
569
}
538
- }
570
+ return result ;
571
+ });
539
572
}
540
573
541
574
@ Override
542
575
public void getAllFunctions (Type returnType , String name , List <AbstractFunction > collection ) {
543
- super .getAllFunctions (returnType , name , collection );
544
-
545
- for (String moduleName : importedModules ) {
546
- ModuleEnvironment mod = getImport (moduleName );
547
-
548
- if (mod != null ) {
549
- mod .getLocalPublicFunctions (returnType , name , collection );
576
+ for (var function : lookupCachedFunctions (name )) {
577
+ if (function .getReturnType ().comparable (returnType )) {
578
+ collection .add (function );
550
579
}
551
580
}
552
581
}
553
582
554
-
555
-
556
583
557
584
private Result <IValue > getLocalPublicVariable (String name ) {
558
585
Result <IValue > var = null ;
@@ -578,20 +605,6 @@ private void getLocalPublicFunctions(String name, List<AbstractFunction> collect
578
605
}
579
606
}
580
607
}
581
-
582
- private void getLocalPublicFunctions (Type returnType , String name , List <AbstractFunction > collection ) {
583
- if (functionEnvironment != null && !isNamePrivate (name )) {
584
- LinkedHashSet <AbstractFunction > lst = functionEnvironment .get (name );
585
-
586
- if (lst != null ) {
587
- for (AbstractFunction func : lst ) {
588
- if (returnType .isSubtypeOf (func .getReturnType ())) {
589
- collection .add (func );
590
- }
591
- }
592
- }
593
- }
594
- }
595
608
596
609
@ Override
597
610
public Type abstractDataType (String name , Type ... parameters ) {
@@ -732,8 +745,7 @@ public Set<GenericKeywordParameters> lookupGenericKeywordParameters(Type adt) {
732
745
result .add (new GenericKeywordParameters (this , list , getStore ().getKeywordParameters (adt )));
733
746
}
734
747
735
- for (String moduleName : importedModules ) {
736
- ModuleEnvironment mod = getImport (moduleName );
748
+ for (ModuleEnvironment mod : importedModulesResolved ) {
737
749
738
750
list = mod .generalKeywordParameters .get (adt );
739
751
if (list != null ) {
@@ -825,13 +837,33 @@ public String toString() {
825
837
826
838
@ Override
827
839
public ModuleEnvironment getImport (String moduleName ) {
828
- if ( importedModules .contains (moduleName )) {
829
- return heap .getModule (moduleName );
830
- }
831
- else {
832
- return null ;
840
+ var result = importedModules .computeIfPresent (moduleName ,
841
+ ( m , c ) -> c . isPresent () ? c : Optional . ofNullable ( heap .getModule (m ))
842
+ );
843
+ if ( result == null || result . isEmpty ()) {
844
+ return null ;
833
845
}
846
+ return result .get ();
834
847
}
848
+
849
+ private Iterable <ModuleEnvironment > importedModulesResolved =
850
+ () -> new Iterator <ModuleEnvironment >() {
851
+ Iterator <Entry <String , Optional <ModuleEnvironment >>> iterator = importedModules .entrySet ().iterator ();
852
+ @ Override
853
+ public boolean hasNext () {
854
+ return iterator .hasNext ();
855
+ }
856
+ @ Override
857
+ public ModuleEnvironment next () {
858
+ var entry = iterator .next ();
859
+ var result = entry .getValue ();
860
+ if (result .isEmpty ()) {
861
+ result = Optional .ofNullable (heap .getModule (entry .getKey ()));
862
+ entry .setValue (result );
863
+ }
864
+ return result .orElse (null );
865
+ }
866
+ };
835
867
836
868
@ Override
837
869
public void storeVariable (QualifiedName name , Result <IValue > result ) {
@@ -870,8 +902,7 @@ public Type lookupConcreteSyntaxType(String name) {
870
902
Type type = concreteSyntaxTypes .get (name );
871
903
872
904
if (type == null ) {
873
- for (String i : importedModules ) {
874
- ModuleEnvironment mod = getImport (i );
905
+ for (ModuleEnvironment mod : importedModulesResolved ) {
875
906
876
907
if (mod == null ) {
877
908
continue ;
@@ -989,8 +1020,7 @@ protected Environment getFlagsEnvironment(String name) {
989
1020
return env ;
990
1021
}
991
1022
992
- for (String moduleName : importedModules ) {
993
- ModuleEnvironment mod = getImport (moduleName );
1023
+ for (ModuleEnvironment mod : importedModulesResolved ) {
994
1024
if (mod == null ) {
995
1025
throw new RuntimeException ("getFlagsEnvironment" );
996
1026
}
@@ -1081,4 +1111,5 @@ public void resetProductions() {
1081
1111
public Set <IValue > getProductions () {
1082
1112
return productions ;
1083
1113
}
1114
+
1084
1115
}
0 commit comments