// (internal use only) turning argument expressions into values // given that application itself is proper list, randExps is always // either nil or pair const SExp *evalArgs(const SExp *randExps, Environment *env) { if (sexpNil == randExps->tag) return newNil(); const SExp *firstVal = evalDispatch(sexpCar(randExps), env); const SExp *restVals = evalArgs(sexpCdr(randExps), env); // if the evaluation for sub-exprs have failed, // stop this immediately if (firstVal == NULL || restVals == NULL) return NULL; const SExp *retVal = newPair(firstVal,restVals); // here we cannot recursively de-allocate the resource, // because eval-handlers might return an existing pointer as results // which means the value returned might be allocated somewhere else. pointerManagerRegister(retVal); return retVal; }
// apply arguments to a function object const SExp *funcObjApp(const FuncObj *rator, const SExp *rands, Environment *env) { assert(rator && "operator cannot be NULL"); switch (rator->tag) { case funcPrim: { FuncPrimHandler handler = rator->fields.primHdlr; const SExp *randVals = evalArgs(rands,env); return handler(randVals); } case funcCompound: { FuncCompound fc = rator->fields.compObj; const SExp *ps = fc.parameters; const SExp *bd = fc.body; Environment *fenv = fc.env; Environment *appEnv = calloc(1,sizeof(Environment)); envInit(appEnv); pointerManagerRegisterCustom(appEnv, (PFreeCallback)releaseTempEnv); envSetParent(appEnv, fenv); while (sexpNil != rands->tag && sexpNil != ps->tag ) { if (sexpSymbol != sexpCar( ps )->tag) return NULL; char *varName = sexpCar( ps )->fields.symbolName; const SExp *rand = sexpCar( rands ); const SExp *randVal = evalDispatch(rand, env); if (!randVal) return NULL; envInsert(appEnv, varName, randVal); rands = sexpCdr(rands); ps = sexpCdr(ps); } if (! (sexpNil == rands->tag && sexpNil == ps->tag) ) return NULL; // execute body under new environment return evSequence(bd, appEnv); } } assert(0 && "invalid function object"); }
void SeExprFuncNode::eval(SeVec3d& result) const { if (!_func) { result = 0.0; return; } // funcx is a catchall that does all its own processing if (_func->type() == SeExprFunc::FUNCX) { _func->funcx()->eval(this, result); return; } // handle the case of a scalar func applied to a vector bool applyScalarToVec = _isVec && !_func->isVec(); int niter = applyScalarToVec ? 3 : 1; // eval args and call the function SeVec3d* a = evalArgs(); for (int i = 0; i < niter; i++) { switch (_func->type()) { default: result[i] = result[1] = result[2] = 0; break; case SeExprFunc::FUNC0: result[i] = _func->func0()(); break; case SeExprFunc::FUNC1: result[i] = _func->func1()(a[0][i]); break; case SeExprFunc::FUNC2: result[i] = _func->func2()(a[0][i], a[1][i]); break; case SeExprFunc::FUNC3: result[i] = _func->func3()(a[0][i], a[1][i], a[2][i]); break; case SeExprFunc::FUNC4: result[i] = _func->func4()(a[0][i], a[1][i], a[2][i], a[3][i]); break; case SeExprFunc::FUNC5: result[i] = _func->func5()(a[0][i], a[1][i], a[2][i], a[3][i], a[4][i]); break; case SeExprFunc::FUNC6: result[i] = _func->func6()(a[0][i], a[1][i], a[2][i], a[3][i], a[4][i], a[5][i]); break; case SeExprFunc::FUNCN: { double* d = scalarArgs(); for (int n = 0; n < _nargs; n++) d[n] = a[n][i]; result[i] = _func->funcn()(_nargs, d); break; } case SeExprFunc::FUNC1V: result[i] = _func->func1v()(a[0]); break; case SeExprFunc::FUNC2V: result[i] = _func->func2v()(a[0], a[1]); break; case SeExprFunc::FUNCNV: result[i] = _func->funcnv()(_nargs, a); break; case SeExprFunc::FUNC1VV: result = _func->func1vv()(a[0]); break; case SeExprFunc::FUNC2VV: result = _func->func2vv()(a[0], a[1]); break; case SeExprFunc::FUNCNVV: result = _func->funcnvv()(_nargs, a); break; } } }