void CHSSysEngines::CutPower(HS_INT32 level) { if (level == 0) { if (GetOwnerObject() && GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *cShip; cShip = (CHSShip *) GetOwnerObject(); if (hsInterface.AtrGet(cShip->GetDbref(), "HSMSG_ENGINES_CUT")) { HS_DBREF idx = cShip->GetDbref(); char *msg = hsInterface.EvalExpression(hsInterface.m_buffer, idx, idx, idx); cShip->NotifySrooms(msg); } else { cShip->NotifySrooms(HSCONF.engines_cut); } } } }
void CHSDamCon::UnassignCrew(HS_DBREF player, int iCrew) { // Be certain this is a valid crew ID. if ((iCrew < 1) || (iCrew > (int) GetNumCrews())) { return; } // Grab this crew's structure from the vector. THSDamageCrew & rtCrew = m_vecCrews[iCrew]; // Only one crew can be assigned to a system at any one time. HS_INT32 iNumCrews = GetNumCrews(); for (int idx = 0; idx < iNumCrews; idx++) { // If this crew is the one we're assigning, ignore it. if (idx == iCrew) { rtCrew.pAssignedTo = NULL; rtCrew.iSecondsLeft = 0; if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *pOwnerShip = static_cast <CHSShip * > (GetOwnerObject()); pOwnerShip->NotifyConsoles(hsInterface. HSPrintf( "%s%s-%s Damage Control crew %i now available.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL, iCrew), MSG_ENGINEERING); } } } }
void CHSSysThrusters::PowerUp(int level) { if (!GetOwnerObject()) { return; } if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *cShip; cShip = (CHSShip *) GetOwnerObject(); if (hsInterface. AtrGet(cShip->GetDbref(), "HSMSG_THRUSTERS_ACTIVATING")) { char *msg = hsInterface.EvalExpression(hsInterface.m_buffer, cShip->GetDbref(), cShip->GetDbref(), cShip->GetDbref()); cShip->NotifySrooms(msg); } else { cShip->NotifySrooms(HSCONF.thrusters_activating); } } }
void CHSJumpDrive::DoCycle() { float rate; // Do base stuff first CHSEngSystem::DoCycle(); // Charge jumpers? if ((GetCurrentPower() > 0) && (m_fChargeLevel < 100)) { rate = GetChargeRate(true); if (rate > 0) { m_fChargeLevel += rate; // Make sure we don't overcharge if (m_fChargeLevel > 100) { m_fChargeLevel = 100; } if (m_fChargeLevel == 100) { if (GetOwnerObject() && GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *cShip; cShip = (CHSShip *) GetOwnerObject(); if (cShip) { cShip->NotifyConsoles(hsInterface. HSPrintf ("%s%s-%s Jump Drive charged.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL), MSG_ENGINEERING); } } } } } // If engaged, consume fuel. if (m_bEngaged) { ConsumeFuelBySpeed(m_uiSublightSpeed * m_iJumpSpeedMultiplier); } }
// Gets the fuel system for the engines. Replaces the m_fuel_source variable. CHSFuelSystem* CHSSysEngines::GetFuelSource(void) { CHSShip *cShip = (CHSShip *) GetOwnerObject(); if (!cShip) return NULL; return (CHSFuelSystem *)cShip->GetSystems().GetSystem(HSS_FUEL_SYSTEM); }
// Gets the fuel system for the engines. Replaces the m_fuel_source variable. CHSFuelSystem* CHSJumpDrive::GetFuelSource(void) { CHSShip *cShip = (CHSShip *) GetOwnerObject(); if (!cShip) { return NULL; } return (CHSFuelSystem *)cShip->GetSystems().GetSystem(HSS_FUEL_SYSTEM); }
void CHSJumpDrive::CutPower(HS_INT32 level) { if (level == 0) { if (GetOwnerObject() && (GetOwnerObject()->GetType() == HST_SHIP)) { CHSShip *cShip; cShip = (CHSShip *) GetOwnerObject(); if (hsInterface.AtrGet(cShip->GetDbref(), "HSMSG_JUMPERS_CUT")) { char *msg = hsInterface.EvalExpression(hsInterface.m_buffer, cShip->GetDbref(), cShip->GetDbref(), cShip->GetDbref()); cShip->NotifySrooms(msg); } else { cShip->NotifySrooms(HSCONF.jumpers_cut); } } // Set charge level to 0. m_fChargeLevel = 0; // If jumpers are engaged and power is set to 0, then // disengage. if (GetEngaged()) { HS_INT8 tbuf[128]; m_bEngaged = false; sprintf(tbuf, "%s%s-%s Jump drive disengaged.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL); if (GetOwnerObject()) { GetOwnerObject()->HandleMessage(tbuf, MSG_ENGINEERING); } } } }
// Tells the engines that they need to gobble up some fuel // from the fuel source. The engines know their efficiency // and such, so they just drain the fuel from the fuel system. // Speed here should be given in units per hour. void CHSSysEngines::ConsumeFuelBySpeed(HS_INT32 speed) { float fConsume; float fRealized; // Do we have a fuel system? if (!GetFuelSource() || (GetFuelSource()->GetFuelRemaining() <= 0)) { return; } // If efficiency is 0, do not consume fuel if (0 == GetEfficiency()) { return; } // Calculate per second travel rate fConsume = (float) (speed * .0002778); // Divide by efficiency fConsume = (float) (fConsume / (1000.0 * GetEfficiency())); // Engines consume burnable fuel fRealized = GetFuelSource()->ExtractFuelUnit(fConsume); // check system consumed the ammount we asked for if (fRealized < fConsume) { // Out of gas. Set desired speed to 0. m_desired_speed = 0; HS_INT8 tbuf[128]; sprintf_s(tbuf, "%s%s-%s A warning light flashing, indicating engines have run \ out of fuel.", ANSI_HILITE, ANSI_YELLOW, ANSI_NORMAL); if (GetOwnerObject()) { GetOwnerObject()->HandleMessage(tbuf, MSG_ENGINEERING, NULL); } } }
// Tells the engines that they need to gobble up some fuel // from the fuel source. The engines know their efficiency // and such, so they just drain the fuel from the fuel system. // Speed here should be given in units per hour. void CHSJumpDrive::ConsumeFuelBySpeed(HS_INT32 speed) { float fConsume; float fRealized; // Do we have a fuel system? if (!GetFuelSource() || (GetFuelSource()->GetFuelRemaining() <= 0)) { return; } // Do not consume fuel if efficiency is 0 if (0 == GetEfficiency()) { return; } // Calculate per second travel rate fConsume = (float) (speed * .0002778); // Divide by efficiency fConsume = (float) (fConsume / (1000.0 * GetEfficiency())); fRealized = GetFuelSource()->ExtractFuelUnit(fConsume); if (fRealized < fConsume) { // Out of gas. Disengage. m_bEngaged = false; HS_INT8 tbuf[128]; sprintf(tbuf, "%s%s-%s A warning light flashing, indicating jump drives have \ run out of fuel.", ANSI_HILITE, ANSI_YELLOW, ANSI_NORMAL); if (GetOwnerObject()) { GetOwnerObject()->HandleMessage(tbuf, MSG_ENGINEERING, NULL); } } }
void CHSDamCon::AssignCrew(HS_DBREF player, int iCrew, CHSEngSystem * pSystem) { // Be certain this is a valid crew ID. if ((iCrew < 1) || (iCrew > (int) GetNumCrews())) { return; } // Grab this crew's structure from the vector. THSDamageCrew & rtCrew = m_vecCrews[iCrew]; // If we're assigning to a valid system, try that. // Otherwise, unassign this crew. if (pSystem) { // Only one crew can be assigned to a system at any one time. HS_INT32 iNumCrews = GetNumCrews(); for (int idx = 0; idx < iNumCrews; idx++) { // If this crew is the one we're assigning, ignore it. if (idx == iCrew) { continue; } THSDamageCrew & rtAssignedCrew = m_vecCrews[idx]; // Is this crew assigned to the system we want? if (rtAssignedCrew.pAssignedTo == pSystem) { hsStdError(player, "A repair crew is already working on that system."); return; } } // This crew is now assigned. rtCrew.pAssignedTo = pSystem; rtCrew.iSecondsLeft = HSCONF.damage_repair_time; if (0 == rtCrew.iSecondsLeft) { rtCrew.iSecondsLeft = 1; } if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *pOwnerShip = static_cast < CHSShip * >(GetOwnerObject()); pOwnerShip->NotifyConsoles(hsInterface. HSPrintf ("%s%s-%s Damage Control crew %i assigned to %s.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL, iCrew, pSystem->GetName()), MSG_ENGINEERING); } } else { // This crew is unassigned. rtCrew.pAssignedTo = NULL; rtCrew.iSecondsLeft = 0; if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *pOwnerShip = static_cast < CHSShip * >(GetOwnerObject()); pOwnerShip->NotifyConsoles(hsInterface. HSPrintf ("%s%s-%s Damage Control crew %i now idle.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL, iCrew), MSG_ENGINEERING); } } }
void CHSDamCon::DoCycle() { // First we do the basic cycle, stress and such. CHSEngSystem::DoCycle(); // Now we'll just go through our damage crews. HS_INT32 iEfficiency; HS_INT32 iRandNum; // Calculate percentage of power allocated to damage control. if (GetCurrentPower() != 0 && GetOptimalPower(false) != 0) { iEfficiency = (int) (100 * ((GetCurrentPower() * 1.00) / (GetOptimalPower(false) * 1.00))); } else { iEfficiency = 0; } iRandNum = hsInterface.GetRandom(99) + 1; // If we roll a random number greater than the power allocated to damage // control, then this round of damage control goes into the toilet. if (iRandNum > iEfficiency) { return; } // Insure that our number of crews matches the vector size. m_vecCrews.resize(GetNumCrews() + 1); // Run through all of our damage crews. // Those that are assigned get their time remaining reduced. unsigned int idx; for (idx = 1; idx <= GetNumCrews(); idx++) { THSDamageCrew & rtCrew = m_vecCrews[idx]; // Is this crew working on anything? if (!rtCrew.pAssignedTo) { continue; } // This crew's time decreases. if (rtCrew.iSecondsLeft > 0) { rtCrew.iSecondsLeft--; } // If the crew is done working, reduce the damage on the system. if (rtCrew.iSecondsLeft <= 0) { rtCrew.pAssignedTo->ReduceDamage(); // If this system is fully repaired, notify everyone, and pull this // crew off duty. if (rtCrew.pAssignedTo->GetDamageLevel() == DMG_NONE) { // If this system is part of a ship, // notify all consoles that repairs are complete. if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *pOwnerShip = static_cast < CHSShip * >(GetOwnerObject()); pOwnerShip->NotifyConsoles(hsInterface. HSPrintf ("%s%s-%s %s repairs complete.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL, rtCrew.pAssignedTo-> GetName()), MSG_ENGINEERING); } // This crew is no longer assigned. rtCrew.pAssignedTo = NULL; } else { // This system is not repaired. Reassign the crew to another // round of repairs. rtCrew.iSecondsLeft = HSCONF.damage_repair_time; if (0 == rtCrew.iSecondsLeft) { rtCrew.iSecondsLeft = 1; } if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *pOwnerShip = static_cast < CHSShip * >(GetOwnerObject()); pOwnerShip->NotifyConsoles(hsInterface. HSPrintf ("%s%s-%s %s repairs incomplete, continuing repairs.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL, rtCrew.pAssignedTo-> GetName()), MSG_ENGINEERING); } } } } }
WfRuntimeExecutionAction WfRuntimeThreadContext::ExecuteInternal(WfInstruction& ins, WfRuntimeStackFrame& stackFrame, IWfDebuggerCallback* callback) { switch (ins.code) { case WfInsCode::LoadValue: PushValue(ins.valueParameter); return WfRuntimeExecutionAction::ExecuteInstruction; case WfInsCode::LoadClosure: { Ptr<WfRuntimeVariableContext> capturedVariables; if (ins.countParameter > 0) { capturedVariables = new WfRuntimeVariableContext; capturedVariables->variables.Resize(ins.countParameter); Value operand; for (vint i = 0; i < ins.countParameter; i++) { CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); capturedVariables->variables[ins.countParameter - 1 - i] = operand; } } auto lambda = MakePtr<WfRuntimeLambda>(globalContext, capturedVariables, ins.indexParameter); PushValue(Value::From(lambda)); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::LoadException: { PushValue(BoxValue(exceptionInfo)); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::LoadLocalVar: { Value operand; CONTEXT_ACTION(LoadLocalVariable(ins.indexParameter, operand), L"illegal local variable index."); PushValue(operand); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::LoadCapturedVar: { Value operand; CONTEXT_ACTION(LoadCapturedVariable(ins.indexParameter, operand), L"illegal captured variable index."); PushValue(operand); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::LoadGlobalVar: { CALL_DEBUGGER(callback->BreakRead(globalContext->assembly.Obj(), ins.indexParameter)); Value operand; CONTEXT_ACTION(LoadGlobalVariable(ins.indexParameter, operand), L"illegal global variable index."); PushValue(operand); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::StoreLocalVar: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); CONTEXT_ACTION(StoreLocalVariable(ins.indexParameter, operand), L"illegal local variable index."); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::StoreGlobalVar: { CALL_DEBUGGER(callback->BreakWrite(globalContext->assembly.Obj(), ins.indexParameter)); Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); CONTEXT_ACTION(StoreGlobalVariable(ins.indexParameter, operand), L"illegal global variable index."); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::Duplicate: { vint index = stack.Count() - 1 - ins.countParameter; Value operand; CONTEXT_ACTION(LoadStackValue(index, operand), L"failed to duplicate a value from the stack."); PushValue(operand); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::Pop: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::Return: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop the function result."); CONTEXT_ACTION(PopStackFrame(), L"failed to pop the stack frame."); PushValue(operand); if (stackFrames.Count() == 0) { status = WfRuntimeExecutionStatus::Finished; } return WfRuntimeExecutionAction::ExitStackFrame; } case WfInsCode::CreateArray: { auto list = IValueList::Create(); Value operand; for (vint i = 0; i < ins.countParameter; i++) { CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); list->Add(operand); } PushValue(Value::From(list)); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::CreateMap: { auto map = IValueDictionary::Create(); Value key, value; for (vint i = 0; i < ins.countParameter; i+=2) { CONTEXT_ACTION(PopValue(value), L"failed to pop a value from the stack."); CONTEXT_ACTION(PopValue(key), L"failed to pop a value from the stack."); map->Set(key, value); } PushValue(Value::From(map)); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::CreateInterface: { auto proxy = MakePtr<WfRuntimeInterfaceInstance>(); Value key, value; for (vint i = 0; i < ins.countParameter; i+=2) { CONTEXT_ACTION(PopValue(value), L"failed to pop a value from the stack."); CONTEXT_ACTION(PopValue(key), L"failed to pop a value from the stack."); auto name = UnboxValue<WString>(key); auto func = UnboxValue<Ptr<IValueFunctionProxy>>(value); proxy->functions.Add(name, func); } PushValue(Value::From(proxy)); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::CreateRange: BEGIN_TYPE EXECUTE(OpCreateRange, I1) EXECUTE(OpCreateRange, I2) EXECUTE(OpCreateRange, I4) EXECUTE(OpCreateRange, I8) EXECUTE(OpCreateRange, U1) EXECUTE(OpCreateRange, U2) EXECUTE(OpCreateRange, U4) EXECUTE(OpCreateRange, U8) END_TYPE case WfInsCode::ReverseEnumerable: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); Value reversedEnumerable = OPERATOR_OpReverseEnumerable(operand); PushValue(reversedEnumerable); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::DeleteRawPtr: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); operand.DeleteRawPtr(); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::ConvertToType: { Value result, converted; CONTEXT_ACTION(PopValue(result), L"failed to pop a value from the stack."); if (OPERATOR_OpConvertToType(result, converted, ins)) { PushValue(converted); return WfRuntimeExecutionAction::ExecuteInstruction; } else { WString from = result.IsNull() ? L"<null>" : L"<" + result.GetText() + L"> of " + result.GetTypeDescriptor()->GetTypeName(); WString to = ins.typeDescriptorParameter->GetTypeName(); RaiseException(L"Failed to convert from \"" + from + L"\" to \"" + to + L"\".", false); return WfRuntimeExecutionAction::Nop; } } case WfInsCode::TryConvertToType: { Value result, converted; CONTEXT_ACTION(PopValue(result), L"failed to pop a value from the stack."); if (OPERATOR_OpConvertToType(result, converted, ins)) { PushValue(converted); } else { PushValue(Value()); } return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::TestType: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); if (operand.GetTypeDescriptor() && operand.GetValueType() == ins.flagParameter && operand.GetTypeDescriptor()->CanConvertTo(ins.typeDescriptorParameter)) { PushValue(BoxValue(true)); } else { PushValue(BoxValue(false)); } return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::GetType: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); PushValue(Value::From(operand.GetTypeDescriptor())); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::Jump: { stackFrame.nextInstructionIndex = ins.indexParameter; return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::JumpIf: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); if (UnboxValue<bool>(operand)) { stackFrame.nextInstructionIndex = ins.indexParameter; } return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::Invoke: { CONTEXT_ACTION(PushStackFrame(ins.indexParameter, ins.countParameter), L"failed to invoke a function."); return WfRuntimeExecutionAction::EnterStackFrame; } case WfInsCode::GetProperty: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); CALL_DEBUGGER(callback->BreakGet(operand.GetRawPtr(), ins.propertyParameter)); Value result = ins.propertyParameter->GetValue(operand); PushValue(result); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::SetProperty: { Value operand, value; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); CONTEXT_ACTION(PopValue(value), L"failed to pop a value from the stack."); CALL_DEBUGGER(callback->BreakSet(operand.GetRawPtr(), ins.propertyParameter)); ins.propertyParameter->SetValue(operand, value); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::InvokeProxy: { Value thisValue; CONTEXT_ACTION(PopValue(thisValue), L"failed to pop a value from the stack."); auto proxy = UnboxValue<Ptr<IValueFunctionProxy>>(thisValue); if (!proxy) { INTERNAL_ERROR(L"failed to invoke a null function proxy."); return WfRuntimeExecutionAction::Nop; } if (auto lambda = proxy.Cast<WfRuntimeLambda>()) { if (lambda->globalContext == globalContext) { CONTEXT_ACTION(PushStackFrame(lambda->functionIndex, ins.countParameter, lambda->capturedVariables), L"failed to invoke a function."); return WfRuntimeExecutionAction::EnterStackFrame; } } List<Value> arguments; for (vint i = 0; i < ins.countParameter; i++) { Value argument; CONTEXT_ACTION(PopValue(argument), L"failed to pop a value from the stack."); arguments.Insert(0, argument); } Ptr<IValueList> list = new ValueListWrapper<List<Value>*>(&arguments); Value result = proxy->Invoke(list); PushValue(result); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::InvokeMethod: { Value thisValue; CONTEXT_ACTION(PopValue(thisValue), L"failed to pop a value from the stack."); CALL_DEBUGGER(callback->BreakInvoke(thisValue.GetRawPtr(), ins.methodParameter)); if (auto staticMethod = dynamic_cast<WfStaticMethod*>(ins.methodParameter)) { if (staticMethod->GetGlobalContext() == globalContext.Obj()) { CONTEXT_ACTION(PushStackFrame(staticMethod->functionIndex, ins.countParameter, nullptr), L"failed to invoke a function."); return WfRuntimeExecutionAction::EnterStackFrame; } } Array<Value> arguments(ins.countParameter); for (vint i = 0; i < ins.countParameter; i++) { Value argument; CONTEXT_ACTION(PopValue(argument), L"failed to pop a value from the stack."); arguments[ins.countParameter - i - 1] = argument; } Value result = ins.methodParameter->Invoke(thisValue, arguments); PushValue(result); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::AttachEvent: { Value thisValue, function; CONTEXT_ACTION(PopValue(function), L"failed to pop a value from the stack."); CONTEXT_ACTION(PopValue(thisValue), L"failed to pop a value from the stack."); CALL_DEBUGGER(callback->BreakAttach(thisValue.GetRawPtr(), ins.eventParameter)); auto proxy = UnboxValue<Ptr<IValueFunctionProxy>>(function); auto handler = ins.eventParameter->Attach(thisValue, proxy); PushValue(Value::From(handler)); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::DetachEvent: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); auto handler = UnboxValue<Ptr<IEventHandler>>(operand); CALL_DEBUGGER(callback->BreakDetach(handler->GetOwnerObject().GetRawPtr(), handler->GetOwnerEvent())); auto result = handler->Detach(); PushValue(BoxValue(result)); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::InstallTry: CONTEXT_ACTION(PushTrapFrame(ins.indexParameter), L"failed to push a trap frame"); return WfRuntimeExecutionAction::ExecuteInstruction; case WfInsCode::UninstallTry: { if (trapFrames.Count() == 0) { INTERNAL_ERROR(L"failed to pop the trap frame."); } auto frame = GetCurrentTrapFrame(); CONTEXT_ACTION(PopTrapFrame(ins.countParameter), L"failed to pop the trap frame."); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::RaiseException: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); if (operand.GetValueType() == Value::Text) { RaiseException(operand.GetText(), false); } else if (auto info = operand.GetSharedPtr().Cast<WfRuntimeExceptionInfo>()) { RaiseException(info); } else { INTERNAL_ERROR(L"failed to raise an exception which is neither a string nor a WfRuntimeExceptionInfo."); } return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::TestElementInSet: { Value element, set; CONTEXT_ACTION(PopValue(set), L"failed to pop a value from the stack."); CONTEXT_ACTION(PopValue(element), L"failed to pop a value from the stack."); auto enumerable = UnboxValue<Ptr<IValueEnumerable>>(set); auto enumerator = enumerable->CreateEnumerator(); while (enumerator->Next()) { if (enumerator->GetCurrent() == element) { PushValue(BoxValue(true)); return WfRuntimeExecutionAction::ExecuteInstruction; } } PushValue(BoxValue(false)); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::CompareLiteral: BEGIN_TYPE EXECUTE(OpCompare, Bool) EXECUTE(OpCompare, I1) EXECUTE(OpCompare, I2) EXECUTE(OpCompare, I4) EXECUTE(OpCompare, I8) EXECUTE(OpCompare, U1) EXECUTE(OpCompare, U2) EXECUTE(OpCompare, U4) EXECUTE(OpCompare, U8) EXECUTE(OpCompare, F4) EXECUTE(OpCompare, F8) EXECUTE(OpCompare, String) END_TYPE case WfInsCode::CompareStruct: { Value first, second; CONTEXT_ACTION(PopValue(second), L"failed to pop a value from the stack."); CONTEXT_ACTION(PopValue(first), L"failed to pop a value from the stack."); if (!first.IsNull() && !first.GetTypeDescriptor()->GetValueSerializer()) { INTERNAL_ERROR(L"type" + first.GetTypeDescriptor()->GetTypeName() + L" is not a struct."); } if (!second.IsNull() && !second.GetTypeDescriptor()->GetValueSerializer()) { INTERNAL_ERROR(L"type" + second.GetTypeDescriptor()->GetTypeName() + L" is not a struct."); } if (first.GetValueType() != second.GetValueType()) { PushValue(BoxValue(false)); } else if (first.IsNull()) { PushValue(BoxValue(true)); } else { PushValue(BoxValue(first.GetText() == second.GetText())); } return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::CompareReference: { Value first, second; CONTEXT_ACTION(PopValue(second), L"failed to pop a value from the stack."); CONTEXT_ACTION(PopValue(first), L"failed to pop a value from the stack."); bool result = first.GetValueType() != Value::Text && second.GetValueType() != Value::Text && first.GetRawPtr() == second.GetRawPtr(); PushValue(BoxValue(result)); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::CompareValue: { Value first, second; CONTEXT_ACTION(PopValue(second), L"failed to pop a value from the stack."); CONTEXT_ACTION(PopValue(first), L"failed to pop a value from the stack."); switch (first.GetValueType()) { case Value::RawPtr: case Value::SharedPtr: switch (first.GetValueType()) { case Value::RawPtr: case Value::SharedPtr: PushValue(BoxValue(first.GetRawPtr() == second.GetRawPtr())); break; default: PushValue(BoxValue(false)); } break; case Value::Text: switch (first.GetValueType()) { case Value::Text: PushValue(BoxValue(first.GetText() == second.GetText())); default: PushValue(BoxValue(false)); } break; default: PushValue(BoxValue(second.IsNull())); } return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::OpNot: BEGIN_TYPE EXECUTE(OpNot_Bool, Bool) EXECUTE(OpNot, I1) EXECUTE(OpNot, I2) EXECUTE(OpNot, I4) EXECUTE(OpNot, I8) EXECUTE(OpNot, U1) EXECUTE(OpNot, U2) EXECUTE(OpNot, U4) EXECUTE(OpNot, U8) END_TYPE case WfInsCode::OpPositive: BEGIN_TYPE EXECUTE(OpPositive, I1) EXECUTE(OpPositive, I2) EXECUTE(OpPositive, I4) EXECUTE(OpPositive, I8) EXECUTE(OpPositive, U1) EXECUTE(OpPositive, U2) EXECUTE(OpPositive, U4) EXECUTE(OpPositive, U8) EXECUTE(OpPositive, F4) EXECUTE(OpPositive, F8) END_TYPE case WfInsCode::OpNegative: BEGIN_TYPE EXECUTE(OpNegative, I1) EXECUTE(OpNegative, I2) EXECUTE(OpNegative, I4) EXECUTE(OpNegative, I8) EXECUTE(OpNegative, F4) EXECUTE(OpNegative, F8) END_TYPE case WfInsCode::OpConcat: { Value first, second; CONTEXT_ACTION(PopValue(second), L"failed to pop a value from the stack."); CONTEXT_ACTION(PopValue(first), L"failed to pop a value from the stack."); PushValue(BoxValue(first.GetText() + second.GetText())); return WfRuntimeExecutionAction::ExecuteInstruction; } case WfInsCode::OpExp: BEGIN_TYPE EXECUTE(OpExp, F4) EXECUTE(OpExp, F8) END_TYPE case WfInsCode::OpAdd: BEGIN_TYPE EXECUTE(OpAdd, I1) EXECUTE(OpAdd, I2) EXECUTE(OpAdd, I4) EXECUTE(OpAdd, I8) EXECUTE(OpAdd, U1) EXECUTE(OpAdd, U2) EXECUTE(OpAdd, U4) EXECUTE(OpAdd, U8) EXECUTE(OpAdd, F4) EXECUTE(OpAdd, F8) END_TYPE case WfInsCode::OpSub: BEGIN_TYPE EXECUTE(OpSub, I1) EXECUTE(OpSub, I2) EXECUTE(OpSub, I4) EXECUTE(OpSub, I8) EXECUTE(OpSub, U1) EXECUTE(OpSub, U2) EXECUTE(OpSub, U4) EXECUTE(OpSub, U8) EXECUTE(OpSub, F4) EXECUTE(OpSub, F8) END_TYPE case WfInsCode::OpMul: BEGIN_TYPE EXECUTE(OpMul, I1) EXECUTE(OpMul, I2) EXECUTE(OpMul, I4) EXECUTE(OpMul, I8) EXECUTE(OpMul, U1) EXECUTE(OpMul, U2) EXECUTE(OpMul, U4) EXECUTE(OpMul, U8) EXECUTE(OpMul, F4) EXECUTE(OpMul, F8) END_TYPE case WfInsCode::OpDiv: BEGIN_TYPE EXECUTE(OpDiv, I1) EXECUTE(OpDiv, I2) EXECUTE(OpDiv, I4) EXECUTE(OpDiv, I8) EXECUTE(OpDiv, U1) EXECUTE(OpDiv, U2) EXECUTE(OpDiv, U4) EXECUTE(OpDiv, U8) EXECUTE(OpDiv, F4) EXECUTE(OpDiv, F8) END_TYPE case WfInsCode::OpMod: BEGIN_TYPE EXECUTE(OpMod, I1) EXECUTE(OpMod, I2) EXECUTE(OpMod, I4) EXECUTE(OpMod, I8) EXECUTE(OpMod, U1) EXECUTE(OpMod, U2) EXECUTE(OpMod, U4) EXECUTE(OpMod, U8) END_TYPE case WfInsCode::OpShl: BEGIN_TYPE EXECUTE(OpShl, I1) EXECUTE(OpShl, I2) EXECUTE(OpShl, I4) EXECUTE(OpShl, I8) EXECUTE(OpShl, U1) EXECUTE(OpShl, U2) EXECUTE(OpShl, U4) EXECUTE(OpShl, U8) END_TYPE case WfInsCode::OpShr: BEGIN_TYPE EXECUTE(OpShr, I1) EXECUTE(OpShr, I2) EXECUTE(OpShr, I4) EXECUTE(OpShr, I8) EXECUTE(OpShr, U1) EXECUTE(OpShr, U2) EXECUTE(OpShr, U4) EXECUTE(OpShr, U8) END_TYPE case WfInsCode::OpXor: BEGIN_TYPE EXECUTE(OpXor, Bool) EXECUTE(OpXor, I1) EXECUTE(OpXor, I2) EXECUTE(OpXor, I4) EXECUTE(OpXor, I8) EXECUTE(OpXor, U1) EXECUTE(OpXor, U2) EXECUTE(OpXor, U4) EXECUTE(OpXor, U8) END_TYPE case WfInsCode::OpAnd: BEGIN_TYPE EXECUTE(OpAnd_Bool, Bool) EXECUTE(OpAnd, I1) EXECUTE(OpAnd, I2) EXECUTE(OpAnd, I4) EXECUTE(OpAnd, I8) EXECUTE(OpAnd, U1) EXECUTE(OpAnd, U2) EXECUTE(OpAnd, U4) EXECUTE(OpAnd, U8) END_TYPE case WfInsCode::OpOr: BEGIN_TYPE EXECUTE(OpOr_Bool, Bool) EXECUTE(OpOr, I1) EXECUTE(OpOr, I2) EXECUTE(OpOr, I4) EXECUTE(OpOr, I8) EXECUTE(OpOr, U1) EXECUTE(OpOr, U2) EXECUTE(OpOr, U4) EXECUTE(OpOr, U8) END_TYPE case WfInsCode::OpLT: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); vint value = UnboxValue<vint>(operand); PushValue(BoxValue(value < 0)); return WfRuntimeExecutionAction::ExecuteInstruction; } break; case WfInsCode::OpGT: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); vint value = UnboxValue<vint>(operand); PushValue(BoxValue(value > 0)); return WfRuntimeExecutionAction::ExecuteInstruction; } break; case WfInsCode::OpLE: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); vint value = UnboxValue<vint>(operand); PushValue(BoxValue(value <= 0)); return WfRuntimeExecutionAction::ExecuteInstruction; } break; case WfInsCode::OpGE: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); vint value = UnboxValue<vint>(operand); PushValue(BoxValue(value >= 0)); return WfRuntimeExecutionAction::ExecuteInstruction; } break; case WfInsCode::OpEQ: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); vint value = UnboxValue<vint>(operand); PushValue(BoxValue(value == 0)); return WfRuntimeExecutionAction::ExecuteInstruction; } break; case WfInsCode::OpNE: { Value operand; CONTEXT_ACTION(PopValue(operand), L"failed to pop a value from the stack."); vint value = UnboxValue<vint>(operand); PushValue(BoxValue(value != 0)); return WfRuntimeExecutionAction::ExecuteInstruction; } break; default: return WfRuntimeExecutionAction::Nop; } }