@@ -20,10 +20,10 @@ namespace clojure.lang.CljCompiler.Ast
2020 public class FnMethod : ObjMethod
2121 {
2222 #region Data
23-
23+
2424 protected IPersistentVector _reqParms = PersistentVector . EMPTY ; // localbinding => localbinding
2525 public IPersistentVector ReqParms { get { return _reqParms ; } }
26-
26+
2727 protected LocalBinding _restParm = null ;
2828 public LocalBinding RestParm { get { return _restParm ; } }
2929
@@ -41,14 +41,14 @@ public class FnMethod : ObjMethod
4141 #region C-tors
4242
4343 public FnMethod ( FnExpr fn , ObjMethod parent )
44- : base ( fn , parent )
44+ : base ( fn , parent )
4545 {
4646 }
4747
4848 // For top-level compilation only
4949 // TODO: Can we get rid of this when the DLR-based compile goes away?
5050 public FnMethod ( FnExpr fn , ObjMethod parent , BodyExpr body )
51- : base ( fn , parent )
51+ : base ( fn , parent )
5252 {
5353 Body = body ;
5454 ArgLocals = PersistentVector . EMPTY ;
@@ -109,7 +109,7 @@ internal static FnMethod Parse(FnExpr fn, ISeq form, object retTag)
109109
110110 try
111111 {
112- FnMethod method = new FnMethod ( fn , ( ObjMethod ) Compiler . MethodVar . deref ( ) )
112+ FnMethod method = new ( fn , ( ObjMethod ) Compiler . MethodVar . deref ( ) )
113113 {
114114 SpanMap = ( IPersistentMap ) Compiler . SourceSpanVar . deref ( )
115115 } ;
@@ -119,18 +119,16 @@ internal static FnMethod Parse(FnExpr fn, ISeq form, object retTag)
119119 Compiler . LocalEnvVar , Compiler . LocalEnvVar . deref ( ) ,
120120 Compiler . LoopLocalsVar , null ,
121121 Compiler . NextLocalNumVar , 0 ,
122- Compiler . MethodReturnContextVar , true ) ) ;
122+ Compiler . MethodReturnContextVar , true ) ) ;
123123
124- method . _prim = PrimInterface ( parms ) ;
125- //if (method._prim != null)
126- // method._prim = method._prim.Replace('.', '/');
124+ // In the JVM code, the call to PrimInterface is here.
125+ // But we need to know if rettag is used and the computed return type, so it should come later.
127126
128-
129127 if ( retTag is String )
130128 retTag = Symbol . intern ( null , ( string ) retTag ) ;
131- if ( ! ( retTag is Symbol ) )
129+ if ( retTag is not Symbol )
132130 retTag = null ;
133- if ( retTag != null )
131+ if ( retTag is not null )
134132 {
135133 string retStr = ( ( Symbol ) retTag ) . Name ;
136134 if ( ! ( retStr . Equals ( "long" ) || retStr . Equals ( "double" ) ) )
@@ -146,12 +144,17 @@ internal static FnMethod Parse(FnExpr fn, ISeq form, object retTag)
146144 else
147145 method . _retType = typeof ( object ) ;
148146
147+ method . _prim = PrimInterface ( parms , method . _retType ) ;
148+ //if (method._prim != null)
149+ // method._prim = method._prim.Replace('.', '/');
150+
151+
149152 // register 'this' as local 0
150153 Compiler . RegisterLocalThis ( Symbol . intern ( fn . ThisName ?? "fn__" + RT . nextID ( ) ) , null , null ) ;
151154
152155 ParamParseState paramState = ParamParseState . Required ;
153156 IPersistentVector argLocals = PersistentVector . EMPTY ;
154- List < Type > argTypes = new List < Type > ( ) ;
157+ List < Type > argTypes = new ( ) ;
155158
156159 int parmsCount = parms . count ( ) ;
157160
@@ -210,7 +213,7 @@ internal static FnMethod Parse(FnExpr fn, ISeq form, object retTag)
210213 Compiler . LoopLocalsVar . set ( argLocals ) ;
211214 method . ArgLocals = argLocals ;
212215 method . _argTypes = argTypes . ToArray ( ) ;
213- method . Body = ( new BodyExpr . Parser ( ) ) . Parse ( new ParserContext ( RHC . Return ) , body ) ;
216+ method . Body = ( new BodyExpr . Parser ( ) ) . Parse ( new ParserContext ( RHC . Return ) , body ) ;
214217 return method ;
215218 }
216219 finally
@@ -250,11 +253,29 @@ public static bool IsPrimType(object x)
250253
251254 return false ;
252255 }
253-
256+
257+ // Use this if we supply the return type rather than getting it from the meta of the arglist vector
258+ public static string PrimInterface ( IPersistentVector arglist , Type retType )
259+ {
260+ StringBuilder sb = new ( ) ;
261+ for ( int i = 0 ; i < arglist . count ( ) ; i ++ )
262+ sb . Append ( TypeChar ( Compiler . TagOf ( arglist . nth ( i ) ) ) ) ;
263+ sb . Append ( TypeChar ( retType ) ) ;
264+ string ret = sb . ToString ( ) ;
265+ bool prim = ret . Contains ( "L" ) || ret . Contains ( "D" ) ;
266+ if ( prim && arglist . count ( ) > 4 )
267+ throw new ArgumentException ( "fns taking primitives support only 4 or fewer args" ) ;
268+ if ( prim )
269+ return "clojure.lang.primifs." + ret ;
270+ return null ;
271+ }
272+
273+
274+ // Use this if we get the return type from the meta of the arglist vector
254275
255276 public static string PrimInterface ( IPersistentVector arglist )
256277 {
257- StringBuilder sb = new StringBuilder ( ) ;
278+ StringBuilder sb = new ( ) ;
258279 for ( int i = 0 ; i < arglist . count ( ) ; i ++ )
259280 sb . Append ( TypeChar ( Compiler . TagOf ( arglist . nth ( i ) ) ) ) ;
260281 sb . Append ( TypeChar ( Compiler . TagOf ( arglist ) ) ) ;
@@ -286,15 +307,15 @@ public static bool HasPrimInterface(ISeq form)
286307 {
287308 return RT . first ( form ) is IPersistentVector parms && IsPrimInterface ( parms ) ;
288309 }
289-
310+
290311 #endregion
291312
292313 #region Code generation
293314
294315
295316 public override void Emit ( ObjExpr fn , TypeBuilder tb )
296317 {
297- if ( fn . CanBeDirect )
318+ if ( fn . CanBeDirect )
298319 {
299320 //Console.WriteLine("emit static: {0}", fn.Name);
300321 DoEmitStatic ( fn , tb ) ;
@@ -321,7 +342,7 @@ private void DoEmitStatic(ObjExpr fn, TypeBuilder tb)
321342
322343 MethodBuilder baseMB = tb . DefineMethod ( methodName , attribs , returnType , _argTypes ) ;
323344
324- CljILGen baseIlg = new CljILGen ( baseMB . GetILGenerator ( ) ) ;
345+ CljILGen baseIlg = new ( baseMB . GetILGenerator ( ) ) ;
325346
326347 try
327348 {
@@ -345,7 +366,7 @@ private void DoEmitStatic(ObjExpr fn, TypeBuilder tb)
345366 MethodBuilder regularMB = tb . DefineMethod ( MethodName , MethodAttributes . ReuseSlot | MethodAttributes . Public | MethodAttributes . Virtual , typeof ( Object ) , ArgTypes ) ;
346367 SetCustomAttributes ( regularMB ) ;
347368
348- CljILGen regIlg = new CljILGen ( regularMB . GetILGenerator ( ) ) ;
369+ CljILGen regIlg = new ( regularMB . GetILGenerator ( ) ) ;
349370
350371 for ( int i = 0 ; i < _argTypes . Length ; i ++ )
351372 {
@@ -377,7 +398,7 @@ private void DoEmitStatic(ObjExpr fn, TypeBuilder tb)
377398 MethodBuilder primMB = tb . DefineMethod ( primMethodName , primAttribs , primReturnType , _argTypes ) ;
378399 SetCustomAttributes ( primMB ) ;
379400
380- CljILGen primIlg = new CljILGen ( primMB . GetILGenerator ( ) ) ;
401+ CljILGen primIlg = new ( primMB . GetILGenerator ( ) ) ;
381402 for ( int i = 0 ; i < _argTypes . Length ; i ++ )
382403 {
383404 primIlg . EmitLoadArg ( i + 1 ) ;
@@ -406,7 +427,7 @@ private void DoEmitPrim(ObjExpr fn, TypeBuilder tb)
406427
407428 SetCustomAttributes ( baseMB ) ;
408429
409- CljILGen baseIlg = new CljILGen ( baseMB . GetILGenerator ( ) ) ;
430+ CljILGen baseIlg = new ( baseMB . GetILGenerator ( ) ) ;
410431
411432 try
412433 {
@@ -430,7 +451,7 @@ private void DoEmitPrim(ObjExpr fn, TypeBuilder tb)
430451 MethodBuilder regularMB = tb . DefineMethod ( MethodName , MethodAttributes . ReuseSlot | MethodAttributes . Public | MethodAttributes . Virtual , typeof ( Object ) , ArgTypes ) ;
431452 SetCustomAttributes ( regularMB ) ;
432453
433- CljILGen regIlg = new CljILGen ( regularMB . GetILGenerator ( ) ) ;
454+ CljILGen regIlg = new ( regularMB . GetILGenerator ( ) ) ;
434455
435456 regIlg . Emit ( OpCodes . Ldarg_0 ) ;
436457 for ( int i = 0 ; i < _argTypes . Length ; i ++ )
@@ -450,7 +471,7 @@ private void DoEmit(ObjExpr fn, TypeBuilder tb)
450471 MethodBuilder mb = tb . DefineMethod ( MethodName , attribs , ReturnType , ArgTypes ) ;
451472 SetCustomAttributes ( mb ) ;
452473
453- CljILGen baseIlg = new CljILGen ( mb . GetILGenerator ( ) ) ;
474+ CljILGen baseIlg = new ( mb . GetILGenerator ( ) ) ;
454475
455476 try
456477 {
0 commit comments