VDScriptInterp.cpp revision 9e0b97c99123f5eb89a851ce0182f7e438000c0d
/** @file
*
* VBox HDD container test utility - scripting engine, interpreter.
*/
/*
* Copyright (C) 2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#define LOGGROUP LOGGROUP_DEFAULT
#include "VDScriptAst.h"
#include "VDScriptStack.h"
#include "VDScriptInternal.h"
/**
* Interpreter variable.
*/
typedef struct VDSCRIPTINTERPVAR
{
/** String space core. */
/** Value. */
/** Pointer to an interpreter variable. */
typedef VDSCRIPTINTERPVAR *PVDSCRIPTINTERPVAR;
/**
* Block scope.
*/
typedef struct VDSCRIPTINTERPSCOPE
{
/** Pointer to the enclosing scope if available. */
struct VDSCRIPTINTERPSCOPE *pParent;
/** String space of declared variables in this scope. */
/** Pointer to a scope block. */
typedef VDSCRIPTINTERPSCOPE *PVDSCRIPTINTERPSCOPE;
/**
* Function call.
*/
typedef struct VDSCRIPTINTERPFNCALL
{
/** Pointer to the caller of this function. */
struct VDSCRIPTINTERPFNCALL *pCaller;
/** Root scope of this function. */
/** Current scope in this function. */
/** Pointer to a function call. */
typedef VDSCRIPTINTERPFNCALL *PVDSCRIPTINTERPFNCALL;
/**
* Interpreter context.
*/
typedef struct VDSCRIPTINTERPCTX
{
/** Pointer to the script context. */
/** Current function call entry. */
/** Stack of calculated values. */
/** Evaluation control stack. */
/** Pointer to an interpreter context. */
typedef VDSCRIPTINTERPCTX *PVDSCRIPTINTERPCTX;
/**
* Interpreter control type.
*/
typedef enum VDSCRIPTINTERPCTRLTYPE
{
/** Function call to evaluate now, all values are computed
* and are stored on the value stack.
*/
/** Cleanup the function call, deleting the scope and restoring the previous one. */
/** If statement to evaluate now, the guard is on the stack. */
VDSCRIPTINTERPCTRLTYPE_32BIT_HACK = 0x7fffffff
/** Pointer to a control type. */
typedef VDSCRIPTINTERPCTRLTYPE *PVDSCRIPINTERPCTRLTYPE;
/**
* Interpreter stack control entry.
*/
typedef struct VDSCRIPTINTERPCTRL
{
/** Flag whether this entry points to an AST node to evaluate. */
bool fEvalAst;
/** Flag dependent data. */
union
{
/** Pointer to the AST node to interprete. */
/** Interpreter control structure. */
struct
{
/** Type of control. */
/** Function call data. */
struct
{
/** Function to call. */
} FnCall;
} Ctrl;
};
/** Pointer to an exec stack control entry. */
typedef VDSCRIPTINTERPCTRL *PVDSCRIPTINTERPCTRL;
/**
* Record an error while interpreting.
*
* @returns VBox status code passed.
* @param pThis The interpreter context.
* @param rc The status code to record.
* @param RT_SRC_POS Position in the source code.
* @param pszFmt Format string.
*/
static int vdScriptInterpreterError(PVDSCRIPTINTERPCTX pThis, int rc, RT_SRC_POS_DECL, const char *pszFmt, ...)
{
return rc;
}
/**
* Pops the topmost value from the value stack.
*
* @returns nothing.
* @param pThis The interpreter context.
* @param pVal Where to store the value.
*/
{
}
/**
* Pushes a given value onto the value stack.
*/
{
if (!pValStack)
return vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory pushing a value on the value stack");
return VINF_SUCCESS;
}
/**
* Pushes a control entry without additional data onto the stack.
*
* @returns VBox status code.
* @param pThis The interpreter context.
* @param enmCtrlType The control entry type.
*/
{
if (pCtrl)
{
return VINF_SUCCESS;
}
return vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory adding an entry on the control stack");
}
/**
* Pushes an AST node onto the control stack.
*
* @returns VBox status code.
* @param pThis The interpreter context.
* @param enmCtrlType The control entry type.
*/
{
if (pCtrl)
{
return VINF_SUCCESS;
}
return vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory adding an entry on the control stack");
}
/**
* Evaluate a statement.
*
* @returns VBox status code.
* @param pThis The interpreter context.
* @param pStmt The statement to evaluate.
*/
{
int rc = VERR_NOT_IMPLEMENTED;
return rc;
}
/**
* Evaluate an expression.
*
* @returns VBox status code.
* @param pThis The interpreter context.
* @param pExpr The expression to evaluate.
*/
{
int rc = VERR_NOT_IMPLEMENTED;
return rc;
}
/**
* Evaluates the given AST node.
*
* @returns VBox statuse code.
* @param pThis The interpreter context.
* @param pAstNode The AST node to interpret.
*/
{
int rc = VERR_NOT_IMPLEMENTED;
{
{
break;
}
{
/*
* Identifiers are pushed only to the stack as an identifier for a variable.
* Look it up and push the value onto the value stack.
*/
PVDSCRIPTINTERPVAR pVar = (PVDSCRIPTINTERPVAR)RTStrSpaceGet(&pThis->pFnCallCurr->pScopeCurr->hStrSpaceVar, pIde->aszIde);
break;
}
{
break;
}
{
break;
}
/* These should never ever appear here. */
case VDSCRIPTASTCLASS_INVALID:
default:
}
return rc;
}
/**
* Destroy variable string space callback.
*/
{
return VINF_SUCCESS;
}
/**
* Evaluate a function call.
*
* @returns VBox status code.
* @param pThis The interpreter context.
* @param
*/
{
int rc = VINF_SUCCESS;
/* Add function call cleanup marker on the stack first. */
if (RT_SUCCESS(rc))
{
/* Create function call frame and set it up. */
if (pFnCall)
{
/* Add the variables, remember order. The first variable in the argument has the value at the top of the value stack. */
{
if (pVar)
{
}
else
{
rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory creating a variable");
break;
}
}
if (RT_SUCCESS(rc))
{
/*
* Push compount statement on the control stack and make the newly created
* call frame the current one.
*/
if (RT_SUCCESS(rc))
}
if (RT_FAILURE(rc))
{
}
}
else
rc = vdScriptInterpreterError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Out of memory creating a call frame");
}
return rc;
}
/**
* The interpreter evaluation core loop.
*
* @returns VBox status code.
* @param pThis The interpreter context.
*/
{
int rc = VINF_SUCCESS;
while (pCtrl)
{
{
}
else
{
{
{
break;
}
{
/* Delete function call entry. */
break;
}
default:
AssertMsgFailed(("Invalid evaluation control type on the stack: %d\n",
}
}
}
return rc;
}
{
int rc = VINF_SUCCESS;
if (pFn)
{
{
/* Push the arguments onto the stack. */
/** @todo: Check expected and given argument types. */
for (unsigned i = 0; i < cArgs; i++)
{
}
if (RT_SUCCESS(rc))
{
/* Push the AST onto the stack. */
/* Run the interpreter. */
}
}
else
rc = vdScriptInterpreterError(&InterpCtx, VERR_INVALID_PARAMETER, RT_SRC_POS, "Invalid number of parameters, expected %d got %d", pFn->cArgs, cArgs);
}
else
rc = vdScriptInterpreterError(&InterpCtx, VERR_NOT_FOUND, RT_SRC_POS, "Function with identifier \"%s\" not found", pszFn);
return rc;
}