/// <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); } }
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(); }
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; } }
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; } }
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; } }
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); }
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); }
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(); }
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; } } }
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; } }