1 module as.context; 2 import as.def; 3 import as.engine; 4 import as.func; 5 6 enum ContextState : asEContextState { 7 Finished = asEContextState.asEXECUTION_FINISHED, 8 Suspended = asEContextState.asEXECUTION_SUSPENDED, 9 Aborted = asEContextState.asEXECUTION_ABORTED, 10 Exception = asEContextState.asEXECUTION_EXCEPTION, 11 Prepared = asEContextState.asEXECUTION_PREPARED, 12 Uninitialized = asEContextState.asEXECUTION_UNINITIALIZED, 13 Active = asEContextState.asEXECUTION_ACTIVE, 14 Error = asEContextState.asEXECUTION_ERROR 15 } 16 17 /** 18 A script execution context 19 */ 20 class ScriptContext { 21 private: 22 ScriptEngine engine; 23 24 ~this() { 25 // Make sure we don't try to destroy the engine 26 this.engine = null; 27 28 // Release the context 29 asContext_Release(ctx); 30 } 31 32 package(as): 33 asIScriptContext* ctx; 34 35 this(ScriptEngine engine, asIScriptContext* ctx) { 36 this.engine = engine; 37 this.ctx = ctx; 38 } 39 40 public: 41 /** 42 Adds a reference to this script context 43 */ 44 int addRef() { 45 return asContext_AddRef(ctx); 46 } 47 48 /** 49 Releases a reference to this script context 50 */ 51 int release() { 52 return asContext_Release(ctx); 53 } 54 55 /** 56 Gets the script engine this context belongs to 57 */ 58 ScriptEngine getEngine() { 59 return engine; 60 } 61 62 /** 63 Prepares this context 64 */ 65 void prepare(Function func) { 66 int err = asContext_Prepare(ctx, func.func); 67 assert(err != asERetCodes.asCONTEXT_ACTIVE, "The context is still active or suspended"); 68 assert(err != asERetCodes.asNO_FUNCTION, "Function pointer is null"); 69 assert(err != asERetCodes.asINVALID_ARG, "Function is from a different engine than context"); 70 assert(err != asERetCodes.asOUT_OF_MEMORY, "Context ran out of memory while allocating call stack"); 71 } 72 73 /** 74 Un-prepares this context 75 */ 76 void unprepare() { 77 int err = asContext_Unprepare(ctx); 78 assert(err != asERetCodes.asCONTEXT_ACTIVE, "The context is still active or suspended"); 79 } 80 81 /** 82 Executes this context 83 */ 84 ContextState execute() { 85 int err = asContext_Execute(ctx); 86 assert(err != asERetCodes.asCONTEXT_NOT_PREPARED, "The context is still active or not suspended"); 87 return cast(ContextState)err; 88 } 89 90 /** 91 Aborts this context 92 */ 93 void abort() { 94 int err = asContext_Abort(ctx); 95 assert(err != asERetCodes.asERROR, "Invalid context"); 96 } 97 98 /** 99 Suspends this context 100 */ 101 void suspend() { 102 int err = asContext_Suspend(ctx); 103 assert(err != asERetCodes.asERROR, "Invalid context"); 104 } 105 106 /** 107 Gets the current state of the context 108 */ 109 ContextState getState() { 110 return cast(ContextState)asContext_GetState(ctx); 111 } 112 113 /** 114 Backups current state and prepares state for a nested call 115 */ 116 void pushState() { 117 int err = asContext_PushState(ctx); 118 assert(err != asERetCodes.asERROR, "Context not active"); 119 assert(err != asERetCodes.asOUT_OF_MEMORY, "Could not allocate memory for state"); 120 } 121 122 /** 123 Restores previous execution state 124 */ 125 void popState() { 126 int err = asContext_PopState(ctx); 127 assert(err != asERetCodes.asERROR, "Could not restore state"); 128 } 129 130 /** 131 Gets whether the context has any nested calls 132 */ 133 bool isNested(ref uint nestCount) { 134 return asContext_IsNested(ctx, &nestCount); 135 } 136 137 /** 138 Sets object for class method call 139 */ 140 void setObject(void* obj) { 141 asContext_SetObject(ctx, obj); 142 } 143 144 /** 145 Sets a base type argument 146 147 Notes: 148 To set object argument values, use setArgObject 149 To set variable arguments, use setArgVarType 150 */ 151 void setArg(T)(asUINT arg, T value) { 152 static if (isPointer!T) { 153 int err = asContext_SetArgAddress(ctx, arg, value); 154 } else static if (T.sizeof == 1) { 155 int err = asContext_SetArgByte(ctx, arg, cast(ubyte)value); 156 } else static if (T.sizeof == 2) { 157 int err = asContext_SetArgWord(ctx, arg, cast(asWORD)value); 158 } else static if (T.sizeof == 4) { 159 int err = asContext_SetArgDWord(ctx, arg, cast(asDWORD)value); 160 } else static if (T.sizeof == 8) { 161 int err = asContext_SetArgQWord(ctx, arg, cast(asQWORD)value); 162 } else static if (is(T : float)) { 163 int err = asContext_SetArgFloat(ctx, arg, value); 164 } else static if (is(T : double)) { 165 int err = asContext_SetArgDouble(ctx, arg, value); 166 } else { 167 assert(0, "Type not supported by setArg"); 168 } 169 assert(err != asERetCodes.asCONTEXT_NOT_PREPARED, "The context is not in a prepared state"); 170 assert(err != asERetCodes.asINVALID_ARG, "Argument is outside function argument bounds"); 171 assert(err != asERetCodes.asINVALID_TYPE, "Value type does not fit argument type"); 172 } 173 174 /** 175 Sets object/handle argument value 176 */ 177 void setArgObject(asUINT arg, void* value) { 178 int err = asContext_SetArgObject(ctx, arg, value); 179 assert(err != asERetCodes.asCONTEXT_NOT_PREPARED, "The context is not in a prepared state"); 180 assert(err != asERetCodes.asINVALID_ARG, "Argument is outside function argument bounds"); 181 assert(err != asERetCodes.asINVALID_TYPE, "Argument is not a object or handle"); 182 } 183 184 /** 185 Sets the variable argument value and type 186 */ 187 void setArgVarType(T)(asUINT arg, T* ptr, int typeId) { 188 int err = asContext_SetArgVarType(ctx, arg, ptr, typeId); 189 assert(err != asERetCodes.asCONTEXT_NOT_PREPARED, "The context is not in a prepared state"); 190 assert(err != asERetCodes.asINVALID_ARG, "Argument is outside function argument bounds"); 191 assert(err != asERetCodes.asINVALID_TYPE, "Argument is not a variable type"); 192 } 193 194 /** 195 Gets the address of an argument 196 */ 197 void* getAddressOfArg(asUINT arg) { 198 return asContext_GetAddressOfArg(ctx, arg); 199 } 200 201 /** 202 Gets the size of the callstack 203 */ 204 asUINT getCallstackSize() { 205 return asContext_GetCallstackSize(ctx); 206 } 207 208 /** 209 Gets the line number based on stackLevel which the context is currently executing 210 */ 211 int getLineNumber(asUINT stackLevel = 0) { 212 return getLineNumber(stackLevel, null); 213 } 214 215 /** 216 Gets the line number, column and sectino name based on stackLevel which the context is currently executing 217 */ 218 int getLineNumber(asUINT stackLevel, int* column) { 219 220 // Get the line number and extra stuff 221 int ln = asContext_GetLineNumber(ctx, stackLevel, column, null); 222 return ln; 223 } 224 225 /** 226 Sets the user data 227 */ 228 void* setUserData(void* data) { 229 return asContext_SetUserData(ctx, data); 230 } 231 232 /** 233 Gets the user data 234 */ 235 void* getUserData() { 236 return asContext_GetUserData(ctx); 237 } 238 }