1 /*
2    AngelCode Scripting Library
3    Copyright (c) 2003-2016 Andreas Jonsson
4 
5    This software is provided 'as-is', without any express or implied
6    warranty. In no event will the authors be held liable for any
7    damages arising from the use of this software.
8 
9    Permission is granted to anyone to use this software for any
10    purpose, including commercial applications, and to alter it and
11    redistribute it freely, subject to the following restrictions:
12 
13    1. The origin of this software must not be misrepresented; you
14       must not claim that you wrote the original software. If you use
15       this software in a product, an acknowledgment in the product
16       documentation would be appreciated but is not required.
17 
18    2. Altered source versions must be plainly marked as such, and
19       must not be misrepresented as being the original software.
20 
21    3. This notice may not be removed or altered from any source
22       distribution.
23 
24    The original version of this library can be located at:
25    http://www.angelcode.com/angelscript/
26 
27    Andreas Jonsson
28    andreas@angelcode.com
29 */
30 
31 
32 //
33 // as_scriptfunction.h
34 //
35 // A container for a compiled script function
36 //
37 
38 
39 
40 #ifndef AS_SCRIPTFUNCTION_H
41 #define AS_SCRIPTFUNCTION_H
42 
43 #include "as_config.h"
44 #include "as_string.h"
45 #include "as_array.h"
46 #include "as_datatype.h"
47 #include "as_atomic.h"
48 
49 BEGIN_AS_NAMESPACE
50 
51 class asCScriptEngine;
52 class asCModule;
53 class asCConfigGroup;
54 class asCGlobalProperty;
55 class asCScriptNode;
56 class asCFuncdefType;
57 struct asSNameSpace;
58 
59 struct asSScriptVariable
60 {
61 	asCString   name;
62 	asCDataType type;
63 	int         stackOffset;
64 	asUINT      declaredAtProgramPos;
65 };
66 
67 enum asEListPatternNodeType
68 {
69 	asLPT_REPEAT,
70 	asLPT_REPEAT_SAME,
71 	asLPT_START,
72 	asLPT_END,
73 	asLPT_TYPE
74 };
75 
76 struct asSListPatternNode
77 {
asSListPatternNodeasSListPatternNode78 	asSListPatternNode(asEListPatternNodeType t) : type(t), next(0) {}
~asSListPatternNodeasSListPatternNode79 	virtual ~asSListPatternNode() {};
DuplicateasSListPatternNode80 	virtual asSListPatternNode *Duplicate() { return asNEW(asSListPatternNode)(type); }
81 	asEListPatternNodeType  type;
82 	asSListPatternNode     *next;
83 };
84 
85 struct asSListPatternDataTypeNode : public asSListPatternNode
86 {
asSListPatternDataTypeNodeasSListPatternDataTypeNode87 	asSListPatternDataTypeNode(const asCDataType &dt) : asSListPatternNode(asLPT_TYPE), dataType(dt) {}
DuplicateasSListPatternDataTypeNode88 	asSListPatternNode *Duplicate() { return asNEW(asSListPatternDataTypeNode)(dataType); }
89 	asCDataType dataType;
90 };
91 
92 enum asEObjVarInfoOption
93 {
94 	asOBJ_UNINIT,
95 	asOBJ_INIT,
96 	asBLOCK_BEGIN,
97 	asBLOCK_END
98 };
99 
100 struct asSObjectVariableInfo
101 {
102 	asUINT              programPos;
103 	int                 variableOffset;
104 	asEObjVarInfoOption option;
105 };
106 
107 struct asSSystemFunctionInterface;
108 
109 // TODO: Might be interesting to allow enumeration of accessed global variables, and
110 //       also functions/methods that are being called. This could be used to build a
111 //       code database with call graphs, etc.
112 
113 void RegisterScriptFunction(asCScriptEngine *engine);
114 
115 class asCScriptFunction : public asIScriptFunction
116 {
117 public:
118 	// From asIScriptFunction
119 	asIScriptEngine     *GetEngine() const;
120 
121 	// Memory management
122 	int AddRef() const;
123 	int Release() const;
124 
125 	// Miscellaneous
126 	int                  GetId() const;
127 	asEFuncType          GetFuncType() const;
128 	const char          *GetModuleName() const;
129 	asIScriptModule     *GetModule() const;
130 	const char          *GetScriptSectionName() const;
131 	const char          *GetConfigGroup() const;
132 	asDWORD              GetAccessMask() const;
133 	void                *GetAuxiliary() const;
134 
135 	// Function signature
136 	asITypeInfo         *GetObjectType() const;
137 	const char          *GetObjectName() const;
138 	const char          *GetName() const;
139 	const char          *GetNamespace() const;
140 	const char          *GetDeclaration(bool includeObjectName = true, bool includeNamespace = false, bool includeParamNames = false) const;
141 	bool                 IsReadOnly() const;
142 	bool                 IsPrivate() const;
143 	bool                 IsProtected() const;
144 	bool                 IsFinal() const;
145 	bool                 IsOverride() const;
146 	bool                 IsShared() const;
147 	asUINT               GetParamCount() const;
148 	int                  GetParam(asUINT index, int *typeId, asDWORD *flags = 0, const char **name = 0, const char **defaultArg = 0) const;
149 #ifdef AS_DEPRECATED
150 	// Deprecated, since 2.29.0, 2014-04-06
151 	int                  GetParamTypeId(asUINT index, asDWORD *flags = 0) const;
152 #endif
153 	int                  GetReturnTypeId(asDWORD *flags = 0) const;
154 
155 	// Type id for function pointers
156 	int                  GetTypeId() const;
157 	bool                 IsCompatibleWithTypeId(int typeId) const;
158 
159 	// Delegates
160 	void                *GetDelegateObject() const;
161 	asITypeInfo         *GetDelegateObjectType() const;
162 	asIScriptFunction   *GetDelegateFunction() const;
163 
164 	// Debug information
165 	asUINT               GetVarCount() const;
166 	int                  GetVar(asUINT index, const char **name, int *typeId = 0) const;
167 	const char *         GetVarDecl(asUINT index, bool includeNamespace = false) const;
168 	int                  FindNextLineWithCode(int line) const;
169 
170 	// For JIT compilation
171 	asDWORD             *GetByteCode(asUINT *length = 0);
172 
173 	// User data
174 	void                *SetUserData(void *userData, asPWORD type);
175 	void                *GetUserData(asPWORD type) const;
176 
177 public:
178 	//-----------------------------------
179 	// Internal methods
180 
181 	asCScriptFunction(asCScriptEngine *engine, asCModule *mod, asEFuncType funcType);
182 	~asCScriptFunction();
183 
184 	// Keep an internal reference counter to separate references coming from
185 	// application or script objects and references coming from the script code
186 	int AddRefInternal();
187 	int ReleaseInternal();
188 
189 	void     DestroyHalfCreated();
190 
191 	// TODO: operator==
192 	// TODO: The asIScriptFunction should provide operator== and operator!= that should do a
193 	//       a value comparison. Two delegate objects that point to the same object and class method should compare as equal
194 	// TODO: The operator== should also be provided in script as opEquals to allow the same comparison in script
195 	//       To do this we'll need some way to adapt the argtype for opEquals for each funcdef, preferrably without instantiating lots of different methods
196 	//       Perhaps reusing 'auto' to mean the same type as the object
197 	//bool      operator==(const asCScriptFunction &other) const;
198 
199 	void      DestroyInternal();
200 
201 	void      AddVariable(asCString &name, asCDataType &type, int stackOffset);
202 
203 	int       GetSpaceNeededForArguments();
204 	int       GetSpaceNeededForReturnValue();
205 	asCString GetDeclarationStr(bool includeObjectName = true, bool includeNamespace = false, bool includeParamNames = false) const;
206 	int       GetLineNumber(int programPosition, int *sectionIdx);
207 	void      ComputeSignatureId();
208 	bool      IsSignatureEqual(const asCScriptFunction *func) const;
209 	bool      IsSignatureExceptNameEqual(const asCScriptFunction *func) const;
210 	bool      IsSignatureExceptNameEqual(const asCDataType &retType, const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &inOutFlags, const asCObjectType *type, bool isReadOnly) const;
211 	bool      IsSignatureExceptNameAndReturnTypeEqual(const asCScriptFunction *fun) const;
212 	bool      IsSignatureExceptNameAndReturnTypeEqual(const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &inOutFlags, const asCObjectType *type, bool isReadOnly) const;
213 	bool      IsSignatureExceptNameAndObjectTypeEqual(const asCScriptFunction *func) const;
214 
215 	asCTypeInfo *GetTypeInfoOfLocalVar(short varOffset);
216 
217 	void      MakeDelegate(asCScriptFunction *func, void *obj);
218 
219 	int       RegisterListPattern(const char *decl, asCScriptNode *listPattern);
220 	int       ParseListPattern(asSListPatternNode *&target, const char *decl, asCScriptNode *listPattern);
221 
222 	bool      DoesReturnOnStack() const;
223 
224 	void      JITCompile();
225 
226 	void      AddReferences();
227 	void      ReleaseReferences();
228 
229 	void      AllocateScriptFunctionData();
230 	void      DeallocateScriptFunctionData();
231 
232 	asCGlobalProperty *GetPropertyByGlobalVarPtr(void *gvarPtr);
233 
234 	// GC methods (for delegates)
235 	int  GetRefCount();
236 	void SetFlag();
237 	bool GetFlag();
238 	void EnumReferences(asIScriptEngine *engine);
239 	void ReleaseAllHandles(asIScriptEngine *engine);
240 
241 public:
242 	//-----------------------------------
243 	// Properties
244 
245 	mutable asCAtomic            externalRefCount; // Used for external referneces
246 	        asCAtomic            internalRefCount; // Used for internal references
247 	mutable bool                 gcFlag;
248 	asCScriptEngine             *engine;
249 	asCModule                   *module;
250 
251 	asCArray<asPWORD>            userData;
252 
253 	// Function signature
254 	asCString                    name;
255 	asCDataType                  returnType;
256 	asCArray<asCDataType>        parameterTypes;
257 	asCArray<asCString>          parameterNames;
258 	asCArray<asETypeModifiers>   inOutFlags;
259 	asCArray<asCString *>        defaultArgs;
260 	bool                         isReadOnly;
261 	bool                         isPrivate;
262 	bool                         isProtected;
263 	bool                         isFinal;
264 	bool                         isOverride;
265 	asCObjectType               *objectType;
266 	int                          signatureId;
267 
268 	int                          id;
269 
270 	asEFuncType                  funcType;
271 	asDWORD                      accessMask;
272 	bool                         isShared;
273 
274 	// Namespace will be null for funcdefs that are declared as child funcdefs
275 	// of a class. In this case the namespace shall be taken from the parentClass
276 	// in the funcdefType
277 	asSNameSpace                *nameSpace;
278 
279 	asCFuncdefType              *funcdefType; // Doesn't increase refCount
280 
281 	// Used by asFUNC_DELEGATE
282 	void              *objForDelegate;
283 	asCScriptFunction *funcForDelegate;
284 
285 	// Used by list factory behaviour
286 	asSListPatternNode *listPattern;
287 
288 	// Used by asFUNC_SCRIPT
289 	struct ScriptFunctionData
290 	{
291 		// Bytecode for the script function
292 		asCArray<asDWORD>               byteCode;
293 
294 		// The stack space needed for the local variables
295 		asDWORD                         variableSpace;
296 
297 		// These hold information on objects and function pointers, including temporary
298 		// variables used by exception handler and when saving bytecode
299 		asCArray<asCTypeInfo*>          objVariableTypes;
300 		asCArray<int>                   objVariablePos;
301 
302 		// The first variables in above array are allocated on the heap, the rest on the stack.
303 		// This variable shows how many are on the heap.
304 		asUINT                          objVariablesOnHeap;
305 
306 		// Holds information on scope for object variables on the stack
307 		asCArray<asSObjectVariableInfo> objVariableInfo;
308 
309 		// The stack needed to execute the function
310 		int                             stackNeeded;
311 
312 		// JIT compiled code of this function
313 		asJITFunction                   jitFunction;
314 
315 		// Holds debug information on explicitly declared variables
316 		asCArray<asSScriptVariable*>    variables;
317 		// Store position, line number pairs for debug information
318 		asCArray<int>                   lineNumbers;
319 		// Store the script section where the code was declared
320 		int                             scriptSectionIdx;
321 		// Store the location where the function was declared  (row in the lower 20 bits, and column in the upper 12)
322 		int                             declaredAt;
323 		// Store position/index pairs if the bytecode is compiled from multiple script sections
324 		asCArray<int>                   sectionIdxs;
325 	};
326 	ScriptFunctionData          *scriptData;
327 
328 	// Stub functions and delegates don't own the object and parameters
329 	bool                         dontCleanUpOnException;
330 
331 	// Used by asFUNC_VIRTUAL
332 	int                          vfTableIdx;
333 
334 	// Used by asFUNC_SYSTEM
335 	asSSystemFunctionInterface  *sysFuncIntf;
336 };
337 
338 const char * const DELEGATE_FACTORY = "$dlgte";
339 asCScriptFunction *CreateDelegate(asCScriptFunction *func, void *obj);
340 
341 END_AS_NAMESPACE
342 
343 #endif
344