/*********************************************************************** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY DEVELOPER: Zihan Chen(vczh) ***********************************************************************/ #include "VlppGlrParser.h" #include "VlppReflection.h" #include "VlppOS.h" #include "Vlpp.h" #include "VlppRegex.h" /*********************************************************************** .\WFRUNTIMEINSTRUCTION.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Workflow::Runtime Interfaces: **********************************************************************/ #ifndef VCZH_WORKFLOW_RUNTIME_WFRUNTIMEINSTRUCTION #define VCZH_WORKFLOW_RUNTIME_WFRUNTIMEINSTRUCTION namespace vl { namespace workflow { namespace runtime { /*********************************************************************** Instruction ***********************************************************************/ enum class WfInsCode { // Instruction // param : -> in the order of Nop, // : () -> () ; LoadValue, // value : () -> Value ; LoadFunction, // function : () -> Value ; push the function index LoadException, // : () -> Value ; LoadLocalVar, // variable : () -> Value ; LoadCapturedVar, // variable : () -> Value ; LoadGlobalVar, // variable : () -> Value ; LoadMethodInfo, // IMethodInfo* : () -> IMethodInfo* ; LoadMethodClosure, // IMethodInfo* : Value-this -> ; LoadClosureContext, // : () -> ; load the current closure context StoreLocalVar, // variable : Value -> () ; StoreCapturedVar, // variable : Value -> () ; StoreGlobalVar, // variable : Value -> () ; Duplicate, // count : () -> Value ; copy stack[stack.Count()-1-count] Pop, // : Value -> () ; Return, // : Value -> Value ; (exit function) NewArray, // count : Value-count, ..., Value-1 -> ; {1 2 3} -> <3 2 1> NewList, // count : Value-count, ..., Value-1 -> ; {1 2 3} -> <3 2 1> NewObservableList, // count : Value-count, ..., Value-1 -> ; {1 2 3} -> <3 2 1> NewDictionary, // count : Value-count*2, ..., Value-1 -> ; {1:2 3:4} -> <3 4 1 2> CreateClosureContext, // count : Value-1, ..., Value-count -> ; CreateClosure, // : , Value-function-index -> ; CreateInterface, // IMethodInfo*, count : , Value-count, ..., Value-1 -> ; {"Get":a "Set":b} -> new TInterface(InterfaceProxy^) CreateRange, // I1248/U1248 : Value-begin, Value-end -> ; CreateStruct, // flag, typeDescriptor : () -> Value ; DeleteRawPtr, // : Value -> () ; ConvertToType, // flag, typeDescriptor : Value -> Value ; TryConvertToType, // flag, typeDescriptor : Value -> Value ; TestType, // flag, typeDescriptor : Value -> ; GetType, // : Value -> ; Jump, // label : () -> () ; JumpIf, // label : -> () ; Invoke, // function, count : Value-1, ..., Value-n -> Value ; InvokeWithContext, // function, count : Value-1, ..., Value-n -> Value ; GetProperty, // IPropertyInfo* : Value-this -> Value ; SetProperty, // IPropertyInfo* : Value, Value-this -> () ; UpdateProperty, // IPropertyInfo* : Value-this, Value -> Value-this ; InvokeProxy, // count : Value-1, ..., Value-n, Value-this -> Value ; InvokeMethod, // IMethodInfo*, count : Value-1, ..., Value-n, Value-this -> Value ; InvokeEvent, // IEventInfo*, count : Value-1, ..., Value-n, Value-this -> ; InvokeBaseCtor, // IMethodInfo*, count : Value-1, ..., Value-n, Value-this -> ; AttachEvent, // IEventInfo* : Value-this, -> ; DetachEvent, // IEventInfo* : Value-this, -> bool ; InstallTry, // label : () -> () ; UninstallTry, // count : () -> () ; RaiseException, // : Value -> () ; (trap) TestElementInSet, // : Value-element, Value-set -> bool ; CompareLiteral, // I48/U48/F48/S : Value, Value -> ; CompareReference, // : Value, Value -> ; CompareValue, // : Value, Value -> ; OpNot, // B/I1248/U1248 : Value -> Value ; OpPositive, // I1248/U1248 : Value -> Value ; OpNegative, // I1248 : Value -> Value ; OpConcat, // : , -> ; OpExp, // I48/U48/F48 : Value, Value -> Value ; OpAdd, // I48/U48/F48 : Value, Value -> Value ; OpSub, // I48/U48/F48 : Value, Value -> Value ; OpMul, // I48/U48/F48 : Value, Value -> Value ; OpDiv, // I48/U48/F48 : Value, Value -> Value ; OpMod, // I48/U48 : Value, Value -> Value ; OpShl, // I48/U48 : Value, Value -> Value ; OpShr, // I48/U48 : Value, Value -> Value ; OpXor, // B/I1248/U1248 : , -> ; OpAnd, // B/I1248/U1248 : , -> ; OpOr, // B/I1248/U1248 : , -> ; OpLT, // : -> ; OpGT, // : -> ; OpLE, // : -> ; OpGE, // : -> ; OpEQ, // : -> ; OpNE, // : -> ; }; #define INSTRUCTION_CASES(APPLY, APPLY_VALUE, APPLY_FUNCTION, APPLY_FUNCTION_COUNT, APPLY_VARIABLE, APPLY_COUNT, APPLY_FLAG_TYPEDESCRIPTOR, APPLY_PROPERTY, APPLY_METHOD, APPLY_METHOD_COUNT, APPLY_EVENT, APPLY_EVENT_COUNT, APPLY_LABEL, APPLY_TYPE)\ APPLY(Nop)\ APPLY_VALUE(LoadValue)\ APPLY_FUNCTION(LoadFunction)\ APPLY(LoadException)\ APPLY_VARIABLE(LoadLocalVar)\ APPLY_VARIABLE(LoadCapturedVar)\ APPLY_VARIABLE(LoadGlobalVar)\ APPLY_METHOD(LoadMethodInfo)\ APPLY_METHOD(LoadMethodClosure)\ APPLY(LoadClosureContext)\ APPLY_VARIABLE(StoreLocalVar)\ APPLY_VARIABLE(StoreCapturedVar)\ APPLY_VARIABLE(StoreGlobalVar)\ APPLY_COUNT(Duplicate)\ APPLY(Pop)\ APPLY(Return)\ APPLY_COUNT(NewArray)\ APPLY_COUNT(NewList)\ APPLY_COUNT(NewObservableList)\ APPLY_COUNT(NewDictionary)\ APPLY_COUNT(CreateClosureContext)\ APPLY(CreateClosure)\ APPLY_METHOD_COUNT(CreateInterface)\ APPLY_TYPE(CreateRange)\ APPLY_FLAG_TYPEDESCRIPTOR(CreateStruct)\ APPLY(DeleteRawPtr)\ APPLY_FLAG_TYPEDESCRIPTOR(ConvertToType)\ APPLY_FLAG_TYPEDESCRIPTOR(TryConvertToType)\ APPLY_FLAG_TYPEDESCRIPTOR(TestType)\ APPLY(GetType)\ APPLY_LABEL(Jump)\ APPLY_LABEL(JumpIf)\ APPLY_FUNCTION_COUNT(Invoke)\ APPLY_FUNCTION_COUNT(InvokeWithContext)\ APPLY_PROPERTY(GetProperty)\ APPLY_PROPERTY(SetProperty)\ APPLY_PROPERTY(UpdateProperty)\ APPLY_COUNT(InvokeProxy)\ APPLY_METHOD_COUNT(InvokeMethod)\ APPLY_EVENT_COUNT(InvokeEvent)\ APPLY_METHOD_COUNT(InvokeBaseCtor)\ APPLY_EVENT(AttachEvent)\ APPLY_EVENT(DetachEvent)\ APPLY_LABEL(InstallTry)\ APPLY_COUNT(UninstallTry)\ APPLY(RaiseException)\ APPLY(TestElementInSet)\ APPLY_TYPE(CompareLiteral)\ APPLY(CompareReference)\ APPLY(CompareValue)\ APPLY_TYPE(OpNot)\ APPLY_TYPE(OpPositive)\ APPLY_TYPE(OpNegative)\ APPLY(OpConcat)\ APPLY_TYPE(OpExp)\ APPLY_TYPE(OpAdd)\ APPLY_TYPE(OpSub)\ APPLY_TYPE(OpMul)\ APPLY_TYPE(OpDiv)\ APPLY_TYPE(OpMod)\ APPLY_TYPE(OpShl)\ APPLY_TYPE(OpShr)\ APPLY_TYPE(OpXor)\ APPLY_TYPE(OpAnd)\ APPLY_TYPE(OpOr)\ APPLY(OpLT)\ APPLY(OpGT)\ APPLY(OpLE)\ APPLY(OpGE)\ APPLY(OpEQ)\ APPLY(OpNE)\ enum class WfInsType { Bool, I1, I2, I4, I8, U1, U2, U4, U8, F4, F8, String, Unknown, }; struct WfRuntimeValue { // U8 with ITypeDescriptor* -> enum // Unknown with ITypeDescriptor* -> type // Unknown -> Null WfInsType type = WfInsType::Unknown; reflection::description::ITypeDescriptor* typeDescriptor = nullptr; WString stringValue; union { bool boolValue; vint8_t i1Value; vint16_t i2Value; vint32_t i4Value; vint64_t i8Value; vuint8_t u1Value; vuint16_t u2Value; vuint32_t u4Value; vuint64_t u8Value = 0; float f4Value; double f8Value; }; WfRuntimeValue() {} WfRuntimeValue(bool value) : type(WfInsType::Bool), boolValue(value) {} WfRuntimeValue(vint8_t value) : type(WfInsType::I1), i1Value(value) {} WfRuntimeValue(vint16_t value) : type(WfInsType::I2), i2Value(value) {} WfRuntimeValue(vint32_t value) : type(WfInsType::I4), i4Value(value) {} WfRuntimeValue(vint64_t value) : type(WfInsType::I8), i8Value(value) {} WfRuntimeValue(vuint8_t value) : type(WfInsType::U1), u1Value(value) {} WfRuntimeValue(vuint16_t value) : type(WfInsType::U2), u2Value(value) {} WfRuntimeValue(vuint32_t value) : type(WfInsType::U4), u4Value(value) {} WfRuntimeValue(vuint64_t value) : type(WfInsType::U8), u8Value(value) {} WfRuntimeValue(float value) : type(WfInsType::F4), f4Value(value) {} WfRuntimeValue(double value) : type(WfInsType::F8), f8Value(value) {} WfRuntimeValue(WString value) : type(WfInsType::String), stringValue(value) {} WfRuntimeValue(vuint64_t value, reflection::description::ITypeDescriptor* enumType) : type(WfInsType::U8), typeDescriptor(enumType), u8Value(value) {} WfRuntimeValue(reflection::description::ITypeDescriptor* td) : type(WfInsType::Unknown), typeDescriptor(td) {} }; struct WfInstruction { WfInsCode code = WfInsCode::Nop; WfRuntimeValue valueParameter; vint countParameter = 0; union { struct { reflection::description::Value::ValueType flagParameter; reflection::description::ITypeDescriptor* typeDescriptorParameter; }; WfInsType typeParameter; vint indexParameter; reflection::description::IPropertyInfo* propertyParameter; reflection::description::IMethodInfo* methodParameter; reflection::description::IEventInfo* eventParameter; }; WfInstruction(); #define CTOR(NAME) static WfInstruction NAME(); #define CTOR_VALUE(NAME) static WfInstruction NAME(const WfRuntimeValue& value); #define CTOR_FUNCTION(NAME) static WfInstruction NAME(vint function); #define CTOR_FUNCTION_COUNT(NAME) static WfInstruction NAME(vint function, vint count); #define CTOR_VARIABLE(NAME) static WfInstruction NAME(vint variable); #define CTOR_COUNT(NAME) static WfInstruction NAME(vint count); #define CTOR_FLAG_TYPEDESCRIPTOR(NAME) static WfInstruction NAME(reflection::description::Value::ValueType flag, reflection::description::ITypeDescriptor* typeDescriptor); #define CTOR_PROPERTY(NAME) static WfInstruction NAME(reflection::description::IPropertyInfo* propertyInfo); #define CTOR_METHOD(NAME) static WfInstruction NAME(reflection::description::IMethodInfo* methodInfo); #define CTOR_METHOD_COUNT(NAME) static WfInstruction NAME(reflection::description::IMethodInfo* methodInfo, vint count); #define CTOR_EVENT(NAME) static WfInstruction NAME(reflection::description::IEventInfo* eventInfo); #define CTOR_EVENT_COUNT(NAME) static WfInstruction NAME(reflection::description::IEventInfo* eventInfo, vint count); #define CTOR_LABEL(NAME) static WfInstruction NAME(vint label); #define CTOR_TYPE(NAME) static WfInstruction NAME(WfInsType type); INSTRUCTION_CASES( CTOR, CTOR_VALUE, CTOR_FUNCTION, CTOR_FUNCTION_COUNT, CTOR_VARIABLE, CTOR_COUNT, CTOR_FLAG_TYPEDESCRIPTOR, CTOR_PROPERTY, CTOR_METHOD, CTOR_METHOD_COUNT, CTOR_EVENT, CTOR_EVENT_COUNT, CTOR_LABEL, CTOR_TYPE) #undef CTOR #undef CTOR_VALUE #undef CTOR_FUNCTION #undef CTOR_FUNCTION_COUNT #undef CTOR_VARIABLE #undef CTOR_COUNT #undef CTOR_FLAG_TYPEDESCRIPTOR #undef CTOR_PROPERTY #undef CTOR_METHOD #undef CTOR_METHOD_COUNT #undef CTOR_EVENT #undef CTOR_EVENT_COUNT #undef CTOR_LABEL #undef CTOR_TYPE }; } } } #endif /*********************************************************************** .\WFRUNTIMETYPEDESCRIPTOR.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Workflow::Runtime Interfaces: **********************************************************************/ #ifndef VCZH_WORKFLOW_RUNTIME_WFRUNTIMETYPEDESCRIPTOR #define VCZH_WORKFLOW_RUNTIME_WFRUNTIMETYPEDESCRIPTOR namespace vl { namespace workflow { namespace typeimpl { class WfClassInstance; class WfInterfaceInstance; } } namespace reflection { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA #define DEFINE_DESCRIPTION(TYPE)\ template<>\ class Description : public virtual DescriptableObject\ {\ private:\ description::ITypeDescriptor* associatedTypeDescriptor;\ public:\ Description(description::ITypeDescriptor* _associatedTypeDescriptor)\ :associatedTypeDescriptor(_associatedTypeDescriptor)\ {\ typeDescriptor = &associatedTypeDescriptor;\ }\ };\ DEFINE_DESCRIPTION(WfClassInstance) DEFINE_DESCRIPTION(WfInterfaceInstance) #undef DEFINE_DESCRIPTION #endif } namespace workflow { namespace runtime { class WfRuntimeGlobalContext; } namespace typeimpl { class WfCustomType; class WfTypeImpl; /*********************************************************************** Method ***********************************************************************/ class WfMethodProxy : public Object, public virtual reflection::description::IValueFunctionProxy { typedef reflection::description::IMethodInfo IMethodInfo; typedef reflection::description::IValueReadonlyList IValueReadonlyList; typedef reflection::description::Value Value; protected: Value thisObject; IMethodInfo* methodInfo; public: WfMethodProxy(const Value& _thisObject, IMethodInfo* _methodInfo); ~WfMethodProxy(); Value Invoke(Ptr arguments)override; }; class WfMethodBase : public reflection::description::MethodInfoImpl { friend class WfCustomType; typedef reflection::description::ITypeInfo ITypeInfo; protected: typedef reflection::description::Value Value; runtime::WfRuntimeGlobalContext* globalContext = nullptr; Value CreateFunctionProxyInternal(const Value& thisObject)override; void SetGlobalContext(runtime::WfRuntimeGlobalContext* _globalContext); public: WfMethodBase(bool isStatic); ~WfMethodBase(); ICpp* GetCpp()override; runtime::WfRuntimeGlobalContext* GetGlobalContext(); void SetReturn(Ptr type); }; class WfStaticMethod : public WfMethodBase { typedef reflection::description::Value Value; protected: Value InvokeInternal(const Value& thisObject, collections::Array& arguments)override; public: vint functionIndex = -1; WfStaticMethod(); }; /*********************************************************************** Class Method ***********************************************************************/ class WfClassConstructor : public WfMethodBase { typedef reflection::description::Value Value; typedef reflection::description::ITypeInfo ITypeInfo; protected: Value InvokeInternal(const Value& thisObject, collections::Array& arguments)override; public: vint functionIndex = -1; WfClassConstructor(Ptr type); void InvokeBaseCtor(const Value& thisObject, collections::Array& arguments); }; class WfClassMethod : public WfMethodBase { typedef reflection::description::Value Value; protected: Value InvokeInternal(const Value& thisObject, collections::Array& arguments)override; public: vint functionIndex = -1; WfClassMethod(); }; /*********************************************************************** Interface Method ***********************************************************************/ class WfInterfaceConstructor : public WfMethodBase { typedef reflection::description::Value Value; typedef reflection::description::ITypeInfo ITypeInfo; protected: Value InvokeInternal(const Value& thisObject, collections::Array& arguments)override; public: WfInterfaceConstructor(Ptr type); }; class WfInterfaceMethod : public WfMethodBase { typedef reflection::description::Value Value; protected: Value InvokeInternal(const Value& thisObject, collections::Array& arguments)override; public: WfInterfaceMethod(); }; /*********************************************************************** Event ***********************************************************************/ class WfEvent : public reflection::description::EventInfoImpl { typedef reflection::description::ITypeDescriptor ITypeDescriptor; typedef reflection::description::ITypeInfo ITypeInfo; typedef reflection::description::IEventHandler IEventHandler; typedef reflection::description::IValueFunctionProxy IValueFunctionProxy; typedef reflection::description::IValueReadonlyList IValueReadonlyList; typedef reflection::description::Value Value; class EventHandlerImpl : public Object, public IEventHandler { public: bool isAttached = true; Ptr proxy; EventHandlerImpl(Ptr _proxy) :proxy(_proxy) { } bool IsAttached()override { return isAttached; } }; typedef collections::Group> EventHandlerGroup; class EventRecord : public Object { public: EventHandlerGroup handlers; }; static const wchar_t* EventRecordInternalPropertyName; protected: Ptr GetEventRecord(DescriptableObject* thisObject, bool createIfNotExist); Ptr AttachInternal(DescriptableObject* thisObject, Ptr handler)override; bool DetachInternal(DescriptableObject* thisObject, Ptr handler)override; void InvokeInternal(DescriptableObject* thisObject, Ptr arguments)override; Ptr GetHandlerTypeInternal()override; public: WfEvent(ITypeDescriptor* ownerTypeDescriptor, const WString& name); ~WfEvent(); ICpp* GetCpp()override; void SetHandlerType(Ptr typeInfo); }; /*********************************************************************** Field ***********************************************************************/ class WfField : public reflection::description::FieldInfoImpl { typedef reflection::description::ITypeDescriptor ITypeDescriptor; typedef reflection::description::ITypeInfo ITypeInfo; typedef reflection::description::Value Value; typedef collections::Dictionary FieldValueMap; class FieldRecord : public Object { public: FieldValueMap values; }; static const wchar_t* FieldRecordInternalPropertyName; protected: Ptr GetFieldRecord(DescriptableObject* thisObject, bool createIfNotExist); Value GetValueInternal(const Value& thisObject)override; void SetValueInternal(Value& thisObject, const Value& newValue)override; public: WfField(ITypeDescriptor* ownerTypeDescriptor, const WString& name); ~WfField(); ICpp* GetCpp()override; void SetReturn(Ptr typeInfo); }; class WfStructField : public reflection::description::FieldInfoImpl { typedef reflection::description::ITypeDescriptor ITypeDescriptor; typedef reflection::description::ITypeInfo ITypeInfo; typedef reflection::description::Value Value; protected: Value GetValueInternal(const Value& thisObject)override; void SetValueInternal(Value& thisObject, const Value& newValue)override; public: WfStructField(ITypeDescriptor* ownerTypeDescriptor, const WString& name); ~WfStructField(); ICpp* GetCpp()override; void SetReturn(Ptr typeInfo); }; /*********************************************************************** Property ***********************************************************************/ class WfProperty : public reflection::description::PropertyInfoImpl { typedef reflection::description::ITypeDescriptor ITypeDescriptor; typedef reflection::description::MethodInfoImpl MethodInfoImpl; typedef reflection::description::EventInfoImpl EventInfoImpl; public: WfProperty(ITypeDescriptor* ownerTypeDescriptor, const WString& name); ~WfProperty(); void SetGetter(MethodInfoImpl* value); void SetSetter(MethodInfoImpl* value); void SetValueChangedEvent(EventInfoImpl* value); }; /*********************************************************************** Custom Type ***********************************************************************/ struct WfTypeInfoContent : reflection::description::TypeInfoContent { WString workflowTypeName; WfTypeInfoContent(const WString& _workflowTypeName); }; template class WfCustomTypeBase : private WfTypeInfoContent, public TBase { public: WfCustomTypeBase(reflection::description::TypeDescriptorFlags typeDescriptorFlags, const WString& typeName) :WfTypeInfoContent(typeName) , TBase(typeDescriptorFlags, this) { } const WString& GetTypeName() override { // TypeDescriptorImplBase::GetTypeName returns WString(this->typeName, false) // which is this->workflowTypeName.Obj() // will become a dangling pointer after this type is unloaded return workflowTypeName; } }; class WfCustomType : public WfCustomTypeBase { protected: typedef reflection::description::TypeDescriptorFlags TypeDescriptorFlags; typedef reflection::description::ITypeDescriptor ITypeDescriptor; typedef reflection::description::ITypeInfo ITypeInfo; typedef reflection::description::IMethodGroupInfo IMethodGroupInfo; typedef collections::List TypeDescriptorList; protected: runtime::WfRuntimeGlobalContext* globalContext = nullptr; bool baseTypeExpanded = false; TypeDescriptorList expandedBaseTypes; void SetGlobalContext(runtime::WfRuntimeGlobalContext* _globalContext, IMethodGroupInfo* group); void SetGlobalContext(runtime::WfRuntimeGlobalContext* _globalContext); void LoadInternal()override; public: WfCustomType(TypeDescriptorFlags typeDescriptorFlags, const WString& typeName); ~WfCustomType(); runtime::WfRuntimeGlobalContext* GetGlobalContext(); const TypeDescriptorList& GetExpandedBaseTypes(); void AddBaseType(ITypeDescriptor* type); void AddMember(const WString& name, Ptr value); void AddMember(Ptr value); void AddMember(Ptr value); void AddMember(Ptr value); void AddMember(Ptr value); void AddMember(Ptr value); }; class WfClass : public WfCustomType { friend class WfTypeImpl; public: vint destructorFunctionIndex = -1; WfClass(const WString& typeName); ~WfClass(); }; class WfInterface : public WfCustomType { friend class WfTypeImpl; public: WfInterface(const WString& typeName); ~WfInterface(); }; class WfStruct : public WfCustomTypeBase { using FieldMap = collections::Dictionary>; using IPropertyInfo = reflection::description::IPropertyInfo; using IValueType = reflection::description::IValueType; using IBoxedValue = reflection::description::IBoxedValue; protected: class WfValueType : public Object, public virtual IValueType { using Value = reflection::description::Value; protected: WfStruct* owner; public: WfValueType(WfStruct* _owner); Value CreateDefault()override; }; protected: FieldMap fields; public: WfStruct(const WString& typeName); ~WfStruct(); vint GetPropertyCount()override; IPropertyInfo* GetProperty(vint index)override; bool IsPropertyExists(const WString& name, bool inheritable)override; IPropertyInfo* GetPropertyByName(const WString& name, bool inheritable)override; void AddMember(Ptr value); }; class WfEnum : public WfCustomTypeBase { using EnumItemMap = collections::Dictionary; using IValueType = reflection::description::IValueType; using IBoxedValue = reflection::description::IBoxedValue; using IEnumType = reflection::description::IEnumType; using Value = reflection::description::Value; protected: class WfValueType : public Object, public virtual IValueType { protected: WfEnum* owner; public: WfValueType(WfEnum* _owner); Value CreateDefault()override; }; class WfEnumType : public Object, public virtual IEnumType { protected: WfEnum* owner; public: WfEnumType(WfEnum* _owner); bool IsFlagEnum()override; vint GetItemCount()override; WString GetItemName(vint index)override; vuint64_t GetItemValue(vint index)override; vint IndexOfItem(WString name)override; Value ToEnum(vuint64_t value)override; vuint64_t FromEnum(const Value& value)override; }; protected: EnumItemMap enumItems; public: WfEnum(bool isFlags, const WString& typeName); ~WfEnum(); void AddEnumItem(const WString& name, vuint64_t value); }; /*********************************************************************** Instance ***********************************************************************/ class WfClassInstance : public Object, public reflection::Description { typedef reflection::description::ITypeDescriptor ITypeDescriptor; typedef reflection::description::Value Value; protected: WfClass* classType = nullptr; public: WfClassInstance(ITypeDescriptor* _typeDescriptor); ~WfClassInstance(); void InstallBaseObject(ITypeDescriptor* td, Value& value); }; class WfInterfaceInstance : public Object, public reflection::IDescriptable, public reflection::Description { typedef reflection::description::ITypeDescriptor ITypeDescriptor; typedef reflection::description::IMethodInfo IMethodInfo; typedef reflection::description::IValueInterfaceProxy IValueInterfaceProxy; protected: Ptr proxy; public: WfInterfaceInstance(ITypeDescriptor* _typeDescriptor, Ptr _proxy, collections::List& baseCtors); ~WfInterfaceInstance(); Ptr GetProxy(); }; class WfStructInstance : public Object, public reflection::description::IBoxedValue { using FieldValueMap = collections::Dictionary; public: reflection::description::ITypeDescriptor* typeDescriptor = nullptr; FieldValueMap fieldValues; WfStructInstance(reflection::description::ITypeDescriptor* _typeDescriptor); reflection::description::PredefinedBoxableType GetBoxableType() override; Ptr Copy() override; CompareResult ComparePrimitive(Ptr boxedValue) override; }; class WfEnumInstance : public Object, public reflection::description::IBoxedValue { public: reflection::description::ITypeDescriptor* typeDescriptor = nullptr; vuint64_t value = 0; WfEnumInstance(reflection::description::ITypeDescriptor* _typeDescriptor); reflection::description::PredefinedBoxableType GetBoxableType() override; Ptr Copy() override; CompareResult ComparePrimitive(Ptr boxedValue) override; }; /*********************************************************************** Plugin ***********************************************************************/ class WfTypeImpl : public Object, public reflection::description::ITypeLoader, public reflection::Description { protected: runtime::WfRuntimeGlobalContext* globalContext = nullptr; public: collections::List> classes; collections::List> interfaces; collections::List> structs; collections::List> enums; runtime::WfRuntimeGlobalContext* GetGlobalContext(); void SetGlobalContext(runtime::WfRuntimeGlobalContext* _globalContext); void Load(reflection::description::ITypeManager* manager)override; void Unload(reflection::description::ITypeManager* manager)override; }; } } } #endif /*********************************************************************** .\WFRUNTIMEASSEMBLY.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Workflow::Runtime Interfaces: **********************************************************************/ #ifndef VCZH_WORKFLOW_RUNTIME_WFRUNTIMEASSEMBLY #define VCZH_WORKFLOW_RUNTIME_WFRUNTIMEASSEMBLY namespace vl { namespace workflow { namespace runtime { /*********************************************************************** Assembly ***********************************************************************/ /// Representing a compiled function. class WfAssemblyFunction : public Object { public: /// Name of the function. WString name; /// Argument names of the function. This index is for accessing [F:vl.workflow.runtime.WfRuntimeVariableContext.variables] in [F:vl.workflow.runtime.WfRuntimeCallStackInfo.arguments] when debugging. collections::List argumentNames; /// Captured variable names of the function. This index is for accessing [F:vl.workflow.runtime.WfRuntimeVariableContext.variables] in [F:vl.workflow.runtime.WfRuntimeCallStackInfo.captured] when debugging. collections::List capturedVariableNames; /// Local variable names of the function. This index is for accessing [F:vl.workflow.runtime.WfRuntimeVariableContext.variables] in [F:vl.workflow.runtime.WfRuntimeCallStackInfo.localVariables] when debugging. collections::List localVariableNames; /// First instruction index of the function. This index is for accessing [F:vl.workflow.runtime.WfAssembly.instructions]. vint firstInstruction = -1; /// Last instruction index of the function. This index is for accessing [F:vl.workflow.runtime.WfAssembly.instructions]. vint lastInstruction = -1; }; /// Representing debug informations. class WfInstructionDebugInfo : public Object { public: /// Module codes. collections::List moduleCodes; // codeIndex -> code /// Mapping information from every instruction to code. Use[F:vl.parsing.ParsingTextRange.codeIndex] for accessing . collections::List instructionCodeMapping; // instruction -> range /// Mapping information from every row in codes to instructions. Value of the key is (codeIndex, row). collections::Group, vint> codeInstructionMapping; // (codeIndex, row) -> instruction [generated] void Initialize(); }; /// Representing metadata errors during loading an assembly. class WfAssemblyLoadErrors { public: /// All unresolvable types. collections::List unresolvedTypes; /// All duplicated types. Types are shared in the process, there is no isolation between assemblies. collections::List duplicatedTypes; /// All unresolvable members in resolved types. collections::List unresolvedMembers; }; /// Representing a Workflow assembly. class WfAssembly : public Object, public reflection::Description { public: /// Debug informations using the module code. Ptr insBeforeCodegen; /// Debug informations using the module code from generated syntax trees from the final compiling pass. Ptr insAfterCodegen; /// Global variable names. This index is for accessing [F:vl.workflow.runtime.WfRuntimeVariableContext.variables] in [F:vl.workflow.runtime.WfRuntimeCallStackInfo.global] when debugging. collections::List variableNames; /// Mapping from function names to function indexes for accessing . collections::Group functionByName; /// Functions. collections::List> functions; /// Instructions. collections::List instructions; /// Custom types. Ptr typeImpl; /// Create an empty assembly. WfAssembly(); void Initialize(); /// Deserialize an assembly. /// The deserialized assembly. Returns null if there are errors. /// Serialized binary data. /// Errors during loading an assembly. static Ptr Deserialize(stream::IStream& input, WfAssemblyLoadErrors& errors); /// Serialize an assembly. /// Serialized binary data. void Serialize(stream::IStream& output); }; } } } #endif /*********************************************************************** .\WFRUNTIMECONSTRUCTIONS.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Workflow::Runtime Interfaces: **********************************************************************/ #ifndef VCZH_WORKFLOW_RUNTIME_WFRUNTIMECONSTRUCTIONS #define VCZH_WORKFLOW_RUNTIME_WFRUNTIMECONSTRUCTIONS #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA namespace vl { namespace workflow { namespace runtime { class WfRuntimeGlobalContext; class WfRuntimeVariableContext; /*********************************************************************** Range ***********************************************************************/ template class WfRuntimeRange : public Object, public reflection::description::IValueEnumerable { protected: T begin; T end; class Enumerator : public Object, public reflection::description::IValueEnumerator { protected: T begin; T end; T current; public: Enumerator(T _begin, T _end) :begin(_begin), end(_end), current(_begin - 1) { } reflection::description::Value GetCurrent() { return reflection::description::BoxValue(current); } vint GetIndex() { return (vint)(current - begin); } bool Next() { if (current >= end) return false; current++; return true; } }; public: WfRuntimeRange(T _begin, T _end) :begin(_begin), end(_end) { } Ptr CreateEnumerator()override { return Ptr(new Enumerator(begin, end)); } }; /*********************************************************************** Lambda ***********************************************************************/ class WfRuntimeLambda : public Object, public reflection::description::IValueFunctionProxy { typedef reflection::description::Value Value; public: // use raw pointer because // if a lambda is stored in a global variable // it is stored in globalContext->globalVariables->variables[i] // so that globalContext has a cyclic reference to itself WfRuntimeGlobalContext* globalContext = nullptr; Ptr capturedVariables; vint functionIndex; WfRuntimeLambda(Ptr _globalContext, Ptr _capturedVariables, vint _functionIndex); Value Invoke(Ptr arguments)override; static Value Invoke(Ptr globalContext, Ptr capturedVariables, vint functionIndex, Ptr arguments); }; /*********************************************************************** InterfaceInstance ***********************************************************************/ class WfRuntimeInterfaceInstance : public Object, public reflection::description::IValueInterfaceProxy { typedef reflection::description::Value Value; typedef reflection::description::IMethodInfo IMethodInfo; typedef reflection::description::IValueFunctionProxy IValueFunctionProxy; typedef reflection::description::IValueReadonlyList IValueReadonlyList; typedef collections::Dictionary FunctionMap; public: // use raw pointer because // if a lambda is stored in a global variable // it is stored in globalContext->globalVariables->variables[i] // so that globalContext has a cyclic reference to itself WfRuntimeGlobalContext* globalContext = nullptr; Ptr capturedVariables; FunctionMap functions; Value Invoke(IMethodInfo* methodInfo, Ptr arguments)override; }; } } } #endif #endif /*********************************************************************** .\WFRUNTIMEDEBUGGER.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Workflow::Runtime Interfaces: **********************************************************************/ #ifndef VCZH_WORKFLOW_RUNTIME_WFRUNTIMEDEBUGGER #define VCZH_WORKFLOW_RUNTIME_WFRUNTIMEDEBUGGER #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA namespace vl { namespace workflow { namespace runtime { class WfRuntimeThreadContext; class WfRuntimeExceptionInfo; class IWfDebuggerCallback; class WfDebugger; /*********************************************************************** Debugger ***********************************************************************/ /// Break point action. It will class IWfBreakPointAction : public virtual Interface { public: /// Called a break point is about to activate. /// Returns false to skip this break point. /// The current attached debugger. virtual bool EvaluateCondition(WfDebugger* debugger) = 0; /// Called when a break point is about to activate, even returns false. /// The current attached debugger. /// The return value from . virtual void PostAction(WfDebugger* debugger, bool activated) = 0; }; /// Break point. struct WfBreakPoint { enum Type { Instruction, // assembly, instruction ReadGlobalVar, // assembly, variable WriteGlobalVar, // assembly, variable GetProperty, // [thisObject], propertyInfo SetProperty, // [thisObject], propertyInfo AttachEvent, // [thisObject], eventInfo DetachEvent, // [thisObject], eventInfo InvokeEvent, // [thisObject], eventInfo InvokeMethod, // [thisObject], methodInfo CreateObject, // typeDescriptor }; vint id = -1; bool available = false; bool enabled = false; Ptr action; Type type; WfAssembly* assembly = nullptr; union { vint instruction = -1; vint variable; }; reflection::DescriptableObject* thisObject = nullptr; union { reflection::description::IPropertyInfo* propertyInfo = nullptr; reflection::description::IEventInfo* eventInfo; reflection::description::IMethodInfo* methodInfo; reflection::description::ITypeDescriptor* typeDescriptor; }; /// Create an instruction break point. /// The created break point. /// The assembly that contains the instruction. /// The index of the instruction. static WfBreakPoint Ins(WfAssembly* assembly, vint instruction); /// Create an global variable reading break point. /// The created break point. /// The assembly that contains the instruction. /// The index of the global variable. static WfBreakPoint Read(WfAssembly* assembly, vint variable); /// Create an global variable writing break point. /// The created break point. /// The assembly that contains the instruction. /// The index of the global variable. static WfBreakPoint Write(WfAssembly* assembly, vint variable); /// Create an property reading break point. /// The created break point. /// The target object. Set to null to apply to every object. /// The property. static WfBreakPoint Get(reflection::DescriptableObject* thisObject, reflection::description::IPropertyInfo* propertyInfo); /// Create an property writing break point. /// The created break point. /// The target object. Set to null to apply to every object. /// The property. static WfBreakPoint Set(reflection::DescriptableObject* thisObject, reflection::description::IPropertyInfo* propertyInfo); /// Create an event attaching break point. /// The created break point. /// The target object. Set to null to apply to every object. /// The event. static WfBreakPoint Attach(reflection::DescriptableObject* thisObject, reflection::description::IEventInfo* eventInfo); /// Create an event detaching break point. /// The created break point. /// The target object. Set to null to apply to every object. /// The event. static WfBreakPoint Detach(reflection::DescriptableObject* thisObject, reflection::description::IEventInfo* eventInfo); /// Create an event invoking break point. /// The created break point. /// The target object. Set to null to apply to every object. /// The event. static WfBreakPoint Invoke(reflection::DescriptableObject* thisObject, reflection::description::IEventInfo* eventInfo); /// Create an function invoking break point. /// The created break point. /// The target object. Set to null to apply to every object. /// The function. static WfBreakPoint Invoke(reflection::DescriptableObject* thisObject, reflection::description::IMethodInfo* methodInfo); /// Create an object creating break point. /// The created break point. /// The target object type. static WfBreakPoint Create(reflection::description::ITypeDescriptor* typeDescriptor); }; class IWfDebuggerCallback : public virtual Interface { public: virtual void EnterThreadContext(WfRuntimeThreadContext* context) = 0; virtual void LeaveThreadContext(WfRuntimeThreadContext* context) = 0; virtual bool BreakIns(WfAssembly* assembly, vint instruction) = 0; virtual bool BreakRead(WfAssembly* assembly, vint variable) = 0; virtual bool BreakWrite(WfAssembly* assembly, vint variable) = 0; virtual bool BreakGet(reflection::DescriptableObject* thisObject, reflection::description::IPropertyInfo* propertyInfo) = 0; virtual bool BreakSet(reflection::DescriptableObject* thisObject, reflection::description::IPropertyInfo* propertyInfo) = 0; virtual bool BreakAttach(reflection::DescriptableObject* thisObject, reflection::description::IEventInfo* eventInfo) = 0; virtual bool BreakDetach(reflection::DescriptableObject* thisObject, reflection::description::IEventInfo* eventInfo) = 0; virtual bool BreakInvoke(reflection::DescriptableObject* thisObject, reflection::description::IEventInfo* eventInfo) = 0; virtual bool BreakInvoke(reflection::DescriptableObject* thisObject, reflection::description::IMethodInfo* methodInfo) = 0; virtual bool BreakCreate(reflection::description::ITypeDescriptor* typeDescriptor) = 0; virtual bool BreakException(Ptr info) = 0; virtual bool WaitForContinue() = 0; }; /// Workflow debugger. /// ///

/// needs to be called to make a debugger works for any Workflow script that is running in the current thread. ///

///

/// needs to be overrided to make a debugger work properly. /// When the target Workflow script stops, /// this function will be called. /// In this function, /// one of , , , and /// must be called to make the target Workflow script continues. ///

///

/// You are allowed to run the debugger logic in another thread, /// for example, /// an GUI application is debugging a Workflow script which is running in another thread. /// In this case, needs to be blocked until it is ready to continue. ///

///

/// Locks are a good choice for this. ///

///
class WfDebugger : public Object, protected virtual IWfDebuggerCallback { friend IWfDebuggerCallback* GetDebuggerCallback(WfDebugger* debugger); typedef collections::List BreakPointList; typedef collections::List ThreadContextList; typedef Tuple AssemblyKey; typedef Tuple PropertyKey; typedef Tuple EventKey; typedef Tuple MethodKey; typedef reflection::description::ITypeDescriptor* TypeKey; typedef collections::Dictionary AssemblyBreakPointMap; typedef collections::Dictionary PropertyBreakPointMap; typedef collections::Dictionary EventBreakPointMap; typedef collections::Dictionary MethodBreakPointMap; typedef collections::Dictionary TypeBreakPointMap; public: /// The state of the debugger. /// ///

/// The state is affected by break points and the following operations: ///

    ///
  • : If the Workflow script is paused, it continues the script.
  • ///
  • : If the Workflow script is running, it pauses the script, following by a call to .
  • ///
  • : If the Workflow script is not stopped, it stops the script by throwing in exception in the script.
  • ///
  • : Stop over to the next code line and pause. It doesn't jump into the function to be called.
  • ///
  • : Stop into the new code line and pause.
  • ///
/// Operations are expected to be called in . ///

///
enum State { // Run Pause Stop StepOver StepInto /// The associated thread is running Workflow script. Running, // R *RTP *RTS /// The target Workflow script is paused by operations other than break points. PauseByOperation, // PBO *C *RTS *C *C /// The target Workflow script is paused by break points. PauseByBreakPoint, // PBB *C *RTS *C *C /// The associated thread has stopped running Workflow script. Stopped, // S *RTP * * /// The debugger allows the target Workflow script to continue. Continue, // C soon becomes Running /// The target Workflow script is required to pause. This value can be observed in . Operations to continue executing the Workflow script await to be called. RequiredToPause, // RTP soon becomes PauseByOperation (should be triggered in OnBlockExecution) /// The target Workflow script is required to stop. It caused to Workflow script to stop by throwing an exception saying this. RequiredToStop, // RTS soon becomes Stopped (should be triggered in OnBlockExecution) }; enum RunningType { RunUntilBreakPoint, RunStepOver, RunStepInto, }; struct InstructionLocation { vint contextIndex = -1; WfAssembly* assembly = nullptr; vint stackFrameIndex = -1; vint instruction = -1; bool BreakStepOver(const InstructionLocation& il, bool beforeCodegen); bool BreakStepInto(const InstructionLocation& il, bool beforeCodegen); }; static const vint InvalidBreakPoint = -1; static const vint PauseBreakPoint = -2; protected: BreakPointList breakPoints; collections::List freeBreakPointIndices; volatile bool evaluatingBreakPoint = false; volatile bool breakException = false; ThreadContextList threadContexts; volatile State state = Stopped; volatile RunningType runningType = RunUntilBreakPoint; volatile vint lastActivatedBreakPoint = InvalidBreakPoint; bool stepBeforeCodegen = true; InstructionLocation instructionLocation; AssemblyBreakPointMap insBreakPoints; AssemblyBreakPointMap getGlobalVarBreakPoints; AssemblyBreakPointMap setGlobalVarBreakPoints; PropertyBreakPointMap getPropertyBreakPoints; PropertyBreakPointMap setPropertyBreakPoints; EventBreakPointMap attachEventBreakPoints; EventBreakPointMap detachEventBreakPoints; EventBreakPointMap invokeEventBreakPoints; MethodBreakPointMap invokeMethodBreakPoints; TypeBreakPointMap createObjectBreakPoints; /// Called for doing something when a break point is activated. This function will be called multiple times before some one let the debugger to continue. /// This function must be overrided, or the Workflow script will hang when it is paused by any reason. virtual void OnBlockExecution(); /// Called when a new Workflow program is about to run. virtual void OnStartExecution(); /// Called when a Workflow program is stopped by any reason. virtual void OnStopExecution(); InstructionLocation MakeCurrentInstructionLocation(); template bool HandleBreakPoint(const TKey& key, collections::Dictionary& breakPointMap); bool SetBreakPoint(const WfBreakPoint& breakPoint, bool available, vint index); void EnterThreadContext(WfRuntimeThreadContext* context)override; void LeaveThreadContext(WfRuntimeThreadContext* context)override; bool BreakIns(WfAssembly* assembly, vint instruction)override; bool BreakRead(WfAssembly* assembly, vint variable)override; bool BreakWrite(WfAssembly* assembly, vint variable)override; bool BreakGet(reflection::DescriptableObject* thisObject, reflection::description::IPropertyInfo* propertyInfo)override; bool BreakSet(reflection::DescriptableObject* thisObject, reflection::description::IPropertyInfo* propertyInfo)override; bool BreakAttach(reflection::DescriptableObject* thisObject, reflection::description::IEventInfo* eventInfo)override; bool BreakDetach(reflection::DescriptableObject* thisObject, reflection::description::IEventInfo* eventInfo)override; bool BreakInvoke(reflection::DescriptableObject* thisObject, reflection::description::IEventInfo* eventInfo)override; bool BreakInvoke(reflection::DescriptableObject* thisObject, reflection::description::IMethodInfo* methodInfo)override; bool BreakCreate(reflection::description::ITypeDescriptor* typeDescriptor)override; bool BreakException(Ptr info)override; bool WaitForContinue()override; public: /// Create a debugger. WfDebugger(); ~WfDebugger(); /// Add a new break point. /// Returns the index of this break point. Returns -1 if failed. /// The break point. vint AddBreakPoint(const WfBreakPoint& breakPoint); /// Add a new source code break point. /// Returns the index of this break point. Returns -1 if failed. /// The assembly. /// The code index of a module. /// The row number, starts from 0. /// Set to true to apply source code information to original source code. vint AddCodeLineBreakPoint(WfAssembly* assembly, vint codeIndex, vint row, bool beforeCodegen = true); /// Get the number of all break points. /// The number of all break points. vint GetBreakPointCount(); /// Test if an index is an available break point. /// Returns true if an index is an available break point. This function returns true for all disabled break points. /// The index of the break point. bool IsBreakPointAvailable(vint index); /// Get a specified break point. For unavailable break points, is false. /// The break point. /// The index of the break point. const WfBreakPoint& GetBreakPoint(vint index); /// Delete a specified break point. /// Returns true if this operation is succeeded. /// The index of the break point. /// After removing a break point, the break point becomes unavailable. The index will be reused later when a new break point is added to the debugger. bool RemoveBreakPoint(vint index); /// Enable or disable a specified break point. /// Returns true if this operation is succeeded. /// The index of the break point. /// Set to true to enable a break point. bool EnableBreakPoint(vint index, bool enabled); /// Test if the exception break point is enabled or not. /// Returns true if the exception break point is enabled. bool GetBreakException(); /// Enable or disable the exception break point. /// Set to true to enable the exception break point. void SetBreakException(bool value); /// Continue to run the Workflow program. /// Returns true if this operation is succeeded. bool Run(); /// Pause the Workflow program. /// Returns true if this operation is succeeded. bool Pause(); /// Stop the Workflow program. /// Returns true if this operation is succeeded. bool Stop(); /// Run until reached the next row in the same function or outside of this function. /// Returns true if this operation is succeeded. /// Set to true to apply the source code information to original source code. bool StepOver(bool beforeCodegen = true); /// Run until reached the next row. /// Returns true if this operation is succeeded. /// Set to true to apply the source code information to original source code. bool StepInto(bool beforeCodegen = true); /// Get the current state of the debugger. /// The state of the debugger. State GetState(); /// Get the running type of the debugger. /// The running type of the debugger. RunningType GetRunningType(); /// Get the index of the last activated break point. /// The index of the last activated break point. vint GetLastActivatedBreakPoint(); const ThreadContextList& GetThreadContexts(); WfRuntimeThreadContext* GetCurrentThreadContext(); /// Get the current position of the executing instruction in the source code. /// The current position in the source code. /// Set to true to apply the source code information to original source code. /// Specify a thread context. Set to null to use the top thread context. /// Specify a call stack index. Set to null to use the top call stack item of the specified thread context. const glr::ParsingTextRange& GetCurrentPosition(bool beforeCodegen = true, WfRuntimeThreadContext* context = nullptr, vint callStackIndex = -1); /// Get the variable value by name in the current scope. /// The value. /// The name. /// Specify a thread context. Set to null to use the top thread context. /// Specify a call stack index. Set to null to use the top call stack item of the specified thread context. reflection::description::Value GetValueByName(const WString& name, WfRuntimeThreadContext* context = nullptr, vint callStackIndex = -1); }; extern IWfDebuggerCallback* GetDebuggerCallback(); extern IWfDebuggerCallback* GetDebuggerCallback(WfDebugger* debugger); /// Get the debugger for the current thread. /// The debugger. extern Ptr GetDebuggerForCurrentThread(); /// Set the debugger for the current thread. /// The debugger. extern void SetDebuggerForCurrentThread(Ptr debugger); /// Reset the debugger for the current thread. extern void ResetDebuggerForCurrentThread(); } } } #endif #endif /*********************************************************************** .\WFRUNTIME.H ***********************************************************************/ /*********************************************************************** Vczh Library++ 3.0 Developer: Zihan Chen(vczh) Workflow::Runtime Interfaces: **********************************************************************/ #ifndef VCZH_WORKFLOW_RUNTIME_WFRUNTIME #define VCZH_WORKFLOW_RUNTIME_WFRUNTIME #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA namespace vl { namespace workflow { namespace runtime { /*********************************************************************** RuntimeEnvironment ***********************************************************************/ /// Variable storage. class WfRuntimeVariableContext : public Object, public reflection::Description { typedef collections::Array VariableArray; public: /// Values of variables in runtime. VariableArray variables; }; /// Global context for executing a Workflow program. After the context is prepared, use [M:vl.workflow.runtime.LoadFunction`1] to call any functions inside the assembly. Function "<initialize>" should be the first to execute. class WfRuntimeGlobalContext : public Object, public reflection::Description { public: /// The loaded assembly. Ptr assembly; /// Global variable storages. Ptr globalVariables; /// Create a global context for executing a Workflow program. /// The assembly. WfRuntimeGlobalContext(Ptr _assembly); ~WfRuntimeGlobalContext(); }; struct WfRuntimeStackFrame { Ptr capturedVariables; vint functionIndex = -1; vint nextInstructionIndex = -1; vint stackBase = 0; vint fixedVariableCount = 0; vint freeStackBase = 0; }; struct WfRuntimeTrapFrame { vint stackFrameIndex = -1; vint instructionIndex = -1; vint stackPatternCount = -1; }; /*********************************************************************** RuntimeException ***********************************************************************/ /// Representing a call stack item. class WfRuntimeCallStackInfo : public Object, public virtual reflection::description::IValueCallStack { using IValueReadonlyDictionary = reflection::description::IValueReadonlyDictionary; protected: Ptr cachedLocalVariables; Ptr cachedLocalArguments; Ptr cachedCapturedVariables; Ptr cachedGlobalVariables; Ptr GetVariables(collections::List& names, Ptr context, Ptr& cache); public: WfRuntimeCallStackInfo(); WfRuntimeCallStackInfo(WfRuntimeThreadContext* context, const WfRuntimeStackFrame& stackFrame); ~WfRuntimeCallStackInfo(); /// The executing assembly. Ptr assembly; /// Global variable values. Ptr global; /// Captured variable values. Ptr captured; /// Argument values. Ptr arguments; /// Local variable values. Ptr localVariables; /// The executing function. vint functionIndex = -1; /// The executing instruction. vint instruction = -1; Ptr GetLocalVariables()override; Ptr GetLocalArguments()override; Ptr GetCapturedVariables()override; Ptr GetGlobalVariables()override; /// Get the name of the executing function. /// The name of the execution function. WString GetFunctionName()override; /// Get the source code of the executing module. /// The source code. WString GetSourceCodeBeforeCodegen()override; /// Get the source code of the executing module from generated syntax trees from the final compiling pass. /// The source code. WString GetSourceCodeAfterCodegen()override; /// Get the row number (starts at 0) of the source code of the executing module. /// The row number. vint GetRowBeforeCodegen()override; /// Get the row number (starts at 0) of the source code of the executing module from generated syntax trees from the final compiling pass. /// The row number. vint GetRowAfterCodegen()override; }; /// Representing an raised exception. class WfRuntimeExceptionInfo : public Object, public virtual reflection::description::IValueException { typedef collections::List> CallStackList; using IValueReadonlyList = reflection::description::IValueReadonlyList; protected: Ptr cachedCallStack; public: /// Exception message. WString message; /// Fatal error flag. bool fatal = false; /// All call stack items. CallStackList callStack; WfRuntimeExceptionInfo(const WString& _message, bool _fatal); ~WfRuntimeExceptionInfo(); #pragma push_macro("GetMessage") #if defined GetMessage #undef GetMessage #endif WString GetMessage()override; #pragma pop_macro("GetMessage") bool GetFatal()override; Ptr GetCallStack()override; }; /// Representing an raised exception object for upper level C++ code. class WfRuntimeException : public reflection::description::TypeDescriptorException { protected: Ptr info; bool fatal = false; public: WfRuntimeException(Ptr _info) :reflection::description::TypeDescriptorException(_info->message) , info(_info) , fatal(_info->fatal) { } WfRuntimeException(const WString& _message, bool _fatal) :reflection::description::TypeDescriptorException(_message) , fatal(_fatal) { } /// Get the detailed information. /// The detailed information. Ptr GetInfo()const { return info; } /// Get the fatal error flag. /// Returns true if this exception is a fatal error, which normally means state corruption in a Workflow runtime. bool IsFatal()const { return fatal; } }; /*********************************************************************** RuntimeThreadContext ***********************************************************************/ enum class WfRuntimeExecutionStatus { Ready, Executing, RaisedException, Finished, FatalError, }; enum class WfRuntimeExecutionAction { ExecuteInstruction, UnwrapStack, EnterStackFrame, ExitStackFrame, Nop, }; enum class WfRuntimeThreadContextError { Success, WrongStackItemIndex, WrongVariableIndex, WrongFunctionIndex, WrongArgumentCount, WrongCapturedVariableCount, EmptyStackFrame, EmptyTrapFrame, EmptyStack, TrapFrameCorrupted, StackCorrupted, }; /// A Workflow script call stack. /// ///

/// This object could be obtained by . /// A thread could have multiple thread contexts, /// a full list could be obtained by . ///

///

/// You are not recommended to update the call stack using this object. ///

///

/// In the current version, /// the debug information doesn't contain enough data, /// so that it could be difficult to read local variables in high-level function constructions, /// like lambda expression or coroutines. ///

/// class WfRuntimeThreadContext { typedef collections::List VariableList; typedef collections::List StackFrameList; typedef collections::List TrapFrameList; public: Ptr globalContext; Ptr exceptionInfo; VariableList stack; StackFrameList stackFrames; TrapFrameList trapFrames; WfRuntimeExecutionStatus status = WfRuntimeExecutionStatus::Finished; WfRuntimeThreadContext(Ptr _context); WfRuntimeThreadContext(Ptr _assembly); WfRuntimeStackFrame& GetCurrentStackFrame(); WfRuntimeThreadContextError PushStackFrame(vint functionIndex, vint argumentCount, Ptr capturedVariables = 0); WfRuntimeThreadContextError PopStackFrame(); WfRuntimeTrapFrame& GetCurrentTrapFrame(); WfRuntimeThreadContextError PushTrapFrame(vint instructionIndex); WfRuntimeThreadContextError PopTrapFrame(vint saveStackPatternCount); WfRuntimeThreadContextError PushRuntimeValue(const WfRuntimeValue& value); WfRuntimeThreadContextError PushValue(const reflection::description::Value& value); WfRuntimeThreadContextError PopValue(reflection::description::Value& value); WfRuntimeThreadContextError RaiseException(const WString& exception, bool fatalError, bool skipDebugger = false); WfRuntimeThreadContextError RaiseException(Ptr info, bool skipDebugger = false); WfRuntimeThreadContextError LoadStackValue(vint stackItemIndex, reflection::description::Value& value); WfRuntimeThreadContextError LoadGlobalVariable(vint variableIndex, reflection::description::Value& value); WfRuntimeThreadContextError StoreGlobalVariable(vint variableIndex, const reflection::description::Value& value); WfRuntimeThreadContextError LoadCapturedVariable(vint variableIndex, reflection::description::Value& value); WfRuntimeThreadContextError StoreCapturedVariable(vint variableIndex, const reflection::description::Value& value); WfRuntimeThreadContextError LoadLocalVariable(vint variableIndex, reflection::description::Value& value); WfRuntimeThreadContextError StoreLocalVariable(vint variableIndex, const reflection::description::Value& value); WfRuntimeExecutionAction ExecuteInternal(WfInstruction& ins, WfRuntimeStackFrame& stackFrame, IWfDebuggerCallback* callback); WfRuntimeExecutionAction Execute(IWfDebuggerCallback* callback); void ExecuteToEnd(); }; /*********************************************************************** Helper Functions ***********************************************************************/ /// Load a function from a global context, raise an exception if multiple functions are found under the same name. Function "<initialize>" should be the first to execute. /// The loaded function. /// The context to the evaluation environment. /// The function name. /// "<initialize>" must be the first function that is executed after an assembly is loaded. It has no argument or return value. extern Ptr LoadFunction(Ptr context, const WString& name); /// Load a C++ friendly function from a global context, raise an exception if multiple functions are found under the same name. Function "<initialize>" should be the first to execute. /// Type of the function. /// The loaded C++ friendly function. /// The context to the evaluation environment. /// The function name. /// "<initialize>" must be the first function that is executed after an assembly is loaded. Its type is void(). template Func LoadFunction(Ptr context, const WString& name) { auto proxy = LoadFunction(context, name); return reflection::description::UnboxParameter>(reflection::description::Value::From(proxy)).Ref(); } } } } #endif #endif