Skip to content

Commit f2e286b

Browse files
author
Chaowlert
committed
wip
1 parent 85d2b25 commit f2e286b

File tree

3 files changed

+57
-46
lines changed

3 files changed

+57
-46
lines changed

ExpressionDebugger/ExpressionCompiler.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@ public void AddFile(string code, string filename)
2525
{
2626
var buffer = Encoding.UTF8.GetBytes(code);
2727

28-
var path = _options?.RootPath == null ? filename : Path.Combine(_options.RootPath, filename);
28+
var path = filename;
2929
if (_options?.EmitFile == true)
3030
{
31+
var root = _options?.RootPath;
32+
if (root == null)
33+
root = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "GeneratedSources");
34+
Directory.CreateDirectory(root);
35+
path = Path.Combine(root, filename);
3136
using (var fs = new FileStream(path, FileMode.Create))
3237
{
3338
fs.Write(buffer, 0, buffer.Length);
@@ -56,7 +61,7 @@ public Assembly CreateAssembly(IEnumerable<Assembly> assemblies)
5661
assemblyName,
5762
_codes,
5863
references,
59-
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, usings: new[] { "System" } )
64+
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, usings: new[] { "System" })
6065
.WithOptimizationLevel(_options?.IsRelease == true ? OptimizationLevel.Release : OptimizationLevel.Debug)
6166
.WithPlatform(Platform.AnyCpu)
6267
);

ExpressionDebugger/ExpressionExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ public static Delegate CompileWithDebugInfo(this LambdaExpression node, Expressi
5454
references.Add(typeof(object).Assembly);
5555
references.Add(Assembly.Load(new AssemblyName("System.Runtime")));
5656
references.Add(Assembly.Load(new AssemblyName("System.Collections")));
57-
//references.Add(Assembly.Load(new AssemblyName("System.Core")));
57+
if (translator.HasDynamic)
58+
references.Add(Assembly.Load(new AssemblyName("Microsoft.CSharp")));
5859

5960
var assembly = compiler.CreateAssembly(references);
6061
var typeName = definitions.Namespace == null

ExpressionDebugger/ExpressionTranslator.cs

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public class ExpressionTranslator : ExpressionVisitor
2424
public Dictionary<object, string> Constants => _constants ?? (_constants = new Dictionary<object, string>());
2525
public Dictionary<Type, string> TypeNames => _typeNames ?? (_typeNames = new Dictionary<Type, string>());
2626

27+
public bool HasDynamic { get; private set; }
28+
2729
public ExpressionTranslator(ExpressionDefinitions definitions = null)
2830
{
2931
_definitions = definitions;
@@ -220,7 +222,7 @@ private void WriteLine()
220222
{
221223
_writer.WriteLine();
222224

223-
var spaceCount = _indentLevel*Tabsize;
225+
var spaceCount = _indentLevel * Tabsize;
224226
_writer.Write(new string(' ', spaceCount));
225227
}
226228

@@ -416,8 +418,11 @@ private string Translate(Type type)
416418
return "ushort";
417419
if (type == typeof(void))
418420
return "void";
419-
if (typeof(IDynamicMetaObjectProvider).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
421+
if (type.IsNotPublic || typeof(IDynamicMetaObjectProvider).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
422+
{
423+
HasDynamic = true;
420424
return "dynamic";
425+
}
421426

422427
if (type.IsArray)
423428
{
@@ -490,8 +495,8 @@ private static bool IsInline(Expression node)
490495
switch (node.NodeType)
491496
{
492497
case ExpressionType.Conditional:
493-
var condExpr = (ConditionalExpression) node;
494-
return condExpr.Type != typeof (void) && IsInline(condExpr.IfTrue) && IsInline(condExpr.IfFalse);
498+
var condExpr = (ConditionalExpression)node;
499+
return condExpr.Type != typeof(void) && IsInline(condExpr.IfTrue) && IsInline(condExpr.IfFalse);
495500

496501
case ExpressionType.Block:
497502
case ExpressionType.DebugInfo:
@@ -512,16 +517,16 @@ private Expression VisitMultiline(Expression node, bool shouldReturn)
512517
switch (node.NodeType)
513518
{
514519
case ExpressionType.Block:
515-
return VisitBlock((BlockExpression) node, shouldReturn);
520+
return VisitBlock((BlockExpression)node, shouldReturn);
516521

517522
case ExpressionType.Conditional:
518523
return VisitConditional((ConditionalExpression)node, shouldReturn);
519524

520525
case ExpressionType.Try:
521-
return VisitTry((TryExpression) node, shouldReturn);
526+
return VisitTry((TryExpression)node, shouldReturn);
522527

523528
case ExpressionType.Switch:
524-
return VisitSwitch((SwitchExpression) node, shouldReturn);
529+
return VisitSwitch((SwitchExpression)node, shouldReturn);
525530

526531
//case ExpressionType.DebugInfo:
527532
//case ExpressionType.Goto:
@@ -534,12 +539,12 @@ private Expression VisitMultiline(Expression node, bool shouldReturn)
534539
private Expression VisitBody(Expression node, bool shouldReturn = false)
535540
{
536541
if (node.NodeType == ExpressionType.Block)
537-
return VisitBlock((BlockExpression) node, shouldReturn);
542+
return VisitBlock((BlockExpression)node, shouldReturn);
538543

539544
if (node.NodeType == ExpressionType.Default && node.Type == typeof(void))
540545
return node;
541546

542-
var lines = VisitBlockBody(new List<Expression> {node}, shouldReturn);
547+
var lines = VisitBlockBody(new List<Expression> { node }, shouldReturn);
543548
return Expression.Block(lines);
544549
}
545550

@@ -602,7 +607,7 @@ private Expression VisitBlock(BlockExpression node, bool shouldReturn)
602607
if (hasDeclaration)
603608
WriteLine();
604609

605-
var lines = VisitBlockBody(node.Expressions, shouldReturn && node.Type != typeof (void));
610+
var lines = VisitBlockBody(node.Expressions, shouldReturn && node.Type != typeof(void));
606611
return Expression.Block(list, lines);
607612
}
608613

@@ -846,15 +851,15 @@ protected override Expression VisitDynamic(DynamicExpression node)
846851
{
847852
var expr = VisitGroup(node.Arguments[0], ExpressionType.Index);
848853
var args = VisitArguments("[", node.Arguments.Skip(1).ToList(), Visit, "]");
849-
return Update(node, new[] {expr}.Concat(args));
854+
return Update(node, new[] { expr }.Concat(args));
850855
}
851856
if (node.Binder is SetIndexBinder)
852857
{
853858
var expr = VisitGroup(node.Arguments[0], ExpressionType.Index);
854859
var args = VisitArguments("[", node.Arguments.Skip(1).Take(node.Arguments.Count - 2).ToList(), Visit, "]");
855860
Write(" = ");
856861
var value = VisitGroup(node.Arguments[node.Arguments.Count - 1], ExpressionType.Assign);
857-
return Update(node, new[] {expr}.Concat(args).Concat(new[] {value}));
862+
return Update(node, new[] { expr }.Concat(args).Concat(new[] { value }));
858863
}
859864
if (node.Binder is DeleteIndexBinder)
860865
{
@@ -935,7 +940,7 @@ protected override ElementInit VisitElementInit(ElementInit node)
935940
if (node.Arguments.Count == 1)
936941
{
937942
var arg = Visit(node.Arguments[0]);
938-
var args = arg != node.Arguments[0] ? new[] {arg}.AsEnumerable() : node.Arguments;
943+
var args = arg != node.Arguments[0] ? new[] { arg }.AsEnumerable() : node.Arguments;
939944
return node.Update(args);
940945
}
941946
else
@@ -1038,12 +1043,7 @@ private Expression VisitMember(Expression instance, Expression node, MemberInfo
10381043
}
10391044
else
10401045
{
1041-
if (member is PropertyInfo p && p.GetIndexParameters().Length == 0 && (member.DeclaringType.IsNotPublic || p.GetGetMethod() == null))
1042-
Write(GetConstant(p.GetValue(null), member.Name));
1043-
else if (member is FieldInfo f && (member.DeclaringType.IsNotPublic || !f.IsPublic))
1044-
Write(GetConstant(f.GetValue(null), member.Name));
1045-
else
1046-
Write(Translate(member.DeclaringType), ".", member.Name);
1046+
Write(Translate(member.DeclaringType), ".", member.Name);
10471047
return null;
10481048
}
10491049
}
@@ -1155,7 +1155,7 @@ protected override Expression VisitLambda<T>(Expression<T> node)
11551155
}
11561156
}
11571157

1158-
private IList<T> VisitElements<T>(IList<T> list, Func<T, T> func) where T: class
1158+
private IList<T> VisitElements<T>(IList<T> list, Func<T, T> func) where T : class
11591159
{
11601160
var wrap = true;
11611161
if (list.Count == 0)
@@ -1186,7 +1186,7 @@ protected override Expression VisitLoop(LoopExpression node)
11861186
Expression body;
11871187
if (node.Body.NodeType == ExpressionType.Conditional)
11881188
{
1189-
var condExpr = (ConditionalExpression) node.Body;
1189+
var condExpr = (ConditionalExpression)node.Body;
11901190

11911191
if (condExpr.IfFalse is GotoExpression @break && @break.Target == node.BreakLabel)
11921192
{
@@ -1229,7 +1229,7 @@ protected override MemberAssignment VisitMemberAssignment(MemberAssignment node)
12291229

12301230
protected override Expression VisitMemberInit(MemberInitExpression node)
12311231
{
1232-
var @new = (NewExpression) Visit(node.NewExpression);
1232+
var @new = (NewExpression)Visit(node.NewExpression);
12331233
var args = VisitElements(node.Bindings, VisitMemberBinding);
12341234
return node.Update(@new, args);
12351235
}
@@ -1250,6 +1250,9 @@ protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBind
12501250

12511251
private static Type GetDelegateType(MethodInfo method)
12521252
{
1253+
if (method.GetParameters().Any(it => it.IsOut || it.ParameterType.IsByRef))
1254+
throw new InvalidOperationException("Cannot handle non-public method");
1255+
12531256
if (method.ReturnType == typeof(void))
12541257
{
12551258
switch (method.GetParameters().Length)
@@ -1271,7 +1274,7 @@ private static Type GetDelegateType(MethodInfo method)
12711274
case 14: return typeof(Action<,,,,,,,,,,,,,>);
12721275
case 15: return typeof(Action<,,,,,,,,,,,,,,>);
12731276
case 16: return typeof(Action<,,,,,,,,,,,,,,,>);
1274-
default: return typeof(Delegate);
1277+
default: throw new InvalidOperationException("Cannot handle non-public method");
12751278
}
12761279
}
12771280
else
@@ -1295,7 +1298,7 @@ private static Type GetDelegateType(MethodInfo method)
12951298
case 14: return typeof(Func<,,,,,,,,,,,,,,>);
12961299
case 15: return typeof(Func<,,,,,,,,,,,,,,,>);
12971300
case 16: return typeof(Func<,,,,,,,,,,,,,,,,>);
1298-
default: return typeof(Delegate);
1301+
default: throw new InvalidOperationException("Cannot handle non-public method");
12991302
}
13001303
}
13011304
}
@@ -1315,22 +1318,15 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
13151318
{
13161319
isNotPublic = true;
13171320
var del = GetDelegateType(node.Method);
1318-
if (del == typeof(Delegate))
1321+
if (del.IsGenericTypeDefinition)
13191322
{
1320-
Write("(", Translate(node.Method.ReturnType), ")", GetConstant(del, GetVarName(node.Method.Name)), ".DynamicInvoke");
1321-
}
1322-
else
1323-
{
1324-
if (del.IsGenericTypeDefinition)
1325-
{
1326-
var types = node.Method.GetParameters().Select(it => it.ParameterType);
1327-
if (node.Method.ReturnType != typeof(void))
1328-
types = types.Concat(new[] { node.Method.ReturnType });
1329-
del = del.MakeGenericType(types.ToArray());
1330-
}
1331-
var func = node.Method.CreateDelegate(del);
1332-
Write(GetConstant(func, GetVarName(node.Method.Name)), ".Invoke");
1323+
var types = node.Method.GetParameters().Select(it => it.ParameterType);
1324+
if (node.Method.ReturnType != typeof(void))
1325+
types = types.Concat(new[] { node.Method.ReturnType });
1326+
del = del.MakeGenericType(types.ToArray());
13331327
}
1328+
var func = node.Method.CreateDelegate(del);
1329+
Write(GetConstant(func, GetVarName(node.Method.Name)), ".Invoke");
13341330
}
13351331
else if (node.Method.GetCustomAttribute<ExtensionAttribute>() != null)
13361332
{
@@ -1370,7 +1366,7 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
13701366
if (isExtension)
13711367
{
13721368
var args = VisitArguments("(", node.Arguments.Skip(1).ToList(), Visit, ")", prefix: prefix.Skip(1).ToList());
1373-
var newArgs = new[] {arg0}.Concat(args).ToList();
1369+
var newArgs = new[] { arg0 }.Concat(args).ToList();
13741370
return newArgs.SequenceEqual(node.Arguments) ? node : node.Update(obj, newArgs);
13751371
}
13761372
else
@@ -1391,19 +1387,28 @@ protected override Expression VisitNewArray(NewArrayExpression node)
13911387
{
13921388
if (node.NodeType == ExpressionType.NewArrayBounds)
13931389
{
1394-
Write("new ", Translate(node.Type.GetElementType()));
1390+
var elemType = node.Type.GetElementType();
1391+
var arrayCount = 1;
1392+
while (elemType.IsArray)
1393+
{
1394+
elemType = elemType.GetElementType();
1395+
arrayCount++;
1396+
}
1397+
Write("new ", Translate(elemType));
13951398
var args = VisitArguments("[", node.Expressions, Visit, "]");
1399+
for (int i = 1; i < arrayCount; i++)
1400+
Write("[]");
13961401
return node.Update(args);
13971402
}
13981403
else
13991404
{
1400-
Write("new[]");
1405+
Write("new ", Translate(node.Type));
14011406
var args = VisitElements(node.Expressions, Visit);
14021407
return node.Update(args);
14031408
}
14041409
}
14051410

1406-
#region _reservedWords
1411+
#region _reservedWords
14071412
private static readonly HashSet<string> ReservedWords = new HashSet<string>
14081413
{
14091414
"abstract",
@@ -1494,7 +1499,7 @@ protected override Expression VisitNewArray(NewArrayExpression node)
14941499
"false",
14951500
"true",
14961501
};
1497-
#endregion
1502+
#endregion
14981503

14991504
protected override Expression VisitParameter(ParameterExpression node)
15001505
{

0 commit comments

Comments
 (0)