/// <summary>
        /// Emit code storing the value on the stack to memory
        /// </summary>
        /// <param name="name"></param>
        /// <param name="types"></param>
        public void Store(VariableName name, TypeStack <TEmit> types)
        {
            // Update the type tracker with the newly discovered type
            _types.Store(name, types.Peek);

            if (_cache.ContainsKey(name))
            {
                var local = _cache[name];

                // Convert to the correct type for this local
                var inType = types.Peek;
                ConvertType(inType, local.Type);
                types.Pop(inType);

                // Store in appropriate local
                _emitter.StoreLocal(local.Local);

                // Mark cache dirty
                _emitter.LoadConstant(true);
                _emitter.StoreLocal(_cacheDirty[name]);
            }
            else
            {
                // Immediately convert type to YololValue
                ConvertType(types.Peek, StackType.YololValue);
                types.Pop(types.Peek);

                // Write directly to backing store
                EmitStoreValue(name);
            }
        }
Example #2
0
        private void CompileRepeat(GMLToken _tok)
        {
            VMLabel vMLabel  = new VMLabel("End", VMB);
            VMLabel vMLabel2 = new VMLabel("Repeat", VMB);

            CompileExpression(_tok.Children[0]);
            eVM_Type eVM_Type = TypeStack.Pop();

            if (eVM_Type != eVM_Type.eVMT_Int)
            {
                Emit(eVM_Instruction.eVMI_CONV, eVM_Type, eVM_Type.eVMT_Int);
            }
            Emit(eVM_Instruction.eVMI_DUP, eVM_Type.eVMT_Int);
            EmitI(eVM_Instruction.eVMI_PUSH, 0);
            Emit(eVM_Instruction.eVMI_SET_LE, eVM_Type.eVMT_Int, eVM_Type.eVMT_Int);
            Emit(eVM_Instruction.eVMI_BTRUE, vMLabel);
            LoopEnv.Push(vMLabel2);
            LoopEndEnv.Push(vMLabel);
            vMLabel2.Mark(VMB.Buffer.Position);
            CompileStatement(_tok.Children[1]);
            EmitI(eVM_Instruction.eVMI_PUSH, 1);
            Emit(eVM_Instruction.eVMI_SUB, eVM_Type.eVMT_Int, eVM_Type.eVMT_Int);
            Emit(eVM_Instruction.eVMI_DUP, eVM_Type.eVMT_Int);
            Emit(eVM_Instruction.eVMI_CONV, eVM_Type.eVMT_Int, eVM_Type.eVMT_Bool);
            Emit(eVM_Instruction.eVMI_BTRUE, vMLabel2);
            vMLabel.Mark(VMB.Buffer.Position);
            Emit(eVM_Instruction.eVMI_POPNULL, eVM_Type.eVMT_Int);
            LoopEnv.Pop();
            LoopEndEnv.Pop();
        }
Example #3
0
        private void CompilePop(GMLToken _tok, eVM_Type _type)
        {
            switch (_tok.Token)
            {
            case eToken.eVariable:
            case eToken.eDot:
                if (_tok.Children.Count >= 2)
                {
                    int num = 0;
                    CompileExpression(_tok.Children[0]);
                    if (TypeStack.Peek() != eVM_Type.eVMT_Int)
                    {
                        Emit(eVM_Instruction.eVMI_CONV, TypeStack.Pop(), eVM_Type.eVMT_Int);
                        TypeStack.Push(eVM_Type.eVMT_Int);
                    }
                    if (_tok.Children[1].Children.Count > 0)
                    {
                        CompileExpression(_tok.Children[1].Children[0]);
                        if (TypeStack.Peek() != eVM_Type.eVMT_Int)
                        {
                            Emit(eVM_Instruction.eVMI_CONV, TypeStack.Pop(), eVM_Type.eVMT_Int);
                            TypeStack.Push(eVM_Type.eVMT_Int);
                        }
                        if (_tok.Children[1].Children.Count > 1)
                        {
                            EmitI(eVM_Instruction.eVMI_PUSH, 32000);
                            Emit(eVM_Instruction.eVMI_MUL, eVM_Type.eVMT_Int, eVM_Type.eVMT_Int);
                            CompileExpression(_tok.Children[1].Children[1]);
                            if (TypeStack.Peek() != eVM_Type.eVMT_Int)
                            {
                                Emit(eVM_Instruction.eVMI_CONV, TypeStack.Pop(), eVM_Type.eVMT_Int);
                                TypeStack.Push(eVM_Type.eVMT_Int);
                            }
                            Emit(eVM_Instruction.eVMI_ADD, eVM_Type.eVMT_Int, eVM_Type.eVMT_Int);
                            TypeStack.Pop();
                        }
                        TypeStack.Pop();
                    }
                    else
                    {
                        num |= int.MinValue;
                    }
                    TypeStack.Pop();
                    EmitIVar(eVM_Instruction.eVMI_POP, _tok.Children[1].Id | num, _type);
                    TypeStack.Push(eVM_Type.eVMT_Variable);
                }
                else
                {
                    Error("Malformed variable reference", _tok);
                }
                break;

            case eToken.eConstant:
                Error("Unsure where these come from", _tok);
                break;
            }
        }
Example #4
0
        private void BinaryTypeCoercion(GMLToken _tok, int _parmNum)
        {
            eVM_Type eVM_Type = TypeStack.Peek();

            switch (_tok.Children[1].Token)
            {
            case eToken.eNot:
            case eToken.eLess:
            case eToken.eLessEqual:
            case eToken.eEqual:
            case eToken.eNotEqual:
            case eToken.eGreaterEqual:
            case eToken.eGreater:
            case eToken.eBitNegate:
                break;

            case eToken.ePlus:
            case eToken.eMinus:
            case eToken.eTime:
            case eToken.eDivide:
            case eToken.eDiv:
            case eToken.eMod:
                if (eVM_Type == eVM_Type.eVMT_Bool)
                {
                    TypeStack.Pop();
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type, eVM_Type.eVMT_Int);
                    TypeStack.Push(eVM_Type.eVMT_Int);
                }
                break;

            case eToken.eAnd:
            case eToken.eOr:
            case eToken.eXor:
                if (eVM_Type != eVM_Type.eVMT_Bool)
                {
                    TypeStack.Pop();
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type, eVM_Type.eVMT_Bool);
                    TypeStack.Push(eVM_Type.eVMT_Bool);
                }
                break;

            case eToken.eBitOr:
            case eToken.eBitAnd:
            case eToken.eBitXor:
            case eToken.eBitShiftLeft:
            case eToken.eBitShiftRight:
                if (eVM_Type == eVM_Type.eVMT_Int)
                {
                    TypeStack.Pop();
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type, eVM_Type.eVMT_Int);
                    TypeStack.Push(eVM_Type.eVMT_Int);
                }
                break;
            }
        }
Example #5
0
        private void CompileUnary(GMLToken _tok)
        {
            CompileExpression(_tok.Children[0]);
            eVM_Type eVM_Type = TypeStack.Peek();

            switch (_tok.Id)
            {
            case 203:
                switch (eVM_Type)
                {
                case eVM_Type.eVMT_String:
                case eVM_Type.eVMT_Error:
                    Error("Unable to Not a string", _tok);
                    break;

                case eVM_Type.eVMT_Double:
                case eVM_Type.eVMT_Float:
                case eVM_Type.eVMT_Int:
                case eVM_Type.eVMT_Long:
                case eVM_Type.eVMT_Variable:
                    TypeStack.Pop();
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type, eVM_Type.eVMT_Bool);
                    TypeStack.Push(eVM_Type.eVMT_Bool);
                    eVM_Type = eVM_Type.eVMT_Bool;
                    break;
                }
                Emit(eVM_Instruction.eVMI_NOT, eVM_Type);
                break;

            case 211:
                Emit(eVM_Instruction.eVMI_NEG, eVM_Type);
                break;

            case 220:
                switch (eVM_Type)
                {
                case eVM_Type.eVMT_String:
                case eVM_Type.eVMT_Error:
                    Error("Unable to Negate a string", _tok);
                    break;

                case eVM_Type.eVMT_Double:
                case eVM_Type.eVMT_Float:
                case eVM_Type.eVMT_Variable:
                    TypeStack.Pop();
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type, eVM_Type.eVMT_Int);
                    TypeStack.Push(eVM_Type.eVMT_Int);
                    eVM_Type = eVM_Type.eVMT_Int;
                    break;
                }
                Emit(eVM_Instruction.eVMI_NOT, eVM_Type);
                break;
            }
        }
Example #6
0
 private void CompileFunction(GMLToken _tok)
 {
     foreach (GMLToken child in _tok.Children)
     {
         CompileExpression(child);
         eVM_Type eVM_Type = TypeStack.Pop();
         if (eVM_Type != eVM_Type.eVMT_Variable)
         {
             Emit(eVM_Instruction.eVMI_CONV, eVM_Type, eVM_Type.eVMT_Variable);
         }
     }
     EmitI(eVM_Instruction.eVMI_CALL, _tok.Id);
     TypeStack.Push(GMAssetCompiler.eVM_Type.eVMT_Variable);
 }
Example #7
0
        private bool SubsumedInner(DataType type1, DataType type2, TypeStack typeStack)
        {
            if (typeStack.Contains(type1, type2))
            {
                return(true);
            }

            if (type1.IsUnknownType() || type1 == DataType.None || type1.Equals(type2))
            {
                return(true);
            }

            if (type1 is TupleType tuple1 && type2 is TupleType tuple2)
            {
                List <DataType> elems1 = tuple1.eltTypes;
                List <DataType> elems2 = tuple2.eltTypes;

                if (elems1.Count == elems2.Count)
                {
                    typeStack.Push(type1, type2);
                    for (int i = 0; i < elems1.Count; i++)
                    {
                        if (!SubsumedInner(elems1[i], elems2[i], typeStack))
                        {
                            typeStack.Pop(type1, type2);
                            return(false);
                        }
                    }
                }
                return(true);
            }

            if (type1 is ListType list1 && type2 is ListType list2)
            {
                return(SubsumedInner(list1.ToTupleType(), list2.ToTupleType(), typeStack));
            }
            return(false);
        }
Example #8
0
        private void Uninitialize()
        {
            var serializable = Model as ISerializable;

            if (serializable != null)
            {
                var registrationInfo = ReferenceManager.GetInfo(serializable);

                //// Note: we need to use the x.Tag instead of x.Instance.ContextMode here because we might be serializing a different thing
                //switch ((SerializationContextMode)x.Tag)
                switch (ContextMode)
                {
                case SerializationContextMode.Serialization:
                    if (!registrationInfo.HasCalledSerialized)
                    {
                        serializable.FinishSerialization();
                        registrationInfo.HasCalledSerialized = true;
                    }
                    break;

                case SerializationContextMode.Deserialization:
                    if (!registrationInfo.HasCalledDeserialized)
                    {
                        serializable.FinishDeserialization();
                        registrationInfo.HasCalledDeserialized = true;
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            TypeStack.Pop();
            Contexts.Pop();
        }
Example #9
0
        private void CompileAssign(GMLToken _tok)
        {
            switch (_tok.Children[1].Token)
            {
            case eToken.eAssign:
                CompileExpression(_tok.Children[2]);
                CompilePop(_tok.Children[0], TypeStack.Pop());
                break;

            case eToken.eAssignPlus:
            {
                CompileVariable(_tok.Children[0]);
                TypeStack.Pop();
                CompileExpression(_tok.Children[2]);
                eVM_Type eVM_Type3 = TypeStack.Pop();
                if (eVM_Type3 == eVM_Type.eVMT_Bool)
                {
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type3, eVM_Type.eVMT_Int);
                    eVM_Type3 = eVM_Type.eVMT_Int;
                }
                Emit(eVM_Instruction.eVMI_ADD, eVM_Type3, eVM_Type.eVMT_Variable);
                CompilePop(_tok.Children[0], eVM_Type.eVMT_Variable);
                break;
            }

            case eToken.eAssignMinus:
            {
                CompileVariable(_tok.Children[0]);
                TypeStack.Pop();
                CompileExpression(_tok.Children[2]);
                eVM_Type eVM_Type7 = TypeStack.Pop();
                if (eVM_Type7 == eVM_Type.eVMT_Bool)
                {
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type7, eVM_Type.eVMT_Int);
                    eVM_Type7 = eVM_Type.eVMT_Int;
                }
                Emit(eVM_Instruction.eVMI_SUB, eVM_Type7, eVM_Type.eVMT_Variable);
                CompilePop(_tok.Children[0], eVM_Type.eVMT_Variable);
                break;
            }

            case eToken.eAssignTimes:
            {
                CompileVariable(_tok.Children[0]);
                TypeStack.Pop();
                CompileExpression(_tok.Children[2]);
                eVM_Type eVM_Type2 = TypeStack.Pop();
                if (eVM_Type2 == eVM_Type.eVMT_Bool)
                {
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type2, eVM_Type.eVMT_Int);
                    eVM_Type2 = eVM_Type.eVMT_Int;
                }
                Emit(eVM_Instruction.eVMI_MUL, eVM_Type2, eVM_Type.eVMT_Variable);
                CompilePop(_tok.Children[0], eVM_Type.eVMT_Variable);
                break;
            }

            case eToken.eAssignDivide:
            {
                CompileVariable(_tok.Children[0]);
                TypeStack.Pop();
                CompileExpression(_tok.Children[2]);
                eVM_Type eVM_Type6 = TypeStack.Pop();
                if (eVM_Type6 == eVM_Type.eVMT_Bool)
                {
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type6, eVM_Type.eVMT_Int);
                    eVM_Type6 = eVM_Type.eVMT_Int;
                }
                Emit(eVM_Instruction.eVMI_DIV, eVM_Type6, eVM_Type.eVMT_Variable);
                CompilePop(_tok.Children[0], eVM_Type.eVMT_Variable);
                break;
            }

            case eToken.eAssignOr:
            {
                CompileVariable(_tok.Children[0]);
                TypeStack.Pop();
                CompileExpression(_tok.Children[2]);
                eVM_Type eVM_Type4 = TypeStack.Pop();
                if (eVM_Type4 != eVM_Type.eVMT_Int && eVM_Type4 != eVM_Type.eVMT_Long)
                {
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type4, eVM_Type.eVMT_Int);
                    eVM_Type4 = eVM_Type.eVMT_Int;
                }
                Emit(eVM_Instruction.eVMI_OR, eVM_Type4, eVM_Type.eVMT_Variable);
                CompilePop(_tok.Children[0], eVM_Type.eVMT_Variable);
                break;
            }

            case eToken.eAssignAnd:
            {
                CompileVariable(_tok.Children[0]);
                TypeStack.Pop();
                CompileExpression(_tok.Children[2]);
                eVM_Type eVM_Type5 = TypeStack.Pop();
                if (eVM_Type5 != eVM_Type.eVMT_Int && eVM_Type5 != eVM_Type.eVMT_Long)
                {
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type5, eVM_Type.eVMT_Int);
                    eVM_Type5 = eVM_Type.eVMT_Int;
                }
                Emit(eVM_Instruction.eVMI_AND, eVM_Type5, eVM_Type.eVMT_Variable);
                CompilePop(_tok.Children[0], eVM_Type.eVMT_Variable);
                break;
            }

            case eToken.eAssignXor:
            {
                CompileVariable(_tok.Children[0]);
                TypeStack.Pop();
                CompileExpression(_tok.Children[2]);
                eVM_Type eVM_Type = TypeStack.Pop();
                if (eVM_Type != eVM_Type.eVMT_Int && eVM_Type != eVM_Type.eVMT_Long)
                {
                    Emit(eVM_Instruction.eVMI_CONV, eVM_Type, eVM_Type.eVMT_Int);
                    eVM_Type = eVM_Type.eVMT_Int;
                }
                Emit(eVM_Instruction.eVMI_XOR, eVM_Type, eVM_Type.eVMT_Variable);
                CompilePop(_tok.Children[0], eVM_Type.eVMT_Variable);
                break;
            }
            }
        }
Example #10
0
        private void CompileBinary(GMLToken _tok)
        {
            CompileExpression(_tok.Children[0]);
            BinaryTypeCoercion(_tok, 1);
            CompileExpression(_tok.Children[2]);
            BinaryTypeCoercion(_tok, 2);
            eVM_Type eVM_Type  = TypeStack.Pop();
            eVM_Type eVM_Type2 = TypeStack.Pop();
            int      num       = TypeSize(eVM_Type);
            int      num2      = TypeSize(eVM_Type2);
            eVM_Type item      = (num > num2) ? eVM_Type : eVM_Type2;

            switch (_tok.Children[1].Token)
            {
            case eToken.eTime:
                Emit(eVM_Instruction.eVMI_MUL, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;

            case eToken.eDivide:
                Emit(eVM_Instruction.eVMI_DIV, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;

            case eToken.eDiv:
                Emit(eVM_Instruction.eVMI_REM, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;

            case eToken.eMod:
                Emit(eVM_Instruction.eVMI_MOD, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;

            case eToken.ePlus:
                Emit(eVM_Instruction.eVMI_ADD, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;

            case eToken.eMinus:
                Emit(eVM_Instruction.eVMI_SUB, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;

            case eToken.eLess:
                Emit(eVM_Instruction.eVMI_SET_LT, eVM_Type, eVM_Type2);
                TypeStack.Push(eVM_Type.eVMT_Bool);
                break;

            case eToken.eLessEqual:
                Emit(eVM_Instruction.eVMI_SET_LE, eVM_Type, eVM_Type2);
                TypeStack.Push(eVM_Type.eVMT_Bool);
                break;

            case eToken.eAssign:
            case eToken.eEqual:
                Emit(eVM_Instruction.eVMI_SET_EQ, eVM_Type, eVM_Type2);
                TypeStack.Push(eVM_Type.eVMT_Bool);
                break;

            case eToken.eNotEqual:
                Emit(eVM_Instruction.eVMI_SET_NE, eVM_Type, eVM_Type2);
                TypeStack.Push(eVM_Type.eVMT_Bool);
                break;

            case eToken.eGreaterEqual:
                Emit(eVM_Instruction.eVMI_SET_GE, eVM_Type, eVM_Type2);
                TypeStack.Push(eVM_Type.eVMT_Bool);
                break;

            case eToken.eGreater:
                Emit(eVM_Instruction.eVMI_SET_GT, eVM_Type, eVM_Type2);
                TypeStack.Push(eVM_Type.eVMT_Bool);
                break;

            case eToken.eAnd:
            case eToken.eBitAnd:
                Emit(eVM_Instruction.eVMI_AND, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;

            case eToken.eOr:
            case eToken.eBitOr:
                Emit(eVM_Instruction.eVMI_OR, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;

            case eToken.eXor:
            case eToken.eBitXor:
                Emit(eVM_Instruction.eVMI_XOR, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;

            case eToken.eBitShiftLeft:
                Emit(eVM_Instruction.eVMI_SHL, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;

            case eToken.eBitShiftRight:
                Emit(eVM_Instruction.eVMI_SHR, eVM_Type, eVM_Type2);
                TypeStack.Push(item);
                break;
            }
        }