1 /*
2    AngelCode Scripting Library
3    Copyright (c) 2003-2017 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 enum asEFuncTrait
101 {
102 	asTRAIT_CONSTRUCTOR = 1,
103 	asTRAIT_DESTRUCTOR  = 2,
104 	asTRAIT_CONST       = 4,
105 	asTRAIT_PRIVATE     = 8,
106 	asTRAIT_PROTECTED   = 16,
107 	asTRAIT_FINAL       = 32,
108 	asTRAIT_OVERRIDE    = 64,
109 	asTRAIT_SHARED      = 128,
110 	asTRAIT_EXTERNAL    = 256
111 };
112 
113 struct asSFunctionTraits
114 {
asSFunctionTraitsasSFunctionTraits115 	asSFunctionTraits() : traits(0) {}
SetTraitasSFunctionTraits116 	void SetTrait(asEFuncTrait trait, bool set) { if (set) traits |= trait; else traits &= ~trait; }
GetTraitasSFunctionTraits117 	bool GetTrait(asEFuncTrait trait) const { return (traits & trait) ? true : false; }
118 protected:
119 	asDWORD traits;
120 };
121 
122 struct asSObjectVariableInfo
123 {
124 	asUINT              programPos;
125 	int                 variableOffset;
126 	asEObjVarInfoOption option;
127 };
128 
129 struct asSSystemFunctionInterface;
130 
131 // TODO: Might be interesting to allow enumeration of accessed global variables, and
132 //       also functions/methods that are being called. This could be used to build a
133 //       code database with call graphs, etc.
134 
135 void RegisterScriptFunction(asCScriptEngine *engine);
136 
137 class asCScriptFunction : public asIScriptFunction
138 {
139 public:
140 	// From asIScriptFunction
141 	asIScriptEngine     *GetEngine() const;
142 
143 	// Memory management
144 	int AddRef() const;
145 	int Release() const;
146 
147 	// Miscellaneous
148 	int                  GetId() const;
149 	asEFuncType          GetFuncType() const;
150 	const char          *GetModuleName() const;
151 	asIScriptModule     *GetModule() const;
152 	const char          *GetScriptSectionName() const;
153 	const char          *GetConfigGroup() const;
154 	asDWORD              GetAccessMask() const;
155 	void                *GetAuxiliary() const;
156 
157 	// Function signature
158 	asITypeInfo         *GetObjectType() const;
159 	const char          *GetObjectName() const;
160 	const char          *GetName() const;
161 	const char          *GetNamespace() const;
162 	const char          *GetDeclaration(bool includeObjectName = true, bool includeNamespace = false, bool includeParamNames = false) const;
163 	bool                 IsReadOnly() const;
164 	bool                 IsPrivate() const;
165 	bool                 IsProtected() const;
166 	bool                 IsFinal() const;
167 	bool                 IsOverride() const;
168 	bool                 IsShared() const;
169 	asUINT               GetParamCount() const;
170 	int                  GetParam(asUINT index, int *typeId, asDWORD *flags = 0, const char **name = 0, const char **defaultArg = 0) const;
171 	int                  GetReturnTypeId(asDWORD *flags = 0) const;
172 
173 	// Type id for function pointers
174 	int                  GetTypeId() const;
175 	bool                 IsCompatibleWithTypeId(int typeId) const;
176 
177 	// Delegates
178 	void                *GetDelegateObject() const;
179 	asITypeInfo         *GetDelegateObjectType() const;
180 	asIScriptFunction   *GetDelegateFunction() const;
181 
182 	// Debug information
183 	asUINT               GetVarCount() const;
184 	int                  GetVar(asUINT index, const char **name, int *typeId = 0) const;
185 	const char *         GetVarDecl(asUINT index, bool includeNamespace = false) const;
186 	int                  FindNextLineWithCode(int line) const;
187 
188 	// For JIT compilation
189 	asDWORD             *GetByteCode(asUINT *length = 0);
190 
191 	// User data
192 	void                *SetUserData(void *userData, asPWORD type);
193 	void                *GetUserData(asPWORD type) const;
194 
195 public:
196 	//-----------------------------------
197 	// Internal methods
198 
SetShared(bool set)199 	void SetShared(bool set) {traits.SetTrait(asTRAIT_SHARED, set);}
SetReadOnly(bool set)200 	void SetReadOnly(bool set) { traits.SetTrait(asTRAIT_CONST, set); }
SetFinal(bool set)201 	void SetFinal(bool set) { traits.SetTrait(asTRAIT_FINAL, set); }
SetOverride(bool set)202 	void SetOverride(bool set) { traits.SetTrait(asTRAIT_OVERRIDE, set); }
SetProtected(bool set)203 	void SetProtected(bool set) { traits.SetTrait(asTRAIT_PROTECTED, set); }
SetPrivate(bool set)204 	void SetPrivate(bool set) { traits.SetTrait(asTRAIT_PRIVATE, set); }
205 
206 	asCScriptFunction(asCScriptEngine *engine, asCModule *mod, asEFuncType funcType);
207 	~asCScriptFunction();
208 
209 	// Keep an internal reference counter to separate references coming from
210 	// application or script objects and references coming from the script code
211 	int AddRefInternal();
212 	int ReleaseInternal();
213 
214 	void     DestroyHalfCreated();
215 
216 	// TODO: operator==
217 	// TODO: The asIScriptFunction should provide operator== and operator!= that should do a
218 	//       a value comparison. Two delegate objects that point to the same object and class method should compare as equal
219 	// TODO: The operator== should also be provided in script as opEquals to allow the same comparison in script
220 	//       To do this we'll need some way to adapt the argtype for opEquals for each funcdef, preferrably without instantiating lots of different methods
221 	//       Perhaps reusing 'auto' to mean the same type as the object
222 	//bool      operator==(const asCScriptFunction &other) const;
223 
224 	void      DestroyInternal();
225 
226 	void      AddVariable(asCString &name, asCDataType &type, int stackOffset);
227 
228 	int       GetSpaceNeededForArguments();
229 	int       GetSpaceNeededForReturnValue();
230 	asCString GetDeclarationStr(bool includeObjectName = true, bool includeNamespace = false, bool includeParamNames = false) const;
231 	int       GetLineNumber(int programPosition, int *sectionIdx);
232 	void      ComputeSignatureId();
233 	bool      IsSignatureEqual(const asCScriptFunction *func) const;
234 	bool      IsSignatureExceptNameEqual(const asCScriptFunction *func) const;
235 	bool      IsSignatureExceptNameEqual(const asCDataType &retType, const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &inOutFlags, const asCObjectType *type, bool isReadOnly) const;
236 	bool      IsSignatureExceptNameAndReturnTypeEqual(const asCScriptFunction *fun) const;
237 	bool      IsSignatureExceptNameAndReturnTypeEqual(const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &inOutFlags, const asCObjectType *type, bool isReadOnly) const;
238 	bool      IsSignatureExceptNameAndObjectTypeEqual(const asCScriptFunction *func) const;
239 
240 	asCTypeInfo *GetTypeInfoOfLocalVar(short varOffset);
241 
242 	void      MakeDelegate(asCScriptFunction *func, void *obj);
243 
244 	int       RegisterListPattern(const char *decl, asCScriptNode *listPattern);
245 	int       ParseListPattern(asSListPatternNode *&target, const char *decl, asCScriptNode *listPattern);
246 
247 	bool      DoesReturnOnStack() const;
248 
249 	void      JITCompile();
250 
251 	void      AddReferences();
252 	void      ReleaseReferences();
253 
254 	void      AllocateScriptFunctionData();
255 	void      DeallocateScriptFunctionData();
256 
257 	asCGlobalProperty *GetPropertyByGlobalVarPtr(void *gvarPtr);
258 
259 	// GC methods (for delegates)
260 	int  GetRefCount();
261 	void SetFlag();
262 	bool GetFlag();
263 	void EnumReferences(asIScriptEngine *engine);
264 	void ReleaseAllHandles(asIScriptEngine *engine);
265 
266 public:
267 	//-----------------------------------
268 	// Properties
269 
270 	mutable asCAtomic            externalRefCount; // Used for external referneces
271 	        asCAtomic            internalRefCount; // Used for internal references
272 	mutable bool                 gcFlag;
273 	asCScriptEngine             *engine;
274 	asCModule                   *module;
275 
276 	asCArray<asPWORD>            userData;
277 
278 	// Function signature
279 	asCString                    name;
280 	asCDataType                  returnType;
281 	asCArray<asCDataType>        parameterTypes;
282 	asCArray<asCString>          parameterNames;
283 	asCArray<asETypeModifiers>   inOutFlags;
284 	asCArray<asCString *>        defaultArgs;
285 	asSFunctionTraits            traits;
286 	asCObjectType               *objectType;
287 	int                          signatureId;
288 
289 	int                          id;
290 
291 	asEFuncType                  funcType;
292 	asDWORD                      accessMask;
293 
294 	// Namespace will be null for funcdefs that are declared as child funcdefs
295 	// of a class. In this case the namespace shall be taken from the parentClass
296 	// in the funcdefType
297 	asSNameSpace                *nameSpace;
298 
299 	asCFuncdefType              *funcdefType; // Doesn't increase refCount
300 
301 	// Used by asFUNC_DELEGATE
302 	void              *objForDelegate;
303 	asCScriptFunction *funcForDelegate;
304 
305 	// Used by list factory behaviour
306 	asSListPatternNode *listPattern;
307 
308 	// Used by asFUNC_SCRIPT
309 	struct ScriptFunctionData
310 	{
311 		// Bytecode for the script function
312 		asCArray<asDWORD>               byteCode;
313 
314 		// The stack space needed for the local variables
315 		asDWORD                         variableSpace;
316 
317 		// These hold information on objects and function pointers, including temporary
318 		// variables used by exception handler and when saving bytecode
319 		asCArray<asCTypeInfo*>          objVariableTypes;
320 		asCArray<int>                   objVariablePos;
321 
322 		// The first variables in above array are allocated on the heap, the rest on the stack.
323 		// This variable shows how many are on the heap.
324 		asUINT                          objVariablesOnHeap;
325 
326 		// Holds information on scope for object variables on the stack
327 		asCArray<asSObjectVariableInfo> objVariableInfo;
328 
329 		// The stack needed to execute the function
330 		int                             stackNeeded;
331 
332 		// JIT compiled code of this function
333 		asJITFunction                   jitFunction;
334 
335 		// Holds debug information on explicitly declared variables
336 		asCArray<asSScriptVariable*>    variables;
337 		// Store position, line number pairs for debug information
338 		asCArray<int>                   lineNumbers;
339 		// Store the script section where the code was declared
340 		int                             scriptSectionIdx;
341 		// Store the location where the function was declared  (row in the lower 20 bits, and column in the upper 12)
342 		int                             declaredAt;
343 		// Store position/index pairs if the bytecode is compiled from multiple script sections
344 		asCArray<int>                   sectionIdxs;
345 	};
346 	ScriptFunctionData          *scriptData;
347 
348 	// Stub functions and delegates don't own the object and parameters
349 	bool                         dontCleanUpOnException;
350 
351 	// Used by asFUNC_VIRTUAL
352 	int                          vfTableIdx;
353 
354 	// Used by asFUNC_SYSTEM
355 	asSSystemFunctionInterface  *sysFuncIntf;
356 };
357 
358 const char * const DELEGATE_FACTORY = "$dlgte";
359 asCScriptFunction *CreateDelegate(asCScriptFunction *func, void *obj);
360 
361 END_AS_NAMESPACE
362 
363 #endif
364