Ejemplo n.º 1
0
        public void Add(ISledLuaVarBaseType luaVar)
        {
            if (luaVar == null)
            {
                return;
            }

            m_dictCustomWatches[luaVar] = WatchedVariableService.ReceivingWatchedCustomVariables;

            if (luaVar.DomNode.Is <SledLuaVarGlobalType>())
            {
                Globals.Add(luaVar.DomNode.As <SledLuaVarGlobalType>());
            }
            else if (luaVar.DomNode.Is <SledLuaVarLocalType>())
            {
                Locals.Add(luaVar.DomNode.As <SledLuaVarLocalType>());
            }
            else if (luaVar.DomNode.Is <SledLuaVarUpvalueType>())
            {
                Upvalues.Add(luaVar.DomNode.As <SledLuaVarUpvalueType>());
            }
            else if (luaVar.DomNode.Is <SledLuaVarEnvType>())
            {
                EnvVars.Add(luaVar.DomNode.As <SledLuaVarEnvType>());
            }
        }
Ejemplo n.º 2
0
        public static LocalObjectDef AllocateLocal(Type type, string name = "")
        {
            List <LocalObjectDef> duplicatedLocals = new List <LocalObjectDef>();
            int number = 0;
            int i;

            for (i = 0; i < Locals.Count; i++)
            {
                if (Locals[i].Scope == ObjectScope.Local && (Locals[i] as LocalObjectDef).Name == name && name != "")
                {
                    duplicatedLocals.Add(Locals[i] as LocalObjectDef);
                    Locals[i].IsUsed = false;
                }
            }

            for (i = 0; i < Locals.Count; i++)
            {
                if (Locals[i].Type.Name == type.Name && !Locals[i].IsUsed)
                {
                    number    = i;
                    Locals[i] = new LocalObjectDef(type, number, name);
                    break;
                }
            }
            if (i == Locals.Count)
            {
                var localVar = iLGenerator.DeclareLocal(type);
                number = localVar.LocalIndex;
                Locals.Add(new LocalObjectDef(type, number, name));
            }

            EmitSaveToLocal(number);

            return(Locals[number]);
        }
Ejemplo n.º 3
0
        public LocalBuilderInfo AddLocal(string name, LocalBuilder builder)
        {
            LocalBuilderInfo info = new LocalBuilderInfo(Locals.Count, name, builder);

            Locals.Add(name, info);
            return(info);
        }
Ejemplo n.º 4
0
 public Catch(Type exception, Lambda filter, IEnumerable <Node> nodes)
     : base(NodeType.Catch, nodes)
 {
     ExceptionType = exception;
     Filter        = filter ?? new Lambda(typeof(Exception), typeof(bool));
     Locals.Add(new Local("$exn", null));
 }
Ejemplo n.º 5
0
        public void Set <T>(string name, T value)
        {
            var pyName = name;
            var pyObj  = value;

            Locals.Add(pyName, pyObj);
        }
Ejemplo n.º 6
0
        private bool Visit(DeclareLocalStatement stmt)
        {
            var value = stmt.Initializer == null ? new BitsValue(0, stmt.Local.BitSize) : Visit(stmt.Initializer);

            Locals.Add(stmt.Local.Name, value);

            return(false);
        }
Ejemplo n.º 7
0
        Variable StoreTempDontDup(DataType dt)
        {
            var v = new Variable(Function.Source, Function, "#temp" + (_tempVariableCounter++), dt);

            Locals.Add(v);
            Emit(Opcodes.StoreLocal, v);
            return(v);
        }
Ejemplo n.º 8
0
        void CreateIndirection(DataType dt)
        {
            var v = new Variable(Function.Source, Function, "#ind" + (_tempVariableCounter++), dt);

            Locals.Add(v);
            Emit(Opcodes.StoreLocal, v);
            Emit(Opcodes.LoadLocalAddress, v);
        }
Ejemplo n.º 9
0
 public IZ_FOR(int numberOfInterations)
 {
     if (Locals["Index"] == null)
     {
         Locals.Add(new Variables.LocalsVariable {
             Name = "Index", VariableType = typeof(Int32), Value = 0
         });
     }
 }
Ejemplo n.º 10
0
        public override void Parse(TokensStack sTokens)
        {
            Token tFunc = sTokens.Pop();

            if (!(tFunc is Statement) || ((Statement)tFunc).Name != "function")
            {
                throw new SyntaxErrorException("Expected function received: " + tFunc, tFunc);
            }
            Token tType = sTokens.Pop();

            if (!(tType is VarType))
            {
                throw new SyntaxErrorException("Expected var type, received " + tType, tType);
            }
            ReturnType = VarDeclaration.GetVarType(tType);
            Token tName = sTokens.Pop();

            if (!(tName is Identifier))
            {
                throw new SyntaxErrorException("Expected function name, received " + tType, tType);
            }
            Name = ((Identifier)tName).Name;

            Token t = sTokens.Pop();                                      //(

            while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses)) //)
            {
                if (sTokens.Count < 3)
                {
                    throw new SyntaxErrorException("Early termination ", t);
                }
                Token          tArgType = sTokens.Pop();
                Token          tArgName = sTokens.Pop();
                VarDeclaration vc       = new VarDeclaration(tArgType, tArgName);
                Args.Add(vc);
                if (sTokens.Count > 0 && sTokens.Peek() is Separator)//,
                {
                    sTokens.Pop();
                }
            }
            t = sTokens.Pop(); //)
            t = sTokens.Pop(); //{
            while (sTokens.Count > 0 && (sTokens.Peek() is Statement) && (((Statement)sTokens.Peek()).Name == "var"))
            {
                VarDeclaration local = new VarDeclaration();
                local.Parse(sTokens);
                Locals.Add(local);
            }
            while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses))
            {
                StatetmentBase s = StatetmentBase.Create(sTokens.Peek());
                s.Parse(sTokens);
                Body.Add(s);
            }
            Token tEnd = sTokens.Pop();//}
        }
Ejemplo n.º 11
0
        Variable StoreTemp(DataType dt, bool pop)
        {
            if (pop)
            {
                return(null);
            }
            var v = new Variable(Function.Source, Function, "#temp" + (_tempVariableCounter++), dt);

            Locals.Add(v);
            Emit(Opcodes.Dup);
            Emit(Opcodes.StoreLocal, v);
            return(v);
        }
Ejemplo n.º 12
0
 public void AddVariable(string name, object value)
 {
     var nameIdx = LocalNames.IndexOf(name);
     if (nameIdx == -1)
     {
         LocalNames.Add(name);
         Locals.Add(value);
     }
     else
     {
         Locals[nameIdx] = value;
     }
 }
        private void EmitArrayCreationWithInitializer()
        {
            var localBuilder = ILGenerator.DeclareLocal(Type);

            Locals.Add(localBuilder);
            Node.Initializer.AcceptVisitor(Visitor, ILGenerator);
            Node.Arguments.ForEach(arg => arg.AcceptVisitor(this, ILGenerator));

            if (TryEmitNewObject())
            {
                ILGenerator.EmitStoreLocal(localBuilder);
            }
        }
Ejemplo n.º 14
0
        public LingoHandler(LingoScriptChunk script, ref ShockwaveReader input)
            : this(script)
        {
            NameIndex             = input.ReadInt16();
            HandlerVectorPosition = input.ReadInt16();

            Body = new LingoHandlerBody(this, ref input);
            int codeOffset = input.ReadInt32();

            Arguments.Capacity = input.ReadInt16();
            int argumentsOffset = input.ReadInt32();

            Locals.Capacity = input.ReadInt16();
            int localsOffset = input.ReadInt32();

            input.ReadInt16(); //offset(?)
            input.ReadInt32(); //length(?)

            input.ReadInt32(); //offset?
            input.ReadInt16(); //length?

            BytesPerLine.Capacity = input.ReadInt16();
            int lineOffset = input.ReadInt32();

            Body.StackHeight = input.ReadInt32();

            int handlerEndOffset = input.Position;

            input.Position = codeOffset;
            input.ReadBytes(Body.Code);

            input.Position = argumentsOffset;
            for (int i = 0; i < Arguments.Capacity; i++)
            {
                Arguments.Add(input.ReadInt16());
            }

            input.Position = localsOffset;
            for (int i = 0; i < Locals.Capacity; i++)
            {
                Locals.Add(input.ReadInt16());
            }

            input.Position = lineOffset;
            for (int i = 0; i < BytesPerLine.Capacity; i++)
            {
                BytesPerLine.Add(input.ReadByte());
            }

            input.Position = handlerEndOffset;
        }
Ejemplo n.º 15
0
        private void EmitVariableDeclarationStatement(CodeVariableDeclarationStatement Statement)
        {
            if (Locals.ContainsKey(Statement.Name))
            {
                throw new CompileException(Statement, "Attempt to redefine local variable " + Statement.Name);
            }

            Type         Top   = EmitExpression(Statement.InitExpression);
            LocalBuilder Local = Generator.DeclareLocal(Top);

            Locals.Add(Statement.Name, Local);

            Generator.Emit(OpCodes.Stloc, Local);
        }
        protected internal override void EmitPrivateReference()
        {
            Type fieldInfoType    = typeof(FieldInfo);
            Type typeOfSystemType = typeof(Type);
            var  localBuilder     = ILGenerator.DeclareLocal(fieldInfoType);

            Locals.Add(localBuilder);
            ILGenerator.Emit(OpCodes.Ldtoken, Target);
            ILGenerator.Emit(OpCodes.Call, typeOfSystemType.GetMethod("GetTypeFromHandle"));
            ILGenerator.Emit(OpCodes.Ldstr, FieldReference.Name);
            ILGenerator.EmitPushInteger(Convert.ToInt32(BindingFlags.NonPublic | BindingFlags.Static));
            ILGenerator.Emit(OpCodes.Callvirt, typeOfSystemType.GetMethod("GetField", new Type[] { TypeSystem.String, typeof(BindingFlags) }));
            ILGenerator.EmitStoreLocal(localBuilder);
            ILGenerator.EmitLoadLocal(localBuilder);
            ILGenerator.Emit(OpCodes.Ldnull);
            ILGenerator.Emit(OpCodes.Callvirt, fieldInfoType.GetMethod("GetValue", new Type[] { TypeSystem.Object }));
        }
Ejemplo n.º 17
0
        private void Visit(DeclareLocalStatement stmt)
        {
            var local = IL.DeclareLocal(typeof(BitsValue), "local_" + stmt.Local.Name);

            Locals.Add(stmt.Local.Name, (local, stmt.Local.BitSize));

            if (stmt.Initializer != null)
            {
                Visit(stmt.Initializer);
                IL.Stloc(local);
            }
            else
            {
                IL.Ldloca(local);
                IL.Initobj(typeof(BitsValue));
            }
        }
Ejemplo n.º 18
0
        private void EmitPrivateDelegate(MethodInfo methodInfo)
        {
            var typeOfDelegate = typeof(Delegate);
            var localArray     = ILGenerator.DeclareLocal(typeof(object[]));
            var parameters     = methodInfo.GetParameters();

            Locals.Add(localArray);
            ILGenerator.Emit(OpCodes.Castclass, typeOfDelegate);
            ILGenerator.EmitPushInteger(parameters.Length);
            ILGenerator.Emit(OpCodes.Newarr, TypeSystem.Object);
            ILGenerator.EmitStoreLocal(localArray);

            Node.AcceptVisitor(this, ILGenerator);

            ILGenerator.EmitLoadLocal(localArray);
            ILGenerator.Emit(OpCodes.Callvirt, typeOfDelegate.GetMethod("DynamicInvoke"));
            ILGenerator.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType);
        }
Ejemplo n.º 19
0
        private void EmitPrivate(MethodInfo methodInfo)
        {
            Type typeArrayType           = typeof(Type[]);
            Type objectArrayType         = typeof(object[]);
            Type methodInfoType          = typeof(MethodInfo);
            var  parameters              = methodInfo.GetParameters();
            var  localTypeArray          = ILGenerator.DeclareLocal(typeArrayType);
            var  localObjectArray        = ILGenerator.DeclareLocal(objectArrayType);
            var  getTypeFromHandleMethod = typeof(Type).GetMethod("GetTypeFromHandle");
            var  invocation              = methodInfoType.BaseType.GetMethod("Invoke", new Type[] { TypeSystem.Object, typeof(object[]) });

            Locals.Add(localTypeArray);
            Locals.Add(localObjectArray);
            ILGenerator.Emit(OpCodes.Ldtoken, methodInfo.DeclaringType);
            ILGenerator.Emit(OpCodes.Call, getTypeFromHandleMethod);
            ILGenerator.Emit(OpCodes.Ldstr, methodInfo.Name);
            ILGenerator.EmitPushInteger(Convert.ToInt32(BindingFlags.NonPublic | BindingFlags.Static));
            ILGenerator.Emit(OpCodes.Ldnull);
            ILGenerator.EmitPushInteger(parameters.Length);
            ILGenerator.Emit(OpCodes.Newarr, typeArrayType.GetElementType());
            ILGenerator.EmitStoreLocal(localTypeArray);

            parameters.ForEach((p, i) => {
                ILGenerator.EmitLoadLocal(localTypeArray);
                ILGenerator.EmitPushInteger(i);
                ILGenerator.Emit(OpCodes.Ldtoken, p.ParameterType);
                ILGenerator.Emit(OpCodes.Call, getTypeFromHandleMethod);
                ILGenerator.Emit(OpCodes.Stelem_Ref);
            });

            ILGenerator.EmitLoadLocal(localTypeArray);
            ILGenerator.Emit(OpCodes.Ldnull);
            ILGenerator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetMethod", new Type[] { TypeSystem.String, typeof(BindingFlags), typeof(Binder), typeof(Type[]), typeof(SysReflection.ParameterModifier[]) }));
            ILGenerator.Emit(OpCodes.Ldnull);
            ILGenerator.EmitPushInteger(parameters.Length);
            ILGenerator.Emit(OpCodes.Newarr, TypeSystem.Object);
            ILGenerator.EmitStoreLocal(localObjectArray);

            Node.AcceptVisitor(this, ILGenerator);

            ILGenerator.EmitLoadLocal(localObjectArray);
            ILGenerator.Emit(OpCodes.Callvirt, invocation);
            ILGenerator.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType);
        }
Ejemplo n.º 20
0
        void BuildRoutine([NotNull] ZilRoutine routine, [NotNull] IRoutineBuilder rb, bool entryPoint, bool traceRoutines)
        {
            // give the user a chance to rewrite the routine
            routine = MaybeRewriteRoutine(Context, routine);

            // set up arguments and locals
            ClearLocalsAndBlocks();

            if (Context.TraceRoutines)
            {
                rb.EmitPrint("[" + routine.Name, false);
            }

            DefineLocalsFromArgSpec();

            if (Context.TraceRoutines)
            {
                rb.EmitPrint("]\n", false);
            }

            // define a block for the routine
            Blocks.Clear();
            Blocks.Push(new Block
            {
                Name        = routine.ActivationAtom,
                AgainLabel  = rb.RoutineStart,
                ReturnLabel = null,
                Flags       = BlockFlags.None
            });

            // generate code for routine body
            int i = 1;

            foreach (var stmt in routine.Body)
            {
                // only want the result of the last statement
                // and we never want results in the entry routine, since it can't return
                CompileStmt(rb, stmt, !entryPoint && i == routine.BodyLength);
                i++;
            }

            // the entry point has to quit instead of returning
            if (entryPoint)
            {
                rb.EmitQuit();
            }

            // clean up
            WarnAboutUnusedLocals();
            ClearLocalsAndBlocks();

            // helpers
            void DefineLocalsFromArgSpec()
            {
                foreach (var arg in routine.ArgSpec)
                {
                    var originalArgName = arg.Atom;
                    var uniqueArgName   = MakeUniqueVariableName(originalArgName);

                    if (uniqueArgName != originalArgName)
                    {
                        /* When a parameter has to be renamed because of a conflict, use TempLocalNames
                         * to reserve the new name so we don't collide with it later. For example:
                         *
                         *   <GLOBAL FOO <>>
                         *   <ROUTINE BLAH (FOO)
                         *     <PROG ((FOO)) ...>>
                         *
                         * We rename the local variable to FOO?1 to avoid shadowing the global.
                         * Now the temporary variable bound by the PROG has to be FOO?2.
                         * ZIL code only sees the name FOO: the local is shadowed inside the PROG,
                         * and the global can always be accessed with SETG and GVAL.
                         */
                        TempLocalNames.Add(uniqueArgName);
                    }

                    var lb = MakeLocalBuilder(arg, uniqueArgName.Text);

                    if (traceRoutines && arg.Type == ArgItem.ArgType.Required)
                    {
                        // TODO: print OPT parameters when tracing routine execution too
                        rb.EmitPrint(" " + originalArgName + "=", false);
                        rb.EmitPrint(PrintOp.Number, lb);
                    }

                    var lbr = new LocalBindingRecord(arg.Type.ToLocalBindingType(), routine.SourceLine, originalArgName.Text, lb);
                    Locals.Add(originalArgName, lbr);
                    AllLocalBindingRecords.Add(lbr);

                    SetOrEmitDefaultValue(lb, arg);
                }
            }

            ILocalBuilder MakeLocalBuilder(ArgItem arg, string uniqueArgName)
            {
                ILocalBuilder lb;

                switch (arg.Type)
                {
                case ArgItem.ArgType.Required:
                    try
                    {
                        lb = rb.DefineRequiredParameter(uniqueArgName);
                    }
                    catch (InvalidOperationException)
                    {
                        throw new CompilerError(
                                  CompilerMessages.Expression_Needs_Temporary_Variables_Not_Allowed_Here);
                    }
                    break;

                case ArgItem.ArgType.Optional:
                    lb = rb.DefineOptionalParameter(uniqueArgName);
                    break;

                case ArgItem.ArgType.Auxiliary:
                    lb = rb.DefineLocal(uniqueArgName);
                    break;

                default:
                    throw UnhandledCaseException.FromEnum(arg.Type);
                }

                return(lb);
            }

            void SetOrEmitDefaultValue(ILocalBuilder lb, ArgItem arg)
            {
                if (arg.DefaultValue == null)
                {
                    return;
                }

                Debug.Assert(arg.Type == ArgItem.ArgType.Optional || arg.Type == ArgItem.ArgType.Auxiliary);

                // setting any default value counts as a write
                MarkVariableAsWritten(lb);

                lb.DefaultValue = CompileConstant(arg.DefaultValue);
                if (lb.DefaultValue != null)
                {
                    return;
                }

                ILabel nextLabel = null;

                // ReSharper disable once SwitchStatementMissingSomeCases
                switch (arg.Type)
                {
                case ArgItem.ArgType.Optional when !rb.HasArgCount:
                    // not a constant
                    throw new CompilerError(routine.SourceLine,
                                            CompilerMessages.Optional_Args_With_Nonconstant_Defaults_Not_Supported_For_This_Target);

                case ArgItem.ArgType.Optional:
                    nextLabel = rb.DefineLabel();
                    rb.Branch(Condition.ArgProvided, lb, null, nextLabel, true);
                    goto default;

                default:
                    var val = CompileAsOperand(rb, arg.DefaultValue, routine.SourceLine, lb);
                    if (val != lb)
                    {
                        rb.EmitStore(lb, val);
                    }
                    break;
                }

                if (nextLabel != null)
                {
                    rb.MarkLabel(nextLabel);
                }
            }

            void WarnAboutUnusedLocals()
            {
                foreach (var lbr in AllLocalBindingRecords)
                {
                    if (lbr.IsEverRead || lbr.IsEverWritten)
                    {
                        continue;
                    }

                    if (lbr.Type == LocalBindingType.CompilerTemporary)
                    {
                        continue;
                    }

                    //XXX not sure about this
                    if (lbr.Type == LocalBindingType.RoutineRequired)
                    {
                        continue;
                    }

                    var warning = new CompilerError(
                        lbr.Definition,
                        CompilerMessages.Local_Variable_0_Is_Never_Used,
                        lbr.BoundName);

                    Context.HandleError(warning);
                }
            }
        }
Ejemplo n.º 21
0
        //This is an example of the implementation of the Parse method
        public override void Parse(TokensStack sTokens)
        {
            //We check that the first token is "function"
            Token tFunc = sTokens.Pop();

            if (!(tFunc is Statement) || ((Statement)tFunc).Name != "function")
            {
                throw new SyntaxErrorException("Expected function received: " + tFunc, tFunc);
            }
            //Now there should be the return type. We pop it from the stack, check for errors, and then set the field
            Token tType = sTokens.Pop();

            if (!(tType is VarType))
            {
                throw new SyntaxErrorException("Expected var type, received " + tType, tType);
            }
            ReturnType = VarDeclaration.GetVarType(tType);
            //Next is the function name
            Token tName = sTokens.Pop();

            if (!(tName is Identifier))
            {
                throw new SyntaxErrorException("Expected function name, received " + tType, tType);
            }
            Name = ((Identifier)tName).Name;

            //After the name there should be opening paranthesis for the arguments
            Token t = sTokens.Pop(); //(

            if (!(t is Parentheses) || ((Parentheses)t).Name != '(')
            {
                throw new SyntaxErrorException($"Expected a '(' but saw '{t}'", t);
            }

            //Now we extract the arguments from the stack until we see a closing parathesis
            while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses))//)
            {
                //For each argument there should be a type, and a name
                if (sTokens.Count < 3)
                {
                    throw new SyntaxErrorException("Early termination ", t);
                }
                Token          tArgType = sTokens.Pop();
                Token          tArgName = sTokens.Pop();
                VarDeclaration vc       = new VarDeclaration(tArgType, tArgName);
                Args.Add(vc);
                //If there is a comma, then there is another argument
                if (sTokens.Count > 0 && sTokens.Peek() is Separator) //,
                {
                    t = sTokens.Pop();
                    if (!(t is Separator) || ((Separator)t).Name != ',')
                    {
                        throw new SyntaxErrorException($"Expected a ',' but saw '{t}'", t);
                    }
                }
            }
            //Now we pop out the ) and the {. Note that you need to check that the stack contains the correct symbols here.
            t = sTokens.Pop();//)
            if (!(t is Parentheses) || ((Parentheses)t).Name != ')')
            {
                throw new SyntaxErrorException($"Expected a ')' but saw '{t}'", t);
            }
            t = sTokens.Pop();//{
            if (!(t is Parentheses) || ((Parentheses)t).Name != '{')
            {
                throw new SyntaxErrorException($"Expected a '{{' but saw '{t}'", t);
            }

            //Now we parse the list of local variable declarations
            while (sTokens.Count > 0 && (sTokens.Peek() is Statement) && (((Statement)sTokens.Peek()).Name == "var"))
            {
                VarDeclaration local = new VarDeclaration();
                //We call the Parse method of the VarDeclaration, which is responsible to parsing the elements of the variable declaration
                local.Parse(sTokens);
                Locals.Add(local);
            }

            //Now we parse the list of statements
            while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses))
            {
                //We create the correct Statement type (if, while, return, let) based on the top token in the stack
                StatetmentBase s = StatetmentBase.Create(sTokens.Peek());
                //And call the Parse method of the statement to parse the different parts of the statement
                s.Parse(sTokens);
                Body.Add(s);
            }

            bool hasReturn = false;

            if (Body.Count > 0)
            {
                StatetmentBase lastStatetment = Body[Body.Count - 1];
                Body.RemoveAt(Body.Count - 1);
                if (lastStatetment is ReturnStatement)
                {
                    Return    = (ReturnStatement)lastStatetment;
                    hasReturn = true;
                }
                else
                {
                    hasReturn = false;
                }
            }

            //Need to check here that the last statement is a return statement
            //Finally, the function should end with }
            Token tEnd = sTokens.Pop();//}

            if (!hasReturn)
            {
                throw new SyntaxErrorException("Missing a return statement.", tEnd);
            }
            if (!(tEnd is Parentheses) || ((Parentheses)tEnd).Name != '}')
            {
                throw new SyntaxErrorException($"Expected a '}}' but saw '{t}'", t);
            }
        }
Ejemplo n.º 22
0
 public MethodBodySymbolContext WithLocal(ILocal local)
 => new MethodBodySymbolContext(SourceSymbolContext, Locals.Add(local), CurrentStatement);
Ejemplo n.º 23
0
        public void CompileExpression(Expression e, bool pop = false, bool addressMode = false, Condition cond = null)
        {
            switch (e.ExpressionType)
            {
            case ExpressionType.NoOp:
                break;

            case ExpressionType.AddressOf:
                CompileExpression((e as AddressOf).Operand, pop, true);
                break;

            case ExpressionType.Constant:
            {
                if (cond != null && !cond.Handled)
                {
                    if ((bool)e.ConstantValue)
                    {
                        cond.CanSkipFalse = true;

                        if (cond.Sequence != ConditionSequence.TrueFollows)
                        {
                            Branch(Opcodes.Br, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()));
                        }
                    }
                    else
                    {
                        cond.CanSkipTrue = true;

                        if (cond.Sequence != ConditionSequence.FalseFollows)
                        {
                            Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));
                        }
                    }

                    cond.Handled = true;
                }
                else if (!pop)
                {
                    if (e.ConstantValue != null)
                    {
                        Emit(Opcodes.Constant, e.ConstantValue);
                    }
                    else if (!e.ReturnType.IsReferenceType || e.ReturnType.IsGenericType)
                    {
                        Emit(Opcodes.DefaultInit, e.ReturnType);
                    }
                    else
                    {
                        Emit(Opcodes.Null);
                    }

                    if (addressMode)
                    {
                        CreateIndirection(e.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.Default:
            {
                if (cond != null && !cond.Handled)
                {
                    Branch(Opcodes.Br, cond.FalseLabel);
                    cond.Handled = true;
                }
                else if (!pop)
                {
                    Emit(Opcodes.DefaultInit, e.ReturnType);

                    if (addressMode)
                    {
                        CreateIndirection(e.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.TypeOf:
            {
                if (!pop)
                {
                    Emit(Opcodes.TypeOf, (e as TypeOf).Type);
                }
            }
            break;

            case ExpressionType.This:
            {
                if (pop)
                {
                    return;
                }
                Emit(Opcodes.This);

                if (!addressMode && Function.DeclaringType.IsValueType)
                {
                    Emit(Opcodes.LoadObj, Function.DeclaringType);
                }
            }
            break;

            case ExpressionType.Base:
            {
                if (pop)
                {
                    return;
                }
                Emit(Opcodes.This);

                if (!Function.DeclaringType.IsValueType)
                {
                    return;
                }

                Emit(Opcodes.LoadObj, Function.DeclaringType);
                Emit(Opcodes.Box, Function.DeclaringType);
            }
            break;

            case ExpressionType.SequenceOp:
            {
                var s = e as SequenceOp;
                CompileExpression(s.Left, !s.Left.ReturnType.IsVoid);
                CompileExpression(s.Right, pop, addressMode);
            }
            break;

            case ExpressionType.IsOp:
            {
                var s = e as IsOp;
                CompileExpression(s.Operand, pop);

                if (pop)
                {
                    break;
                }
                if (s.Operand.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.Box, s.Operand.ReturnType);
                }

                Emit(Opcodes.AsClass, s.TestType);
                Emit(Opcodes.Null);
                Emit(Opcodes.Neq);

                if (addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.AsOp:
            {
                var s = e as AsOp;
                CompileExpression(s.Operand, pop);

                if (pop)
                {
                    break;
                }
                if (s.Operand.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.Box, s.Operand.ReturnType);
                }

                Emit(Opcodes.AsClass, s.ReturnType);

                if (s.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.UnboxAny, s.ReturnType);
                }
                if (addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.LoadLocal:
            {
                var s = e as LoadLocal;
                if (pop)
                {
                    break;
                }

                Emit(addressMode
                                ? Opcodes.LoadLocalAddress
                                : Opcodes.LoadLocal,
                     s.Variable);
            }
            break;

            case ExpressionType.LoadField:
            {
                var s = e as LoadField;

                if (s.Object != null)
                {
                    CompileExpression(s.Object, false, addressMode && s.Object is This);

                    if (pop)
                    {
                        Pop();
                    }
                    else
                    {
                        Emit(addressMode
                                        ? Opcodes.LoadFieldAddress
                                        : Opcodes.LoadField,
                             s.Field);
                    }
                }
                else
                {
                    if (!pop)
                    {
                        Emit(addressMode
                                        ? Opcodes.LoadStaticFieldAddress
                                        : Opcodes.LoadStaticfield,
                             s.Field);
                    }
                }
            }
            break;

            case ExpressionType.LoadElement:
            {
                var s = e as LoadElement;
                CompileExpression(s.Array, pop);
                CompileExpression(s.Index, pop);

                if (pop)
                {
                    return;
                }

                Emit(addressMode
                                ? Opcodes.LoadArrayElementAddress
                                : Opcodes.LoadArrayElement,
                     s.Array.ReturnType.ElementType);
            }
            break;

            case ExpressionType.LoadArgument:
            {
                if (pop)
                {
                    return;
                }
                var s        = e as LoadArgument;
                var paramRef = s.Parameter.IsReference;

                if (paramRef)
                {
                    if (addressMode)
                    {
                        Emit(Opcodes.LoadArg, s.Index);
                    }
                    else
                    {
                        Emit(Opcodes.LoadArg, s.Index);
                        Emit(Opcodes.LoadObj, s.Parameter.Type);
                    }
                }
                else
                {
                    Emit(addressMode
                                    ? Opcodes.LoadArgAddress
                                    : Opcodes.LoadArg,
                         s.Index);
                }
            }
            break;

            case ExpressionType.StoreLocal:
            {
                var s = e as StoreLocal;

                // TODO: This is a workaround for bug in sub ctor calls, remove this later
                if (!Locals.Contains(s.Variable))
                {
                    Locals.Add(s.Variable);
                }

                CompileExpression(s.Value);
                if (!pop)
                {
                    Emit(Opcodes.Dup);
                }
                Emit(Opcodes.StoreLocal, s.Variable);
            }
            break;

            case ExpressionType.StoreArgument:
            {
                var s = e as StoreArgument;

                if (s.Parameter.IsReference)
                {
                    Emit(Opcodes.LoadArg, s.Index);         // Loads the pointer from a out/ref argument
                    CompileExpression(s.Value);
                    var temp = StoreTemp(s.Value.ReturnType, pop);
                    Emit(Opcodes.StoreObj, s.Value.ReturnType);
                    LoadTemp(temp);
                }
                else
                {
                    CompileExpression(s.Value);
                    var temp = StoreTemp(s.Value.ReturnType, pop);
                    Emit(Opcodes.StoreArg, s.Index);
                    LoadTemp(temp);
                }

                if (!pop && addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.StoreField:
            {
                var s = e as StoreField;

                if (s.Object != null)
                {
                    CompileObject(s.Object, s.Field);
                    CompileExpression(s.Value);

                    var temp = StoreTemp(s.Value.ReturnType, pop);
                    Emit(Opcodes.StoreField, s.Field);
                    LoadTemp(temp);
                }
                else
                {
                    CompileExpression(s.Value);

                    var temp = StoreTemp(s.Value.ReturnType, pop);
                    Emit(Opcodes.StoreStaticField, s.Field);
                    LoadTemp(temp);
                }

                if (!pop & addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.StoreThis:
            {
                var s = e as StoreThis;

                Emit(Opcodes.This);

                if (!pop & addressMode)
                {
                    Emit(Opcodes.Dup);
                }

                CompileExpression(s.Value);
                Emit(Opcodes.StoreObj, s.Value.ReturnType);
            }
            break;

            case ExpressionType.StoreElement:
            {
                var s = e as StoreElement;

                CompileExpression(s.Array);
                CompileExpression(s.Index);
                CompileExpression(s.Value);

                var temp = StoreTemp(s.Value.ReturnType, pop);
                Emit(Opcodes.StoreArrayElement, s.Value.ReturnType);
                LoadTemp(temp);

                if (!pop & addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.SetProperty:
            {
                var s = e as SetProperty;
                CompileObject(s.Object, s.Property);

                foreach (var arg in s.Arguments)
                {
                    CompileExpression(arg);
                }

                CompileExpression(s.Value);

                var temp = StoreTemp(s.Value.ReturnType, pop);

                Call(s.Object, s.Property.SetMethod);

                LoadTemp(temp);

                if (!pop & addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.GetProperty:
            {
                var s = e as GetProperty;
                CompileObject(s.Object, s.Property);

                foreach (var arg in s.Arguments)
                {
                    CompileExpression(arg);
                }

                if (s.Property.DeclaringType.IsArray && s.Property.Parameters.Length == 0 && s.Property.UnoName == "Length")
                {
                    Emit(Opcodes.LoadArrayLength);
                }
                else
                {
                    Call(s.Object, s.Property.GetMethod);
                }

                if (pop)
                {
                    Pop();
                }
                else if (addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.AddListener:
            {
                var s = e as AddListener;
                CompileObject(s.Object, s.Event);
                CompileExpression(s.Listener);
                Call(s.Object, s.Event.AddMethod);
            }
            break;

            case ExpressionType.RemoveListener:
            {
                var s = e as RemoveListener;
                CompileObject(s.Object, s.Event);
                CompileExpression(s.Listener);
                Call(s.Object, s.Event.RemoveMethod);
            }
            break;

            case ExpressionType.ReferenceOp:
            {
                var s = e as ReferenceOp;

                CompileExpression(s.Left);

                if (s.Left.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.Box, s.Left.ReturnType);
                }

                CompileExpression(s.Right);

                if (s.Right.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.Box, s.Right.ReturnType);
                }

                if (cond != null && !cond.Handled)
                {
                    if (s.EqualityType == EqualityType.NotEqual)
                    {
                        Branch(Opcodes.BrNeq, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()));
                        Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));
                    }
                    else
                    {
                        Branch(Opcodes.BrEq, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()));
                        Branch(Opcodes.Br, cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));
                    }

                    cond.Handled = true;
                    return;
                }

                Emit(s.EqualityType == EqualityType.NotEqual
                                ? Opcodes.Neq
                                : Opcodes.Eq);

                if (pop)
                {
                    Pop();
                }
                else if (addressMode)
                {
                    CreateIndirection(e.ReturnType);
                }
            }
            break;

            case ExpressionType.BranchOp:
            {
                var s = e as BranchOp;

                if (s.BranchType == BranchType.And)
                {
                    if (cond != null && !cond.Handled)
                    {
                        var brtrue = NewLabel();
                        CompileCondition(s.Left, ConditionSequence.TrueFollows, brtrue, cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));

                        MarkLabel(brtrue);
                        CompileCondition(s.Right, ConditionSequence.NoneFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));

                        cond.Handled = true;
                    }
                    else
                    {
                        var c = CompileCondition(s.Left, ConditionSequence.TrueFollows);

                        var brafter = NewLabel();

                        MarkLabel(c.TrueLabel);
                        CompileExpression(s.Right);
                        Branch(Opcodes.Br, brafter);

                        MarkLabel(c.FalseLabel);
                        Emit(Opcodes.Constant, false);

                        MarkLabel(brafter);
                    }
                }
                else
                {
                    if (cond != null && !cond.Handled)
                    {
                        var brfalse = NewLabel();
                        CompileCondition(s.Left, ConditionSequence.FalseFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), brfalse);

                        MarkLabel(brfalse);
                        CompileCondition(s.Right, ConditionSequence.NoneFollows, cond.TrueLabel ?? (cond.TrueLabel = NewLabel()), cond.FalseLabel ?? (cond.FalseLabel = NewLabel()));

                        cond.Handled = true;
                    }
                    else
                    {
                        var c = CompileCondition(s.Left, ConditionSequence.TrueFollows);

                        var brafter = NewLabel();

                        MarkLabel(c.TrueLabel);
                        Emit(Opcodes.Constant, true);
                        Branch(Opcodes.Br, brafter);

                        MarkLabel(c.FalseLabel);
                        CompileExpression(s.Right);

                        MarkLabel(brafter);
                    }
                }
            }
            break;

            case ExpressionType.ConditionalOp:
            {
                var s       = e as ConditionalOp;
                var brtrue  = NewLabel();
                var brfalse = NewLabel();
                var brafter = NewLabel();
                var cc      = CompileCondition(s.Condition, ConditionSequence.TrueFollows, brtrue, brfalse);

                if (!cc.CanSkipTrue)
                {
                    MarkLabel(brtrue);
                    CompileExpression(s.True, pop, addressMode);
                    Branch(Opcodes.Br, brafter);
                }

                if (!cc.CanSkipFalse)
                {
                    MarkLabel(brfalse);
                    CompileExpression(s.False, pop, addressMode);
                }

                MarkLabel(brafter);
            }
            break;

            case ExpressionType.NullOp:
            {
                var s       = e as NullOp;
                var brnull  = NewLabel();
                var brafter = NewLabel();

                CompileExpression(s.Left);
                Emit(Opcodes.Dup);

                if (s.Left.ReturnType.IsGenericParameter)
                {
                    Emit(Opcodes.Box, s.Left.ReturnType);
                }

                Branch(Opcodes.BrNotNull, brafter);

                MarkLabel(brnull);
                Emit(Opcodes.Pop);
                CompileExpression(s.Right);

                MarkLabel(brafter);

                if (pop)
                {
                    Pop();
                }
            }
            break;

            case ExpressionType.CallCast:
            {
                var s = e as CallCast;
                CompileExpression(s.Operand);

                // TODO: Many casts are NOOP - i.e. byte -> char, char -> int
                switch (s.Operand.ReturnType.BuiltinType)
                {
                case BuiltinType.Char:
                case BuiltinType.Byte:
                case BuiltinType.SByte:
                case BuiltinType.UShort:
                case BuiltinType.Short:
                case BuiltinType.UInt:
                case BuiltinType.Int:
                case BuiltinType.ULong:
                case BuiltinType.Long:
                case BuiltinType.Float:
                case BuiltinType.Double:
                    switch (s.ReturnType.BuiltinType)
                    {
                    case BuiltinType.Char: Emit(Opcodes.ConvChar); break;

                    case BuiltinType.Byte: Emit(Opcodes.ConvByte); break;

                    case BuiltinType.SByte: Emit(Opcodes.ConvSByte); break;

                    case BuiltinType.UShort: Emit(Opcodes.ConvUShort); break;

                    case BuiltinType.Short: Emit(Opcodes.ConvShort); break;

                    case BuiltinType.UInt: Emit(Opcodes.ConvUInt); break;

                    case BuiltinType.Int: Emit(Opcodes.ConvInt); break;

                    case BuiltinType.ULong: Emit(Opcodes.ConvULong); break;

                    case BuiltinType.Long: Emit(s.Operand.ReturnType.IsUnsignedType ? Opcodes.ConvULong : Opcodes.ConvLong); break;

                    case BuiltinType.Float: Emit(Opcodes.ConvFloat); break;

                    case BuiltinType.Double: Emit(Opcodes.ConvDouble); break;

                    default: Call(null, s.Cast); break;
                    }

                    break;

                default:
                    Call(null, s.Cast);
                    break;
                }

                if (pop)
                {
                    Pop();
                }
                else if (addressMode)
                {
                    CreateIndirection(s.ReturnType);
                }
            }
            break;

            case ExpressionType.CallConstructor:
            {
                var s = e as CallConstructor;

                Emit(Opcodes.This);

                for (int i = 0; i < s.Arguments.Length; i++)
                {
                    CompileExpression(s.Arguments[i]);
                }

                Call(null, s.Constructor);
            }
            break;

            case ExpressionType.CallMethod:
            {
                var s = e as CallMethod;
                CompileObject(s.Object, s.Method);

                for (int i = 0; i < s.Arguments.Length; i++)
                {
                    CompileExpression(s.Arguments[i]);
                }

                Call(s.Object, s.Method);

                if (!s.ReturnType.IsVoid)
                {
                    if (pop)
                    {
                        Pop();
                    }
                    else if (addressMode)
                    {
                        CreateIndirection(s.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.CallDelegate:
            {
                var s = e as CallDelegate;
                CompileExpression(s.Object);

                foreach (var arg in s.Arguments)
                {
                    CompileExpression(arg);
                }

                Emit(Opcodes.CallDelegate, s.Object.ReturnType);

                if (!s.ReturnType.IsVoid)
                {
                    if (pop)
                    {
                        Pop();
                    }
                    else if (addressMode)
                    {
                        CreateIndirection(s.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.CallBinOp:
            {
                CompileBinOp(e as CallBinOp, pop, cond);
                if (addressMode)
                {
                    CreateIndirection(e.ReturnType);
                }
            }
            break;

            case ExpressionType.CallUnOp:
            {
                CompileUnOp(e as CallUnOp, pop);
                if (addressMode)
                {
                    CreateIndirection(e.ReturnType);
                }
            }
            break;

            case ExpressionType.CastOp:
            {
                var s = e as CastOp;
                CompileExpression(s.Operand);

                if (s.ReturnType.IsReferenceType && !s.ReturnType.IsGenericParameter)
                {
                    if (s.Operand.ReturnType.IsValueType || s.Operand.ReturnType.IsGenericParameter)
                    {
                        Emit(Opcodes.Box, s.Operand.ReturnType);
                    }
                    else
                    {
                        Emit(Opcodes.CastClass, s.ReturnType);
                    }

                    if (pop)
                    {
                        Pop();
                    }
                }
                else if (s.Operand.ReturnType.IsReferenceType && !s.Operand.ReturnType.IsGenericParameter)
                {
                    if (s.ReturnType.IsValueType)
                    {
                        Emit(Opcodes.Unbox, s.ReturnType);
                        Emit(Opcodes.LoadObj, s.ReturnType);

                        if (pop)
                        {
                            Pop();
                        }
                        else if (addressMode)
                        {
                            CreateIndirection(e.ReturnType);
                        }
                    }
                    else if (s.ReturnType.IsGenericParameter)
                    {
                        Emit(Opcodes.UnboxAny, s.ReturnType);

                        if (pop)
                        {
                            Pop();
                        }
                        else if (addressMode)
                        {
                            CreateIndirection(e.ReturnType);
                        }
                    }
                    else
                    {
                        Emit(Opcodes.CastClass, s.ReturnType);
                        if (pop)
                        {
                            Pop();
                        }
                    }
                }
                else
                {
                    if (addressMode && !pop)
                    {
                        CreateIndirection(s.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.NewObject:
            {
                var s = e as NewObject;
                foreach (var arg in s.Arguments)
                {
                    CompileExpression(arg);
                }

                Emit(Opcodes.NewObject, s.Constructor);

                if (pop)
                {
                    Pop();
                }
                else if (s.ReturnType.IsValueType && addressMode)
                {
                    CreateIndirection(e.ReturnType);
                }
            }
            break;

            case ExpressionType.NewDelegate:
            {
                var s = e as NewDelegate;

                if (s.Object != null)
                {
                    CompileExpression(s.Object);
                }
                else
                {
                    Emit(Opcodes.Null);
                }

                if (s.Object == null ||
                    s.Object is Base)
                {
                    Emit(Opcodes.LoadFunction, s.Method);
                }
                else
                {
                    Emit(Opcodes.Dup);
                    Emit(Opcodes.LoadFunctionVirtual, s.Method);
                }

                Emit(Opcodes.NewDelegate, s.ReturnType);
            }
            break;

            case ExpressionType.NewArray:
            {
                var s = e as NewArray;

                if (s.Size != null)
                {
                    CompileExpression(s.Size);
                }
                else
                {
                    Emit(Opcodes.Constant, s.Initializers.Length);
                }

                Emit(Opcodes.NewArray, ((RefArrayType)s.ReturnType).ElementType);

                if (s.Initializers != null)
                {
                    for (int i = 0; i < s.Initializers.Length; i++)
                    {
                        Emit(Opcodes.Dup);
                        Emit(Opcodes.Constant, i);
                        CompileExpression(s.Initializers[i]);
                        Emit(Opcodes.StoreArrayElement, s.Initializers[i].ReturnType);
                    }
                }

                if (pop)
                {
                    Pop();
                }
            }
            break;

            case ExpressionType.FixOp:
                CompileFixOp(e as FixOp, pop, addressMode);
                break;

            case ExpressionType.Swizzle:
            {
                var sw = e as Swizzle;

                CompileExpression(sw.Object);
                var temp = StoreTemp(sw.Object.ReturnType, false);

                foreach (var f in sw.Fields)
                {
                    LoadTemp(temp);
                    Emit(Opcodes.LoadField, f);
                }

                Emit(Opcodes.NewObject, sw.Constructor);

                if (pop)
                {
                    Pop();
                }
                else if (sw.ReturnType.IsValueType && addressMode)
                {
                    CreateIndirection(e.ReturnType);
                }
            }
            break;

            // Shader expression types must be handled to be able to use the bytecode backend for control flow validation of shaders,
            // as well as generating bytecode/assembly shaders
            case ExpressionType.RuntimeConst:
            {
                var s = e as RuntimeConst;
                Emit(Opcodes.GetShaderConst, s.State.RuntimeConstants[s.Index]);
            }
            break;

            case ExpressionType.LoadUniform:
            {
                var s = e as LoadUniform;
                Emit(Opcodes.LoadShaderUniform, s.State.Uniforms[s.Index]);
            }
            break;

            case ExpressionType.LoadPixelSampler:
            {
                var s = e as LoadPixelSampler;
                Emit(Opcodes.LoadShaderPixelSampler, s.State.PixelSamplers[s.Index]);
            }
            break;

            case ExpressionType.LoadVarying:
            {
                var s = e as LoadVarying;
                Emit(Opcodes.LoadShaderVarying, s.State.Varyings[s.Index]);
            }
            break;

            case ExpressionType.LoadVertexAttrib:
            {
                var s = e as LoadVertexAttrib;
                Emit(Opcodes.LoadShaderVarying, s.State.VertexAttributes[s.Index]);
            }
            break;

            case ExpressionType.CallShader:
            {
                var s = e as CallShader;

                for (int i = 0; i < s.Arguments.Length; i++)
                {
                    CompileExpression(s.Arguments[i]);
                }

                Call(null, s.Function);

                if (!s.ReturnType.IsVoid)
                {
                    if (pop)
                    {
                        Pop();
                    }
                    else if (addressMode)
                    {
                        CreateIndirection(s.ReturnType);
                    }
                }
            }
            break;

            case ExpressionType.LoadPtr:
            {
                var s = e as LoadPtr;
                CompileExpression(s.Argument, pop, addressMode, cond);
            }
            break;

            default:
                throw new Exception("<" + e.ExpressionType + "> is not supported in bytecode backend - at " + e.Source);
            }
        }
Ejemplo n.º 24
0
 public Iter(Expression init, Block body)
     : base(NodeType.Iter, init, body ?? new Block())
 {
     Locals.Add(new Local("$el", null));
 }
Ejemplo n.º 25
0
 public Using(Expression init, Block body)
     : base(NodeType.Using, init, body ?? new Block())
 {
     Locals.Add(new Local("$res", null));
 }
Ejemplo n.º 26
0
        /// <summary>
        /// Compiles the statement, and returns wether or not control flow falls through to the next statement.
        /// </summary>
        public void CompileStatement(Statement s, bool markSource)
        {
            switch (s.StatementType)
            {
                case StatementType.Expression:
                    {
                        var e = s as Expression;
                        var pop = !e.ReturnType.IsVoid;
                        if (markSource)
                            MarkSource(e.Source);

                        CompileExpression(e, pop, false);
                    }
                    break;

                case StatementType.VariableDeclaration:
                    {
                        var ld = s as VariableDeclaration;
                        for (var var = ld.Variable; var != null; var = var.Next)
                        {
                            Locals.Add(var);
                            if (var.OptionalValue != null)
                            {
                                if (markSource)
                                    MarkSource(var.Source);
                                CompileExpression(var.OptionalValue);
                                Emit(Opcodes.StoreLocal, var);
                            }
                        }
                    }
                    break;

                case StatementType.FixedArrayDeclaration:
                    {
                        var ld = s as FixedArrayDeclaration;
                        Locals.Add(ld.Variable);

                        if (ld.OptionalInitializer != null)
                        {
                            for (int i = 0; i < ld.OptionalInitializer.Length; i++)
                            {
                                if (markSource)
                                    MarkSource(ld.OptionalInitializer[i].Source);
                                Emit(Opcodes.Constant, i);
                                CompileExpression(ld.OptionalInitializer[i]);
                                Emit(Opcodes.StoreArrayElement, ld.Variable);
                            }
                        }
                    }
                    break;

                case StatementType.Scope:
                    {
                        var sc = s as Scope;

                        foreach (var st in sc.Statements)
                        {
                            var scopeCall = st as CallMethod;
                            var markScopeCall = !(scopeCall?.Method != null && scopeCall.Method.IsGenerated);
                            CompileStatement(st, markSource && markScopeCall);
                        }

                        if (sc.Statements.Count == 0 && markSource)
                            MarkSource(sc.Source);
                    }
                    break;

                case StatementType.While:
                    {
                        var w = s as While;

                        var body = NewLabel();
                        var cond = NewLabel();
                        var after = NewLabel();
                        _breakLabels.Push(after);
                        _continueLabels.Push(cond);

                        if (w.DoWhile)
                        {
                            MarkLabel(body);
                            if (w.OptionalBody != null)
                                CompileStatement(w.OptionalBody, markSource);

                            MarkLabel(cond);
                            if (markSource)
                                MarkSource(w.Condition.Source);
                            CompileCondition(w.Condition, ConditionSequence.FalseFollows, body, after);
                        }
                        else
                        {
                            MarkLabel(cond);
                            if (markSource)
                                MarkSource(w.Condition.Source);
                            CompileCondition(w.Condition, ConditionSequence.TrueFollows, body, after);

                            MarkLabel(body);
                            if (w.OptionalBody != null)
                                CompileStatement(w.OptionalBody, markSource);

                            Branch(Opcodes.Br, cond);
                        }

                        _breakLabels.Pop();
                        _continueLabels.Pop();

                        MarkLabel(after);
                    }
                    break;

                case StatementType.For:
                    {
                        var f = s as For;
                        var body = NewLabel();
                        var inc = NewLabel();
                        var cond = NewLabel();
                        var after = NewLabel();

                        _breakLabels.Push(after);
                        _continueLabels.Push(inc);

                        if (f.OptionalInitializer != null)
                            CompileStatement(f.OptionalInitializer, markSource);

                        Branch(Opcodes.Br, cond);

                        MarkLabel(body);
                        if (f.OptionalBody != null)
                            CompileStatement(f.OptionalBody, markSource);

                        MarkLabel(inc);
                        if (f.OptionalIncrement != null)
                        {
                            if (markSource)
                                MarkSource(f.OptionalIncrement.Source);
                            CompileExpression(f.OptionalIncrement, true);
                        }

                        MarkLabel(cond);
                        if (f.OptionalCondition != null)
                        {
                            if (markSource)
                                MarkSource(f.OptionalCondition.Source);
                            CompileCondition(f.OptionalCondition, ConditionSequence.FalseFollows, body, after);
                        }
                        else
                        {
                            Branch(Opcodes.Br, body);
                        }

                        _breakLabels.Pop();
                        _continueLabels.Pop();

                        MarkLabel(after);
                    }
                    break;

                case StatementType.IfElse:
                    {
                        var ife = s as IfElse;
                        if (markSource)
                            MarkSource(ife.Condition.Source);
                        var cond = CompileCondition(ife.Condition, ConditionSequence.TrueFollows);

                        MarkLabel(cond.TrueLabel);
                        if (ife.OptionalIfBody != null)
                            CompileStatement(ife.OptionalIfBody, markSource);

                        if (ife.OptionalElseBody != null)
                        {
                            var after = NewLabel();
                            Branch(Opcodes.Br, after);

                            MarkLabel(cond.FalseLabel);
                            CompileStatement(ife.OptionalElseBody, markSource);

                            MarkLabel(after);
                        }
                        else
                        {
                            MarkLabel(cond.FalseLabel);
                        }
                    }
                    break;

                case StatementType.Return:
                    {
                        var r = s as Return;
                        if (r.Value != null)
                        {
                            if (markSource)
                                MarkSource(r.Value.Source);
                            CompileExpression(r.Value);
                            Return(r.Value.ReturnType);
                        }
                        else
                        {
                            if (markSource)
                                MarkSource(s.Source);
                            Return(null);
                        }
                    }
                    break;

                case StatementType.Break:
                    {
                        if (_breakLabels.Count == 0)
                            throw new FatalException(s.Source, ErrorCode.E0015, "Invalid break");

                        if (markSource)
                            MarkSource(s.Source);
                        Branch(Opcodes.Br, _breakLabels.Peek());
                    }
                    break;

                case StatementType.Continue:
                    {
                        if (_continueLabels.Count == 0)
                            throw new FatalException(s.Source, ErrorCode.E0016, "Invalid continue");

                        if (markSource)
                            MarkSource(s.Source);
                        Branch(Opcodes.Br, _continueLabels.Peek());
                    }
                    break;

                case StatementType.TryCatchFinally:
                    {
                        var tc = s as TryCatchFinally;

                        _tryCatchStack.Add(tc);

                        Emit(Opcodes.BeginExceptionBlock);
                        CompileStatement(tc.TryBody, markSource);

                        foreach (var c in tc.CatchBlocks)
                        {
                            Emit(Opcodes.BeginCatchBlock, c.Exception.ValueType);

                            if (markSource)
                                MarkSource(c.Body.Source);
                            Locals.Add(c.Exception);
                            Emit(Opcodes.StoreLocal, c.Exception);
                            CompileStatement(c.Body, markSource);
                        }

                        _tryCatchStack.RemoveLast();

                        // TODO: finally-clause goes here (_AFTER_ "POP"!)

                        if (tc.OptionalFinallyBody != null)
                        {
                            Emit(Opcodes.BeginFinallyBlock);
                            if (markSource)
                                MarkSource(tc.OptionalFinallyBody.Source);
                            CompileStatement(tc.OptionalFinallyBody, markSource);
                        }

                        Emit(Opcodes.EndExceptionBlock);
                    }
                    break;

                case StatementType.Switch:
                    {
                        var sw = s as Switch;
                        if (markSource)
                            MarkSource(sw.ControlVariable.Source);
                        CompileExpression(sw.ControlVariable);
                        var temp = StoreTempDontDup(sw.ControlVariable.ReturnType);

                        var after = NewLabel();

                        Label defaultLabel = null;
                        _breakLabels.Push(after);

                        var caseLabels = new Label[sw.Cases.Length];

                        for (var i = 0; i < sw.Cases.Length; i++)
                            caseLabels[i] = NewLabel();

                        for (var i = 0; i < sw.Cases.Length; i++)
                        {
                            for (int v = 0; v < sw.Cases[i].Values.Length; v++)
                            {
                                CompileExpression(sw.Cases[i].Values[v]);
                                LoadTemp(temp);
                                Branch(Opcodes.BrEq, caseLabels[i]);
                            }

                            if (sw.Cases[i].HasDefault)
                            {
                                defaultLabel = caseLabels[i];
                            }
                        }

                        Branch(Opcodes.Br, defaultLabel ?? after);

                        for (var i = 0; i < sw.Cases.Length; i++)
                        {
                            MarkLabel(caseLabels[i]);
                            CompileStatement(sw.Cases[i].Scope, markSource);
                            Branch(Opcodes.Br, after);
                        }

                        _breakLabels.Pop();
                        MarkLabel(after);
                    }
                    break;

                case StatementType.Throw:
                    {
                        var t = s as Throw;
                        if (markSource)
                            MarkSource(t.Source);
                        CompileExpression(t.Exception);
                        Emit(Opcodes.Throw);
                        if (markSource)
                            MarkSource(t.Source);
                    }
                    break;

                case StatementType.Draw:
                case StatementType.DrawDispose:
                    break;

                default:
                    throw new FatalException(s.Source, ErrorCode.I0017, "Statement type not supported in bytecode backend: " + s.StatementType);
            }
        }
Ejemplo n.º 27
0
        private Type EmitAssignment(CodeExpression Left, CodeExpression Right, bool ForceTypes)
        {
            Depth++;
            Debug("Emitting assignment expression");
            Type Generated = typeof(void);

            if (Left is CodeVariableReferenceExpression)
            {
                // local IL variables generated by parser
                var Reference = Left as CodeVariableReferenceExpression;

                LocalBuilder Var;
                if (Locals.ContainsKey(Reference.VariableName))
                {
                    Var = Locals[Reference.VariableName];
                }
                else
                {
                    Var = Generator.DeclareLocal(typeof(int));
                    Locals.Add(Reference.VariableName, Var);
                }

                EmitExpression(Right, ForceTypes);
                Generator.Emit(OpCodes.Stloc, Var);
                Generator.Emit(OpCodes.Pop);
            }
            else if (Left is CodeArrayIndexerExpression)
            {
                var index = (CodeArrayIndexerExpression)Left;

                Generator.Emit(OpCodes.Ldloc, VarsProperty);

                EmitExpression(index.Indices[0]);
                Type resultType = EmitExpression(Right, ForceTypes);
                if (resultType.IsValueType)
                {
                    Generator.Emit(OpCodes.Box, resultType);
                }

                Generator.Emit(OpCodes.Callvirt, SetVariable);

                Generated = typeof(object);
            }
            else if (Left is CodePropertyReferenceExpression)
            {
                var prop = (CodePropertyReferenceExpression)Left;

                // HACK: property set method target
                var info = typeof(Rusty.Core).GetProperty(prop.PropertyName);

                if (Mirror != null)
                {
                    info = Mirror.GrabProperty(info);
                }

                var set = info == null ? null : info.GetSetMethod();

                if (set == null)
                {
                    Generator.Emit(OpCodes.Ldnull);
                }
                else
                {
                    EmitExpression(Right);
                    Generator.Emit(OpCodes.Dup);
                    Generator.Emit(OpCodes.Call, set);
                }

                Generated = typeof(object);
            }
            else
            {
                throw new CompileException(Left, "Left hand is unassignable");
            }

            Depth--;

            return(Generated);
        }
Ejemplo n.º 28
0
 public void AddVariable(string name, object value)
 {
     LocalNames.Add(name);
     Locals.Add(value);
 }
Ejemplo n.º 29
0
        public override void Parse(TokensStack sTokens)
        {
            /*
             * Function Type ID( args ){
             * varDec*
             * Statments*
             * Return Statment
             * }
             *
             * check more errors
             */
            Token t;

            StackIsNotEmpty(sTokens);
            Token tFunc = sTokens.Pop();

            if (!(tFunc is Statement) || ((Statement)tFunc).Name != "function")
            {
                throw new SyntaxErrorException("Expected function received: " + tFunc, tFunc);
            }
            StackIsNotEmpty(sTokens);
            Token tType = sTokens.Pop();

            if (!(tType is VarType))
            {
                throw new SyntaxErrorException("Expected var type, received " + tType, tType);
            }
            ReturnType = VarDeclaration.GetVarType(tType);
            StackIsNotEmpty(sTokens);
            Token tName = sTokens.Pop();

            if (!(tName is Identifier))
            {
                throw new SyntaxErrorException("Expected function name, received " + tType, tType);
            }
            Name = ((Identifier)tName).Name;
            StackIsNotEmpty(sTokens);
            if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == "(")
            {
                t = sTokens.Pop(); //(
            }
            else
            {
                throw new SyntaxErrorException("Expected ( Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek());
            }
            StackIsNotEmpty(sTokens);
            while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses))
            {
                if (sTokens.Count < 3)
                {
                    throw new SyntaxErrorException("Early termination ", t);
                }
                Token          tArgType = sTokens.Pop();
                Token          tArgName = sTokens.Pop();
                VarDeclaration vc       = new VarDeclaration(tArgType, tArgName);
                Args.Add(vc);
                if (sTokens.Count > 0 && sTokens.Peek() is Separator)//,
                {
                    sTokens.Pop();
                }
            }
            StackIsNotEmpty(sTokens);
            if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == ")")
            {
                t = sTokens.Pop(); //)
            }
            else
            {
                throw new SyntaxErrorException("Expected ) Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek());
            }
            StackIsNotEmpty(sTokens);
            if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == "{")
            {
                t = sTokens.Pop(); //{
            }
            else
            {
                throw new SyntaxErrorException("Expected { Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek());
            }
            StackIsNotEmpty(sTokens);
            while (sTokens.Count > 0 && (sTokens.Peek() is Statement) && (((Statement)sTokens.Peek()).Name == "var"))
            {
                VarDeclaration local = new VarDeclaration();
                local.Parse(sTokens);
                Locals.Add(local);
            }
            StackIsNotEmpty(sTokens);
            while (sTokens.Count > 0 && !(sTokens.Peek() is Parentheses))
            {
                StatetmentBase s = StatetmentBase.Create(sTokens.Peek());
                s.Parse(sTokens);
                Body.Add(s);
            }
            StackIsNotEmpty(sTokens);
            if (sTokens.Peek() is Parentheses && sTokens.Peek().ToString() == "}")
            {
                t = sTokens.Pop(); //}
            }
            else
            {
                throw new SyntaxErrorException("Expected } Parentheses received: " + sTokens.Peek().ToString(), sTokens.Peek());
            }
        }