/// <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);
            }
        }
Exemple #2
0
        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);
        }