99 **/
1010
1111using clojure . lang . CljCompiler . Context ;
12+
1213using System ;
1314using System . Collections ;
1415using System . Collections . Generic ;
15- using System . Linq ;
1616using System . Reflection ;
1717using System . Reflection . Emit ;
1818using System . Runtime . CompilerServices ;
@@ -45,14 +45,26 @@ public class ObjExpr : Expr
4545 public IPersistentMap Keywords { get ; internal set ; }
4646 public IPersistentMap Vars { get ; internal set ; }
4747 public IPersistentVector Constants { get ; internal set ; }
48- public IPersistentSet UsedConstants { get ; } = PersistentHashSet . EMPTY ;
4948
50- public Dictionary < int , FieldBuilder > ConstantFields { get ; protected set ; }
49+ public class FieldBuilderRecord
50+ {
51+ public FieldBuilderRecord ( FieldBuilder fb )
52+ {
53+ FieldBuilder = fb ;
54+ Emitted = false ;
55+ }
56+
57+ public FieldBuilder FieldBuilder { get ; private set ; }
58+ public bool Emitted { get ; private set ; }
59+ public void MarkEmitted ( ) { Emitted = true ; }
60+ }
61+
62+ public Dictionary < int , FieldBuilderRecord > ConstantFields { get ; protected set ; } = [ ] ;
5163 public IPersistentMap Fields { get ; protected set ; } // symbol -> lb
5264 public IPersistentMap SpanMap { get ; protected set ; }
5365 public Type CompiledType { get ; protected set ; }
5466 public IPersistentMap ClassMeta { get ; protected set ; }
55- public TypeBuilder TypeBuilder { get ; protected set ; }
67+ public TypeBuilder TypeBuilder { get ; internal set ; }
5668 public ConstructorInfo CtorInfo { get ; protected set ; }
5769 public ConstructorInfo BaseClassClosedOverCtor { get ; protected set ; } // needed by NewInstanceExpr
5870 public ConstructorInfo BaseClassAltCtor { get ; protected set ; } // needed by NewInstanceExpr
@@ -292,10 +304,8 @@ public Type Compile(Type superType, Type stubType, IPersistentVector interfaces,
292304 //,
293305 //Compiler.COMPILE_STUB_CLASS, _baseType));
294306 }
295- EmitConstantFieldDefs ( TypeBuilder ) ;
296- EmitKeywordCallsiteDefs ( TypeBuilder ) ;
297307
298- DefineStaticConstructor ( TypeBuilder ) ;
308+ EmitKeywordCallsiteDefs ( TypeBuilder ) ;
299309
300310 if ( SupportsMeta )
301311 MetaField = TypeBuilder . DefineField ( "__meta" , typeof ( IPersistentMap ) , FieldAttributes . Public | FieldAttributes . InitOnly ) ;
@@ -318,6 +328,7 @@ public Type Compile(Type superType, Type stubType, IPersistentVector interfaces,
318328
319329 EmitStatics ( TypeBuilder ) ;
320330 EmitMethods ( TypeBuilder ) ;
331+ DefineStaticConstructor ( TypeBuilder ) ;
321332
322333 CompiledType = TypeBuilder . CreateType ( ) ;
323334
@@ -425,13 +436,17 @@ private void EmitConstantFieldInits(CljILGen ilg)
425436
426437 for ( int i = 0 ; i < Constants . count ( ) ; i ++ )
427438 {
428- if ( ConstantFields [ i ] != null )
439+ if ( ConstantFields . TryGetValue ( i , out FieldBuilderRecord fbr ) )
429440 {
430- EmitValue ( Constants . nth ( i ) , ilg ) ;
431- if ( Constants . nth ( i ) . GetType ( ) != ConstantType ( i ) )
432- ilg . Emit ( OpCodes . Castclass , ConstantType ( i ) ) ;
433- FieldBuilder fb = ConstantFields [ i ] ;
434- ilg . Emit ( OpCodes . Stsfld , fb ) ;
441+ if ( ! fbr . Emitted )
442+ {
443+ EmitValue ( Constants . nth ( i ) , ilg ) ;
444+ if ( Constants . nth ( i ) . GetType ( ) != ConstantType ( i ) )
445+ ilg . Emit ( OpCodes . Castclass , ConstantType ( i ) ) ;
446+ //FieldBuilder fb = ConstantFields[i];
447+ ilg . Emit ( OpCodes . Stsfld , fbr . FieldBuilder ) ;
448+ fbr . MarkEmitted ( ) ;
449+ }
435450 }
436451 }
437452 }
@@ -690,32 +705,7 @@ protected virtual void EmitStatics(TypeBuilder tb)
690705 {
691706 }
692707
693- public void EmitConstantFieldDefs ( TypeBuilder baseTB )
694- {
695- // We have to do this different than the JVM version.
696- // The JVM does all these at the end.
697- // That works for the usual ObjExpr, but not for the top-level one that becomes __Init__.Initialize in the assembly.
698- // That one need the constants defined incrementally.
699- // This version accommodates the all-at-end approach for general ObjExprs and the incremental approach in Compiler.Compile1.
700-
701- if ( ConstantFields == null )
702- ConstantFields = new Dictionary < int , FieldBuilder > ( Constants . count ( ) ) ;
703-
704- int nextKey = ConstantFields . Count == 0 ? 0 : ConstantFields . Keys . Max ( ) + 1 ;
705-
706- for ( int i = nextKey ; i < Constants . count ( ) ; i ++ )
707- {
708- if ( ! ConstantFields . ContainsKey ( i ) )
709- {
710- string fieldName = ConstantName ( i ) ;
711- Type fieldType = ConstantType ( i ) ;
712- FieldBuilder fb = baseTB . DefineField ( fieldName , fieldType , FieldAttributes . FamORAssem | FieldAttributes . Static ) ;
713- ConstantFields [ i ] = fb ;
714- }
715- }
716- }
717-
718- public MethodBuilder EmitConstants ( TypeBuilder fnTB )
708+ public MethodBuilder DefineConstantFieldInitMethod ( TypeBuilder fnTB )
719709 {
720710 try
721711 {
@@ -726,12 +716,17 @@ public MethodBuilder EmitConstants(TypeBuilder fnTB)
726716
727717 for ( int i = 0 ; i < Constants . count ( ) ; i ++ )
728718 {
729- if ( ConstantFields . TryGetValue ( i , out FieldBuilder fb ) )
719+ if ( ConstantFields . TryGetValue ( i , out FieldBuilderRecord fbr ) )
730720 {
731- EmitValue ( Constants . nth ( i ) , ilg ) ;
732- if ( Constants . nth ( i ) . GetType ( ) != ConstantType ( i ) )
733- ilg . Emit ( OpCodes . Castclass , ConstantType ( i ) ) ;
734- ilg . Emit ( OpCodes . Stsfld , fb ) ;
721+ if ( ! fbr . Emitted )
722+ {
723+ EmitValue ( Constants . nth ( i ) , ilg ) ;
724+ if ( Constants . nth ( i ) . GetType ( ) != ConstantType ( i ) )
725+ ilg . Emit ( OpCodes . Castclass , ConstantType ( i ) ) ;
726+ //FieldBuilder fb = ConstantFields[i];
727+ ilg . Emit ( OpCodes . Stsfld , fbr . FieldBuilder ) ;
728+ fbr . MarkEmitted ( ) ;
729+ }
735730 }
736731 }
737732 ilg . Emit ( OpCodes . Ret ) ;
@@ -968,15 +963,19 @@ private void EmitListAsObjectArray(object value, CljILGen ilg)
968963 }
969964 }
970965
971- internal void EmitConstant ( CljILGen ilg , int id , object val )
966+ internal void EmitConstant ( CljILGen ilg , int id /* , object val */ )
972967 {
973- if ( ConstantFields != null && ConstantFields . TryGetValue ( id , out FieldBuilder fb ) )
968+ if ( ! ConstantFields . TryGetValue ( id , out FieldBuilderRecord fbr ) )
974969 {
975- ilg . MaybeEmitVolatileOp ( fb ) ;
976- ilg . Emit ( OpCodes . Ldsfld , fb ) ;
970+ string fieldName = ConstantName ( id ) ;
971+ Type fieldType = ConstantType ( id ) ;
972+ FieldBuilder fb = TypeBuilder . DefineField ( fieldName , fieldType , FieldAttributes . FamORAssem | FieldAttributes . Static ) ;
973+ ConstantFields [ id ] = fbr = new FieldBuilderRecord ( fb ) ;
977974 }
978- else
979- EmitValue ( val , ilg ) ;
975+
976+ ilg . MaybeEmitVolatileOp ( fbr . FieldBuilder ) ;
977+ ilg . Emit ( OpCodes . Ldsfld , fbr . FieldBuilder ) ;
978+
980979 }
981980
982981
@@ -1018,27 +1017,29 @@ internal void EmitConstant(CljILGen ilg, int id, object val)
10181017 internal void EmitVar ( CljILGen ilg , Var var )
10191018 {
10201019 int i = ( int ) Vars . valAt ( var ) ;
1021- EmitConstant ( ilg , i , var ) ;
1020+ EmitConstant ( ilg , i ) ;
1021+
10221022 }
10231023
10241024
10251025 internal void EmitKeyword ( CljILGen ilg , Keyword kw )
10261026 {
10271027 int i = ( int ) Keywords . valAt ( kw ) ;
1028- EmitConstant ( ilg , i , kw ) ;
1028+ EmitConstant ( ilg , i ) ;
1029+
10291030 }
10301031
10311032 internal void EmitVarValue ( CljILGen ilg , Var v )
10321033 {
10331034 int i = ( int ) Vars . valAt ( v ) ;
10341035 if ( ! v . isDynamic ( ) )
10351036 {
1036- EmitConstant ( ilg , i , v ) ;
1037+ EmitConstant ( ilg , i ) ;
10371038 ilg . Emit ( OpCodes . Call , Compiler . Method_Var_getRawRoot ) ;
10381039 }
10391040 else
10401041 {
1041- EmitConstant ( ilg , i , v ) ;
1042+ EmitConstant ( ilg , i ) ;
10421043 ilg . Emit ( OpCodes . Call , Compiler . Method_Var_get ) ; // or just Method_Var_get??
10431044 }
10441045 }
0 commit comments