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); }
/// <summary> /// Emit code to load a value onto the stack /// </summary> /// <param name="name"></param> /// <param name="types"></param> public void Load(VariableName name, TypeStack <TEmit> types) { // Check if we know what type this variable is var type = _types.TypeOf(name) ?? StackType.YololValue; if (_cache.ContainsKey(name)) { var local = _cache[name]; _emitter.LoadLocal(local.Local); ConvertType(local.Type, type); types.Push(type); } else { // Load from backing store EmitLoadValue(name); // Unbox it to that type (bypassing dynamic type checking) StaticUnbox(type); types.Push(type); } }
private void CompileConstant(GMLToken _tok) { switch (_tok.Value.Kind) { case eKind.eConstant: Error("constant token", _tok); break; case eKind.eNone: Error("None constant token", _tok); break; case eKind.eNumber: { double num = (long)_tok.Value.ValueI; if (num == _tok.Value.ValueI) { long num2 = (long)_tok.Value.ValueI; if (num2 > int.MaxValue || num2 < int.MinValue) { EmitI(eVM_Instruction.eVMI_PUSH, num2); TypeStack.Push(eVM_Type.eVMT_Long); } else if (num2 > 32767 || num2 < -32768) { EmitI(eVM_Instruction.eVMI_PUSH, (int)num2); TypeStack.Push(eVM_Type.eVMT_Int); } else { VMB.Add(VMBuffer.EncodeInstructionArg(192, 15) | (int)(num2 & 0xFFFF)); TypeStack.Push(eVM_Type.eVMT_Int); } } else { EmitI(eVM_Instruction.eVMI_PUSH, _tok.Value.ValueI); TypeStack.Push(eVM_Type.eVMT_Double); } break; } case eKind.eString: EmitI(eVM_Instruction.eVMI_PUSH, _tok.Value.ValueS); TypeStack.Push(eVM_Type.eVMT_String); break; } }
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 Initialize() { Contexts.Push(this); TypeStack.Push(ModelType); 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.HasCalledSerializing) { serializable.StartSerialization(); registrationInfo.HasCalledSerializing = true; } break; case SerializationContextMode.Deserialization: if (!registrationInfo.HasCalledDeserializing) { serializable.StartDeserialization(); registrationInfo.HasCalledDeserializing = true; } break; default: throw new ArgumentOutOfRangeException(); } } }
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; } }