#include "daScript/misc/platform.h"
#include "daScript/simulate/simulate.h"
#include "daScript/simulate/runtime_string.h"
// this is here for the default implementation of to_out and to_err
#include
namespace das
{
bool SimNode::evalBool ( Context & context ) {
assert(0 && "we should never be here");
return cast::to(eval(context));
}
float SimNode::evalFloat ( Context & context ) {
assert(0 && "we should never be here");
return cast::to(eval(context));
}
int32_t SimNode::evalInt ( Context & context ) {
assert(0 && "we should never be here");
return cast::to(eval(context));
}
uint32_t SimNode::evalUInt ( Context & context ) {
assert(0 && "we should never be here");
return cast::to(eval(context));
}
int64_t SimNode::evalInt64 ( Context & context ) {
assert(0 && "we should never be here");
return cast::to(eval(context));
}
uint64_t SimNode::evalUInt64 ( Context & context ) {
assert(0 && "we should never be here");
return cast::to(eval(context));
}
char * SimNode::evalPtr ( Context & context ) {
assert(0 && "we should never be here");
return cast::to(eval(context));
}
vec4f SimNode_Swizzle::eval ( Context & context ) {
union {
vec4f res;
float val[4];
} R, S;
S.res = value->eval(context);
DAS_EXCEPTION_POINT;
R.val[0] = S.val[fields[0]];
R.val[1] = S.val[fields[1]];
R.val[2] = S.val[fields[2]];
R.val[3] = S.val[fields[3]];
return R.res;
}
// SimNode_MakeBlock
vec4f SimNode_MakeBlock::eval ( Context & context ) {
Block block;
block.stackOffset = context.stack.spi();
block.argumentsOffset = argStackTop ? (context.stack.spi() + argStackTop) : 0;
block.body = subexpr;
return cast::from(block);
}
// SimNode_Call
vec4f SimNode_Call::eval ( Context & context ) {
vec4f * argValues = (vec4f *)(alloca(nArguments * sizeof(vec4f)));
evalArgs(context, argValues);
DAS_EXCEPTION_POINT;
return context.call(fnIndex, argValues, nullptr, debug.line);
}
vec4f SimNode_CallAndCopyOrMove::eval ( Context & context ) {
vec4f * argValues = (vec4f *)(alloca(nArguments * sizeof(vec4f)));
evalArgs(context, argValues);
DAS_EXCEPTION_POINT;
auto cmres = context.stack.sp() + stackTop;
return context.call(fnIndex, argValues, cmres, debug.line);
}
// SimNode_Invoke
vec4f SimNode_Invoke::eval ( Context & context ) {
vec4f * argValues = (vec4f *)(alloca(nArguments * sizeof(vec4f)));
evalArgs(context, argValues);
DAS_EXCEPTION_POINT;
Block block = cast::to(argValues[0]);
if ( nArguments>1 ) {
return context.invoke(block, argValues + 1, nullptr);
} else {
return context.invoke(block, nullptr, nullptr);
}
}
vec4f SimNode_InvokeAndCopyOrMove::eval ( Context & context ) {
vec4f * argValues = (vec4f *)(alloca(nArguments * sizeof(vec4f)));
evalArgs(context, argValues);
DAS_EXCEPTION_POINT;
Block block = cast::to(argValues[0]);
auto cmres = context.stack.sp() + stackTop;
if ( nArguments>1 ) {
return context.invoke(block, argValues + 1, cmres);
} else {
return context.invoke(block, nullptr, cmres);
}
}
// SimNode_Debug
vec4f SimNode_Debug::eval ( Context & context ) {
vec4f res = subexpr->eval(context);
DAS_EXCEPTION_POINT;
stringstream ssw;
if ( message ) ssw evalPtr(context);
DAS_EXCEPTION_POINT;
auto pr = r->evalPtr(context);
DAS_EXCEPTION_POINT;
memcpy ( pl, pr, size );
memset ( pr, 0, size );
return v_zero();
}
// SimNode_Block
vec4f SimNode_Block::eval ( Context & context ) {
for ( uint32_t i = 0; i!=total && !context.stopFlags; ++i )
list[i]->eval(context);
return v_zero();
}
vec4f SimNode_ClosureBlock::eval ( Context & context ) {
for ( uint32_t i = 0; i!=total && !context.stopFlags; ++i )
list[i]->eval(context);
if ( context.stopFlags & EvalFlags::stopForReturn ) {
context.stopFlags &= ~EvalFlags::stopForReturn;
return context.abiResult();
} else {
if ( needResult ) context.throw_error("end of block without return");
return v_zero();
}
}
// SimNode_Let
vec4f SimNode_Let::eval ( Context & context ) {
for ( uint32_t i = 0; i!=total && !context.stopFlags; ++i )
list[i]->eval(context);
DAS_EXCEPTION_POINT;
return subexpr ? subexpr->eval(context) : v_zero();
}
// SimNode_IfThenElse
vec4f SimNode_IfThenElse::eval ( Context & context ) {
bool cmp = cond->evalBool(context);
DAS_EXCEPTION_POINT;
if ( cmp ) {
return if_true->eval(context);
} else if ( if_false ) {
return if_false->eval(context);
} else {
return v_zero();
}
}
// SimNode_While
vec4f SimNode_While::eval ( Context & context ) {
while ( cond->evalBool(context) && !context.stopFlags ) {
body->eval(context);
}
context.stopFlags &= ~EvalFlags::stopForBreak;
return v_zero();
}
// Return
vec4f SimNode_Return::eval ( Context & context ) {
if ( subexpr ) context.abiResult() = subexpr->eval(context);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnAndCopy::eval ( Context & context ) {
auto pr = subexpr->evalPtr(context);
DAS_EXCEPTION_POINT;
auto pl = context.abiCopyOrMoveResult();
memcpy ( pl, pr, size);
context.abiResult() = cast::from(pl);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnAndMove::eval ( Context & context ) {
auto pr = subexpr->evalPtr(context);
DAS_EXCEPTION_POINT;
auto pl = context.abiCopyOrMoveResult();
memcpy ( pl, pr, size);
memset ( pr, 0, size);
context.abiResult() = cast::from(pl);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnReference::eval ( Context & context ) {
char * ref = subexpr->evalPtr(context);
if ( context.stack.bottom()stackSize;
if ( context.stack.sp()copyOrMoveResult;
memcpy ( pl, pr, size);
context.abiResult() = cast::from(pl);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnAndMoveFromBlock::eval ( Context & context ) {
auto pr = subexpr->evalPtr(context);
DAS_EXCEPTION_POINT;
auto ba = (BlockArguments *) ( context.stack.sp() + argStackTop );
auto pl = ba->copyOrMoveResult;
memcpy ( pl, pr, size);
memset ( pr, 0, size);
context.abiResult() = cast::from(pl);
context.stopFlags |= EvalFlags::stopForReturn;
return v_zero();
}
vec4f SimNode_ReturnReferenceFromBlock::eval ( Context & context ) {
char * ref = subexpr->evalPtr(context);
if ( context.stack.bottom()copyOrMoveResult = (char *) cmres;
}
when(block.body);
if ( ba ) {
*ba = saveArguments;
}
stack.pop(watermark);
return result;
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
vec4f Context::callEx(int fnIndex, vec4f *args, void * cmres, int line, function && when) {
assert(fnIndex>=0 && fnIndexarguments = args;
pp->copyOrMoveResult = (char *)cmres;
#if DAS_ENABLE_STACK_WALK
pp->info = fn.debug;
pp->line = line;
#endif
// CALL
when(fn.code);
stopFlags &= ~(EvalFlags::stopForReturn | EvalFlags::stopForBreak);
// POP
stack.pop(watermark);
return result;
}
void Context::runInitScript ( void ) {
for ( int i=0; i!=totalVariables && !stopFlags; ++i ) {
auto & pv = globalVariables[i];
if ( pv.init ) {
pv.init->eval(*this);
} else {
memset ( cast::to(pv.value), 0, pv.size );
}
}
}
int Context::findFunction ( const char * name ) const {
for ( int fni = 0; fni != totalFunctions; ++fni ) {
if ( strcmp(functions[fni].name, name)==0 ) {
return fni;
}
}
return -1;
}
int Context::findVariable ( const char * name ) const {
for ( int vni = 0; vni != totalVariables; ++vni ) {
if ( strcmp(globalVariables[vni].name, name)==0 ) {
return vni;
}
}
return -1;
}
void Context::stackWalk() {
auto str = getStackWalk();
to_out(str.c_str());
}
string Context::getStackWalk( bool args ) {
stringstream ssw;
#if DAS_ENABLE_STACK_WALK
ssw