openclonk/src/script/C4AulScriptFunc.h

230 lines
6.1 KiB
C++

/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2016, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
#ifndef C4AULSCRIPTFUNC_H_
#define C4AULSCRIPTFUNC_H_
#include "script/C4Value.h"
#include "script/C4ValueMap.h"
// byte code chunk type
// some special script functions defined hard-coded to reduce the exec context
enum C4AulBCCType : int
{
AB_ARRAYA, // array or proplist access
AB_ARRAYA_SET,
AB_PROP, // proplist access with static key
AB_PROP_SET,
AB_ARRAY_SLICE, // array slicing
AB_ARRAY_SLICE_SET,
AB_DUP, // duplicate value from stack
AB_DUP_CONTEXT, // duplicate value from stack of parent function
AB_STACK_SET, // copy top of stack to stack
AB_POP_TO, // pop top of stack to stack
AB_LOCALN, // a property of this
AB_LOCALN_SET,
AB_GLOBALN, // a named global
AB_GLOBALN_SET,
AB_PAR, // Par statement
AB_THIS, // this()
AB_FUNC, // function
// prefix
AB_Inc, // ++
AB_Dec, // --
AB_BitNot, // ~
AB_Not, // !
AB_Neg, // -
// postfix
AB_Pow, // **
AB_Div, // /
AB_Mul, // *
AB_Mod, // %
AB_Sub, // -
AB_Sum, // +
AB_LeftShift, // <<
AB_RightShift, // >>
AB_LessThan, // <
AB_LessThanEqual, // <=
AB_GreaterThan, // >
AB_GreaterThanEqual, // >=
AB_Equal, // ==
AB_NotEqual, // !=
AB_BitAnd, // &
AB_BitXOr, // ^
AB_BitOr, // |
AB_CALL, // direct object call
AB_CALLFS, // failsafe direct call
AB_STACK, // push nulls / pop
AB_INT, // constant: int
AB_BOOL, // constant: bool
AB_STRING, // constant: string
AB_CPROPLIST, // constant: proplist
AB_CARRAY, // constant: array
AB_CFUNCTION, // constant: function
AB_NIL, // constant: nil
AB_NEW_ARRAY, // semi-constant: array
AB_NEW_PROPLIST, // create a new proplist
AB_JUMP, // jump
AB_JUMPAND, // jump if convertible to false, else pop the stack
AB_JUMPOR, // jump if convertible to true, else pop the stack
AB_JUMPNNIL, // jump if not nil, else pop the stack
AB_CONDN, // conditional jump (negated, pops stack)
AB_COND, // conditional jump (pops stack)
AB_FOREACH_NEXT, // foreach: next element
AB_RETURN, // return statement
AB_ERR, // parse error at this position
AB_DEBUG, // debug break
AB_EOFN, // end of function
};
// byte code chunk
class C4AulBCC
{
public:
C4AulBCCType bccType{AB_EOFN}; // chunk type
union
{
intptr_t X;
int32_t i;
C4String * s;
C4PropList * p;
C4ValueArray * a;
C4AulFunc * f;
} Par; // extra info
C4AulBCC() = default;
C4AulBCC(C4AulBCCType bccType, intptr_t X): bccType(bccType), Par{X}
{
IncRef();
}
C4AulBCC(const C4AulBCC & from): C4AulBCC(from.bccType, from.Par.X) { }
C4AulBCC & operator = (const C4AulBCC & from)
{
DecRef();
bccType = from.bccType;
Par = from.Par;
IncRef();
return *this;
}
C4AulBCC(C4AulBCC && from): bccType(from.bccType), Par(from.Par)
{
from.bccType = AB_EOFN;
}
C4AulBCC & operator = (C4AulBCC && from)
{
DecRef();
bccType = from.bccType;
Par = from.Par;
from.bccType = AB_EOFN;
return *this;
}
~C4AulBCC()
{
DecRef();
}
private:
void IncRef()
{
switch (bccType)
{
case AB_ERR:
if (Par.s)
case AB_STRING: case AB_CALL: case AB_CALLFS: case AB_LOCALN: case AB_LOCALN_SET: case AB_PROP: case AB_PROP_SET:
Par.s->IncRef();
break;
case AB_CARRAY:
Par.a->IncRef();
break;
default: break;
}
}
void DecRef()
{
switch (bccType)
{
case AB_ERR:
if (Par.s)
case AB_STRING: case AB_CALL: case AB_CALLFS: case AB_LOCALN: case AB_LOCALN_SET: case AB_PROP: case AB_PROP_SET:
Par.s->DecRef();
break;
case AB_CARRAY:
Par.a->DecRef();
break;
default: break;
}
}
};
// script function class
class C4AulScriptFunc : public C4AulFunc
{
public:
C4AulFunc *OwnerOverloaded; // overloaded owner function; if present
void SetOverloaded(C4AulFunc *);
C4AulScriptFunc *SFunc() override { return this; } // type check func...
protected:
void AddBCC(C4AulBCCType eType, intptr_t = 0, const char * SPos = nullptr); // add byte code chunk and advance
void RemoveLastBCC();
void ClearCode();
int GetCodePos() const { return Code.size(); }
C4AulBCC *GetCodeByPos(int iPos) { return &Code[iPos]; }
C4AulBCC *GetLastCode() { return Code.empty() ? nullptr : &Code.back(); }
void DumpByteCode();
std::vector<C4AulBCC> Code;
std::vector<const char *> PosForCode;
int ParCount;
C4V_Type ParType[C4AUL_MAX_Par]; // parameter types
public:
const char *Script; // script pos
C4ValueMapNames VarNamed; // list of named vars in this function
C4ValueMapNames ParNamed; // list of named pars in this function
void AddPar(const char * Idtf, C4V_Type type = C4V_Any)
{
assert(ParCount < C4AUL_MAX_Par);
assert(ParCount == ParNamed.iSize);
ParNamed.AddName(Idtf);
ParType[ParCount] = type;
++ParCount;
}
C4ScriptHost *pOrgScript; // the orginal script (!= Owner if included or appended)
C4AulScriptFunc(C4PropListStatic * Parent, C4ScriptHost *pOrgScript, const char *pName, const char *Script);
C4AulScriptFunc(C4PropListStatic * Parent, const C4AulScriptFunc &FromFunc); // copy script/code, etc from given func
~C4AulScriptFunc() override;
void ParseDirectExecFunc(C4AulScriptEngine *Engine, C4AulScriptContext* context = nullptr);
void ParseDirectExecStatement(C4AulScriptEngine *Engine, C4AulScriptContext* context = nullptr);
bool GetPublic() const override { return true; }
int GetParCount() const override { return ParCount; }
const C4V_Type *GetParType() const override { return ParType; }
C4V_Type GetRetType() const override { return C4V_Any; }
C4Value Exec(C4PropList * p, C4Value pPars[], bool fPassErrors=false) override; // execute func
int GetLineOfCode(C4AulBCC * bcc);
C4AulBCC * GetCode();
uint32_t tProfileTime; // internally set by profiler
friend class C4AulCompiler;
friend class C4AulParse;
friend class C4ScriptHost;
};
#endif /* C4AULSCRIPTFUNC_H_ */