Skip to content

Commit 3054967

Browse files
committed
CLRCLR-182: Fix handling of a primitive type hint on the var name for a derfn .
1 parent 2ff3bbb commit 3054967

File tree

1 file changed

+45
-24
lines changed

1 file changed

+45
-24
lines changed

Clojure/Clojure/CljCompiler/Ast/FnMethod.cs

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)