diff --git a/Clojure/Clojure/CljCompiler/Ast/CaseExpr.cs b/Clojure/Clojure/CljCompiler/Ast/CaseExpr.cs
index d8575a76..17c2913c 100644
--- a/Clojure/Clojure/CljCompiler/Ast/CaseExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/CaseExpr.cs
@@ -8,10 +8,7 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/Clojure/Clojure/CljCompiler/Ast/ConstantExpr.cs b/Clojure/Clojure/CljCompiler/Ast/ConstantExpr.cs
index 22e99295..65ef60a7 100644
--- a/Clojure/Clojure/CljCompiler/Ast/ConstantExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/ConstantExpr.cs
@@ -46,6 +46,7 @@ public override bool HasClrType
get
{
return _v.GetType().IsPublic
+ || _v.GetType().IsNestedPublic
|| typeof(Type).IsInstanceOfType(_v); // This bit of hackery is due to the fact that RuntimeType is not public.
// Without this, System.Int64 would be seen as only type System.Object, not System.RuntimeType.
}
diff --git a/Clojure/Clojure/CljCompiler/Ast/FnExpr.cs b/Clojure/Clojure/CljCompiler/Ast/FnExpr.cs
index e3643d10..f0916022 100644
--- a/Clojure/Clojure/CljCompiler/Ast/FnExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/FnExpr.cs
@@ -8,15 +8,12 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Reflection.Emit;
using System.Reflection;
+using System.Reflection.Emit;
namespace clojure.lang.CljCompiler.Ast
{
diff --git a/Clojure/Clojure/CljCompiler/Ast/FnMethod.cs b/Clojure/Clojure/CljCompiler/Ast/FnMethod.cs
index 39c079e7..48253e04 100644
--- a/Clojure/Clojure/CljCompiler/Ast/FnMethod.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/FnMethod.cs
@@ -8,15 +8,12 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Collections.Generic;
-using System.Text;
-using System.Reflection.Emit;
using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
namespace clojure.lang.CljCompiler.Ast
{
diff --git a/Clojure/Clojure/CljCompiler/Ast/IfExpr.cs b/Clojure/Clojure/CljCompiler/Ast/IfExpr.cs
index 97f5a429..07251910 100644
--- a/Clojure/Clojure/CljCompiler/Ast/IfExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/IfExpr.cs
@@ -8,10 +8,7 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Reflection.Emit;
diff --git a/Clojure/Clojure/CljCompiler/Ast/IlGen.cs b/Clojure/Clojure/CljCompiler/Ast/IlGen.cs
index 2ce3b601..5fef617d 100644
--- a/Clojure/Clojure/CljCompiler/Ast/IlGen.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/IlGen.cs
@@ -8,11 +8,6 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
-
using System;
using System.Reflection;
using System.Reflection.Emit;
@@ -25,9 +20,16 @@ namespace clojure.lang.CljCompiler.Ast
{
public class CljILGen : ILGen
{
+ private readonly ILGenerator _ilGenerator;
+ public ILGenerator ILGenerator
+ {
+ get { return _ilGenerator; }
+ }
+
public CljILGen(ILGenerator baseIlg)
: base(baseIlg)
{
+ _ilGenerator = baseIlg;
}
private static bool IsVolatile(FieldInfo fi)
diff --git a/Clojure/Clojure/CljCompiler/Ast/InstanceFieldExpr.cs b/Clojure/Clojure/CljCompiler/Ast/InstanceFieldExpr.cs
index 2bb647ec..0cf733b2 100644
--- a/Clojure/Clojure/CljCompiler/Ast/InstanceFieldExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/InstanceFieldExpr.cs
@@ -8,10 +8,7 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Reflection;
using System.Reflection.Emit;
diff --git a/Clojure/Clojure/CljCompiler/Ast/InvokeExpr.cs b/Clojure/Clojure/CljCompiler/Ast/InvokeExpr.cs
index 9be11c0b..175c7775 100644
--- a/Clojure/Clojure/CljCompiler/Ast/InvokeExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/InvokeExpr.cs
@@ -8,10 +8,7 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Collections.Generic;
using System.Reflection;
@@ -170,10 +167,15 @@ public static Expr Parse(ParserContext pcon, ISeq form)
int arity = RT.count(form.next());
object sigtag = SigTag(arity, v);
object vtag = RT.get(RT.meta(v), RT.TagKey);
- if (StaticInvokeExpr.Parse(v, RT.next(form), formTag ?? sigtag ?? vtag) is StaticInvokeExpr ret && !((Compiler.IsCompiling || Compiler.IsCompilingDefType) && GenContext.IsInternalAssembly(ret.Method.DeclaringType.Assembly)))
+ if (StaticInvokeExpr.Parse(v, RT.next(form), formTag ?? sigtag ?? vtag) is StaticInvokeExpr ret )
{
+ var isCompiling = Compiler.IsCompiling || Compiler.IsCompilingDefType;
+ var retAssembly = ret.Method.DeclaringType.Assembly;
+ var isInternal = GenContext.IsInternalAssembly(retAssembly);
+ if (! (isCompiling && isInternal))
+ return ret;
//Console.WriteLine("invoke direct: {0}", v);
- return ret;
+ // return ret;
}
//Console.WriteLine("NOT direct: {0}", v);
}
diff --git a/Clojure/Clojure/CljCompiler/Ast/KeywordInvokeExpr.cs b/Clojure/Clojure/CljCompiler/Ast/KeywordInvokeExpr.cs
index dd586d4a..ac75be4f 100644
--- a/Clojure/Clojure/CljCompiler/Ast/KeywordInvokeExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/KeywordInvokeExpr.cs
@@ -8,10 +8,8 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
+using clojure.lang.CljCompiler.Context;
using System;
using System.Reflection.Emit;
diff --git a/Clojure/Clojure/CljCompiler/Ast/LetExpr.cs b/Clojure/Clojure/CljCompiler/Ast/LetExpr.cs
index 17e79888..6f80afe9 100644
--- a/Clojure/Clojure/CljCompiler/Ast/LetExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/LetExpr.cs
@@ -8,10 +8,7 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Collections.Generic;
using System.Reflection.Emit;
diff --git a/Clojure/Clojure/CljCompiler/Ast/LocalBinding.cs b/Clojure/Clojure/CljCompiler/Ast/LocalBinding.cs
index f85b66b8..5c1eb361 100644
--- a/Clojure/Clojure/CljCompiler/Ast/LocalBinding.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/LocalBinding.cs
@@ -59,6 +59,9 @@ public sealed class LocalBinding
public LocalBinding(int index, Symbol sym, Symbol tag, Expr init, Type declaredType, bool isThis, bool isArg, bool isByRef)
{
+ if (Compiler.MaybePrimitiveType(init) != null && tag != null)
+ throw new InvalidOperationException("Can't type hint a local with a primitive initializer");
+
Index = index;
_sym = sym;
Tag = tag;
diff --git a/Clojure/Clojure/CljCompiler/Ast/MethodExpr.cs b/Clojure/Clojure/CljCompiler/Ast/MethodExpr.cs
index 977c69f7..cff8c5b7 100644
--- a/Clojure/Clojure/CljCompiler/Ast/MethodExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/MethodExpr.cs
@@ -8,19 +8,15 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
+using clojure.lang.Runtime;
+using clojure.lang.Runtime.Binding;
using System;
using System.Collections.Generic;
-using System.Linq.Expressions;
using System.Dynamic;
+using System.Linq.Expressions;
using System.Reflection;
-using clojure.lang.Runtime.Binding;
-using clojure.lang.Runtime;
using System.Reflection.Emit;
-using System.Linq;
namespace clojure.lang.CljCompiler.Ast
{
@@ -168,7 +164,7 @@ public static void CacheDelegate(int key, Delegate d)
private void EmitComplexCall(ObjExpr objx, CljILGen ilg)
{
- // TOD: We have gotten rid of light-compile. Simplify this.
+ // TODO: We have gotten rid of light-compile. Simplify this.
// This is made more complex than I'd like by light-compiling.
// Without light-compile, we could just:
// Emit the target expression
@@ -445,7 +441,7 @@ public static void EmitTypedArgs(ObjExpr objx, CljILGen ilg, ParameterInfo[] par
{
EmitTypedArg(objx, ilg, parms[i].ParameterType, args[i].ArgExpr);
LocalBuilder loc = ilg.DeclareLocal(pi.ParameterType);
-#if NET462
+#if NETFRAMEWORK
loc.SetLocalSymInfo("_byRef_temp" + i);
#endif
ilg.Emit(OpCodes.Stloc, loc);
diff --git a/Clojure/Clojure/CljCompiler/Ast/NewExpr.cs b/Clojure/Clojure/CljCompiler/Ast/NewExpr.cs
index a42811d5..094baa15 100644
--- a/Clojure/Clojure/CljCompiler/Ast/NewExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/NewExpr.cs
@@ -8,17 +8,14 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
+using clojure.lang.Runtime;
+using clojure.lang.Runtime.Binding;
using System;
using System.Collections.Generic;
-using System.Reflection;
-using System.Linq.Expressions;
using System.Dynamic;
-using clojure.lang.Runtime.Binding;
-using clojure.lang.Runtime;
+using System.Linq.Expressions;
+using System.Reflection;
using System.Reflection.Emit;
namespace clojure.lang.CljCompiler.Ast
diff --git a/Clojure/Clojure/CljCompiler/Ast/NewInstanceExpr.cs b/Clojure/Clojure/CljCompiler/Ast/NewInstanceExpr.cs
index b95dbbfc..350e9bad 100644
--- a/Clojure/Clojure/CljCompiler/Ast/NewInstanceExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/NewInstanceExpr.cs
@@ -8,16 +8,12 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
+using Microsoft.Scripting.Generation;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
-using System.Runtime.CompilerServices;
-using Microsoft.Scripting.Generation;
namespace clojure.lang.CljCompiler.Ast
{
@@ -170,7 +166,9 @@ internal static ObjExpr Build(
ret._methodMap = overrideables;
-
+ // TODO: This is a tempoaray fix until we figure out how to deal with PersistedAssemblyBuilder SAVE9 !!!
+
+#if NETFRAMEWORK
GenContext context = Compiler.IsCompiling
? Compiler.CompilerContextVar.get() as GenContext
: (ret.IsDefType
@@ -178,6 +176,15 @@ internal static ObjExpr Build(
: (Compiler.CompilerContextVar.get() as GenContext
??
Compiler.EvalContext));
+#else
+ GenContext context = Compiler.IsCompiling
+ ? Compiler.CompilerContextVar.get() as GenContext
+ : (ret.IsDefType
+ ? GenContext.CreateWithInternalAssembly("deftype" + RT.nextID().ToString(), true)
+ : (Compiler.CompilerContextVar.get() as GenContext
+ ??
+ Compiler.EvalContext));
+#endif
GenContext genC = context.WithNewDynInitHelper(ret.InternalName + "__dynInitHelper_" + RT.nextID().ToString());
@@ -391,6 +398,9 @@ private static void DefineBaseClassMethods(Type[] interfaces, TypeBuilder tb)
{
bool isExplicit = HasShadowedMethod(mi, impled);
+ var attrs = mi.Attributes;
+ var customs = mi.CustomAttributes;
+
EmitDummyMethod(tb, mi, isExplicit);
if (!impled.ContainsKey(mi.Name))
@@ -440,7 +450,7 @@ private static bool ParametersMatch(MethodInfo m1, MethodInfo m2)
// return t.FullName.Replace(',', '/');
//}
- #endregion
+#endregion
#region Method reflection
diff --git a/Clojure/Clojure/CljCompiler/Ast/NewInstanceMethod.cs b/Clojure/Clojure/CljCompiler/Ast/NewInstanceMethod.cs
index a1b3a63e..bee221b9 100644
--- a/Clojure/Clojure/CljCompiler/Ast/NewInstanceMethod.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/NewInstanceMethod.cs
@@ -8,10 +8,7 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Collections.Generic;
using System.Reflection;
diff --git a/Clojure/Clojure/CljCompiler/Ast/Node.cs b/Clojure/Clojure/CljCompiler/Ast/Node.cs
deleted file mode 100644
index 9612ee4e..00000000
--- a/Clojure/Clojure/CljCompiler/Ast/Node.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Copyright (c) Rich Hickey. All rights reserved.
- * The use and distribution terms for this software are covered by the
- * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
- * which can be found in the file epl-v10.html at the root of this distribution.
- * By using this software in any fashion, you are agreeing to be bound by
- * the terms of this license.
- * You must not remove this notice, or any other, from this software.
- **/
-
-/**
- * Author: David Miller
- **/
-
-using Microsoft.Scripting;
-
-namespace clojure.lang.CljCompiler.Ast
-{
- // TODO: Remove Node class
-
- /*
- ///
- /// Base class for AST expressions in the compiler.
- ///
- /// Stolen from IronPython.
- public abstract class Node
- {
- #region Data
-
- private Microsoft.Scripting.SourceLocation _start = SourceLocation.Invalid;
- private Microsoft.Scripting.SourceLocation _end = SourceLocation.Invalid;
-
- #endregion
-
- #region Location methods
-
- public void SetLoc(SourceLocation start, SourceLocation end)
- {
- _start = start;
- _end = end;
- }
-
- public void SetLoc(SourceSpan span)
- {
- _start = span.Start;
- _end = span.End;
- }
-
- public SourceLocation Start
- {
- get { return _start; }
- set { _start = value; }
- }
-
- public SourceLocation End
- {
- get { return _end; }
- set { _end = value; }
- }
-
- public SourceSpan Span
- {
- get
- {
- return new SourceSpan(_start, _end);
- }
- }
-
- #endregion
- }
- */
-}
diff --git a/Clojure/Clojure/CljCompiler/Ast/ObjExpr.cs b/Clojure/Clojure/CljCompiler/Ast/ObjExpr.cs
index 2da716cb..579eca48 100644
--- a/Clojure/Clojure/CljCompiler/Ast/ObjExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/ObjExpr.cs
@@ -8,16 +8,13 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using System.Reflection.Emit;
using System.Reflection;
-using System.Collections;
+using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
@@ -65,37 +62,17 @@ public class ObjExpr : Expr
public IPersistentVector ProtocolCallsites { get; protected set; }
public IPersistentSet VarCallsites { get; protected set; }
-
-
public IList KeywordLookupSiteFields { get; protected set; }
-
public IList ThunkFields { get; protected set; }
-
public IList CachedTypeFields { get; protected set; }
-
- internal FieldBuilder KeywordLookupSiteField(int i)
- {
- return KeywordLookupSiteFields[i];
- }
-
- internal FieldBuilder CachedTypeField(int i)
- {
- return CachedTypeFields[i];
- }
-
- internal FieldBuilder ThunkField(int i)
- {
- return ThunkFields[i];
- }
-
+ internal FieldBuilder KeywordLookupSiteField(int i) => KeywordLookupSiteFields[i];
+ internal FieldBuilder CachedTypeField(int i) => CachedTypeFields[i];
+ internal FieldBuilder ThunkField(int i) => ThunkFields[i];
public FieldBuilder MetaField { get; protected set; }
-
public IList ClosedOverFields { get; protected set; }
-
public Dictionary ClosedOverFieldsMap { get; protected set; }
-
public Dictionary ClosedOverFieldsToBindingsMap { get; protected set; }
public IPersistentVector HintedFields { get; protected set; }
@@ -107,9 +84,8 @@ internal FieldBuilder ThunkField(int i)
public bool OnceOnly { get; protected set; }
public bool CanBeDirect { get; protected set; }
-
- protected bool IsDefType { get { return Fields != null; } }
- protected virtual bool SupportsMeta { get { return !IsDefType; } }
+ protected bool IsDefType => Fields is not null;
+ protected virtual bool SupportsMeta => !IsDefType;
internal bool IsVolatile(LocalBinding lb)
{
@@ -127,41 +103,18 @@ internal bool IsMutable(LocalBinding lb)
lb.IsByRef;
}
- static String SiteName(int n)
- {
- return "__site__" + n;
- }
-
- public static String SiteNameStatic(int n)
- {
- return SiteName(n) + "__";
- }
-
- static String ThunkName(int n)
- {
- return "__thunk__" + n;
- }
-
- public static String ThunkNameStatic(int n)
- {
- return ThunkName(n) + "__";
- }
-
- internal static String CachedClassName(int n)
- {
- return "__cached_class__" + n;
- }
-
- private static string ConstantName(int i)
- {
- return ConstPrefix + i;
- }
+ static String SiteName(int n) => "__site__" + n;
+ public static String SiteNameStatic(int n) => SiteName(n) + "__";
+ static String ThunkName(int n) => "__thunk__" + n;
+ public static String ThunkNameStatic(int n) => ThunkName(n) + "__";
+ internal static String CachedClassName(int n) => "__cached_class__" + n;
+ private static string ConstantName(int i) => ConstPrefix + i;
private Type ConstantType(int i)
{
object o = Constants.nth(i);
Type t = o?.GetType();
- if (t != null && t.IsPublic)
+ if (t != null && (t.IsPublic || t.IsNestedPublic))
{
// Java: can't emit derived fn types due to visibility
if (typeof(LazySeq).IsAssignableFrom(t))
diff --git a/Clojure/Clojure/CljCompiler/Ast/ObjMethod.cs b/Clojure/Clojure/CljCompiler/Ast/ObjMethod.cs
index 51ef5af5..84e84429 100644
--- a/Clojure/Clojure/CljCompiler/Ast/ObjMethod.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/ObjMethod.cs
@@ -8,13 +8,10 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
-using System.Reflection.Emit;
using System.Reflection;
+using System.Reflection.Emit;
namespace clojure.lang.CljCompiler.Ast
diff --git a/Clojure/Clojure/CljCompiler/Ast/StaticFieldExpr.cs b/Clojure/Clojure/CljCompiler/Ast/StaticFieldExpr.cs
index b08a76e4..6fbc95ea 100644
--- a/Clojure/Clojure/CljCompiler/Ast/StaticFieldExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/StaticFieldExpr.cs
@@ -8,10 +8,7 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Reflection;
using System.Reflection.Emit;
diff --git a/Clojure/Clojure/CljCompiler/Ast/StaticInvokeExpr.cs b/Clojure/Clojure/CljCompiler/Ast/StaticInvokeExpr.cs
index 729afd45..11b101db 100644
--- a/Clojure/Clojure/CljCompiler/Ast/StaticInvokeExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/StaticInvokeExpr.cs
@@ -13,6 +13,7 @@
**/
using System;
+using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
@@ -83,7 +84,16 @@ public static Expr Parse(Var v, ISeq args, object tag)
Type target = v.get().GetType();
- MethodInfo[] allMethods = target.GetMethods();
+ {
+ var directLinkMap = Compiler.DirectLinkingMapVar.deref() as Dictionary;
+ if (directLinkMap != null && directLinkMap.TryGetValue(v, out Type t))
+ {
+ if (t != null)
+ target = t;
+ }
+ }
+
+ MethodInfo[] allMethods = target.GetMethods();
bool variadic = false;
int argcount = RT.count(args);
MethodInfo method = null;
diff --git a/Clojure/Clojure/CljCompiler/Ast/StaticMethodExpr.cs b/Clojure/Clojure/CljCompiler/Ast/StaticMethodExpr.cs
index 9b572535..96f7a350 100644
--- a/Clojure/Clojure/CljCompiler/Ast/StaticMethodExpr.cs
+++ b/Clojure/Clojure/CljCompiler/Ast/StaticMethodExpr.cs
@@ -8,10 +8,7 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Collections.Generic;
using System.Reflection;
diff --git a/Clojure/Clojure/CljCompiler/Compiler.cs b/Clojure/Clojure/CljCompiler/Compiler.cs
index eb3a6b0e..ef29e4cb 100644
--- a/Clojure/Clojure/CljCompiler/Compiler.cs
+++ b/Clojure/Clojure/CljCompiler/Compiler.cs
@@ -8,23 +8,19 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Ast;
+using clojure.lang.CljCompiler.Context;
using System;
+using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
-using System.Text;
using System.IO;
-using System.Threading;
-using clojure.lang.CljCompiler.Ast;
using System.Reflection;
using System.Reflection.Emit;
-using System.Text.RegularExpressions;
using System.Runtime.Serialization;
-using System.Collections;
-using System.Net;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
namespace clojure.lang
{
@@ -40,16 +36,23 @@ public static class Compiler
#region Duplicate types
- static readonly Dictionary _duplicateTypeMap = new Dictionary();
+ static readonly Dictionary _evalTypeMap = new Dictionary();
+ static readonly Dictionary _compilerTypeMap = new Dictionary();
internal static void RegisterDuplicateType(Type type)
{
- _duplicateTypeMap[type.FullName] = type;
+ if (Compiler.IsCompiling)
+ _compilerTypeMap[type.FullName] = type;
+ else
+ _evalTypeMap[type.FullName] = type;
}
internal static Type FindDuplicateType(string typename)
{
- _duplicateTypeMap.TryGetValue(typename, out Type type);
+ if (Compiler.IsCompiling && _compilerTypeMap.TryGetValue(typename, out Type compiledType))
+ { return compiledType; }
+
+ _evalTypeMap.TryGetValue(typename, out Type type);
return type;
}
@@ -197,7 +200,8 @@ internal static int ColumnVarDeref()
internal static readonly Var CompilerContextVar = Var.create(null).setDynamic();
internal static readonly Var CompilerActiveVar = Var.create(false).setDynamic();
-
+ internal static readonly Var DirectLinkingMapVar = Var.create(null).setDynamic();
+
public static Var CompilerOptionsVar;
public static object GetCompilerOption(Keyword k)
@@ -1691,7 +1695,8 @@ public static object Compile(GenContext context,TextReader rdr, string sourceDir
RT.WarnOnReflectionVar, RT.WarnOnReflectionVar.deref(),
RT.DataReadersVar, RT.DataReadersVar.deref(),
CompilerContextVar, context,
- CompilerActiveVar, true
+ CompilerActiveVar, true,
+ DirectLinkingMapVar, new Dictionary()
));
try
@@ -1776,7 +1781,17 @@ private static void Compile1(TypeBuilder tb, CljILGen ilg, ObjExpr objx, object
objx.EmitConstantFieldDefs(tb);
expr.Emit(RHC.Expression,objx,ilg);
ilg.Emit(OpCodes.Pop);
+
+ if ( expr is DefExpr dex && dex.Init is FnExpr fnx)
+ {
+ ((Dictionary)DirectLinkingMapVar.deref())[dex.Var] = fnx.CompiledType;
+ }
+
+#if NET9_0_OR_GREATER
+ DoSeparateEval(evPC, form);
+#else
expr.Eval();
+#endif
}
}
finally
@@ -1785,8 +1800,41 @@ private static void Compile1(TypeBuilder tb, CljILGen ilg, ObjExpr objx, object
}
}
+ private static void DoSeparateEval(ParserContext evPC, Object form)
+ {
+ // Reset the environment to avoid leaking the compile environment
+
+ Var.pushThreadBindings(RT.mapUniqueKeys(
+ MethodVar, null,
+ LocalEnvVar, null,
+ LoopLocalsVar, null,
+ NextLocalNumVar, 0,
+ //RT.ReadEvalVar, true /* RT.T */,
+ //RT.CurrentNSVar, RT.CurrentNSVar.deref(), Do not reset this -- we need to see changes to this that might happen, e.g. with (ns ..) or (in-ns ...) calls
+ ConstantsVar, PersistentVector.EMPTY,
+ ConstantIdsVar, new IdentityHashMap(),
+ KeywordsVar, PersistentHashMap.EMPTY,
+ VarsVar, PersistentHashMap.EMPTY,
+ //RT.UncheckedMathVar, RT.UncheckedMathVar.deref(),
+ //RT.WarnOnReflectionVar, RT.WarnOnReflectionVar.deref(),
+ //RT.DataReadersVar, RT.DataReadersVar.deref(),
+ CompilerContextVar, null,
+ CompilerActiveVar, false,
+ DirectLinkingMapVar, null // we do not want to have the evaluated version try to direct link to functions in the compile assembly
+ ));
+ try
+ {
+ Compiler.eval(form);
+ }
+ finally
+ {
+ Var.popThreadBindings();
+ }
+ }
+
+
#endregion
-
+
#region Loading
internal static void LoadAssembly(FileInfo assyInfo, string relativePath)
diff --git a/Clojure/Clojure/CljCompiler/Ast/DynInitHelper.cs b/Clojure/Clojure/CljCompiler/Context/DynInitHelper.cs
similarity index 96%
rename from Clojure/Clojure/CljCompiler/Ast/DynInitHelper.cs
rename to Clojure/Clojure/CljCompiler/Context/DynInitHelper.cs
index 03318074..c90cf8e0 100644
--- a/Clojure/Clojure/CljCompiler/Ast/DynInitHelper.cs
+++ b/Clojure/Clojure/CljCompiler/Context/DynInitHelper.cs
@@ -8,23 +8,20 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Ast;
+using clojure.lang.Runtime.Binding;
+using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
using System;
using System.Collections.Generic;
-using System.Text;
-using System.Reflection.Emit;
-using System.Reflection;
using System.Linq.Expressions;
-using Microsoft.Scripting.Generation;
+using System.Reflection;
+using System.Reflection.Emit;
using System.Runtime.CompilerServices;
-using Microsoft.Scripting.Utils;
-using Microsoft.Scripting.Runtime;
-using clojure.lang.Runtime.Binding;
+using System.Text;
-namespace clojure.lang.CljCompiler.Ast
+namespace clojure.lang.CljCompiler.Context
{
class DynInitHelper
@@ -32,9 +29,9 @@ class DynInitHelper
#region Data
int _id;
- readonly AssemblyGen _assemblyGen;
+ readonly MyAssemblyGen _assemblyGen;
TypeBuilder _typeBuilder;
- TypeGen _typeGen;
+ MyTypeGen _typeGen;
readonly string _typeName;
@@ -63,7 +60,7 @@ public SiteInfo(FieldBuilder fb, Type st, CallSiteBinder binder, Type delegateTy
#region Ctors and factories
- public DynInitHelper(AssemblyGen ag, string typeName)
+ public DynInitHelper(MyAssemblyGen ag, string typeName)
{
_assemblyGen = ag;
_typeName = typeName;
@@ -111,13 +108,13 @@ private void MaybeInit()
if (_typeBuilder == null)
{
_typeBuilder = _assemblyGen.DefinePublicType(_typeName, typeof(object), true);
- _typeGen = new TypeGen(_assemblyGen, _typeBuilder);
+ _typeGen = new MyTypeGen(_assemblyGen, _typeBuilder);
_siteInfos = new List();
}
}
- private Expression RewriteCallSite(CallSite site, TypeGen tg, Type delegateType, out SiteInfo siteInfo)
+ private Expression RewriteCallSite(CallSite site, MyTypeGen tg, Type delegateType, out SiteInfo siteInfo)
{
if (!(site.Binder is IExpressionSerializable))
{
@@ -195,7 +192,7 @@ private bool ShouldRewriteDelegate(Type delegateType)
{
return false;
}
-#if NET462
+#if NETFRAMEWORK
if (module.IsTransient())
{
return true;
diff --git a/Clojure/Clojure/CljCompiler/Ast/GenContext.cs b/Clojure/Clojure/CljCompiler/Context/GenContext.cs
similarity index 66%
rename from Clojure/Clojure/CljCompiler/Ast/GenContext.cs
rename to Clojure/Clojure/CljCompiler/Context/GenContext.cs
index 4e4f4ad6..36601ec2 100644
--- a/Clojure/Clojure/CljCompiler/Ast/GenContext.cs
+++ b/Clojure/Clojure/CljCompiler/Context/GenContext.cs
@@ -8,29 +8,28 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-using System.Reflection.Emit;
-using System.Reflection;
-using System.Linq.Expressions;
+using clojure.lang.CljCompiler.Ast;
+using clojure.lang.Runtime;
using Microsoft.Scripting.Generation;
using System;
+using System.Collections;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
using System.Diagnostics.SymbolStore;
-using clojure.lang.Runtime;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Reflection.Emit;
using AstUtils = Microsoft.Scripting.Ast.Utils;
-using System.Collections.Generic;
-using System.Collections;
-namespace clojure.lang.CljCompiler.Ast
+namespace clojure.lang.CljCompiler.Context
{
public sealed class GenContext
{
#region Data
- readonly AssemblyGen _assyGen;
- public AssemblyGen AssemblyGen
+ readonly MyAssemblyGen _assyGen;
+ public MyAssemblyGen AssemblyGen
{
get { return _assyGen; }
}
@@ -77,28 +76,44 @@ public ISymbolDocumentWriter DocWriter
#region C-tors & factory methods
- private readonly static Dictionary InternalAssemblies = new Dictionary();
-
- private static void AddInternalAssembly(Assembly a)
+ private class DefaultAssemblyComparer : IEqualityComparer
{
- lock (((ICollection)InternalAssemblies).SyncRoot)
- {
- InternalAssemblies[a] = true;
- }
+ public bool Equals(Assembly x, Assembly y) => Object.ReferenceEquals(x, y);
+ public int GetHashCode(Assembly obj) => obj.GetHashCode();
}
- public static bool IsInternalAssembly(Assembly a)
+ private readonly static ConcurrentDictionary _internalAssemblies = new ConcurrentDictionary(new DefaultAssemblyComparer());
+ public static bool IsInternalAssembly(Assembly a) => a is not null && _internalAssemblies.ContainsKey(a);
+
+ private static void AddInternalAssembly(GenContext ctx)
{
- lock (((ICollection)InternalAssemblies).SyncRoot)
- {
- return InternalAssemblies.ContainsKey(a);
- }
+ // Sometime we are looking up via the AssemblyBuilder.
+ // But sometimes we are accessing via a method on a type. The defining assembly is actually a RuntimeAssembly, not the AssemblyBuilder itself.
+ // I'm not sure how else to find out what that RuntimeAssembly is, other than creating a type and a method and getting its assembly.
+ // We'll then register both the RuntimeAssembly and the AssemblyBuilder.
+
+ var module = ctx.ModuleBuilder;
+ var dummyType = module.DefineType("__________________DummyType");
+ var method = dummyType.DefineMethod("__________________DummyMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(void), Type.EmptyTypes);
+ var il = method.GetILGenerator();
+ il.Emit(OpCodes.Ret);
+
+ dummyType.CreateType();
+
+ var runtimeMethod = dummyType.GetMethod("__________________DummyMethod");
+ var runtimeAssembly = runtimeMethod.DeclaringType.Assembly;
+
+ _internalAssemblies[ctx.AssemblyBuilder] = true;
+ _internalAssemblies[runtimeAssembly] = true;
}
+
+ enum AssemblyType { Internal, External }
+
public static GenContext CreateWithInternalAssembly(string assyName, bool createDynInitHelper)
{
- GenContext ctx = CreateGenContext(assyName, assyName, ".dll", null, createDynInitHelper);
- AddInternalAssembly(ctx.AssemblyBuilder);
+ GenContext ctx = CreateGenContext(AssemblyType.Internal, assyName, assyName, ".dll", null, createDynInitHelper);
+ AddInternalAssembly(ctx);
return ctx;
}
@@ -112,7 +127,7 @@ public static GenContext CreateWithInternalAssembly(string assyName, bool create
public static GenContext CreateWithExternalAssembly(string sourceName, string assyName, string extension, bool createDynInitHelper)
{
string path = Compiler.CompilePathVar.deref() as string;
- return CreateGenContext(sourceName, assyName, extension, path ?? System.IO.Directory.GetCurrentDirectory(),createDynInitHelper);
+ return CreateGenContext(AssemblyType.External, sourceName, assyName, extension, path ?? System.IO.Directory.GetCurrentDirectory(),createDynInitHelper);
}
public static GenContext CreateWithExternalAssembly(string assyName, string extension, bool createDynInitHelper)
@@ -120,7 +135,7 @@ public static GenContext CreateWithExternalAssembly(string assyName, string exte
return CreateWithExternalAssembly(assyName, assyName, extension, createDynInitHelper);
}
- private static GenContext CreateGenContext(string sourceName, string assyName, string extension, string directory, bool createDynInitHelper)
+ private static GenContext CreateGenContext(AssemblyType assemblyType, string sourceName, string assyName, string extension, string directory, bool createDynInitHelper)
{
if (directory != null)
{
@@ -129,10 +144,10 @@ private static GenContext CreateGenContext(string sourceName, string assyName, s
}
AssemblyName aname = new AssemblyName(assyName);
- return new GenContext(directory, aname, extension, createDynInitHelper, sourceName);
+ return new GenContext(assemblyType, directory, aname, extension, createDynInitHelper, sourceName);
}
- private GenContext(string directory, AssemblyName aname, string extension, bool createDynInitHelper, string sourceName)
+ private GenContext(AssemblyType assemblyType, string directory, AssemblyName aname, string extension, bool createDynInitHelper, string sourceName)
{
// TODO: Make this settable from a *debug* flag
#if DEBUG
@@ -141,7 +156,24 @@ private GenContext(string directory, AssemblyName aname, string extension, bool
_isDebuggable = false;
#endif
- _assyGen = new AssemblyGen(aname, directory, extension, _isDebuggable);
+#if NETFRAMEWORK || NET9_0_OR_GREATER
+ switch (assemblyType)
+ {
+ case AssemblyType.Internal:
+ _assyGen = new MyAssemblyGen(aname, _isDebuggable);
+ break;
+ case AssemblyType.External:
+ _assyGen = new MyAssemblyGen(aname, directory, extension, _isDebuggable);
+ break;
+ default:
+ throw new InvalidOperationException("Unknown AssemblyType");
+ }
+#else
+ _assyGen = new MyAssemblyGen(aname, _isDebuggable);
+#endif
+
+
+
if (createDynInitHelper)
_dynInitHelper = new DynInitHelper(_assyGen, GenerateName());
@@ -151,9 +183,12 @@ private GenContext(string directory, AssemblyName aname, string extension, bool
Path = ComputeAssemblyPath(directory, aname.Name, extension);
-#if NET462
+#if NETFRAMEWORK
if (_isDebuggable)
_docWriter = ModuleBuilder.DefineDocument(sourceName, ClojureContext.Default.LanguageGuid, ClojureContext.Default.VendorGuid, Guid.Empty);
+#elif NET9_0_OR_GREATER
+ if (_isDebuggable && assemblyType == AssemblyType.External)
+ _docWriter = ModuleBuilder.DefineDocument(sourceName, ClojureContext.Default.LanguageGuid);
#endif
}
@@ -208,13 +243,10 @@ internal void SaveAssembly()
if ( _dynInitHelper != null )
_dynInitHelper.FinalizeType();
-#if NET462
+#if NETFRAMEWORK || NET9_0_OR_GREATER
_assyGen.SaveAssembly();
#else
Console.WriteLine("AOT-compilation not available");
- //var assembly = AssemblyBuilder;
- //var generator = new Lokad.ILPack.AssemblyGenerator();
- //generator.GenerateAssembly(assembly,Path);
#endif
}
@@ -243,22 +275,22 @@ public Expression MaybeAddDebugInfo(Expression expr, IPersistentMap spanMap)
return expr;
}
- public static void EmitDebugInfo(ILGen ilg, IPersistentMap spanMap)
+ public static void EmitDebugInfo(CljILGen ilg, IPersistentMap spanMap)
{
if (Compiler.CompilerContextVar.deref() is GenContext context)
context.MaybeEmitDebugInfo(ilg, spanMap);
}
- public void MaybeEmitDebugInfo(ILGen ilg, IPersistentMap spanMap)
+ public void MaybeEmitDebugInfo(CljILGen ilg, IPersistentMap spanMap)
{
-#if NET462
+#if NETFRAMEWORK || NET9_0_OR_GREATER
if ( _docWriter != null && spanMap != null )
{
if (Compiler.GetLocations(spanMap, out int startLine, out int startCol, out int finishLine, out int finishCol))
{
try
{
- ilg.MarkSequencePoint(_docWriter, startLine, startCol, finishLine, finishCol);
+ ilg.ILGenerator.MarkSequencePoint(_docWriter, startLine, startCol, finishLine, finishCol);
}
catch (NotSupportedException)
{
@@ -277,7 +309,7 @@ public static void SetLocalName(LocalBuilder lb, string name)
public void MaybSetLocalName(LocalBuilder lb, string name)
{
-#if NET462
+#if NETFRAMEWORK
if (_isDebuggable)
lb.SetLocalSymInfo(name);
#endif
diff --git a/Clojure/Clojure/CljCompiler/Context/MyAssemblyGen.cs b/Clojure/Clojure/CljCompiler/Context/MyAssemblyGen.cs
new file mode 100644
index 00000000..6012872f
--- /dev/null
+++ b/Clojure/Clojure/CljCompiler/Context/MyAssemblyGen.cs
@@ -0,0 +1,317 @@
+using Microsoft.Scripting.Utils;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Security;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+
+#if ! NETFRAMEWORK
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+using System.Reflection.PortableExecutable;
+using System.Diagnostics.SymbolStore;
+using System.Collections.Immutable;
+#endif
+
+// This class is based on the original Microsoft code for Microsoft.Scripting.Gneeration.AssemblyGen.
+// Lots of code copied here.
+//
+// // Licensed to the .NET Foundation under one or more agreements.
+// // The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// // See the LICENSE file in the project root for more information.
+//
+
+// Even before rolling my own version here, I had made my own versions of some its methods, such as MakeDelegateType.
+// The main adaptation here is to allow for creating a PersistedAssemblyBuilder for when we are in creating a persisted assembly in the context of .NET 9 or later.
+// To help make the code clearer to the outside and easier to implement, I created two constructors, one for persisted assemblies and one for non-persisted assemblies.
+// The constructor for persisted assemblies is only visible in .NET Framework and .NET 9 or later.
+
+namespace clojure.lang.CljCompiler.Context;
+
+public sealed class MyAssemblyGen
+{
+ private readonly AssemblyBuilder _myAssembly;
+ private readonly ModuleBuilder _myModule;
+ private readonly bool _isDebuggable;
+ private readonly bool _isPersistable;
+
+ private int _index;
+
+
+#if NETFRAMEWORK || NET9_0_OR_GREATER
+ private readonly string _outFileName; // can be null iff not saveable
+ private readonly string _outDir; // null means the current directory
+#endif
+
+#if NET9_0_OR_GREATER
+ MethodBuilder _entryPointMethodBuilder; // non-null means we have an entry point
+ ISymbolDocumentWriter _docWriter = null; // non-null means we are writing debug info
+#endif
+
+ internal AssemblyBuilder AssemblyBuilder => _myAssembly;
+ internal ModuleBuilder ModuleBuilder => _myModule;
+ internal bool IsDebuggable => _isDebuggable;
+
+ // This is the constructor for the non-persisted assembly.
+ public MyAssemblyGen(AssemblyName name, bool isDebuggable)
+ {
+ ContractUtils.RequiresNotNull(name, nameof(name));
+
+ _myAssembly = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
+ _myModule = _myAssembly.DefineDynamicModule(name.Name, isDebuggable);
+ _isDebuggable = isDebuggable;
+ _isPersistable = false;
+
+#if NETFRAMEWORK || NET9_0_OR_GREATER
+ _outFileName = null;
+ _outDir = null;
+#endif
+
+ if (isDebuggable)
+ {
+ SetDebuggableAttributes();
+ }
+ }
+
+#if NETFRAMEWORK || NET9_0_OR_GREATER
+
+ // This is the constructor for the persisted assembly.
+ public MyAssemblyGen(AssemblyName name, string outDir, string outFileExtension, bool isDebuggable, IDictionary attrs = null)
+ {
+ ContractUtils.RequiresNotNull(name, nameof(name));
+
+ if (outFileExtension == null)
+ {
+ outFileExtension = ".dll";
+ }
+
+ if (outDir != null)
+ {
+ try
+ {
+ outDir = Path.GetFullPath(outDir);
+ }
+ catch (Exception)
+ {
+ throw new InvalidOperationException("Invalid directory name");
+ }
+ try
+ {
+ Path.Combine(outDir, name.Name + outFileExtension);
+ }
+ catch (ArgumentException)
+ {
+ throw new InvalidOperationException("Invalid assembly name or extension");
+ }
+
+ _outFileName = name.Name + outFileExtension;
+ _outDir = outDir;
+ }
+
+
+ // mark the assembly transparent so that it works in partial trust:
+ var attributes = new List {
+ new CustomAttributeBuilder(typeof(SecurityTransparentAttribute).GetConstructor(ReflectionUtils.EmptyTypes), ArrayUtils.EmptyObjects) };
+
+ if (attrs != null)
+ {
+ foreach (var attr in attrs)
+ {
+ if (!(attr.Value is string a) || string.IsNullOrWhiteSpace(a))
+ {
+ continue;
+ }
+
+ ConstructorInfo ctor = null;
+ switch (attr.Key)
+ {
+ case "assemblyFileVersion":
+ ctor = typeof(AssemblyFileVersionAttribute).GetConstructor(new[] { typeof(string) });
+ break;
+ case "copyright":
+ ctor = typeof(AssemblyCopyrightAttribute).GetConstructor(new[] { typeof(string) });
+ break;
+ case "productName":
+ ctor = typeof(AssemblyProductAttribute).GetConstructor(new[] { typeof(string) });
+ break;
+ case "productVersion":
+ ctor = typeof(AssemblyInformationalVersionAttribute).GetConstructor(new[] { typeof(string) });
+ break;
+ }
+
+ if (ctor != null)
+ {
+ attributes.Add(new CustomAttributeBuilder(ctor, new object[] { a }));
+ }
+ }
+ }
+
+#if NETFRAMEWORK
+ _myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave, outDir, false, attributes);
+ _myModule = _myAssembly.DefineDynamicModule(name.Name, _outFileName, isDebuggable);
+ _myAssembly.DefineVersionInfoResource();
+#elif NET9_0_OR_GREATER
+ PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(name,typeof(object).Assembly, attributes);
+ _myAssembly = ab;
+ _myModule = ab.DefineDynamicModule(name.Name, isDebuggable);
+#endif
+ _isPersistable = true;
+ _isDebuggable = isDebuggable;
+
+ if (isDebuggable) {
+ SetDebuggableAttributes();
+ }
+
+
+ }
+#endif
+
+ internal void SetDebuggableAttributes()
+ {
+ DebuggableAttribute.DebuggingModes attrs =
+ DebuggableAttribute.DebuggingModes.Default |
+ DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
+ DebuggableAttribute.DebuggingModes.DisableOptimizations;
+
+ Type[] argTypes = new Type[] { typeof(DebuggableAttribute.DebuggingModes) };
+ Object[] argValues = new Object[] { attrs };
+
+ var debuggableCtor = typeof(DebuggableAttribute).GetConstructor(argTypes);
+
+ _myAssembly.SetCustomAttribute(new CustomAttributeBuilder(debuggableCtor, argValues));
+ _myModule.SetCustomAttribute(new CustomAttributeBuilder(debuggableCtor, argValues));
+ }
+
+
+ public string SaveAssembly()
+ {
+ if (!_isPersistable)
+ {
+ throw new InvalidOperationException("Assembly is not persistable");
+ }
+
+#if NETFRAMEWORK
+ _myAssembly.Save(_outFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
+ return Path.Combine(_outDir, _outFileName);
+#elif NET9_0_OR_GREATER
+ if ( _entryPointMethodBuilder is not null || _docWriter is not null)
+ SavePersistedAssemblyHard();
+ else
+ ((PersistedAssemblyBuilder)_myAssembly).Save(_outFileName);
+ return Path.Combine(_outDir, _outFileName);
+#else
+ return null;
+#endif
+
+ }
+
+#if NET9_0_OR_GREATER
+ private void SavePersistedAssemblyHard()
+ {
+ PersistedAssemblyBuilder ab = (PersistedAssemblyBuilder)_myAssembly;
+ MetadataBuilder metadataBuilder = ab.GenerateMetadata(out BlobBuilder ilStream, out BlobBuilder fieldData, out MetadataBuilder pdbBuilder);
+
+ MethodDefinitionHandle entryPointHandle =
+ _entryPointMethodBuilder is null
+ ? default(MethodDefinitionHandle)
+ : MetadataTokens.MethodDefinitionHandle(_entryPointMethodBuilder.MetadataToken);
+ DebugDirectoryBuilder debugDirectoryBuilder = GeneratePdb(pdbBuilder, metadataBuilder.GetRowCounts(), entryPointHandle);
+
+ ManagedPEBuilder peBuilder = new(
+ header: PEHeaderBuilder.CreateExecutableHeader(),
+ metadataRootBuilder: new MetadataRootBuilder(metadataBuilder),
+ ilStream: ilStream,
+ mappedFieldData: fieldData,
+ debugDirectoryBuilder: debugDirectoryBuilder,
+ entryPoint: entryPointHandle);
+
+ BlobBuilder peBlob = new();
+ peBuilder.Serialize(peBlob);
+
+ // Create the executable:
+ using FileStream fileStream = new(_outFileName, FileMode.Create, FileAccess.Write);
+ peBlob.WriteContentTo(fileStream);
+ }
+
+ static DebugDirectoryBuilder GeneratePdb(MetadataBuilder pdbBuilder, ImmutableArray rowCounts, MethodDefinitionHandle entryPointHandle)
+ {
+ BlobBuilder portablePdbBlob = new BlobBuilder();
+ PortablePdbBuilder portablePdbBuilder = new PortablePdbBuilder(pdbBuilder, rowCounts, entryPointHandle);
+ BlobContentId pdbContentId = portablePdbBuilder.Serialize(portablePdbBlob);
+ // In case saving PDB to a file
+ using FileStream fileStream = new FileStream("MyAssemblyEmbeddedSource.pdb", FileMode.Create, FileAccess.Write);
+ portablePdbBlob.WriteContentTo(fileStream);
+
+ DebugDirectoryBuilder debugDirectoryBuilder = new DebugDirectoryBuilder();
+ debugDirectoryBuilder.AddCodeViewEntry("MyAssemblyEmbeddedSource.pdb", pdbContentId, portablePdbBuilder.FormatVersion);
+ // In case embedded in PE:
+ // debugDirectoryBuilder.AddEmbeddedPortablePdbEntry(portablePdbBlob, portablePdbBuilder.FormatVersion);
+ return debugDirectoryBuilder;
+ }
+#endif
+
+
+#if NETFRAMEWORK
+ internal void SetEntryPoint(MethodInfo mi, PEFileKinds kind)
+ {
+ _myAssembly.SetEntryPoint(mi, kind);
+ }
+#elif NET9_0_OR_GREATER
+ internal void SetEntryPoint(MethodBuilder mb)
+ {
+ _entryPointMethodBuilder = mb;
+ }
+#endif
+
+
+ public TypeBuilder DefinePublicType(string name, Type parent, bool preserveName)
+ {
+ return DefineType(name, parent, TypeAttributes.Public, preserveName);
+ }
+
+ internal TypeBuilder DefineType(string name, Type parent, TypeAttributes attr, bool preserveName)
+ {
+ ContractUtils.RequiresNotNull(name, nameof(name));
+ ContractUtils.RequiresNotNull(parent, nameof(parent));
+
+ StringBuilder sb = new StringBuilder(name);
+ if (!preserveName)
+ {
+ int index = Interlocked.Increment(ref _index);
+ sb.Append("$");
+ sb.Append(index);
+ }
+
+ // There is a bug in Reflection.Emit that leads to
+ // Unhandled Exception: System.Runtime.InteropServices.COMException (0x80131130): Record not found on lookup.
+ // if there is any of the characters []*&+,\ in the type name and a method defined on the type is called.
+ sb.Replace('+', '_').Replace('[', '_').Replace(']', '_').Replace('*', '_').Replace('&', '_').Replace(',', '_').Replace('\\', '_');
+
+ name = sb.ToString();
+
+ return _myModule.DefineType(name, attr, parent);
+ }
+
+
+ private const MethodAttributes CtorAttributes = MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public;
+ private const MethodImplAttributes ImplAttributes = MethodImplAttributes.Runtime | MethodImplAttributes.Managed;
+ private const MethodAttributes InvokeAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual;
+ private const TypeAttributes DelegateAttributes = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass;
+ private static readonly Type[] _DelegateCtorSignature = new Type[] { typeof(object), typeof(IntPtr) };
+
+ public Type MakeDelegateType(string name, Type[] parameters, Type returnType)
+ {
+ TypeBuilder builder = DefineType(name, typeof(MulticastDelegate), DelegateAttributes, false);
+ builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, _DelegateCtorSignature).SetImplementationFlags(ImplAttributes);
+ builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes);
+ return builder.CreateTypeInfo();
+ }
+
+}
diff --git a/Clojure/Clojure/CljCompiler/Context/MyTypeGen.cs b/Clojure/Clojure/CljCompiler/Context/MyTypeGen.cs
new file mode 100644
index 00000000..da6ca877
--- /dev/null
+++ b/Clojure/Clojure/CljCompiler/Context/MyTypeGen.cs
@@ -0,0 +1,93 @@
+// I had to copy Microsoft.Scripting.Generation.TypeGen.cs to this project and modify it to use MyAssemblyGen instead of Microsoft.Scripting.Generation.AssemblyGen.
+// The latter is sealed, so I couldn't just derive. Sigh.
+
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information.
+
+//#if FEATURE_REFEMIT
+
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using clojure.lang.CljCompiler.Context;
+using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Utils;
+
+namespace clojure.lang.CljCompiler.Context;
+
+public sealed class MyTypeGen {
+ private ILGen _initGen; // The IL generator for the .cctor()
+
+ ///
+ /// Gets the Compiler associated with the Type Initializer (cctor) creating it if necessary.
+ ///
+ public ILGen TypeInitializer {
+ get {
+ if (_initGen == null) {
+ _initGen = new ILGen(TypeBuilder.DefineTypeInitializer().GetILGenerator());
+ }
+ return _initGen;
+ }
+ }
+
+ internal MyAssemblyGen AssemblyGen { get; }
+
+ public TypeBuilder TypeBuilder { get; }
+
+ public MyTypeGen(MyAssemblyGen myAssembly, TypeBuilder myType) {
+ Assert.NotNull(myAssembly, myType);
+
+ AssemblyGen = myAssembly;
+ TypeBuilder = myType;
+ }
+
+ public override string ToString() {
+ return TypeBuilder.ToString();
+ }
+
+ public Type FinishType() {
+ _initGen?.Emit(OpCodes.Ret);
+ Type ret = TypeBuilder.CreateTypeInfo();
+ return ret;
+ }
+
+ public FieldBuilder AddStaticField(Type fieldType, string name) {
+ return TypeBuilder.DefineField(name, fieldType, FieldAttributes.Public | FieldAttributes.Static);
+ }
+
+ public FieldBuilder AddStaticField(Type fieldType, FieldAttributes attributes, string name) {
+ return TypeBuilder.DefineField(name, fieldType, attributes | FieldAttributes.Static);
+ }
+
+ public ILGen DefineExplicitInterfaceImplementation(MethodInfo baseMethod) {
+ ContractUtils.RequiresNotNull(baseMethod, nameof(baseMethod));
+
+ MethodAttributes attrs = baseMethod.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.Public);
+ attrs |= MethodAttributes.NewSlot | MethodAttributes.Final;
+
+ Type[] baseSignature = baseMethod.GetParameters().Map(p => p.ParameterType);
+ MethodBuilder mb = TypeBuilder.DefineMethod(
+ baseMethod.DeclaringType.Name + "." + baseMethod.Name,
+ attrs,
+ baseMethod.ReturnType,
+ baseSignature);
+
+ TypeBuilder.DefineMethodOverride(mb, baseMethod);
+ return new ILGen(mb.GetILGenerator());
+ }
+
+ private const MethodAttributes MethodAttributesToEraseInOveride = MethodAttributes.Abstract | MethodAttributes.ReservedMask;
+
+ // TODO: Use ReflectionUtils.DefineMethodOverride?
+ public ILGen DefineMethodOverride(MethodInfo baseMethod) {
+ MethodAttributes finalAttrs = baseMethod.Attributes & ~MethodAttributesToEraseInOveride;
+ Type[] baseSignature = baseMethod.GetParameters().Map(p => p.ParameterType);
+ MethodBuilder mb = TypeBuilder.DefineMethod(baseMethod.Name, finalAttrs, baseMethod.ReturnType, baseSignature);
+
+ TypeBuilder.DefineMethodOverride(mb, baseMethod);
+ return new ILGen(mb.GetILGenerator());
+ }
+}
+
+//#endif
diff --git a/Clojure/Clojure/CljCompiler/GenClass.cs b/Clojure/Clojure/CljCompiler/GenClass.cs
index 8f50e847..e9dccd4e 100644
--- a/Clojure/Clojure/CljCompiler/GenClass.cs
+++ b/Clojure/Clojure/CljCompiler/GenClass.cs
@@ -8,21 +8,18 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler;
+using clojure.lang.CljCompiler.Ast;
+using clojure.lang.CljCompiler.Context;
+using Microsoft.Scripting.Generation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
-using clojure.lang.CljCompiler;
-using clojure.lang.CljCompiler.Ast;
-using Microsoft.Scripting.Generation;
namespace clojure.lang
-{
+{
public static class GenClass
{
#region Data
@@ -415,7 +412,7 @@ static void EmitMain(GenContext context, TypeBuilder proxyTB, string mainName, F
gen.MarkLabel(endLabel);
gen.Emit(OpCodes.Ret);
-#if NET462
+#if NETFRAMEWORK
//context.AssyBldr.SetEntryPoint(cb);
context.AssemblyBuilder.SetEntryPoint(cb);
#endif
diff --git a/Clojure/Clojure/CljCompiler/GenDelegate.cs b/Clojure/Clojure/CljCompiler/GenDelegate.cs
index 25b65b44..4f7584f0 100644
--- a/Clojure/Clojure/CljCompiler/GenDelegate.cs
+++ b/Clojure/Clojure/CljCompiler/GenDelegate.cs
@@ -8,15 +8,11 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
using System;
using System.Collections.Generic;
-using System.Reflection;
using System.Linq.Expressions;
-using clojure.lang.CljCompiler.Ast;
+using System.Reflection;
namespace clojure.lang
diff --git a/Clojure/Clojure/CljCompiler/GenInterface.cs b/Clojure/Clojure/CljCompiler/GenInterface.cs
index 490dc4fb..3332c515 100644
--- a/Clojure/Clojure/CljCompiler/GenInterface.cs
+++ b/Clojure/Clojure/CljCompiler/GenInterface.cs
@@ -8,15 +8,12 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
+using clojure.lang.CljCompiler.Context;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
-using clojure.lang.CljCompiler.Ast;
namespace clojure.lang
{
@@ -40,8 +37,13 @@ public static Type GenerateInterface(string iName, IPersistentMap attributes, Se
}
else
// TODO: In CLR4, should create a collectible type?
- context = GenContext.CreateWithExternalAssembly(iName+"_"+RT.nextID(), ".dll", false);
+ // TODO: This is temporry until we get things sorted out: SAVE9 !!!
+#if NETFRAMEWORK
+ context = GenContext.CreateWithExternalAssembly(iName+"_"+RT.nextID(), ".dll", false);
+#else
+ context = GenContext.CreateWithInternalAssembly(iName + "_" + RT.nextID(), false);
+#endif
for (ISeq s = RT.seq(extends); s != null; s = s.next())
{
object f = s.first();
@@ -73,12 +75,12 @@ public static Type GenerateInterface(string iName, IPersistentMap attributes, Se
//if ( Compiler.IsCompiling )
// context.SaveAssembly();
- Compiler.RegisterDuplicateType(t);
+ Compiler.RegisterDuplicateType(t);
return t;
}
- #endregion
+#endregion
#region Fun with attributes
diff --git a/Clojure/Clojure/CljCompiler/GenProxy.cs b/Clojure/Clojure/CljCompiler/GenProxy.cs
index f85e2da4..5dc27955 100644
--- a/Clojure/Clojure/CljCompiler/GenProxy.cs
+++ b/Clojure/Clojure/CljCompiler/GenProxy.cs
@@ -8,18 +8,14 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler;
+using clojure.lang.CljCompiler.Ast;
+using clojure.lang.CljCompiler.Context;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
-using clojure.lang.CljCompiler;
-using clojure.lang.CljCompiler.Ast;
-using Microsoft.Scripting.Generation;
using System.Runtime.Serialization;
namespace clojure.lang
@@ -122,6 +118,10 @@ Type Generate(Type superclass, ISeq interfaces, IPersistentMap attributes, strin
Type t = proxyTB.CreateType();
//if (Compiler.IsCompiling)
// SaveProxyContext();
+
+ if (Compiler.IsCompiling)
+ Compiler.RegisterDuplicateType(t);
+
return t;
}
diff --git a/Clojure/Clojure/Lib/RT.cs b/Clojure/Clojure/Lib/RT.cs
index b4107df8..2909137b 100644
--- a/Clojure/Clojure/Lib/RT.cs
+++ b/Clojure/Clojure/Lib/RT.cs
@@ -8,18 +8,16 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Context;
+using clojure.lang.Runtime;
+using Microsoft.Scripting.Hosting;
+using Microsoft.Scripting.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
-using System.Net;
-using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -27,9 +25,6 @@
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
-using clojure.lang.CljCompiler.Ast;
-using clojure.lang.Runtime;
-using Microsoft.Scripting.Hosting;
using RTProperties = clojure.runtime.Properties;
@@ -65,7 +60,7 @@ static IEnumerable GetAllTypesInNamespace(string nspace)
.SelectMany(t => getTypes(t))
.Where(t => (t.IsClass || t.IsInterface || t.IsValueType) &&
t.Namespace == nspace &&
- t.IsPublic &&
+ (t.IsPublic || t.IsNestedPublic) &&
!t.IsGenericTypeDefinition &&
!t.Name.StartsWith("_") &&
!t.Name.StartsWith("<"));
@@ -454,7 +449,18 @@ static RT()
try
{
+#if NETFRAMEWORK
+ Console.WriteLine("Framework!");
+#elif NET9_0_OR_GREATER
+ Console.WriteLine("Net 9! (or later)");
+#else
+ Console.WriteLine("must be 6 or 8");
+#endif
+
+ RT.StartStopwatch();
load("clojure/core");
+ RT.StopStopwatch();
+ Console.WriteLine("Clojure core loaded in " + _stopwatch.ElapsedMilliseconds + " milliseconds.");
}
finally
{
@@ -547,7 +553,7 @@ public static void PostBootstrapInit()
}
}
- #endregion
+#endregion
#region Id generation
@@ -2767,12 +2773,16 @@ public static Type classForName(string p)
// e.g. System.Environment in assemblies System.Private.CoreLib and System.Runtime.Exceptions.
// It is private in the former and public in the latter.
// Unfortunately, Type.GetType was finding the former.
- if (t != null && t.IsPublic)
+ if (t != null && (t.IsPublic || t.IsNestedPublic))
+ {
return t;
+ }
t = Compiler.FindDuplicateType(p);
if (t != null)
+ {
return t;
+ }
AppDomain domain = AppDomain.CurrentDomain;
Assembly[] assys = domain.GetAssemblies();
@@ -2783,42 +2793,41 @@ public static Type classForName(string p)
foreach (Assembly assy in assys)
{
Type t1 = assy.GetType(p, false);
- if (t1 != null && t1.IsPublic)
+ if (t1 != null && (t1.IsPublic || t1.IsNestedPublic))
+ {
return t1;
+ }
}
// slow path, will succeed for display names (returned by Type.Name)
// e.g. "Transform"
foreach (Assembly assy1 in assys)
{
- Type t1 = assy1.GetType(p, false);
+ Type t1 = null;
if (IsRunningOnMono)
{
// I do not know why Assembly.GetType fails to find types in our assemblies in Mono
- if (t1 == null)
+ if (!assy1.IsDynamic)
{
- if (!assy1.IsDynamic)
+ try
{
- try
- {
- foreach (Type tt in assy1.GetTypes())
+ foreach (Type tt in assy1.GetTypes())
+ {
+ if (tt.Name.Equals(p))
{
- if (tt.Name.Equals(p))
- {
- t1 = tt;
- break;
- }
+ t1 = tt;
+ break;
}
}
- catch (System.Reflection.ReflectionTypeLoadException)
- {
- }
+ }
+ catch (System.Reflection.ReflectionTypeLoadException)
+ {
}
}
}
-
+
if (t1 != null && !candidateTypes.Contains(t1))
candidateTypes.Add(t1);
}
@@ -2831,7 +2840,13 @@ public static Type classForName(string p)
t = null;
if (t == null && p.IndexOfAny(_triggerTypeChars) != -1)
+ {
t = ClrTypeSpec.GetTypeFromName(p);
+ if (t != null)
+ {
+ return t;
+ }
+ }
return t;
}
@@ -3260,7 +3275,7 @@ public static string StringReverse(string input)
#endregion
- # region Loading/compiling
+ #region Loading/compiling
public static void load(String relativePath)
diff --git a/Clojure/Clojure/Runtime/Binding/ClojureInvokeMemberBinder.cs b/Clojure/Clojure/Runtime/Binding/ClojureInvokeMemberBinder.cs
index f54e4113..32b6c0b1 100644
--- a/Clojure/Clojure/Runtime/Binding/ClojureInvokeMemberBinder.cs
+++ b/Clojure/Clojure/Runtime/Binding/ClojureInvokeMemberBinder.cs
@@ -8,21 +8,19 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
+using clojure.lang.CljCompiler.Ast;
+using clojure.lang.CljCompiler.Context;
+using Microsoft.Scripting.Actions;
+using Microsoft.Scripting.Actions.Calls;
+using Microsoft.Scripting.Runtime;
using System;
using System.Collections.Generic;
+using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
-using System.Dynamic;
-using Microsoft.Scripting.Runtime;
-using Microsoft.Scripting.Actions;
-using Microsoft.Scripting.Actions.Calls;
using System.Reflection;
using System.Reflection.Emit;
-using clojure.lang.CljCompiler.Ast;
namespace clojure.lang.Runtime.Binding
{
diff --git a/Clojure/Clojure/Runtime/Reflector.cs b/Clojure/Clojure/Runtime/Reflector.cs
index 824409e4..55cebbda 100644
--- a/Clojure/Clojure/Runtime/Reflector.cs
+++ b/Clojure/Clojure/Runtime/Reflector.cs
@@ -8,24 +8,21 @@
* You must not remove this notice, or any other, from this software.
**/
-/**
- * Author: David Miller
- **/
-
+using clojure.lang.CljCompiler.Ast;
+using clojure.lang.CljCompiler.Context;
+using clojure.lang.Runtime;
+using clojure.lang.Runtime.Binding;
+using Microsoft.Scripting.Actions;
+using Microsoft.Scripting.Actions.Calls;
+using Microsoft.Scripting.Runtime;
using System;
using System.Collections.Generic;
+using System.Dynamic;
using System.Linq;
-using System.Reflection;
using System.Linq.Expressions;
-using Microsoft.Scripting.Actions;
-using System.Dynamic;
-using Microsoft.Scripting.Actions.Calls;
-using Microsoft.Scripting.Runtime;
-using clojure.lang.CljCompiler.Ast;
-using System.Text;
-using clojure.lang.Runtime.Binding;
-using clojure.lang.Runtime;
+using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Text;
namespace clojure.lang
{
diff --git a/Clojure/Csharp.Tests/LibTests/FutureTests.cs b/Clojure/Csharp.Tests/LibTests/FutureTests.cs
index e83cbb2a..baf65c3e 100644
--- a/Clojure/Csharp.Tests/LibTests/FutureTests.cs
+++ b/Clojure/Csharp.Tests/LibTests/FutureTests.cs
@@ -74,7 +74,7 @@ public void PropagatesExceptions()
}
}
-#if NET462
+#if NETFRAMEWORK
// Thread.Abort not supported in .Net Core
[Test]
@@ -112,7 +112,7 @@ public void CancelFailsAfterSuccessfulCompletion()
Expect(f.isCancelled()).To.Equal(false);
}
-#if NET462
+#if NETFRAMEWORK
// Thread.Abort not supported in .Net Core
[Test]
[ExpectedException(typeof(FutureAbortedException))]
diff --git a/Clojure/Csharp.Tests/LibTests/GenProxyTests.cs b/Clojure/Csharp.Tests/LibTests/GenProxyTests.cs
index 2f71a6a0..dd2ca94f 100644
--- a/Clojure/Csharp.Tests/LibTests/GenProxyTests.cs
+++ b/Clojure/Csharp.Tests/LibTests/GenProxyTests.cs
@@ -821,7 +821,7 @@ public class Impl3 : Impl2
{
}
-#if NET462
+#if NETFRAMEWORK
[Test]
public void FindTypeInAssembly()
{
@@ -922,7 +922,7 @@ public interface I1
int m2(int x);
}
-#if NET462
+#if NETFRAMEWORK
[Test]
public void CanCreateConcreteImplementationOverAbstractProperty()
{