Beispiel #1
0
        public static MethodInfo methodof(object host, Type returnType, string methodName, Type[] arguments)
        {
            Type ty = HostType.GetHostType(host);

            MemberInfo[] members = ty.GetMember(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
            foreach (MemberInfo member in members)
            {
                if (member is MethodInfo)
                {
                    MethodInfo method = (MethodInfo)member;
                    if (method.ReturnType == returnType)
                    {
                        ParameterInfo[] parameters = method.GetParameters();
                        if (parameters.Length == arguments.Length)
                        {
                            int i     = 0;
                            int count = 0;
                            foreach (ParameterInfo parameterInfo in parameters)
                            {
                                if (parameterInfo.ParameterType == arguments[i])
                                {
                                    count++;
                                }
                                i++;
                            }

                            if (count == arguments.Length)
                            {
                                return(method);
                            }
                        }
                    }
                }
            }

            return(null);
        }
Beispiel #2
0
        /*
         *
         * .net object format/protocol:
         *
         *      (1) new className(args,...)
         *          如 new System.Windows.Form.TextBox()
         *             new Tie.VAL(20)
         *
         *
         *      (2) new SerializedObject(string className, string value.ToString(), string SerializedValue);
         *          请看Encode()生成的格式
         *
         * 例如:
         *      前提:
         *          System.Windows.Form.Label的值是Type, 已经用Register函数登记在数据字典Computer.DS中.
         *
         *      求:
         *          new System.Windows.Form.Label();   转化为  new Label(System.Window.Form);
         *
         * */
        public static VAL Decode(string className, VAL args, VAL scope, Context context)
        {
            VAL clss = new VAL();

            /*
             * 如果是注册过的class, 那么它的namespace是定义在Computer.DS中
             * 譬如
             *      A= new NS.CLSS();
             *      scope[className] --> clss;
             *
             * 如果没有定义namespace,那么直接到Computer.DS中去取值
             * 譬如
             *      A= CLSS();
             *      Computer.DS[className] --> clss
             *
             * */
            clss = scope[className];
            if (clss.Undefined)
            {
                clss = context.GetVAL(className, true);         //如果没有找到val.Class, context.GetVAL(...)返回new VAL()
            }
            //返回注册过的class名字
            if (clss.Defined && clss.value is Type)
            {
                Type   type     = (Type)clss.value;
                object instance = Activator.CreateInstance(type, ConstructorArguments(args));
                return(VAL.Boxing1(instance)); //返回实例
            }

            //throw new RuntimeException(string.Format("class [{0}]has not registered yet.", scope.name + "." + val.Class));
            //如果没有注册过
            if (scope.name != null)
            {
                object instance = HostType.NewInstance(scope.name + "." + className, ConstructorArguments(args));

                if (instance != null)
                {
                    //把HostType类型注册到CPU.DS2中去
                    VAL hostType = VAL.NewHostType(instance.GetType());
                    scope[className] = hostType;

                    return(VAL.Boxing1(instance));  //返回实例
                }
            }


            if (clss.IsNull)
            {
                throw new HostTypeException("class {0} is not defined.", className);
            }


            if (clss.value != null)
            {
                Type type;
                if (clss.value is Type)
                {
                    type = (Type)clss.value;
                }
                else
                {
                    type = clss.value.GetType();
                }

                object instance = Activator.CreateInstance(type, ConstructorArguments(args));
                return(VAL.NewHostType(instance));
            }


            return(args);
        }
Beispiel #3
0
        public VAL Run(int breakPoint)
        {
L1:

            Instruction I = CS[IP];
            Operand operand = I.operand;

            position.line  = I.line;
            position.col   = I.col;
            position.cur   = I.cur;
            position.block = I.block;

            if (I.line == breakPoint)
            {
                return(null);
            }

            switch (I.cmd)
            {
                //----------------------------------------------------------------------------

                #region  MOV, STO,STO1, RMT. RCP

            case INSTYPE.MOV:
                if (operand.ty == OPRTYPE.identcon)         // MOV [v]
                {
                    if (CS[IP + 1].cmd == INSTYPE.OFS)      // if this is offset of a struct, keep variable name
                    {
                        REG.Push(new VAL(operand));
                    }
                    else
                    {
                        REG.Push(GetVAL(operand.Str, false));
                    }
                }
                else if (operand.ty == OPRTYPE.addrcon)         // MOV [BP-3]
                {
                    //VAL opr = Register.BPAddr(BP, operand);

                    VAL opr = new VAL();
                    opr.ty    = VALTYPE.addrcon;
                    opr.value = BP + operand.Addr;
                    opr.name  = operand.name;

                    REG.Push(opr);
                }
                else
                {
                    VAL x = new VAL(operand);
                    if (operand.ty == OPRTYPE.funccon)
                    {
                        if (ES.SP > -1)
                        {
                            x.temp = new ContextInstance(this.context, ES.Top());
                        }
                        else
                        {
                            x.temp = new ContextInstance(this.context, new VAL());
                        }
                    }

                    REG.Push(VAL.Clone(x));     // MOV 3
                }
                break;



            //----------------------------------------------------------------------------


            case INSTYPE.STO1:
            case INSTYPE.STO:
                R0 = REG.Pop();
                R1 = REG.pop();
                if (R1.ty == VALTYPE.addrcon)
                {
                    SS[R1.Address] = R0;
                }
                else
                {
                    HostOperation.Assign(R1, R0);
                }

                if (I.cmd == INSTYPE.STO)
                {
                    REG.Push(R1);
                }
                break;

            case INSTYPE.RMT:
                if (CS[IP + 1].cmd != INSTYPE.HALT)      //used for expression decoding,keep last value
                {
                    REG.Pop();
                }
                break;

            case INSTYPE.RCP:
                REG.Push(VAL.Clone(REG.Top()));
                break;

                #endregion


                //----------------------------------------------------------------------------

                #region PUSH/POP/SP/ESI/ESO
            case INSTYPE.ESI:
                R0 = REG.Pop();
                ES.Push(R0);
                break;

            case INSTYPE.ESO:
                ES.Pop();
                break;

            case INSTYPE.PUSH:
                if (operand != null && operand.ty == OPRTYPE.regcon)
                {
                    switch (operand.SEG)
                    {
                    case SEGREG.BP: SS.Push(new VAL(BP)); break;

                    case SEGREG.SP: SS.Push(new VAL(SS.SP)); break;

                    case SEGREG.SI: SS.Push(new VAL(SI)); break;

                    case SEGREG.IP: SS.Push(new VAL(IP + 2)); break;

                    case SEGREG.EX: EX.Push((int)operand.value); break;
                    }
                }
                else
                {
                    R0 = REG.Pop();
                    SS.Push(R0);
                }
                break;

            case INSTYPE.POP:
                if (operand.ty == OPRTYPE.regcon)
                {
                    switch (operand.SEG)
                    {
                    case SEGREG.BP: BP = (SS.Pop()).Address; break;

                    case SEGREG.SI: SI = (SS.Pop()).Address; break;

                    case SEGREG.SP: SS.SP = (SS.Pop()).Address; break;

                    case SEGREG.EX: EX.Pop(); break;
                    }
                }
                else
                {
                    R0 = SS.Pop();
                    REG.Push(R0);
                }
                break;

            case INSTYPE.SP:
                SS.SP += operand.Addr;
                break;

                #endregion


                //----------------------------------------------------------------------------

                #region OFS, ARR
            //----------------------------------------------------------------------------
            // Associative List
            // Mike={{"street", "3620 Street"},{"zip", 20201},{"phone","111-222-333},{"apt",1111}}
            // Mike.street = "3620 Street";
            // Mike.zip = 40802;
            case INSTYPE.OFS:
                R0 = REG.Pop();
                R1 = REG.pop();
                {
                    VAL v = new VAL();
                    switch (R1.ty)
                    {
                    case VALTYPE.hostcon:
                        v = R1.getter(R0, true, OffsetType.STRUCT);
                        goto LOFS;

                    case VALTYPE.addrcon:
                        v = SS[R1.Address];
                        if (v.Undefined || v.IsNull)
                        {
                            v.ty    = VALTYPE.listcon;
                            v.value = new VALL();
                        }
                        break;

                    case VALTYPE.listcon:
                        v = R1;
                        break;

                    default:           // if assoicative arrary is empty or not list
                        R1.ty    = VALTYPE.listcon;
                        R1.value = new VALL();
                        v        = R1;
                        break;
                    }

                    switch (v.ty)
                    {
                    case VALTYPE.listcon:
                        VALL L = v.List;
                        v = L[R0.Str];

                        // if property is not found in the associative array
                        if (!v.Defined)
                        {
                            L[R0.Str] = v;
                        }

                        break;

                    case VALTYPE.hostcon:
                        //VAL.Assign(v, VAL.HostTypeOffset(v.value, R0.value));
                        v = HostOperation.HostTypeOffset(v, R0, OffsetType.STRUCT);
                        break;
                    }

LOFS:
                    if ((object)v == null)
                    {
                        v = new VAL();
                    }

                    v.name = R1.name + "." + R0.name;
                    REG.Push(v);
                }
                break;

            case INSTYPE.ARR:
                R0 = REG.Pop();
                R1 = REG.pop();
                {
                    VAL v = new VAL();
                    switch (R1.ty)
                    {
                    case VALTYPE.addrcon:
                        v = SS[R1.Address];           //indirect addressing
                        if (v.Undefined || v.IsNull)
                        {
                            v.ty    = VALTYPE.listcon;
                            v.value = new VALL();
                            v       = v.getter(R0, true, OffsetType.ARRAY);
                        }
                        else
                        {
                            v = v.getter(R0, true, OffsetType.ARRAY);
                        }
                        break;

                    case VALTYPE.listcon:                       //push reference
                        v = R1.getter(R0, true, OffsetType.ARRAY);
                        break;

                    case VALTYPE.hostcon:
                        v = R1.getter(R0, true, OffsetType.ARRAY);
                        if (!v.Defined)
                        {
                            throw new RuntimeException(position, "{0} does not have property {1}.", R1, R0);
                        }
                        break;

                    default:
                        //refer: public VAL this[VAL arr], when R1 == null, dynamically allocate a list
                        R1.ty    = VALTYPE.listcon;
                        R1.value = new VALL();
                        v        = R1.getter(R0, true, OffsetType.ARRAY);

                        //JError.OnRuntime(0);
                        break;
                    }

                    v.name = R1.name + "[" + R0.ToString() + "]";
                    REG.Push(v);
                }
                break;

                #endregion


                //----------------------------------------------------------------------------

                #region  CALL, NEW, ENDP, RET, GNRC
            case  INSTYPE.GNRC:
                R0 = REG.Pop();         // R0 = new Type[] { string, int }
                R1 = REG.Pop();         // R1 = System.Collection.Generic
                {
                    Operand opr = I.operand;
                    VAL     R2  = R1[opr.Str];    // I.val.Str == Dictionary`2
                    if (R2.Undefined)             // Type is not registered
                    {
                        object t = HostType.GetType(R1.name + "." + opr.Str);
                        if (t != null)
                        {
                            R2 = VAL.NewHostType(t);
                        }
                        else
                        {
                            throw new RuntimeException(position, "Type {0}.{1} is not registered.", R1.name, opr.Str);
                        }
                    }

                    object A = R0.HostValue;
                    if (A is object[] && ((object[])A).Length == 0)         //case: typeof(Dictionary<,>)
                    {
                        if (R2.value is Type)
                        {
                            REG.Push(VAL.NewHostType(R2.value));
                        }
                        else
                        {
                            throw new RuntimeException(position, "{0} is not System.Type.", R1);
                        }
                    }
                    else
                    {
                        if (!(A is Type[]))
                        {
                            throw new RuntimeException(position, "<{0}> is not System.Type[].", R0.ToString2());
                        }

                        if (R2.value is Type)
                        {
                            Type t = (Type)R2.value;
                            REG.Push(VAL.NewHostType(t.MakeGenericType((Type[])A)));
                        }
                        else if (R2.value is MethodInfo)
                        {
                            MethodInfo t = (MethodInfo)R2.value;
                            VAL        m = VAL.NewHostType(t.MakeGenericMethod((Type[])A));
                            m.temp = R2.temp;
                            REG.Push(m);
                        }
                        else if (R2.value is MethodInfo[])
                        {
                            MethodInfo[] T = (MethodInfo[])R2.value;
                            for (int i = 0; i < T.Length; i++)
                            {
                                T[i] = T[i].MakeGenericMethod((Type[])A);
                            }
                            VAL m = VAL.NewHostType(T);
                            m.temp = R2.temp;
                            REG.Push(m);
                        }
                        else
                        {
                            throw new RuntimeException(position, "{0} is not System.Type.", R1);
                        }
                    }
                }

                break;

            case INSTYPE.CALL:
                if (operand.ty == OPRTYPE.intcon)
                {
                    IP = operand.Addr;
                }
                else if (operand.ty == OPRTYPE.addrcon)      // high-level programming
                {
                    SysFuncCallByAddr(SS[operand.Addr + BP]);
                }
                else if (operand.ty == OPRTYPE.regcon)
                {
                    SysFuncCallByAddr(SS[operand.Addr + SS.SP]);
                }
                else if (operand.ty == OPRTYPE.none)       //used for Generic method
                {
                    if (ES.IsEmpty())
                    {
                        R0 = REG.Pop();
                    }
                    else
                    {
                        R0 = ES.Top();
                    }

                    SysFuncCallByName(R0);
                }
                else
                {
                    SysFuncCallByName(new VAL(operand));
                }
                goto L1;

            case INSTYPE.NEW:
                if (operand.ty == OPRTYPE.funccon)
                {
                    NewInstance(new VAL(operand));         //system predifined class & user-defined class
                }
                else if (operand.ty == OPRTYPE.none)       //used for Generic class
                {
                    if (ES.IsEmpty())
                    {
                        R0 = REG.Pop();
                    }
                    else
                    {
                        R0 = ES.Top();
                    }

                    NewInstance(R0);
                }
                else if (operand.ty == OPRTYPE.intcon)
                {
                    int opr = (int)operand.value;
                    if (opr > 1)
                    {
                        R0 = REG.Pop();
                        R1 = REG.Pop();
                    }
                    else
                    {
                        R1 = REG.Pop();
                    }

                    if (R1.value is Type)
                    {
                        Type ty = (Type)R1.value;

                        if (opr == 1)
                        {
                            if (ty.IsArray)
                            {
                                R0 = VAL.Array();
                            }
                            else
                            {
                                R0 = new VAL();
                            }
                        }

                        if (R0.ty == VALTYPE.listcon)
                        {
                            if (ty.IsArray)
                            {
                                R0.List.ty = ty;
                            }
                            else
                            {
                                throw new RuntimeException(position, "new object failed. {0} is not Array Type", R1);
                            }
                        }

                        R0.Class = ty.FullName;
                        REG.Push(R0);
                    }
                    else
                    {
                        throw new RuntimeException(position, "new object failed. {0} is not System.Type", R1);
                    }

                    IP++;
                }

                goto L1;

            case INSTYPE.ENDP:
                if ((OPRTYPE)operand.Intcon == OPRTYPE.classcon)
                {
                    REG.Push(ES.Top());                 //return this;
                }
                else
                {
                    REG.Push(VAL.VOID);        //return void;
                }
                SS.SP = BP;                    //PUSH BP; POP SP;
                BP    = (SS.Pop()).Address;    //POP BP;

                R0 = SS.Top();                 //EXEC RET
                IP = R0.Address;
                goto L1;

            case INSTYPE.RET:
                if (!SS.IsEmpty())
                {
                    R0 = SS.Top();
                    IP = R0.Address;                        //goto V.i
                }
                else
                {
                    if (REG.IsEmpty())
                    {
                        return(VAL.VOID);
                    }
                    else
                    {
                        return(REG.Top());
                    }
                }

                goto L1;

                #endregion


                //----------------------------------------------------------------------------

                #region  +,-,*,/,%,>,<,!=,==,<=,>=, ++, --
            //----------------------------------------------------------------------------
            case INSTYPE.NEG:
                R0 = REG.Pop();
                if (operand.Intcon == -1)
                {
                    R0 = -R0;       //call VAL.operator -(VAL)
                }
                else
                {
                    R0 = +R0;       //call VAL.operator +(VAL)
                }
                REG.Push(R0);
                break;

            case INSTYPE.ADD: R0 = REG.Pop(); R1 = REG.Pop(); R1 += R0; REG.Push(R1); break;

            case INSTYPE.SUB: R0 = REG.Pop(); R1 = REG.Pop(); R1 -= R0; REG.Push(R1); break;

            case INSTYPE.MUL: R0 = REG.Pop(); R1 = REG.Pop(); R1 *= R0; REG.Push(R1); break;

            case INSTYPE.DIV: R0 = REG.Pop(); R1 = REG.Pop(); R1 /= R0; REG.Push(R1); break;

            case INSTYPE.MOD: R0 = REG.Pop(); R1 = REG.Pop(); R1 %= R0; REG.Push(R1); break;

            case INSTYPE.GTR: R0 = REG.Pop(); R1 = REG.Pop(); REG.Push(new VAL(R1 > R0)); break;

            case INSTYPE.LSS: R0 = REG.Pop(); R1 = REG.Pop(); REG.Push(new VAL(R1 < R0)); break;

            case INSTYPE.GEQ: R0 = REG.Pop(); R1 = REG.Pop(); REG.Push(new VAL(R1 >= R0)); break;

            case INSTYPE.LEQ: R0 = REG.Pop(); R1 = REG.Pop(); REG.Push(new VAL(R1 <= R0)); break;

            case INSTYPE.EQL: R0 = REG.Pop(); R1 = REG.Pop(); REG.Push(new VAL(R1 == R0)); break;

            case INSTYPE.NEQ: R0 = REG.Pop(); R1 = REG.Pop(); REG.Push(new VAL(R1 != R0)); break;

            case INSTYPE.INC:
                R0 = REG.pop();
                R1 = VAL.Clone(R0);
                if (R0.ty == VALTYPE.addrcon)
                {
                    SS[R0.Address] += new VAL(1);
                }
                else     //global varible
                {
                    HostOperation.Assign(R0, R0 + new VAL(1));
                }
                REG.Push(R1);
                break;

            case INSTYPE.DEC:
                R0 = REG.pop();
                R1 = VAL.Clone(R0);
                if (R0.ty == VALTYPE.addrcon)
                {
                    SS[R0.Address] -= new VAL(1);
                }
                else     //global varible
                {
                    HostOperation.Assign(R0, R0 - new VAL(1));
                }
                REG.Push(R1);
                break;

                #endregion


                //----------------------------------------------------------------------------

                #region MARK, END, EACH, CAS, DIRC

            case INSTYPE.MARK: REG.Push(Mark); break;

            case INSTYPE.END:
            {
                VAL L = new VAL(new VALL());
                while (REG.Top() != Mark)
                {
                    L.List.Insert(REG.Pop());
                }
                REG.Pop();                      // pop mark
                REG.Push(L);
            } break;

            case INSTYPE.EACH:
                R0 = REG.Pop();             //Collection
                R1 = REG.pop();             //address of element [BP+addr]
                REG.Push(ForEach(R0, SS[R1.Intcon], SS[R1.Intcon + 1]));
                break;

            case INSTYPE.CAS:
                R0 = REG.Pop(); R1 = REG.Top();
                if (R1 == R0)
                {
                    REG.Pop(); IP = operand.Addr; goto L1;
                }                                                            //goto V.i
                break;

            case INSTYPE.DIRC:          //directive command
                switch (operand.mod)
                {
                case Constant.SCOPE:
                    this.scope = (string)operand.value;
                    break;
                }
                break;

                #endregion


                //----------------------------------------------------------------------------

                #region &&, ||, ~, &, |, >>, <<
            //----------------------------------------------------------------------------
            case INSTYPE.NOTNOT:
                R0 = REG.Pop();
                if (R0.ty == VALTYPE.stringcon)
                {
                    REG.Push(Computer.Run(scope, R0.Str, CodeType.statements, context));
                }
                else
                {
                    REG.Push(new VAL(!R0));         //call VAL.operator !(VAL)
                }
                break;

            case INSTYPE.ANDAND: R0 = REG.pop(); R1 = REG.Pop();
                REG.Push(new VAL(R0.ty == VALTYPE.boolcon && R1.ty == VALTYPE.boolcon? R0.Boolcon && R1.Boolcon: false));
                break;

            case INSTYPE.OROR: R0 = REG.pop(); R1 = REG.Pop();
                REG.Push(new VAL(R0.ty == VALTYPE.boolcon && R1.ty == VALTYPE.boolcon ? R0.Boolcon || R1.Boolcon : false));
                break;


            //----------------------------------------------------------------------------
            case INSTYPE.NOT: R0 = REG.Pop();
                REG.Push(~R0);      //call VAL.operator ~(VAL)
                break;

            case INSTYPE.AND: R0 = REG.pop(); R1 = REG.Pop();
                REG.Push(R1 & R0);
                break;

            case INSTYPE.OR: R0 = REG.pop(); R1 = REG.Pop();
                REG.Push(R1 | R0);
                break;

            case INSTYPE.XOR: R0 = REG.pop(); R1 = REG.Pop();
                REG.Push(R1 ^ R0);
                break;

            //----------------------------------------------------------------------------
            case INSTYPE.SHL: R0 = REG.pop(); R1 = REG.Pop();
                if (!(R0.value is int))
                {
                    throw new RuntimeException(position, "the 2nd operand {0} in << operation must be integer", R0);
                }
                REG.Push(R1 << (int)R0.value);
                break;

            case INSTYPE.SHR: R0 = REG.pop(); R1 = REG.Pop();
                if (!(R0.value is int))
                {
                    throw new RuntimeException(position, "the 2nd operand {0} in >> operation must be integer", R0);
                }
                REG.Push(R1 >> (int)R0.value);
                break;
                #endregion


                //----------------------------------------------------------------------------

                #region JUMP, ADR, VLU

            case INSTYPE.JMP: IP = operand.Addr; goto L1;

            case INSTYPE.LJMP: IP += operand.Addr; goto L1;

            case INSTYPE.JNZ:
                if (REG.Pop() == new VAL(true))
                {
                    IP = operand.Addr; goto L1;
                }
                else
                {
                    break;
                }

            case INSTYPE.JZ:
                if (REG.Pop() != new VAL(true))
                {
                    IP = operand.Addr; goto L1;
                }
                else
                {
                    break;
                }

            case INSTYPE.LJZ:
                if (REG.Pop() != new VAL(true))
                {
                    IP += operand.Addr; goto L1;
                }
                else
                {
                    break;
                }

            case INSTYPE.ADR:
                R0 = REG.Pop();
                REG.Push(new VAL(R0.name));
                break;

            case INSTYPE.VLU:
                R0 = REG.Pop();
                if (R0.ty == VALTYPE.stringcon)
                {
                    REG.Push(Computer.Run(scope, R0.Str, CodeType.expression, context));
                }
                else
                {
                    throw new RuntimeException(position, "Invalid address type:" + R0.ToString());
                }
                break;

                #endregion


                //----------------------------------------------------------------------------


                #region  THIS,BASE
            case INSTYPE.THIS:                                           //this.x
                if (ES.SP > -1)
                {
                    if (this.scope != "")
                    {
                        VAL NS = GetScopeVAL(this.scope);
                        if (NS != ES.Top())
                        {
                            REG.Push(NS);
                        }
                    }
                    else
                    {
                        REG.Push(ES.Top());
                    }
                }
                else if (this.scope != "")
                {
                    if (operand.ty == OPRTYPE.intcon)                         //this.x=100;
                    {
                        REG.Push(GetScopeVAL(this.scope));
                    }
                    else
                    {
                        REG.Push(new VAL(this.scope));             //p=&this.x;
                    }
                }
                else
                {
                    if (CS[IP + 2].cmd == INSTYPE.OFS)
                    {
                        CS[IP + 2].cmd = INSTYPE.NOP;
                    }
                    else
                    {
                        throw new RuntimeException(position, "Operator[this] is invalid since namespace is empty.");
                    }
                }
                break;

            case INSTYPE.BASE:           //base.x
                //if (ES.SP > -1)
                //{
                //    VAL BS = ES.Top()[JExpression.BASE_INSTANCE];
                //    if((object)BS!=null)
                //        REG.Push(BS);
                //    else
                //        throw new RuntimeException(string.Format("Operator[base] is invalid since class {0} does not have base class.",ES.Top()));
                //}
                if (this.scope != "")
                {
                    string bv = "";
                    int    n  = 1;
                    if (operand.ty == OPRTYPE.intcon)          //base.base.x=10;
                    {
                        n = operand.Intcon;

                        bv = GetBaseScope(this.scope, n);

                        if (bv != "")
                        {
                            REG.Push(GetScopeVAL(bv));
                        }
                        else
                        {
                            if (CS[IP + 2].cmd == INSTYPE.OFS)
                            {
                                CS[IP + 2].cmd = INSTYPE.NOP;
                            }
                        }
                    }
                    else
                    {
                        n  = operand.Addr;                 // p = &base.base.x;
                        bv = GetBaseScope(this.scope, n);
                        REG.Push(new VAL(bv));
                    }
                }
                else
                {
                    throw new RuntimeException(position, "Operator[base] is invalid since scope is root.");
                }
                break;

                #endregion


                //----------------------------------------------------------------------------

                #region THRW, DDT, HALT

            case INSTYPE.THRW:
                R0 = REG.Top();
                if (!(R0.HostValue is Exception))
                {
                    throw new RuntimeException(position, "{0} is not type of System.Exception.", R0.HostValue);
                }

                if (EX.IsEmpty())
                {
                    throw (Exception)R0.HostValue;
                }
                IP = EX.Pop();

                if (IP == -1)
                {
                    throw (Exception)R0.HostValue;
                }
                break;

            case INSTYPE.DDT:
                Logger.WriteLine(DebugInfo());
                break;

            case INSTYPE.HALT:
                if (REG.IsEmpty())
                {
                    return(VAL.VOID);
                }
                else
                {
                    return(REG.Top());
                }

                #endregion
            }

            IP++;
            goto L1;
        }
Beispiel #4
0
        public static VAL Function(string func, VAL parameters, Memory DS, Position position)
        {
            VALL L = (VALL)parameters.value;
            VAL  R0;

            int size = L.Size;
            VAL L0   = size > 0 ? L[0] : null;
            VAL L1   = size > 1 ? L[1] : null;

            switch (func)
            {
            /*
             *  register(Type type)
             *  register(Assembly assemby)
             * */
            case "register":
                if (size == 1)
                {
                    if (L0.ty == VALTYPE.hostcon)
                    {
                        object host = L0.HostValue;
                        if (host is Type)
                        {
                            return(new VAL(HostType.Register((Type)host)));
                        }
                        if (host is Type[])
                        {
                            return(new VAL(HostType.Register((Type[])host)));
                        }
                        else if (host is Assembly)
                        {
                            return(new VAL(HostType.Register((Assembly)host)));
                        }
                    }
                }
                break;

            case "addreference":
                if (size == 2 && L0.ty == VALTYPE.stringcon && L1.ty == VALTYPE.hostcon)
                {
                    object host = L1.HostValue;
                    if (host is Assembly)
                    {
                        HostType.AddReference(L0.Str, (Assembly)host);
                        return(VAL.NewHostType(host));
                    }
                }
                break;

            //return VAL type
            case "type":
                if (size == 1)
                {
                    return(new VAL((int)L0.ty));
                }
                break;

            case "GetType":
                if (size == 1)
                {
                    if (L0.value == null)
                    {
                        return(new VAL());
                    }
                    else
                    {
                        return(VAL.NewHostType(L0.value.GetType()));
                    }
                }
                break;

            case "typeof":
                if (size == 2)
                {
                    if (L0.ty == VALTYPE.listcon && L1.ty == VALTYPE.stringcon)                //1.
                    {
                        L0.Class = L1.Str;
                        return(L0);
                    }
                }
                else if (size == 1)
                {
                    if (L0.value == null)
                    {
                        Type ty = HostType.GetType(L0.name);
                        if (ty != null)
                        {
                            return(VAL.NewHostType(ty));
                        }
                        else
                        {
                            return(new VAL());
                        }
                    }
                    else if (L0.ty == VALTYPE.listcon)
                    {
                        if (L0.Class == null)
                        {
                            return(VAL.VOID);
                        }
                        return(new VAL(L0.Class));
                    }
                    else if (L0.ty == VALTYPE.hostcon)
                    {
                        if (L0.value is Type)
                        {
                            return(L0);
                        }
                        else
                        {
                            return(VAL.NewHostType(L0.value.GetType()));
                        }
                    }
                    else if (L0.ty == VALTYPE.stringcon)
                    {
                        return(VAL.NewHostType(HostType.GetType(L0.Str)));       //6.
                    }
                }
                break;

            case "classof":
                if (size == 1)
                {
                    if (L0.ty == VALTYPE.hostcon)
                    {
                        return(HostValization.Host2Val(L0.value));
                    }
                }
                else if (size == 2)
                {
                    if (L0.ty == VALTYPE.hostcon && L1.ty == VALTYPE.listcon)                //1.
                    {
                        HostValization.Val2Host(L1, L0.value);
                        return(L0);
                    }
                }
                break;


            case "valize":
                if (size == 1)
                {
                    return(VAL.Script(L0.Valor));
                }
                break;

            case "isnull":
                if (size == 2)
                {
                    if (L0.ty == VALTYPE.nullcon)
                    {
                        return(L1);
                    }
                    else
                    {
                        return(L0);
                    }
                }
                break;

            case "VAL":
                if (size == 1)
                {
                    R0       = VAL.Clone(L0);
                    R0.Class = "VAL";                  //force to CAST VAL, don't do HostValue unboxing
                    return(R0);
                }
                break;

            case "HOST":                           //cast to hostcon
                if (size == 1)
                {
                    R0    = VAL.Clone(L0);
                    R0.ty = VALTYPE.hostcon;
                    return(R0);
                }
                break;


            case "ctype":
                if (size == 2)
                {
                    if (L1.value is Type)
                    {
                        return(VAL.cast(VAL.Clone(L0), (Type)L1.value));
                    }
                    else if (L[1].value is string)
                    {
                        Type ty = HostType.GetType(L1.Str);
                        if (ty != null)
                        {
                            return(VAL.cast(VAL.Clone(L0), ty));
                        }
                    }
                }
                break;



            case "DateTime":
                if (size == 6)
                {
                    return(VAL.NewHostType(new DateTime(L0.Intcon, L1.Intcon, L[2].Intcon, L[3].Intcon, L[4].Intcon, L[5].Intcon)));
                }
                else if (size == 3)
                {
                    return(VAL.NewHostType(new DateTime(L0.Intcon, L1.Intcon, L[2].Intcon)));
                }
                break;

            //STRING
            case "format":
                if (size >= 1 && L0.ty == VALTYPE.stringcon)
                {
                    return(format(L));
                }
                break;



                #region LIST function

            case "size":
                if (size == 1)
                {
                    return(new VAL(L0.Size));
                }
                break;

            case "array":               //array(2,3,4)
                int[] A = new int[size];
                for (int i = 0; i < size; i++)
                {
                    if (L[1].ty != VALTYPE.intcon)
                    {
                        return(null);
                    }

                    A[i] = L[i].Intcon;
                }
                return(VAL.Array(A));

            case "slice":
                return(Slice(L));

            case "append":
            case "push":
                if (size == 2 && L0.ty == VALTYPE.listcon)
                {
                    R0 = L1;
                    L0.List.Add(VAL.Clone(R0));
                    return(L0);
                }
                break;

            case "pop":
                if (size == 1 && L0.ty == VALTYPE.listcon)
                {
                    int index = L0.List.Size - 1;
                    R0 = L0.List[index];
                    L0.List.Remove(index);
                    return(R0);
                }
                else if (size == 2 && L0.ty == VALTYPE.listcon && L1.ty == VALTYPE.intcon)
                {
                    int index = L1.Intcon;
                    R0 = L0.List[index];
                    L0.List.Remove(index);
                    return(R0);
                }
                break;


            case "insert":
                if (size == 3 && L0.ty == VALTYPE.listcon && L1.ty == VALTYPE.intcon)
                {
                    L0.List.Insert(L1.Intcon, VAL.Clone(L[2]));
                    return(L0);
                }
                break;

            case "remove":
                if (size == 2 && L0.ty == VALTYPE.listcon && L1.ty == VALTYPE.intcon)
                {
                    L0.List.Remove(L1.Intcon);
                    return(L0);
                }
                break;
                #endregion


            //DEBUG
            case "echo":
                return(new VAL(L));

            case "write":
                return(WriteLine(L));

            case "loginfo":
                return(LogInfo(L));



                #region internal functions used by parser

            case Constant.FUNC_CAST_TYPE_VALUE:
                if (size == 2)
                {
                    return(cast(L1, L0));
                }
                break;

            case Constant.FUNC_CAST_VALUE_TYPE:
                if (size == 2)
                {
                    return(cast(L0, L1));
                }
                break;

            case Constant.FUNC_IS_TYPE:
                if (size == 2)
                {
                    Type type = SystemFunction.GetValDefinitionType(L1);
                    if (type != null)
                    {
                        if (L0.value == null)
                        {
                            return(new VAL(false));
                        }
                        else
                        {
                            return(new VAL(type.IsAssignableFrom(L0.value.GetType())));
                        }
                    }
                    else
                    {
                        throw new RuntimeException(position, "{0} is not type or not registered.", L1.value);
                    }
                }
                break;

            case Constant.FUNC_MAKE_ARRAY_TYPE:
                if (size == 1 || size == 2)
                {
                    Type ty = SystemFunction.GetValDefinitionType(L0);
                    if (ty != null)
                    {
                        if (size == 1)
                        {
                            return(VAL.Boxing1(ty.MakeArrayType()));
                        }
                        else if (L1.value is int)
                        {
                            return(VAL.Boxing1(ty.MakeArrayType(L1.Intcon)));
                        }
                    }
                    else
                    {
                        throw new RuntimeException(position, "declare array failed, {0} is not type.", L0.value);
                    }
                }
                break;


            case Constant.FUNC_FUNCTION:
                if (L[1].ty == VALTYPE.intcon)
                {
                    return(new VAL(Operand.Func(L[1].Intcon, L[0].Str)));
                }
                else
                {
                    return(new VAL(Operand.Func(L[1].Str, L[0].Str)));
                }

            case Constant.FUNC_CLASS:
                return(new VAL(Operand.Clss(L[1].Intcon, L[0].Str)));


                #endregion


                #region propertyof, methodof, fieldof


            case "propertyof":
                if (size >= 2 && size <= 4)
                {
                    object host = L0.value;
                    if (host == null)
                    {
                        break;
                    }

                    if (L0.ty == VALTYPE.hostcon && L1.ty == VALTYPE.stringcon)
                    {
                        if (size == 2 || size == 3)
                        {
                            return(HostFunction.propertyof(size == 2, null, (string)L1.value, host, size == 2 ? null: L[2].HostValue));
                        }
                    }
                    else if (L0.ty == VALTYPE.hostcon &&
                             L1.ty == VALTYPE.hostcon && L1.value is Type &&
                             L[2].ty == VALTYPE.stringcon)
                    {
                        if (size == 3 || size == 4)
                        {
                            return(HostFunction.propertyof(size == 3, (Type)L1.value, (string)L[2].value, host, size == 3 ? null : L[3].HostValue));
                        }
                    }
                }
                break;


            case "fieldof":
                if (size == 2 || size == 3)
                {
                    object host = L0.value;
                    if (host == null)
                    {
                        break;
                    }

                    if (L0.ty == VALTYPE.hostcon && L1.ty == VALTYPE.stringcon)
                    {
                        Type      ty        = HostType.GetHostType(host);
                        FieldInfo fieldInfo = ty.GetField((string)L1.value, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
                        if (fieldInfo == null)
                        {
                            throw new RuntimeException(position, string.Format("Invalid field name: {0}.{1}", ty.FullName, L1.value));
                        }

                        if (size == 2)
                        {
                            return(VAL.Boxing1(fieldInfo.GetValue(host)));
                        }
                        else
                        {
                            fieldInfo.SetValue(host, L[2].HostValue);
                            return(VAL.VOID);
                        }
                    }
                }
                break;



            case "methodof":
                if (size == 4)
                {
                    object host = L0.value;
                    if (host == null)
                    {
                        break;
                    }

                    VAL    L2   = L[2];
                    object args = L[3].HostValue;

                    if (L0.ty == VALTYPE.hostcon &&
                        L1.ty == VALTYPE.hostcon && L1.value is Type &&
                        L2.ty == VALTYPE.stringcon &&
                        args is Type[])
                    {
                        MethodInfo methodInfo = HostFunction.methodof(host, (Type)L1.value, (string)L2.value, (Type[])args);
                        if (methodInfo != null)
                        {
                            VAL method = VAL.Boxing1(methodInfo);
                            method.temp = new HostOffset(host, methodInfo);
                            return(method);
                        }
                        else
                        {
                            throw new RuntimeException(position, "method {0} is not existed", L2.value);
                        }
                    }
                }
                break;

                #endregion
            }

            return(null);
        }