/// <summary> /// Emits an expression method. /// </summary> /// <param name="emitter">A reference to an emitter.</param> /// <param name="expressionMethod">A reference to the expression method.</param> /// <param name="arguments">A reference to the argument stack.</param> internal static void EmitMethod(this IEmitter emitter, MethodInfo expressionMethod, Stack <object> arguments) { if (expressionMethod.DeclaringType == typeof(IExpression) || expressionMethod.DeclaringType == typeof(IInitialiser) || expressionMethod.DeclaringType == typeof(ICondition) || expressionMethod.DeclaringType == typeof(IIterator)) { if (expressionMethod.Name != "Value") { var method = SupportedMethods.FirstOrDefault(m => m.Name == expressionMethod.Name); if (method == null) { throw new NotSupportedException($"OpCode '{expressionMethod.Name}' not supported"); } var parameters = method.GetParameters(); //Console.WriteLine("expresionMethod: {0}, parameters: {1}", expressionMethod.Name, string.Join(", ", parameters.Select(p => p.ParameterType.Name))); object[] values = new object[parameters.Length]; values[0] = emitter; if (parameters.Length > 1) { for (int i = 1; i < parameters.Length; i++) { values[i] = arguments.Pop(); } } method.Invoke(null, values); } } else { emitter.Call(expressionMethod); } }
public void EmitDeferredInstructions() { if (!_outputEnabled) { return; } foreach (MethodInstruction instruction in _deferredInstructions) { switch (instruction.OpCode) { case MethodOpCode.Assign: _emitter.Store((IrisType)instruction.Operand); break; case MethodOpCode.BranchCond: _emitter.BranchCondition(instruction.Condition, (int)instruction.Operand); break; case MethodOpCode.BranchFalse: _emitter.BranchFalse((int)instruction.Operand); break; case MethodOpCode.BranchTrue: _emitter.BranchTrue((int)instruction.Operand); break; case MethodOpCode.Call: _emitter.Call((Symbol)instruction.Operand); break; case MethodOpCode.Goto: _emitter.Goto((int)instruction.Operand); break; case MethodOpCode.Label: _emitter.Label((int)instruction.Operand); break; case MethodOpCode.Load: _emitter.Load((IrisType)instruction.Operand); break; case MethodOpCode.LoadElem: _emitter.LoadElement((IrisType)instruction.Operand); break; case MethodOpCode.LoadElemA: _emitter.LoadElementAddress((IrisType)instruction.Operand); break; case MethodOpCode.Operator: _emitter.Operator((Operator)instruction.Operand); break; case MethodOpCode.Dup: _emitter.Dup(); break; case MethodOpCode.Pop: _emitter.Pop(); break; case MethodOpCode.PushArg: _emitter.PushArgument((int)instruction.Operand); break; case MethodOpCode.PushArgA: _emitter.PushArgumentAddress((int)instruction.Operand); break; case MethodOpCode.PushInt: _emitter.PushIntConst((int)instruction.Operand); break; case MethodOpCode.PushGbl: _emitter.PushGlobal((Symbol)instruction.Operand); break; case MethodOpCode.PushGblA: _emitter.PushGlobalAddress((Symbol)instruction.Operand); break; case MethodOpCode.PushLoc: _emitter.PushLocal((int)instruction.Operand); break; case MethodOpCode.PushLocA: _emitter.PushLocalAddress((int)instruction.Operand); break; case MethodOpCode.PushString: _emitter.PushString((string)instruction.Operand); break; case MethodOpCode.StoreArg: _emitter.StoreArgument((int)instruction.Operand); break; case MethodOpCode.StoreElem: _emitter.StoreElement((IrisType)instruction.Operand); break; case MethodOpCode.StoreGbl: _emitter.StoreGlobal((Symbol)instruction.Operand); break; case MethodOpCode.StoreLoc: _emitter.StoreLocal((int)instruction.Operand); break; default: throw new InvalidOperationException("Unknown opcode. Missing case?"); } } _deferredInstructions.Clear(); }
/// <summary> /// Emits a type converter. /// </summary> /// <param name="methodIL">An emitter.</param> /// <param name="fromType">The type to convert from.</param> /// <param name="toType">The type to convert to.</param> /// <returns>The emitter.</returns> public static IEmitter EmitConverter(this IEmitter methodIL, Type fromType, Type toType) { if (fromType == toType) { return(methodIL); } if (toType == typeof(string)) { if (fromType == typeof(byte[])) { var toBase64Method = typeof(Convert).GetMethod("ToBase64String", new[] { typeof(byte[]) }); return(methodIL.Call(toBase64Method)); } var toStringMethod = typeof(Convert).GetMethod("ToString", new[] { fromType }); return(methodIL.Call(toStringMethod)); } if (toType == typeof(byte[])) { if (fromType == typeof(string)) { var fromBase64Method = typeof(Convert).GetMethod("FromBase64String", new[] { typeof(string) }); return(methodIL.Call(fromBase64Method)); } methodIL.ThrowException(typeof(NotSupportedException)); return(methodIL); } else if (toType == typeof(short)) { var toMethod = typeof(Convert).GetMethod("ToInt16", new[] { fromType }); return(methodIL.Call(toMethod)); } else if (toType == typeof(int)) { var toMethod = typeof(Convert).GetMethod("ToInt32", new[] { fromType }); return(methodIL.Call(toMethod)); } else if (toType == typeof(long)) { var toMethod = typeof(Convert).GetMethod("ToInt64", new[] { fromType }); return(methodIL.Call(toMethod)); } else if (toType == typeof(float)) { var toMethod = typeof(Convert).GetMethod("ToFloat", new[] { fromType }); return(methodIL.Call(toMethod)); } else if (toType == typeof(double)) { var toMethod = typeof(Convert).GetMethod("ToDouble", new[] { fromType }); return(methodIL.Call(toMethod)); } else if (toType == typeof(bool)) { var toMethod = typeof(Convert).GetMethod("ToBoolean", new[] { fromType }); return(methodIL.Call(toMethod)); } else if (toType == typeof(DateTime)) { var toMethod = typeof(Convert).GetMethod("ToDateTime", new[] { fromType }); return(methodIL.Call(toMethod)); } methodIL.ThrowException(typeof(NotSupportedException)); return(methodIL); }