stk-code_catmod/lib/angelscript/source/as_compiler.h

415 lines
20 KiB
C
Raw Normal View History

/*
AngelCode Scripting Library
2016-02-17 23:07:55 -05:00
Copyright (c) 2003-2015 Andreas Jonsson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
The original version of this library can be located at:
http://www.angelcode.com/angelscript/
Andreas Jonsson
andreas@angelcode.com
*/
//
// as_compiler.h
//
// The class that does the actual compilation of the functions
//
#ifndef AS_COMPILER_H
#define AS_COMPILER_H
#include "as_config.h"
#ifndef AS_NO_COMPILER
#include "as_builder.h"
#include "as_scriptfunction.h"
#include "as_variablescope.h"
#include "as_bytecode.h"
#include "as_array.h"
#include "as_datatype.h"
#include "as_typeinfo.h"
BEGIN_AS_NAMESPACE
struct asSExprContext;
struct asSDeferredParam
{
asSDeferredParam() {argNode = 0; origExpr = 0;}
asCScriptNode *argNode;
asCTypeInfo argType;
int argInOutFlags;
asSExprContext *origExpr;
};
// TODO: refactor: asSExprContext should have indicators to inform where the value is,
// i.e. if the reference to an object is pushed on the stack or not, etc
struct asSExprContext
{
asSExprContext(asCScriptEngine *engine) : bc(engine)
{
2016-02-17 23:07:55 -05:00
property_arg = 0;
Clear();
}
~asSExprContext()
{
if( property_arg )
asDELETE(property_arg, asSExprContext);
}
void Clear()
{
bc.ClearAll();
2016-02-17 23:07:55 -05:00
type.Set(asCDataType());
deferredParams.SetLength(0);
if( property_arg )
asDELETE(property_arg, asSExprContext);
2016-02-17 23:07:55 -05:00
property_arg = 0;
exprNode = 0;
origExpr = 0;
property_get = 0;
property_set = 0;
property_const = false;
property_handle = false;
property_ref = false;
methodName = "";
enumValue = "";
isVoidExpression = false;
isCleanArg = false;
}
2016-02-17 23:07:55 -05:00
bool IsClassMethod() const
{
if( type.dataType.GetObjectType() == 0 ) return false;
if( methodName == "" ) return false;
if( type.dataType.GetObjectType() == &type.dataType.GetObjectType()->engine->functionBehaviours ) return false;
return true;
}
2016-02-17 23:07:55 -05:00
bool IsGlobalFunc() const
{
if( type.dataType.GetObjectType() == 0 ) return false;
if( methodName == "" ) return false;
if( type.dataType.GetObjectType() != &type.dataType.GetObjectType()->engine->functionBehaviours ) return false;
return true;
}
2016-02-17 23:07:55 -05:00
void SetLambda(asCScriptNode *funcDecl)
{
asASSERT( funcDecl && funcDecl->nodeType == snFunction );
asASSERT( bc.GetLastInstr() == -1 );
Clear();
type.SetUndefinedFuncHandle(bc.GetEngine());
exprNode = funcDecl;
}
bool IsLambda() const
{
if( type.IsUndefinedFuncHandle() && exprNode && exprNode->nodeType == snFunction )
return true;
return false;
}
void SetVoidExpression()
{
Clear();
type.SetVoid();
isVoidExpression = true;
}
bool IsVoidExpression() const
{
if( isVoidExpression && type.IsVoid() && exprNode == 0 )
return true;
return false;
}
void Merge(asSExprContext *after)
{
type = after->type;
property_get = after->property_get;
property_set = after->property_set;
property_const = after->property_const;
property_handle = after->property_handle;
property_ref = after->property_ref;
property_arg = after->property_arg;
exprNode = after->exprNode;
methodName = after->methodName;
enumValue = after->enumValue;
isVoidExpression = after->isVoidExpression;
isCleanArg = after->isCleanArg;
after->property_arg = 0;
// Do not copy the origExpr member
}
asCByteCode bc;
asCTypeInfo type;
int property_get;
int property_set;
2016-02-17 23:07:55 -05:00
bool property_const; // If the object that is being accessed through property accessor is read-only
bool property_handle; // If the property accessor is called on an object stored in a handle
bool property_ref; // If the property accessor is called on a reference
bool isVoidExpression; // Set to true if the expression is an explicit 'void', e.g. used to ignore out parameters in func calls
bool isCleanArg; // Set to true if the expression has only been initialized with default constructor
asSExprContext *property_arg;
asCArray<asSDeferredParam> deferredParams;
asCScriptNode *exprNode;
asSExprContext *origExpr;
// TODO: cleanup: use ambiguousName and an enum to say if it is a method, global func, or enum value
asCString methodName;
asCString enumValue;
};
struct asSOverloadCandidate
{
asSOverloadCandidate() : funcId(0), cost(0) {}
asSOverloadCandidate(int _id, asUINT _cost ) : funcId(_id), cost(_cost) {}
int funcId;
asUINT cost;
};
2015-05-11 19:40:43 -04:00
struct asSNamedArgument
{
asCString name;
asSExprContext *ctx;
asUINT match;
};
enum EImplicitConv
{
asIC_IMPLICIT_CONV,
asIC_EXPLICIT_REF_CAST,
asIC_EXPLICIT_VAL_CAST
};
enum EConvCost
{
asCC_NO_CONV = 0,
asCC_CONST_CONV = 1,
asCC_PRIMITIVE_SIZE_CONV = 2,
asCC_SIGNED_CONV = 3,
asCC_INT_FLOAT_CONV = 4,
asCC_REF_CONV = 5,
asCC_OBJ_TO_PRIMITIVE_CONV = 6,
asCC_TO_OBJECT_CONV = 7,
asCC_VARIABLE_CONV = 8
};
class asCCompiler
{
public:
asCCompiler(asCScriptEngine *engine);
~asCCompiler();
int CompileFunction(asCBuilder *builder, asCScriptCode *script, asCArray<asCString> &parameterNames, asCScriptNode *func, asCScriptFunction *outFunc, sClassDeclaration *classDecl);
int CompileDefaultConstructor(asCBuilder *builder, asCScriptCode *script, asCScriptNode *node, asCScriptFunction *outFunc, sClassDeclaration *classDecl);
int CompileFactory(asCBuilder *builder, asCScriptCode *script, asCScriptFunction *outFunc);
int CompileGlobalVariable(asCBuilder *builder, asCScriptCode *script, asCScriptNode *expr, sGlobalVariableDescription *gvar, asCScriptFunction *outFunc);
protected:
friend class asCBuilder;
void Reset(asCBuilder *builder, asCScriptCode *script, asCScriptFunction *outFunc);
// Statements
void CompileStatementBlock(asCScriptNode *block, bool ownVariableScope, bool *hasReturn, asCByteCode *bc);
void CompileDeclaration(asCScriptNode *decl, asCByteCode *bc);
void CompileStatement(asCScriptNode *statement, bool *hasReturn, asCByteCode *bc);
void CompileIfStatement(asCScriptNode *node, bool *hasReturn, asCByteCode *bc);
void CompileSwitchStatement(asCScriptNode *node, bool *hasReturn, asCByteCode *bc);
void CompileCase(asCScriptNode *node, asCByteCode *bc);
void CompileForStatement(asCScriptNode *node, asCByteCode *bc);
void CompileWhileStatement(asCScriptNode *node, asCByteCode *bc);
void CompileDoWhileStatement(asCScriptNode *node, asCByteCode *bc);
void CompileBreakStatement(asCScriptNode *node, asCByteCode *bc);
void CompileContinueStatement(asCScriptNode *node, asCByteCode *bc);
void CompileReturnStatement(asCScriptNode *node, asCByteCode *bc);
void CompileExpressionStatement(asCScriptNode *node, asCByteCode *bc);
// Expressions
int CompileAssignment(asCScriptNode *expr, asSExprContext *out);
int CompileCondition(asCScriptNode *expr, asSExprContext *out);
int CompileExpression(asCScriptNode *expr, asSExprContext *out);
int CompilePostFixExpression(asCArray<asCScriptNode *> *postfix, asSExprContext *out);
int CompileExpressionTerm(asCScriptNode *node, asSExprContext *out);
int CompileExpressionPreOp(asCScriptNode *node, asSExprContext *out);
int CompileExpressionPostOp(asCScriptNode *node, asSExprContext *out);
int CompileExpressionValue(asCScriptNode *node, asSExprContext *out);
int CompileFunctionCall(asCScriptNode *node, asSExprContext *out, asCObjectType *objectType, bool objIsConst, const asCString &scope = "");
2016-02-17 23:07:55 -05:00
int CompileConstructCall(asCScriptNode *node, asSExprContext *out);
int CompileConversion(asCScriptNode *node, asSExprContext *out);
2015-05-11 19:40:43 -04:00
int CompileOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
void CompileOperatorOnHandles(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
void CompileMathOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
void CompileBitwiseOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
void CompileComparisonOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
void CompileBooleanOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
bool CompileOverloadedDualOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, bool isHandle = false, eTokenType opToken = ttUnrecognizedToken);
int CompileOverloadedDualOperator2(asCScriptNode *node, const char *methodName, asSExprContext *l, asSExprContext *r, asSExprContext *out, bool specificReturn = false, const asCDataType &returnType = asCDataType::CreatePrimitive(ttVoid, false));
void CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByteCode *bc, int isVarGlobOrMem);
2015-05-11 19:40:43 -04:00
int CompileInitListElement(asSListPatternNode *&patternNode, asCScriptNode *&valueNode, int bufferTypeId, short bufferVar, asUINT &bufferSize, asCByteCode &byteCode, int &elementsInSubList);
2015-05-11 19:40:43 -04:00
int CallDefaultConstructor(const asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCScriptNode *node, int isVarGlobOrMem = 0, bool derefDest = false);
int CallCopyConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asSExprContext *arg, asCScriptNode *node, bool isGlobalVar = false, bool derefDestination = false);
void CallDestructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc);
2015-05-11 19:40:43 -04:00
int CompileArgumentList(asCScriptNode *node, asCArray<asSExprContext *> &args, asCArray<asSNamedArgument> &namedArgs);
int CompileDefaultAndNamedArgs(asCScriptNode *node, asCArray<asSExprContext*> &args, int funcId, asCObjectType *type, asCArray<asSNamedArgument> *namedArgs = 0);
asUINT MatchFunctions(asCArray<int> &funcs, asCArray<asSExprContext*> &args, asCScriptNode *node, const char *name, asCArray<asSNamedArgument> *namedArgs = NULL, asCObjectType *objectType = NULL, bool isConstMethod = false, bool silent = false, bool allowObjectConstruct = true, const asCString &scope = "");
int CompileVariableAccess(const asCString &name, const asCString &scope, asSExprContext *ctx, asCScriptNode *errNode, bool isOptional = false, bool noFunction = false, bool noGlobal = false, asCObjectType *objType = 0);
void CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults);
2015-05-11 19:40:43 -04:00
bool CompileAutoType(asCDataType &autoType, asSExprContext &compiledCtx, asCScriptNode *exprNode, asCScriptNode *errNode);
bool CompileInitialization(asCScriptNode *node, asCByteCode *bc, asCDataType &type, asCScriptNode *errNode, int offset, asQWORD *constantValue, int isVarGlobOrMem, asSExprContext *preCompiled = 0);
void CompileInitAsCopy(asCDataType &type, int offset, asCByteCode *bc, asSExprContext *arg, asCScriptNode *node, bool derefDestination);
// Helper functions
2016-02-17 23:07:55 -05:00
void ConvertToPostFix(asCScriptNode *expr, asCArray<asCScriptNode *> &postfix);
void ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode *node);
int ProcessPropertySetAccessor(asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node);
2015-05-11 19:40:43 -04:00
int ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprContext *lctx, asSExprContext *rctx, eTokenType op, asCScriptNode *errNode);
int FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess = false);
int FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess = false);
void PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ctx, bool forceOnHeap = false);
void PrepareOperand(asSExprContext *ctx, asCScriptNode *node);
void PrepareForAssignment(asCDataType *lvalue, asSExprContext *rvalue, asCScriptNode *node, bool toTemporary, asSExprContext *lvalueExpr = 0);
int PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asCByteCode *bc, asCScriptNode *node);
bool IsVariableInitialized(asCTypeInfo *type, asCScriptNode *node);
void Dereference(asSExprContext *ctx, bool generateCode);
bool CompileRefCast(asSExprContext *ctx, const asCDataType &to, bool isExplicit, asCScriptNode *node, bool generateCode = true);
asUINT MatchArgument(asCArray<int> &funcs, asCArray<asSOverloadCandidate> &matches, const asSExprContext *argExpr, int paramNum, bool allowObjectConstruct = true);
2015-05-11 19:40:43 -04:00
int MatchArgument(asCScriptFunction *desc, const asSExprContext *argExpr, int paramNum, bool allowObjectConstruct = true);
void PerformFunctionCall(int funcId, asSExprContext *out, bool isConstructor = false, asCArray<asSExprContext*> *args = 0, asCObjectType *objTypeForConstruct = 0, bool useVariable = false, int varOffset = 0, int funcPtrVar = 0);
void MoveArgsToStack(int funcId, asCByteCode *bc, asCArray<asSExprContext *> &args, bool addOneToOffset);
void MakeFunctionCall(asSExprContext *ctx, int funcId, asCObjectType *objectType, asCArray<asSExprContext*> &args, asCScriptNode *node, bool useVariable = false, int stackOffset = 0, int funcPtrVar = 0);
void PrepareFunctionCall(int funcId, asCByteCode *bc, asCArray<asSExprContext *> &args);
void AfterFunctionCall(int funcId, asCArray<asSExprContext*> &args, asSExprContext *ctx, bool deferAll);
void ProcessDeferredParams(asSExprContext *ctx);
2015-05-11 19:40:43 -04:00
int PrepareArgument(asCDataType *paramType, asSExprContext *ctx, asCScriptNode *node, bool isFunction = false, int refType = 0, bool isMakingCopy = false);
void PrepareArgument2(asSExprContext *ctx, asSExprContext *arg, asCDataType *paramType, bool isFunction = false, int refType = 0, bool isMakingCopy = false);
bool IsLValue(asCTypeInfo &type);
2015-05-11 19:40:43 -04:00
int DoAssignment(asSExprContext *out, asSExprContext *lctx, asSExprContext *rctx, asCScriptNode *lexpr, asCScriptNode *rexpr, eTokenType op, asCScriptNode *opNode);
void MergeExprBytecode(asSExprContext *before, asSExprContext *after);
void MergeExprBytecodeAndType(asSExprContext *before, asSExprContext *after);
void FilterConst(asCArray<int> &funcs, bool removeConst = true);
void ConvertToVariable(asSExprContext *ctx);
void ConvertToVariableNotIn(asSExprContext *ctx, asSExprContext *exclude);
void ConvertToTempVariable(asSExprContext *ctx);
void ConvertToTempVariableNotIn(asSExprContext *ctx, asSExprContext *exclude);
void ConvertToReference(asSExprContext *ctx);
void PushVariableOnStack(asSExprContext *ctx, bool asReference);
void DestroyVariables(asCByteCode *bc);
asSNameSpace *DetermineNameSpace(const asCString &scope);
int SetupParametersAndReturnVariable(asCArray<asCString> &parameterNames, asCScriptNode *func);
void DetermineSingleFunc(asSExprContext *ctx, asCScriptNode *node);
// Returns the cost of the conversion (the sum of the EConvCost performed)
asUINT ImplicitConversion(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true);
asUINT ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true);
asUINT ImplicitConvObjectToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true);
asUINT ImplicitConvPrimitiveToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true);
asUINT ImplicitConvObjectToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true);
asUINT ImplicitConvObjectRef(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode);
asUINT ImplicitConvObjectValue(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode);
void ImplicitConversionConstant(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType);
2015-05-11 19:40:43 -04:00
void ImplicitConvObjectToBestMathType(asSExprContext *ctx, asCScriptNode *node);
2016-02-17 23:07:55 -05:00
asUINT ImplicitConvLambdaToFunc(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true);
void LineInstr(asCByteCode *bc, size_t pos);
asUINT ProcessStringConstant(asCString &str, asCScriptNode *node, bool processEscapeSequences = true);
void ProcessHeredocStringConstant(asCString &str, asCScriptNode *node);
int GetPrecedence(asCScriptNode *op);
void Error(const asCString &msg, asCScriptNode *node);
void Warning(const asCString &msg, asCScriptNode *node);
void Information(const asCString &msg, asCScriptNode *node);
2015-05-11 19:40:43 -04:00
void PrintMatchingFuncs(asCArray<int> &funcs, asCScriptNode *node, asCObjectType *inType = 0);
void AddVariableScope(bool isBreakScope = false, bool isContinueScope = false);
void RemoveVariableScope();
void FinalizeFunction();
asCByteCode byteCode;
bool hasCompileErrors;
int nextLabel;
2016-02-17 23:07:55 -05:00
int numLambdas;
2016-02-17 23:07:55 -05:00
asCVariableScope *variables;
asCBuilder *builder;
asCScriptEngine *engine;
asCScriptCode *script;
asCScriptFunction *outFunc;
2016-02-17 23:07:55 -05:00
bool m_isConstructor;
bool m_isConstructorCalled;
sClassDeclaration *m_classDecl;
sGlobalVariableDescription *m_globalVar;
asCArray<int> breakLabels;
asCArray<int> continueLabels;
int AllocateVariable(const asCDataType &type, bool isTemporary, bool forceOnHeap = false);
int AllocateVariableNotIn(const asCDataType &type, bool isTemporary, bool forceOnHeap, asSExprContext *ctx);
int GetVariableOffset(int varIndex);
int GetVariableSlot(int varOffset);
void DeallocateVariable(int pos);
void ReleaseTemporaryVariable(asCTypeInfo &t, asCByteCode *bc);
void ReleaseTemporaryVariable(int offset, asCByteCode *bc);
bool IsVariableOnHeap(int offset);
// This ordered array indicates the type of each variable
asCArray<asCDataType> variableAllocations;
// This ordered array indicates which variables are temporaries or not
asCArray<bool> variableIsTemporary;
// This unordered array gives the offsets of all temporary variables, whether currently allocated or not
asCArray<int> tempVariableOffsets;
// This ordered array indicated if the variable is on the heap or not
asCArray<bool> variableIsOnHeap;
// This unordered array gives the indexes of the currently unused variables
asCArray<int> freeVariables;
// This array holds the offsets of the currently allocated temporary variables
asCArray<int> tempVariables;
// This array holds the indices of variables that must not be used in an allocation
asCArray<int> reservedVariables;
bool isCompilingDefaultArg;
bool isProcessingDeferredParams;
2016-02-17 23:07:55 -05:00
int noCodeOutput;
};
END_AS_NAMESPACE
#endif // AS_NO_COMPILER
#endif