windows-nt/Source/XPSP1/NT/multimedia/directx/dmusic/dmscript/engexec.h

77 lines
3.8 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
// Copyright (c) 1999 Microsoft Corporation. All rights reserved.
//
// Declaration of Executor.
//
// Runs the script, interpreting its routines and managing its variables.
#include "engcontrol.h"
#include "enginc.h"
#include "oleaut.h"
// While a script is executing, a stack is used to hold routines' local parameters and temporaries for evaluating expressions.
// This stack's memory grows as needed. Memory allocation/deallocation is minimized because many calls to a script will grow
// the stack to its needed size.
class CallStack
{
public:
CallStack() : m_iNext(0) {}
UINT Next() { return m_iNext; }
VARIANT &operator[](UINT i) { assert(i < m_iNext); return m_vec[i]; }
// used for routines' local variables
HRESULT Push(UINT i); // pushes i empty slots
void PopTo(UINT i); // pops everything down to and including i (following this, i will be Next)
private:
SmartRef::Vector<VARIANT> m_vec;
UINT m_iNext;
};
class Executor
{
public:
Executor(Script &script, IDispatch *pGlobalDispatch);
~Executor();
HRESULT SetGlobal(Variables::index ivar, const VARIANT &varValue, bool fPutRef, EXCEPINFO *pExcepInfo);
const VARIANT &GetGlobal(Variables::index ivar);
HRESULT ExecRoutine(Routines::index irtn, EXCEPINFO *pExcepInfo);
private:
enum DispatchOperationType { _get, _put, _putref, _call };
HRESULT EnsureInitialized();
HRESULT Error(EXCEPINFO *pExcepInfo, bool fOperation, const WCHAR *pwszBeginning, const char *paszMiddle = NULL, const WCHAR *pwszEnd = NULL); // A bit hokey, but it works. Creates an error using wide strings with an ascii string (typically an identifier) in between.
HRESULT ErrorIfImproperRef(const VARIANT &v, bool fRef, Strings::index istrIdentifier, EXCEPINFO *pExcepInfo);
HRESULT ErrorObjectRequired(Strings::index istrIdentifier, EXCEPINFO *pExcepInfo) { return Error(pExcepInfo, false, L"Object required: '", m_script.strings[istrIdentifier], L"'"); }
HRESULT ErrorIfInvokeProblem(DispatchOperationType e, HRESULT hr, Strings::index istrIdentifier, EXCEPINFO *pExcepInfo);
HRESULT ExecStatements(Statements::index istmt, EXCEPINFO *pExcepInfo, UINT iLocals);
HRESULT ExecAssignment(Assignments::index iasgn, EXCEPINFO *pExcepInfo, UINT iLocals);
HRESULT ExecIf(IfBlocks::index iif, EXCEPINFO *pExcepInfo, UINT iLocals);
HRESULT ExecCall(Calls::index icall, bool fPushResult, EXCEPINFO *pExcepInfo, UINT iLocals);
HRESULT ExecCallInternal(Calls::index icall, bool fPushResult, EXCEPINFO *pExcepInfo, UINT iLocals); // helper used by ExecCall
HRESULT EvalExpression(VARIANT &varResult, ExprBlocks::index iexpr, EXCEPINFO *pExcepInfo, UINT iLocals);
HRESULT EvalValue(Values::index ival, VARIANT &v, EXCEPINFO *pExcepInfo, UINT iLocals); // evaluates ival, saving the result in v
HRESULT EvalUnaryOp(Token t, VARIANT &v); // evaluates t on v -- saving the result back into v
HRESULT EvalBinaryOp(Token t, VARIANT &v1, VARIANT &v2, EXCEPINFO *pExcepInfo); // evaluates t on v1 and v2 -- saving the result back into v2
HRESULT GetVariableReference(Variables::index ivarref, VARIANT &v, EXCEPINFO *pExcepInfo, UINT iLocals) { return VariableReferenceInternal(_get, ivarref, v, pExcepInfo, iLocals); }
HRESULT SetVariableReference(bool fSet, Variables::index ivarref, const VARIANT &v, EXCEPINFO *pExcepInfo, UINT iLocals) { return VariableReferenceInternal(fSet ? _putref : _put, ivarref, const_cast<VARIANT&>(v), pExcepInfo, iLocals); }
HRESULT VariableReferenceInternal(DispatchOperationType e, Variables::index ivarref, VARIANT &v, EXCEPINFO *pExcepInfo, UINT iLocals);
HRESULT ChangeToDispatch(VARIANT &var, EXCEPINFO *pExcepInfo, ReferenceNames::index irnameIdentifier);
// Data
bool m_fInitialized;
Script &m_script;
SmartRef::ComPtr<IDispatch> m_scomGlobalDispatch;
VARIANT m_varEmpty; // varient we hold around so we can return a ref to a cleared variant
CallStack m_stack;
};