public override void Compile(EmitCompilerContext context, EmitIl il) { foreach (var statement in Statements) { statement.Compile(context, il); } }
public override void Compile(EmitCompilerContext context, EmitIl il) { var arrayType = GetExpressionType(); if (Lengths.Count == 1) { il.Emit(EmitOpCodes.Ldc_I4, Lengths[0]); il.Emit(EmitOpCodes.Newarr, Type); for (var i = 0; i < Initializer.Length; i++) { var element = (EmitExpression)Initializer[i]; il.Emit(EmitOpCodes.Dup); il.Emit(EmitOpCodes.Ldc_I4, i); element.Compile(context, il); il.Emit(EmitOpCodes.Stelem, Type); } } else { var constructor = arrayType.Members.OfType <EmitConstructor>().Single(x => x.Parameters.Count() == Rank); var setter = arrayType.Members.OfType <EmitMethod>().Single(x => x.Name == "Set"); foreach (var length in Lengths) { il.Emit(EmitOpCodes.Ldc_I4, length); } il.Emit(EmitOpCodes.Newobj, constructor); var indices = new int[Lengths.Count]; Action <int, IEmitArrayElement> recurse = null; recurse = (level, element) => { if (level == Rank - 1) { var expression = (EmitExpression)element; il.Emit(EmitOpCodes.Dup); foreach (var index in indices) { il.Emit(EmitOpCodes.Ldc_I4, index); } expression.Compile(context, il); il.Emit(EmitOpCodes.Call, setter); } else { for (var i = 0; i < element.Length; i++) { indices[level + 1] = i; var current = element[i]; recurse(level + 1, current); } } }; for (var i = 0; i < Initializer.Length; i++) { var element = Initializer[i]; indices[0] = i; recurse(0, element); } } }
public override void Compile(EmitCompilerContext context, EmitIl il) { Condition.Compile(context, il); var ifNotTrue = il.DefineLabel(); il.Emit(EmitOpCodes.Brfalse, ifNotTrue); Statement.Compile(context, il); var statementReturned = il.Instructions.Last().OpCode == EmitOpCodes.Ret; if (Else != null) { EmitLabel end = null; if (!statementReturned) { end = il.DefineLabel(); il.Emit(EmitOpCodes.Br, end); } il.MarkLabel(ifNotTrue); Else.Compile(context, il); if (!statementReturned) { il.MarkLabel(end); il.Emit(EmitOpCodes.Nop); } } else { il.MarkLabel(ifNotTrue); } }
public override void Compile(EmitCompilerContext context, EmitIl il) { switch (Operator) { case EmitBinaryOperator.Assign: ((IEmitReferenceExpression)Left).CompileAssignment(context, il, () => Right.Compile(context, il)); break; case EmitBinaryOperator.BooleanAnd: Left.Compile(context, il); il.Emit(EmitOpCodes.Dup); var andEnd = il.DefineLabel(); il.Emit(EmitOpCodes.Brfalse, andEnd); il.Emit(EmitOpCodes.Pop); Right.Compile(context, il); il.MarkLabel(andEnd); break; case EmitBinaryOperator.BooleanOr: Left.Compile(context, il); il.Emit(EmitOpCodes.Dup); var orEnd = il.DefineLabel(); il.Emit(EmitOpCodes.Brtrue, orEnd); il.Emit(EmitOpCodes.Pop); Right.Compile(context, il); il.MarkLabel(orEnd); break; default: var instruction = GetOpCode(); var isInverted = IsOperatorInverse(); var isAssignment = IsOperatorAssignment(); Left.Compile(context, il); Right.Compile(context, il); il.Emit(instruction); if (isInverted) { il.Emit(EmitOpCodes.Ldc_I4_0); il.Emit(EmitOpCodes.Ceq); } if (isAssignment) { var local = il.DeclareLocal(typeof(bool)); il.Emit(EmitOpCodes.Stloc, local); ((IEmitReferenceExpression)Left).CompileAssignment(context, il, () => il.Emit(EmitOpCodes.Ldloc, local)); } break; } }
public override void Compile(EmitCompilerContext context, EmitIl il) { if (Value == null) { il.Emit(EmitOpCodes.Ldnull); } else if (Value is int) { il.Emit(EmitOpCodes.Ldc_I4, (int)Value); } else if (Value is long) { il.Emit(EmitOpCodes.Ldc_I8, (long)Value); } else if (Value is float) { il.Emit(EmitOpCodes.Ldc_R4, (float)Value); } else if (Value is double) { il.Emit(EmitOpCodes.Ldc_R8, (double)Value); } else if (Value is bool) { il.Emit(EmitOpCodes.Ldc_I4, (bool)Value ? 1 : 0); } else if (Value is string) { il.Emit(EmitOpCodes.Ldstr, (string)Value); } else { throw new Exception(); } }
public override void Compile(EmitCompilerContext context, EmitIl il) { Initializer?.Compile(context, il); var start = il.DefineLabel(); var end = il.DefineLabel(); il.MarkLabel(start); if (Predicate != null) { Predicate.Compile(context, il); } else { il.Emit(EmitOpCodes.Ldc_I4_1); } il.Emit(EmitOpCodes.Brfalse, end); Body.Compile(context, il); Incrementor?.Compile(context, il); il.Emit(EmitOpCodes.Br, start); il.MarkLabel(end); }
public void CompileAssignment(EmitCompilerContext context, EmitIl il, Action compileValue) { var local = Variable.GetData(context); compileValue(); il.Emit(EmitOpCodes.Dup); // We want to leave the assigned value on the stack, since assignment is an expression il.Emit(EmitOpCodes.Stloc, local); }
public override void Compile(EmitCompilerContext context, EmitIl il) { foreach (var variable in Variables) { var local = il.DeclareLocal(variable.Type); variable.SetData(context, local); } }
public override void Compile(EmitCompilerContext context, EmitIl il) { var arrayType = GetExpressionType(); if (Lengths.Count == 1) { il.Emit(EmitOpCodes.Ldc_I4, Lengths[0]); il.Emit(EmitOpCodes.Newarr, Type); for (var i = 0; i < Initializer.Length; i++) { var element = (EmitExpression)Initializer[i]; il.Emit(EmitOpCodes.Dup); il.Emit(EmitOpCodes.Ldc_I4, i); element.Compile(context, il); il.Emit(EmitOpCodes.Stelem, Type); } } else { var constructor = arrayType.Members.OfType<EmitConstructor>().Single(x => x.Parameters.Count() == Rank); var setter = arrayType.Members.OfType<EmitMethod>().Single(x => x.Name == "Set"); foreach (var length in Lengths) il.Emit(EmitOpCodes.Ldc_I4, length); il.Emit(EmitOpCodes.Newobj, constructor); var indices = new int[Lengths.Count]; Action<int, IEmitArrayElement> recurse = null; recurse = (level, element) => { if (level == Rank - 1) { var expression = (EmitExpression)element; il.Emit(EmitOpCodes.Dup); foreach (var index in indices) { il.Emit(EmitOpCodes.Ldc_I4, index); } expression.Compile(context, il); il.Emit(EmitOpCodes.Call, setter); } else { for (var i = 0; i < element.Length; i++) { indices[level + 1] = i; var current = element[i]; recurse(level + 1, current); } } }; for (var i = 0; i < Initializer.Length; i++) { var element = Initializer[i]; indices[0] = i; recurse(0, element); } } }
public override void Compile(EmitCompilerContext context, EmitIl il) { if (Arguments.Count != Method.Parameters.Count()) throw new Exception($"Incorrect number of arguments passed to method {Method}"); Target?.Compile(context, il); foreach (var argument in Arguments) argument.Compile(context, il); var opCode = Method.IsVirtual || Method.DeclaringType.IsInterface ? (IEmitOpCodeMethod)EmitOpCodes.Callvirt : EmitOpCodes.Call; il.Emit(opCode, Method); }
public override void Compile(EmitCompilerContext context, EmitIl il) { Expression.Compile(context, il); var expressionType = Expression.GetExpressionType(); EmitType voidType = typeof(void); if (expressionType.IsValueType && !context.Method.ReturnType.IsValueType && !Equals(expressionType, voidType)) { il.Emit(EmitOpCodes.Box, Expression.GetExpressionType()); } // else if (!Expression.GetType(context.TypeSystem).IsValueType && !context.Method.ReturnType.IsValueType) // { // // } il.Emit(EmitOpCodes.Ret); }
public override void Compile(EmitCompilerContext context, EmitIl il) { if (Arguments.Count != Method.Parameters.Count()) { throw new Exception($"Incorrect number of arguments passed to method {Method}"); } Target?.Compile(context, il); foreach (var argument in Arguments) { argument.Compile(context, il); } var opCode = Method.IsVirtual || Method.DeclaringType.IsInterface ? (IEmitOpCodeMethod)EmitOpCodes.Callvirt : EmitOpCodes.Call; il.Emit(opCode, Method); }
public override void Compile(EmitCompilerContext context, EmitIl il) { if (Lengths.Count == 1) { Lengths[0].Compile(context, il); il.Emit(EmitOpCodes.Newarr, Type); } else { var arrayType = GetExpressionType(); var constructor = arrayType.Members.OfType<EmitConstructor>().Single(x => x.Parameters.Count() == Lengths.Count); foreach (var length in Lengths) { length.Compile(context, il); } il.Emit(EmitOpCodes.Newobj, constructor); } }
public override void Compile(EmitCompilerContext context, EmitIl il) { if (Lengths.Count == 1) { Lengths[0].Compile(context, il); il.Emit(EmitOpCodes.Newarr, Type); } else { var arrayType = GetExpressionType(); var constructor = arrayType.Members.OfType <EmitConstructor>().Single(x => x.Parameters.Count() == Lengths.Count); foreach (var length in Lengths) { length.Compile(context, il); } il.Emit(EmitOpCodes.Newobj, constructor); } }
public override void Compile(EmitCompilerContext context, EmitIl il) { // Special handling for value types without a constructor if (Constructor == null) { var local = il.DeclareLocal(Type); il.Emit(EmitOpCodes.Ldloca, local); il.Emit(EmitOpCodes.Initobj, Type); il.Emit(EmitOpCodes.Ldloc, local); return; } foreach (var argument in Arguments) { argument.Compile(context, il); } il.Emit(EmitOpCodes.Newobj, Constructor); }
public override void Compile(EmitCompilerContext context, EmitIl il) { if (Value == null) il.Emit(EmitOpCodes.Ldnull); else if (Value is int) il.Emit(EmitOpCodes.Ldc_I4, (int)Value); else if (Value is long) il.Emit(EmitOpCodes.Ldc_I8, (long)Value); else if (Value is float) il.Emit(EmitOpCodes.Ldc_R4, (float)Value); else if (Value is double) il.Emit(EmitOpCodes.Ldc_R8, (double)Value); else if (Value is bool) il.Emit(EmitOpCodes.Ldc_I4, (bool)Value ? 1 : 0); else if (Value is string) il.Emit(EmitOpCodes.Ldstr, (string)Value); else throw new Exception(); }
public override void Compile(EmitCompilerContext context, EmitIl il) { var item = il.DeclareLocal(Item.Type); Item.SetData(context, item); EmitType genericEnumerableType = typeof(IEnumerable <>); var enumerableType = genericEnumerableType.MakeGenericType(Item.Type); var getEnumeratorMethod = enumerableType.Members.OfType <EmitMethod>().Single(x => x.Name == nameof(IEnumerable <object> .GetEnumerator)); EmitType genericEnumeratorType = typeof(IEnumerator <>); var enumeratorType = genericEnumeratorType.MakeGenericType(Item.Type); var moveNextMethod = enumerableType.Members.OfType <EmitMethod>().Single(x => x.Name == nameof(IEnumerator <object> .MoveNext)); var getCurrentMethod = enumerableType.Members.OfType <EmitProperty>().Single(x => x.Name == nameof(IEnumerator <object> .Current)).GetMethod; var enumerator = il.DeclareLocal(enumeratorType); Collection.Compile(context, il); il.Emit(EmitOpCodes.Callvirt, getEnumeratorMethod); il.Emit(EmitOpCodes.Stloc, enumerator); var topOfLoop = il.DefineLabel(); var end = il.DefineLabel(); il.MarkLabel(topOfLoop); il.Emit(EmitOpCodes.Ldloc, enumerator); il.Emit(EmitOpCodes.Callvirt, moveNextMethod); il.Emit(EmitOpCodes.Brfalse, end); il.Emit(EmitOpCodes.Ldloc, enumerator); il.Emit(EmitOpCodes.Callvirt, getCurrentMethod); il.Emit(EmitOpCodes.Stloc, item); Statement.Compile(context, il); il.Emit(EmitOpCodes.Br, topOfLoop); il.MarkLabel(end); il.Emit(EmitOpCodes.Nop); }
public override void Compile(EmitCompilerContext context, EmitIl il) { var item = il.DeclareLocal(Item.Type); Item.SetData(context, item); EmitType genericEnumerableType = typeof(IEnumerable<>); var enumerableType = genericEnumerableType.MakeGenericType(Item.Type); var getEnumeratorMethod = enumerableType.Members.OfType<EmitMethod>().Single(x => x.Name == nameof(IEnumerable<object>.GetEnumerator)); EmitType genericEnumeratorType = typeof(IEnumerator<>); var enumeratorType = genericEnumeratorType.MakeGenericType(Item.Type); var moveNextMethod = enumerableType.Members.OfType<EmitMethod>().Single(x => x.Name == nameof(IEnumerator<object>.MoveNext)); var getCurrentMethod = enumerableType.Members.OfType<EmitProperty>().Single(x => x.Name == nameof(IEnumerator<object>.Current)).GetMethod; var enumerator = il.DeclareLocal(enumeratorType); Collection.Compile(context, il); il.Emit(EmitOpCodes.Callvirt, getEnumeratorMethod); il.Emit(EmitOpCodes.Stloc, enumerator); var topOfLoop = il.DefineLabel(); var end = il.DefineLabel(); il.MarkLabel(topOfLoop); il.Emit(EmitOpCodes.Ldloc, enumerator); il.Emit(EmitOpCodes.Callvirt, moveNextMethod); il.Emit(EmitOpCodes.Brfalse, end); il.Emit(EmitOpCodes.Ldloc, enumerator); il.Emit(EmitOpCodes.Callvirt, getCurrentMethod); il.Emit(EmitOpCodes.Stloc, item); Statement.Compile(context, il); il.Emit(EmitOpCodes.Br, topOfLoop); il.MarkLabel(end); il.Emit(EmitOpCodes.Nop); }
public override void Compile(EmitCompilerContext context, EmitIl il) { var local = Variable.GetData(context); il.Emit(EmitOpCodes.Ldloc, local); }
public abstract void Compile(EmitCompilerContext context, EmitIl il);
public override void Compile(EmitCompilerContext context, EmitIl il) { Expression.Compile(context, il); il.Emit(EmitOpCodes.Pop); }
public override void Compile(EmitCompilerContext context, EmitIl il) { Operand.Compile(context, il); var operandType = Operand.GetExpressionType(); EmitType typeInt = typeof(int); EmitType typeUint = typeof(uint); EmitType typeShort = typeof(short); EmitType typeUshort = typeof(ushort); EmitType typeByte = typeof(byte); EmitType typeSbyte = typeof(sbyte); EmitType typeLong = typeof(long); EmitType typeUlong = typeof(ulong); EmitType typeDouble = typeof(double); EmitType typeFloat = typeof(float); EmitType typeDecimal = typeof(decimal); EmitType typeBool = typeof(bool); var typeIs32Bit = Equals(Type, typeByte) || Equals(Type, typeShort) || Equals(Type, typeInt) || Equals(Type, typeSbyte) || Equals(Type, typeUshort) || Equals(Type, typeUint); var operandIs32Bit = Equals(operandType, typeByte) || Equals(operandType, typeShort) || Equals(operandType, typeInt) || Equals(operandType, typeSbyte) || Equals(operandType, typeUshort) || Equals(operandType, typeUint); var typeIsFloatingPoint = Equals(Type, typeFloat) || Equals(Type, typeDouble); var operandIsFloatingPoint = Equals(operandType, typeFloat) || Equals(operandType, typeDouble); if (operandIs32Bit || operandIsFloatingPoint || Equals(operandType, typeLong)) { if (Equals(Type, operandType)) { return; } if (Equals(Type, typeFloat)) { il.Emit(EmitOpCodes.Conv_R4); return; } if (Equals(Type, typeDouble)) { il.Emit(EmitOpCodes.Conv_R8); return; } if (Equals(Type, typeByte)) { il.Emit(EmitOpCodes.Conv_U1); return; } if (Equals(Type, typeSbyte)) { il.Emit(EmitOpCodes.Conv_I1); return; } if (Equals(Type, typeShort)) { il.Emit(EmitOpCodes.Conv_I2); return; } if (Equals(Type, typeUshort)) { il.Emit(EmitOpCodes.Conv_U2); return; } if (Equals(Type, typeInt)) { il.Emit(EmitOpCodes.Conv_I4); return; } if (Equals(Type, typeUint)) { il.Emit(EmitOpCodes.Conv_U4); return; } if (Equals(Type, typeLong)) { il.Emit(EmitOpCodes.Conv_I8); return; } if (Equals(Type, typeUlong)) { il.Emit(EmitOpCodes.Conv_U8); return; } } // All else fails, then: il.Emit(EmitOpCodes.Castclass, Type); }
public override void Compile(EmitCompilerContext context, EmitIl il) { switch (Operator) { case EmitUnaryOperator.BooleanNot: Operand.Compile(context, il); il.Emit(EmitOpCodes.Ldc_I4_0); il.Emit(EmitOpCodes.Ceq); break; case EmitUnaryOperator.BitwiseNot: Operand.Compile(context, il); il.Emit(EmitOpCodes.Not); break; case EmitUnaryOperator.Minus: Operand.Compile(context, il); il.Emit(EmitOpCodes.Neg); break; case EmitUnaryOperator.Plus: Operand.Compile(context, il); break; case EmitUnaryOperator.PostfixDecrement: { Operand.Compile(context, il); var local = il.DeclareLocal(Operand.GetExpressionType()); il.Emit(EmitOpCodes.Stloc, local); ((IEmitReferenceExpression)Operand).CompileAssignment(context, il, () => { il.Emit(EmitOpCodes.Ldloc, local); il.Emit(EmitOpCodes.Ldc_I4_1); il.Emit(EmitOpCodes.Sub); }); il.Emit(EmitOpCodes.Pop); il.Emit(EmitOpCodes.Ldloc, local); break; } case EmitUnaryOperator.PostfixIncrement: { Operand.Compile(context, il); var local = il.DeclareLocal(Operand.GetExpressionType()); il.Emit(EmitOpCodes.Stloc, local); ((IEmitReferenceExpression)Operand).CompileAssignment(context, il, () => { il.Emit(EmitOpCodes.Ldloc, local); il.Emit(EmitOpCodes.Ldc_I4_1); il.Emit(EmitOpCodes.Add); }); il.Emit(EmitOpCodes.Pop); il.Emit(EmitOpCodes.Ldloc, local); break; } case EmitUnaryOperator.PrefixDecrement: { Operand.Compile(context, il); il.Emit(EmitOpCodes.Ldc_I4_1); il.Emit(EmitOpCodes.Sub); var local = il.DeclareLocal(Operand.GetExpressionType()); il.Emit(EmitOpCodes.Stloc, local); ((IEmitReferenceExpression)Operand).CompileAssignment(context, il, () => { il.Emit(EmitOpCodes.Ldloc, local); }); break; } case EmitUnaryOperator.PrefixIncrement: { Operand.Compile(context, il); il.Emit(EmitOpCodes.Ldc_I4_1); il.Emit(EmitOpCodes.Add); var local = il.DeclareLocal(Operand.GetExpressionType()); il.Emit(EmitOpCodes.Stloc, local); ((IEmitReferenceExpression)Operand).CompileAssignment(context, il, () => { il.Emit(EmitOpCodes.Ldloc, local); }); break; } } }
private void GenerateIl(ILGenerator il, EmitIl emitIl) { var locals = emitIl.Locals.ToDictionary(x => x, x => il.DeclareLocal(x.Type)); var labels = emitIl.Labels.ToDictionary(x => x, x => il.DefineLabel()); foreach (var instruction in emitIl.Instructions) { foreach (var label in instruction.Labels) { il.MarkLabel(labels[label]); } var opCode = instruction.OpCode.ToOpCode(); if (instruction.Operand == null) { il.Emit(opCode); } else if (instruction.Operand is EmitType) { il.Emit(opCode, (EmitType)instruction.Operand); } else if (instruction.Operand is EmitMethod) { il.Emit(opCode, (EmitMethod)instruction.Operand); } else if (instruction.Operand is EmitConstructor) { il.Emit(opCode, (EmitConstructor)instruction.Operand); } else if (instruction.Operand is EmitField) { il.Emit(opCode, (EmitField)instruction.Operand); } else if (instruction.Operand is int) { il.Emit(opCode, (int)instruction.Operand); } else if (instruction.Operand is short) { il.Emit(opCode, (short)instruction.Operand); } else if (instruction.Operand is byte) { il.Emit(opCode, (byte)instruction.Operand); } else if (instruction.Operand is sbyte) { il.Emit(opCode, (sbyte)instruction.Operand); } else if (instruction.Operand is long) { il.Emit(opCode, (long)instruction.Operand); } else if (instruction.Operand is double) { il.Emit(opCode, (double)instruction.Operand); } else if (instruction.Operand is float) { il.Emit(opCode, (float)instruction.Operand); } else if (instruction.Operand is string) { il.Emit(opCode, (string)instruction.Operand); } else if (instruction.Operand is EmitLocal) { il.Emit(opCode, locals[(EmitLocal)instruction.Operand]); } else if (instruction.Operand is EmitLabel) { il.Emit(opCode, labels[(EmitLabel)instruction.Operand]); } else if (instruction.Operand is EmitLabel[]) { il.Emit(opCode, ((EmitLabel[])instruction.Operand).Select(x => labels[x]).ToArray()); } else { throw new Exception("Unexpected operand type: " + instruction.Operand.GetType().FullName); } } }