1 /*
2    AngelCode Scripting Library
3    Copyright (c) 2003-2019 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_builder.h
34 //
35 // This is the class that manages the compilation of the scripts
36 //
37 
38 
39 #ifndef AS_BUILDER_H
40 #define AS_BUILDER_H
41 
42 #include "as_config.h"
43 #include "as_symboltable.h"
44 #include "as_scriptengine.h"
45 #include "as_module.h"
46 #include "as_array.h"
47 #include "as_scriptcode.h"
48 #include "as_scriptnode.h"
49 #include "as_datatype.h"
50 #include "as_property.h"
51 
52 BEGIN_AS_NAMESPACE
53 
54 #ifdef AS_NO_COMPILER
55 // Forward declare the structure, as it is part of some function signatures used even without the compiler
56 struct sGlobalVariableDescription;
57 #endif
58 
59 #ifndef AS_NO_COMPILER
60 
61 struct sFunctionDescription
62 {
63 	asCScriptCode       *script;
64 	asCScriptNode       *node;
65 	asCString            name;
66 	asCObjectType       *objType;
67 	asCArray<asCString>  paramNames;
68 	int                  funcId;
69 	bool                 isExistingShared;
70 };
71 
72 struct sGlobalVariableDescription
73 {
74 	asCScriptCode     *script;
75 	asCScriptNode     *declaredAtNode;
76 	asCScriptNode     *initializationNode;
77 	asCString          name;
78 	asCGlobalProperty *property;
79 	asCDataType        datatype;
80 	asSNameSpace      *ns;
81 	int                index;
82 	bool               isCompiled;
83 	bool               isPureConstant;
84 	bool               isEnumValue;
85 	asQWORD            constantValue;
86 };
87 
88 struct sPropertyInitializer
89 {
sPropertyInitializersPropertyInitializer90 	sPropertyInitializer() : declNode(0), initNode(0), file(0) {}
sPropertyInitializersPropertyInitializer91 	sPropertyInitializer(const asCString &nm, asCScriptNode *decl, asCScriptNode *init, asCScriptCode *f) : name(nm), declNode(decl), initNode(init), file(f) {}
92 	sPropertyInitializer &operator=(const sPropertyInitializer &o) {name = o.name; declNode = o.declNode; initNode = o.initNode; file = o.file; return *this;}
93 
94 	asCString      name;
95 	asCScriptNode *declNode;
96 	asCScriptNode *initNode;
97 	asCScriptCode *file;
98 };
99 
100 struct sClassDeclaration
101 {
sClassDeclarationsClassDeclaration102 	sClassDeclaration() {script = 0; node = 0; validState = 0; typeInfo = 0; isExistingShared = false; isFinal = false;}
103 
104 	asCScriptCode *script;
105 	asCScriptNode *node;
106 	asCString      name;
107 	int            validState;
108 	asCTypeInfo   *typeInfo;
109 	bool           isExistingShared;
110 	bool           isFinal;
111 
112 	asCArray<sPropertyInitializer> propInits;
113 };
114 
115 struct sFuncDef
116 {
117 	asCScriptCode *script;
118 	asCScriptNode *node;
119 	asCString      name;
120 	int            idx;
121 };
122 
123 struct sMixinClass
124 {
125 	asCScriptCode *script;
126 	asCScriptNode *node;
127 	asCString      name;
128 	asSNameSpace  *ns;
129 };
130 
131 #endif // AS_NO_COMPILER
132 
133 class asCBuilder
134 {
135 public:
136 	asCBuilder(asCScriptEngine *engine, asCModule *module);
137 	~asCBuilder();
138 
139 	// These methods are used by the application interface
140 	int VerifyProperty(asCDataType *dt, const char *decl, asCString &outName, asCDataType &outType, asSNameSpace *ns);
141 	int ParseDataType(const char *datatype, asCDataType *result, asSNameSpace *implicitNamespace, bool isReturnType = false);
142 	int ParseTemplateDecl(const char *decl, asCString *name, asCArray<asCString> &subtypeNames);
143 	int ParseFunctionDeclaration(asCObjectType *type, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles = 0, bool *returnAutoHandle = 0, asSNameSpace *ns = 0, asCScriptNode **outListPattern = 0, asCObjectType **outParentClass = 0);
144 	int ParseVariableDeclaration(const char *decl, asSNameSpace *implicitNamespace, asCString &outName, asSNameSpace *&outNamespace, asCDataType &outDt);
145 	int CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code, asSNameSpace *ns, bool isProperty, bool isVirtualProperty);
146 	int CheckNameConflictMember(asCTypeInfo *type, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty, bool isVirtualProperty);
147 	int ValidateVirtualProperty(asCScriptFunction *func);
148 
149 #ifndef AS_NO_COMPILER
150 	int AddCode(const char *name, const char *code, int codeLength, int lineOffset, int sectionIdx, bool makeCopy);
151 	asCScriptCode *FindOrAddCode(const char *name, const char *code, size_t length);
152 	int Build();
153 
154 	int CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asCScriptFunction **outFunc);
155 	int CompileGlobalVar(const char *sectionName, const char *code, int lineOffset);
156 #endif
157 
158 protected:
159 	friend class asCModule;
160 	friend class asCParser;
161 	friend class asCScriptFunction;
162 	friend class asCScriptEngine;
163 
164 	void               Reset();
165 
166 	void               WriteInfo(const asCString &scriptname, const asCString &msg, int r, int c, bool preMessage);
167 	void               WriteInfo(const asCString &msg, asCScriptCode *file, asCScriptNode *node);
168 	void               WriteError(const asCString &scriptname, const asCString &msg, int r, int c);
169 	void               WriteError(const asCString &msg, asCScriptCode *file, asCScriptNode *node);
170 	void               WriteWarning(const asCString &scriptname, const asCString &msg, int r, int c);
171 	void               WriteWarning(const asCString &msg, asCScriptCode *file, asCScriptNode *node);
172 
173 	bool               DoesGlobalPropertyExist(const char *prop, asSNameSpace *ns, asCGlobalProperty **outProp = 0, sGlobalVariableDescription **outDesc = 0, bool *isAppProp = 0);
174 	asCGlobalProperty *GetGlobalProperty(const char *prop, asSNameSpace *ns, bool *isCompiled, bool *isPureConstant, asQWORD *constantValue, bool *isAppProp);
175 	int                ValidateDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func);
176 	asCString          GetCleanExpressionString(asCScriptNode *n, asCScriptCode *file);
177 
178 	asSNameSpace      *GetNameSpaceFromNode(asCScriptNode *node, asCScriptCode *script, asSNameSpace *implicitNs, asCScriptNode **next, asCObjectType **objType = 0);
179 	asSNameSpace      *GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script, asCTypeInfo **scopeType = 0, bool isRequired = true);
180 	asCString          GetScopeFromNode(asCScriptNode *n, asCScriptCode *script, asCScriptNode **next = 0);
181 
182 	asCTypeInfo       *GetType(const char *type, asSNameSpace *ns, asCObjectType *parentType);
183 	asCObjectType     *GetObjectType(const char *type, asSNameSpace *ns);
184 	asCFuncdefType    *GetFuncDef(const char *type, asSNameSpace *ns, asCObjectType *parentType);
185 	asCTypeInfo       *GetTypeFromTypesKnownByObject(const char *type, asCObjectType *currentType);
186 	asCDataType        CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, asSNameSpace *implicitNamespace, bool acceptHandleForScope = false, asCObjectType *currentType = 0, bool reportError = true, bool *isValid = 0);
187 	asCObjectType     *GetTemplateInstanceFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *templateType, asSNameSpace *implicitNamespace, asCObjectType *currentType, asCScriptNode **next = 0);
188 	asCDataType        ModifyDataTypeFromNode(const asCDataType &type, asCScriptNode *node, asCScriptCode *file, asETypeModifiers *inOutFlag, bool *autoHandle);
189 
190 	int numErrors;
191 	int numWarnings;
192 	bool silent;
193 
194 	asCScriptEngine *engine;
195 	asCModule       *module;
196 
197 #ifndef AS_NO_COMPILER
198 protected:
199 	friend class asCCompiler;
200 
201 	int                CheckForConflictsDueToDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func, asCObjectType *objType);
202 	int                GetNamespaceAndNameFromNode(asCScriptNode *n, asCScriptCode *script, asSNameSpace *implicitNs, asSNameSpace *&outNs, asCString &outName);
203 	int                RegisterMixinClass(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
204 	sMixinClass       *GetMixinClass(const char *name, asSNameSpace *ns);
205 	void               IncludePropertiesFromMixins(sClassDeclaration *decl);
206 	void               IncludeMethodsFromMixins(sClassDeclaration *decl);
207 	void               AddInterfaceToClass(sClassDeclaration *decl, asCScriptNode *errNode, asCObjectType *intf);
208 	void               AddInterfaceFromMixinToClass(sClassDeclaration *decl, asCScriptNode *errNode, sMixinClass *mixin);
209 
210 	int                RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false, asSNameSpace *ns = 0, bool isExistingShared = false, bool isMixin = false);
211 	int                RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, asSFunctionTraits funcTraits);
212 	int                RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false, asSNameSpace *ns = 0, bool isExistingShared = false);
213 	int                RegisterImportedFunction(int funcID, asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
214 	int                RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
215 	int                RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
216 	int                RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
217 	int                RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
218 	int                RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
219 	int                RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns, asCObjectType *parent);
220 	asCScriptFunction *RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns);
221 	void               CompleteFuncDef(sFuncDef *funcDef);
222 	void               CompileInterfaces();
223 	void               CompileClasses(asUINT originalNumTempl);
224 	void               DetermineTypeRelations();
225 	void               GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, asSFunctionTraits &traits, asSNameSpace *implicitNamespace);
226 	bool               DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex = 0);
227 	void               AddDefaultConstructor(asCObjectType *objType, asCScriptCode *file);
228 	asCObjectProperty *AddPropertyToClass(sClassDeclaration *c, const asCString &name, const asCDataType &type, bool isPrivate, bool isProtected, bool isInherited, asCScriptCode *file = 0, asCScriptNode *node = 0);
229 	int                CreateVirtualFunction(asCScriptFunction *func, int idx);
230 	void               ParseScripts();
231 	void               RegisterTypesFromScript(asCScriptNode *node, asCScriptCode *script, asSNameSpace *ns);
232 	void               RegisterNonTypesFromScript(asCScriptNode *node, asCScriptCode *script, asSNameSpace *ns);
233 	void               CompileFunctions();
234 	void               CompileGlobalVariables();
235 	int                GetEnumValueFromType(asCEnumType *type, const char *name, asCDataType &outDt, asDWORD &outValue);
236 	int                GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outValue, asSNameSpace *ns);
237 	bool               DoesTypeExist(const asCString &type);
238 	asCObjectProperty *GetObjectProperty(asCDataType &obj, const char *prop);
239 	asCScriptFunction *GetFunctionDescription(int funcId);
240 	void               GetFunctionDescriptions(const char *name, asCArray<int> &funcs, asSNameSpace *ns);
241 	void               GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray<int> &methods, bool objIsConst, const asCString &scope = "", asCScriptNode *errNode = 0, asCScriptCode *script = 0);
242 	void               EvaluateTemplateInstances(asUINT startIdx, bool keepSilent);
243 	void               CleanupEnumValues();
244 
245 	asCArray<asCScriptCode *>                  scripts;
246 	asCArray<sFunctionDescription *>           functions;
247 	asCSymbolTable<sGlobalVariableDescription> globVariables;
248 	asCArray<sClassDeclaration *>              classDeclarations;
249 	asCArray<sClassDeclaration *>              interfaceDeclarations;
250 	asCArray<sClassDeclaration *>              namedTypeDeclarations;
251 	asCArray<sFuncDef *>                       funcDefs;
252 	asCArray<sMixinClass *>                    mixinClasses;
253 
254 	// For use with the DoesTypeExists() method
255 	bool                    hasCachedKnownTypes;
256 	asCMap<asCString, bool> knownTypes;
257 #endif
258 };
259 
260 END_AS_NAMESPACE
261 
262 #endif
263