示例#1
0
			Ptr<IValueReadonlyList> WfRuntimeExceptionInfo::GetCallStack()
			{
				if (!cachedCallStack)
				{
					cachedCallStack = IValueList::Create(
						From(callStack)
							.Cast<IValueCallStack>()
							.Select([](Ptr<IValueCallStack> callStack)
							{
								return BoxValue(callStack);
							})
						);
				}
				return cachedCallStack;
			}
示例#2
0
			WfRuntimeExecutionAction OPERATOR_OpCompare(WfRuntimeThreadContext& context)
			{
				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 firstNull = first.GetValueType() == Value::Null;
				bool secondNull = second.GetValueType() == Value::Null;
				if (firstNull)
				{
					if (secondNull)
					{
						context.PushValue(BoxValue((vint)0));
					}
					else
					{
						context.PushValue(BoxValue((vint)-1));
					}
				}
				else
				{
					if (secondNull)
					{context.PushValue(BoxValue((vint)1));
					}
					else
					{
						T firstValue = UnboxValue<T>(first);
						T secondValue = UnboxValue<T>(second);
						if (firstValue < secondValue)
						{
							context.PushValue(BoxValue((vint)-1));
						}
						else if (firstValue > secondValue)
						{
							context.PushValue(BoxValue((vint)1));
						}
						else
						{
							context.PushValue(BoxValue((vint)0));
						}
					}
				}
				return WfRuntimeExecutionAction::ExecuteInstruction;
			}
示例#3
0
			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;
				}
			}
int
main(int argc, char* argv[])
{
  // setting default parameters for Wifi
  // enable rts cts all the time.
  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("0"));
  // disable fragmentation
  Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
  Config::SetDefault("ns3::WifiRemoteStationManager::NonUnicastMode",
                     StringValue("OfdmRate24Mbps"));

  // setting default parameters for PointToPoint links and channels
  Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("1Mbps"));
  Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
  Config::SetDefault("ns3::DropTailQueue::MaxPackets", StringValue("20"));


  std::uint32_t max_routers = 1;
  std::string cSize = "100";
  std::string cSplit = "75";

  // Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
  CommandLine cmd;
  cmd.AddValue("cSize", "Cache Size", cSize);
  cmd.AddValue("cSplit", "Cache Split", cSplit);
  cmd.AddValue("routers", "number of routers", max_routers);
  cmd.Parse(argc, argv);


  Packet::EnablePrinting ();

  // Wifi config

  WifiHelper wifi = WifiHelper::Default ();


  // Nodes
  NodeContainer sta_consumers;
  NodeContainer sta_mobile_consumers;
  NodeContainer ap;
  NodeContainer routers;
  NodeContainer producers;

  // ??
  NetDeviceContainer staDevs;
  PacketSocketHelper packetSocket;

  // 5 stationary consumers, 5 mobile, 4 APs and 1 router
  sta_consumers.Create(3*max_routers);
  sta_mobile_consumers.Create(7*max_routers);
  ap.Create (5*max_routers);
  routers.Create(max_routers);
  producers.Create(1);

  // give packet socket powers to nodes.
  packetSocket.Install(sta_mobile_consumers);
  packetSocket.Install(sta_consumers);
  packetSocket.Install (ap);

  // Wifi Config
  NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
  YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
  YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
  wifiPhy.SetChannel (wifiChannel.Create ());
  wifiPhy.Set("TxPowerStart", DoubleValue(5));
  wifiPhy.Set("TxPowerEnd", DoubleValue(5));
  Ssid ssid = Ssid ("wifi-default");
  wifi.SetRemoteStationManager ("ns3::ArfWifiManager");
  // setup stas.
  wifiMac.SetType ("ns3::StaWifiMac",
                   "Ssid", SsidValue (ssid),
                   "ActiveProbing", BooleanValue (false));
  // install wifi
  wifi.Install(wifiPhy, wifiMac, sta_mobile_consumers);
  wifi.Install(wifiPhy, wifiMac, sta_consumers);
  // setup ap.
  wifiMac.SetType ("ns3::ApWifiMac",
                   "Ssid", SsidValue (ssid));
  wifi.Install (wifiPhy, wifiMac, ap);


  // Mobility config -- Change max_routers value to change size of sim
  int number_rows = sqrt(max_routers);
  int x = 0;
  int y = 0;
  int pos_counter = 0;
  Ptr<UniformRandomVariable> randomizerX = CreateObject<UniformRandomVariable>();
  Ptr<UniformRandomVariable> randomizerY = CreateObject<UniformRandomVariable>();

  MobilityHelper stationary_mobility;
  stationary_mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");

  MobilityHelper mobility;
  mobility.SetMobilityModel("ns3::GaussMarkovMobilityModel", "Bounds", BoxValue(Box (0, number_rows*10, 0, number_rows*10, 0, 0)), 
	  "TimeStep", TimeValue(Seconds(1)));

  // Place router in center of box
  randomizerX->SetAttribute("Min", DoubleValue(5));
  randomizerX->SetAttribute("Max", DoubleValue(5));
  randomizerY->SetAttribute("Min", DoubleValue(5));
  randomizerY->SetAttribute("Max", DoubleValue(5));
  stationary_mobility.SetPositionAllocator("ns3::RandomBoxPositionAllocator", "X", PointerValue(randomizerX),
	  "Y", PointerValue(randomizerY));

  // Install on routers
  stationary_mobility.Install(producers.Get(0));

  // p2p helper
  PointToPointHelper p2p;
  // for each row
  for (int i=0; i < number_rows; i++)
  {
	  x = i * 10 + 5;
	  // for each column
	  for (int j=0; j < number_rows; j++)
	  {
		  y = j * 10 + 5;

		  // Place router in center of box
		  randomizerX->SetAttribute("Min", DoubleValue(x));
		  randomizerX->SetAttribute("Max", DoubleValue(x));
		  randomizerY->SetAttribute("Min", DoubleValue(y));
		  randomizerY->SetAttribute("Max", DoubleValue(y));
		  stationary_mobility.SetPositionAllocator("ns3::RandomBoxPositionAllocator", "X", PointerValue(randomizerX),
			  "Y", PointerValue(randomizerY));

		  // Install on routers
		  stationary_mobility.Install(routers.Get(pos_counter));

		  // Set box (center +/-5)
		  randomizerX->SetAttribute("Min", DoubleValue(x-5));
		  randomizerX->SetAttribute("Max", DoubleValue(x+5));
		  randomizerY->SetAttribute("Min", DoubleValue(y-5));
		  randomizerY->SetAttribute("Max", DoubleValue(y+5));
		  // Connect router to previous if not 1
		  if (pos_counter == 0)
		  {
			  p2p.Install(routers.Get(0), producers.Get(0));
		  }
		  else  // Otherwise connect to router behind you
		  {
			  p2p.Install(routers.Get(pos_counter), routers.Get(pos_counter-1));
		  }
		  // APs
		  for (int k=0; k < 5; k++)
		  {
			  stationary_mobility.SetPositionAllocator("ns3::RandomBoxPositionAllocator", "X", PointerValue(randomizerX),
				  "Y", PointerValue(randomizerY));
			  stationary_mobility.Install(ap.Get(pos_counter * 5 + k));
			  p2p.Install(routers.Get(pos_counter), ap.Get(pos_counter * 5 + k));

		  }

		  // Consumers (stationary)
		  for (int l=0; l < 3; l++)
		  {
			  stationary_mobility.SetPositionAllocator("ns3::RandomBoxPositionAllocator", "X", PointerValue(randomizerX),
				  "Y", PointerValue(randomizerY));
			  stationary_mobility.Install(sta_consumers.Get(pos_counter * 3 + l));
		  }

		  // Consumers (Mobile)
		  for (int m=0; m < 7; m++)
		  {
			  mobility.SetPositionAllocator("ns3::RandomBoxPositionAllocator", "X", PointerValue(randomizerX),
				  "Y", PointerValue(randomizerY));
			  mobility.Install(sta_mobile_consumers.Get(pos_counter * 7 + m));
		  }
	  // Keep track of overall position
	  pos_counter++;
	  }
  }
  // Install NDN stack on all nodes
  ndn::StackHelper ndnHelper;
  ndnHelper.SetDefaultRoutes(true);
  
  ndnHelper.SetOldContentStore("ns3::ndn::cs::Splitcache",
							   "NormalPolicy", "ns3::ndn::cs::Lru", 
							   "SpecialPolicy", "ns3::ndn::cs::Lfu", 
							   "TotalCacheSize", cSize, 
							   "Configure", cSplit); 
  //                       Percentage Special^
  
  //ndnHelper.SetOldContentStore("ns3::ndn::cs::Lru");

  ndnHelper.Install(ap);
  ndnHelper.Install(routers);
  ndnHelper.SetOldContentStore("ns3::ndn::cs::Nocache");
  ndnHelper.Install(sta_consumers);
  ndnHelper.Install(sta_mobile_consumers);
  ndnHelper.Install(producers);

  // Choosing forwarding strategy
  ndn::StrategyChoiceHelper::Install(sta_consumers, "/", "/localhost/nfd/strategy/best-route");
  ndn::StrategyChoiceHelper::Install(sta_mobile_consumers, "/", "/localhost/nfd/strategy/best-route");
  ndn::StrategyChoiceHelper::Install(ap, "/", "/localhost/nfd/strategy/best-route");
  ndn::StrategyChoiceHelper::Install(routers, "/", "/localhost/nfd/strategy/best-route");
  ndn::StrategyChoiceHelper::Install(producers, "/", "/localhost/nfd/strategy/best-route");

  // Installing applications

  // Consumer (basic and special data)
  ndn::AppHelper consumerHelper("ns3::ndn::ConsumerZipfMandelbrot");
  consumerHelper.SetAttribute("NumberOfContents", StringValue("100")); // 10 different contents
  // Consumer will request /prefix/0, /prefix/1, ...

  // Basic consumers request basic data (and pumpkin spice coffee)
  consumerHelper.SetPrefix("data/basic");
  consumerHelper.SetAttribute("Frequency", StringValue("10")); // 1 interests a second
  consumerHelper.Install(sta_consumers);   

  // Mobile consumers request special data only
  consumerHelper.SetPrefix("data/special");
  consumerHelper.SetAttribute("Frequency", StringValue("10")); //  2 interests a second
  consumerHelper.Install(sta_mobile_consumers);



  // Producer
  ndn::AppHelper producerHelper("ns3::ndn::Producer");
  // Producer will reply to all requests starting with /prefix
  producerHelper.SetPrefix("/data");
  producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
  producerHelper.SetAttribute("Freshness", TimeValue(Seconds(-1.0))); // unlimited freshness
  producerHelper.Install(producers); 

  // Tracers 'n stuff
  //AthstatsHelper athstats;
  //athstats.EnableAthstats("athstats-sta", sta_mobile_consumers);
  //athstats.EnableAthstats("athstats-sta", sta_consumers);
  //athstats.EnableAthstats ("athstats-ap", ap);

  ndn::AppDelayTracer::Install(sta_consumers, "app-delays-trace-stationary-03.txt");
  ndn::AppDelayTracer::Install(sta_mobile_consumers, "app-delays-trace-mobile-03.txt");
  ndn::CsTracer::Install(ap, "cs-trace-ap-03.txt", Seconds(1));
  ndn::CsTracer::Install(routers, "cs-trace-routers-03.txt", Seconds(1));

  // 10 min
  Simulator::Stop(Seconds(600.0));

  Simulator::Run();
  Simulator::Destroy();

  return 0;
}