diff options
author | Marius Kintel <marius@kintel.net> | 2013-04-09 04:28:16 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2013-04-09 04:28:16 (GMT) |
commit | a37813a8999571f4b9235f33fdc7c22bcbe5fd17 (patch) | |
tree | 266d8c106100edab9f51b93cf229cf55cd083918 /src/func.cc | |
parent | b16c24fb2888d932ec035fff27cb29b4ffbc256b (diff) |
Refactored context handling into using separate Module contexts and Eval contexts. This allows for recursive module calls, and cascading children. I believe this fixes issue #116
Diffstat (limited to 'src/func.cc')
-rw-r--r-- | src/func.cc | 220 |
1 files changed, 109 insertions, 111 deletions
diff --git a/src/func.cc b/src/func.cc index 791e957..ecd1f87 100644 --- a/src/func.cc +++ b/src/func.cc @@ -26,7 +26,7 @@ #include "function.h" #include "expression.h" -#include "context.h" +#include "evalcontext.h" #include "builtin.h" #include <sstream> #include <ctime> @@ -61,7 +61,7 @@ AbstractFunction::~AbstractFunction() { } -Value AbstractFunction::evaluate(const Context*, const std::vector<std::string>&, const std::vector<Value>&) const +Value AbstractFunction::evaluate(const Context*, const EvalContext *evalctx) const { return Value(); } @@ -79,12 +79,10 @@ Function::~Function() delete expr; } -Value Function::evaluate(const Context *ctx, - const std::vector<std::string> &call_argnames, - const std::vector<Value> &call_argvalues) const +Value Function::evaluate(const Context *ctx, const EvalContext *evalctx) const { Context c(ctx); - c.args(argnames, argexpr, call_argnames, call_argvalues); + c.setVariables(argnames, argexpr, evalctx); return expr ? expr->evaluate(&c) : Value(); } @@ -105,9 +103,9 @@ BuiltinFunction::~BuiltinFunction() { } -Value BuiltinFunction::evaluate(const Context *ctx, const std::vector<std::string> &call_argnames, const std::vector<Value> &call_argvalues) const +Value BuiltinFunction::evaluate(const Context *ctx, const EvalContext *evalctx) const { - return eval_func(ctx, call_argnames, call_argvalues); + return eval_func(ctx, evalctx); } std::string BuiltinFunction::dump(const std::string &indent, const std::string &name) const @@ -127,37 +125,37 @@ static inline double rad2deg(double x) return x * 180.0 / M_PI; } -Value builtin_abs(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_abs(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(fabs(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(fabs(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_sign(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_sign(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value((args[0].toDouble()<0) ? -1.0 : ((args[0].toDouble()>0) ? 1.0 : 0.0)); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value((evalctx->eval_arguments[0].second.toDouble()<0) ? -1.0 : ((evalctx->eval_arguments[0].second.toDouble()>0) ? 1.0 : 0.0)); return Value(); } -Value builtin_rands(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_rands(const Context *, const EvalContext *evalctx) { bool deterministic = false; - if (args.size() == 3 && - args[0].type() == Value::NUMBER && - args[1].type() == Value::NUMBER && - args[2].type() == Value::NUMBER) + if (evalctx->eval_arguments.size() == 3 && + evalctx->eval_arguments[0].second.type() == Value::NUMBER && + evalctx->eval_arguments[1].second.type() == Value::NUMBER && + evalctx->eval_arguments[2].second.type() == Value::NUMBER) { deterministic = false; } - else if (args.size() == 4 && - args[0].type() == Value::NUMBER && - args[1].type() == Value::NUMBER && - args[2].type() == Value::NUMBER && - args[3].type() == Value::NUMBER) + else if (evalctx->eval_arguments.size() == 4 && + evalctx->eval_arguments[0].second.type() == Value::NUMBER && + evalctx->eval_arguments[1].second.type() == Value::NUMBER && + evalctx->eval_arguments[2].second.type() == Value::NUMBER && + evalctx->eval_arguments[3].second.type() == Value::NUMBER) { - deterministic_rng.seed( (unsigned int) args[3].toDouble() ); + deterministic_rng.seed( (unsigned int) evalctx->eval_arguments[3].second.toDouble() ); deterministic = true; } else @@ -165,11 +163,11 @@ Value builtin_rands(const Context *, const std::vector<std::string>&, const std: return Value(); } - double min = std::min( args[0].toDouble(), args[1].toDouble() ); - double max = std::max( args[0].toDouble(), args[1].toDouble() ); + double min = std::min( evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble() ); + double max = std::max( evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble() ); boost::uniform_real<> distributor( min, max ); Value::VectorType vec; - for (int i=0; i<args[2].toDouble(); i++) { + for (int i=0; i<evalctx->eval_arguments[2].second.toDouble(); i++) { if ( deterministic ) { vec.push_back( Value( distributor( deterministic_rng ) ) ); } else { @@ -181,169 +179,169 @@ Value builtin_rands(const Context *, const std::vector<std::string>&, const std: } -Value builtin_min(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_min(const Context *, const EvalContext *evalctx) { - if (args.size() >= 1 && args[0].type() == Value::NUMBER) { - double val = args[0].toDouble(); - for (size_t i = 1; i < args.size(); i++) - if (args[1].type() == Value::NUMBER) - val = fmin(val, args[i].toDouble()); + if (evalctx->eval_arguments.size() >= 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) { + double val = evalctx->eval_arguments[0].second.toDouble(); + for (size_t i = 1; i < evalctx->eval_arguments.size(); i++) + if (evalctx->eval_arguments[1].second.type() == Value::NUMBER) + val = fmin(val, evalctx->eval_arguments[i].second.toDouble()); return Value(val); } return Value(); } -Value builtin_max(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_max(const Context *, const EvalContext *evalctx) { - if (args.size() >= 1 && args[0].type() == Value::NUMBER) { - double val = args[0].toDouble(); - for (size_t i = 1; i < args.size(); i++) - if (args[1].type() == Value::NUMBER) - val = fmax(val, args[i].toDouble()); + if (evalctx->eval_arguments.size() >= 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) { + double val = evalctx->eval_arguments[0].second.toDouble(); + for (size_t i = 1; i < evalctx->eval_arguments.size(); i++) + if (evalctx->eval_arguments[1].second.type() == Value::NUMBER) + val = fmax(val, evalctx->eval_arguments[i].second.toDouble()); return Value(val); } return Value(); } -Value builtin_sin(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_sin(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(sin(deg2rad(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(sin(deg2rad(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_cos(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_cos(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(cos(deg2rad(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(cos(deg2rad(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_asin(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_asin(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(rad2deg(asin(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(rad2deg(asin(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_acos(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_acos(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(rad2deg(acos(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(rad2deg(acos(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_tan(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_tan(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(tan(deg2rad(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(tan(deg2rad(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_atan(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_atan(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(rad2deg(atan(args[0].toDouble()))); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(rad2deg(atan(evalctx->eval_arguments[0].second.toDouble()))); return Value(); } -Value builtin_atan2(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_atan2(const Context *, const EvalContext *evalctx) { - if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER) - return Value(rad2deg(atan2(args[0].toDouble(), args[1].toDouble()))); + if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER) + return Value(rad2deg(atan2(evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble()))); return Value(); } -Value builtin_pow(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_pow(const Context *, const EvalContext *evalctx) { - if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER) - return Value(pow(args[0].toDouble(), args[1].toDouble())); + if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER) + return Value(pow(evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble())); return Value(); } -Value builtin_round(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_round(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(round(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(round(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_ceil(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_ceil(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(ceil(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(ceil(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_floor(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_floor(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(floor(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(floor(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_sqrt(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_sqrt(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(sqrt(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(sqrt(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_exp(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_exp(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(exp(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(exp(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_length(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_length(const Context *, const EvalContext *evalctx) { - if (args.size() == 1) { - if (args[0].type() == Value::VECTOR) return Value(int(args[0].toVector().size())); - if (args[0].type() == Value::STRING) return Value(int(args[0].toString().size())); + if (evalctx->eval_arguments.size() == 1) { + if (evalctx->eval_arguments[0].second.type() == Value::VECTOR) return Value(int(evalctx->eval_arguments[0].second.toVector().size())); + if (evalctx->eval_arguments[0].second.type() == Value::STRING) return Value(int(evalctx->eval_arguments[0].second.toString().size())); } return Value(); } -Value builtin_log(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_log(const Context *, const EvalContext *evalctx) { - if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER) - return Value(log(args[1].toDouble()) / log(args[0].toDouble())); - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(log(args[0].toDouble()) / log(10.0)); + if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER) + return Value(log(evalctx->eval_arguments[1].second.toDouble()) / log(evalctx->eval_arguments[0].second.toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(log(evalctx->eval_arguments[0].second.toDouble()) / log(10.0)); return Value(); } -Value builtin_ln(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_ln(const Context *, const EvalContext *evalctx) { - if (args.size() == 1 && args[0].type() == Value::NUMBER) - return Value(log(args[0].toDouble())); + if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) + return Value(log(evalctx->eval_arguments[0].second.toDouble())); return Value(); } -Value builtin_str(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_str(const Context *, const EvalContext *evalctx) { std::stringstream stream; - for (size_t i = 0; i < args.size(); i++) { - stream << args[i].toString(); + for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) { + stream << evalctx->eval_arguments[i].second.toString(); } return Value(stream.str()); } -Value builtin_lookup(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_lookup(const Context *, const EvalContext *evalctx) { double p, low_p, low_v, high_p, high_v; - if (args.size() < 2 || // Needs two args - !args[0].getDouble(p) || // First must be a number - args[1].toVector().size() < 2 || // Second must be a vector of vectors - args[1].toVector()[0].toVector().size() < 2) + if (evalctx->eval_arguments.size() < 2 || // Needs two args + !evalctx->eval_arguments[0].second.getDouble(p) || // First must be a number + evalctx->eval_arguments[1].second.toVector().size() < 2 || // Second must be a vector of vectors + evalctx->eval_arguments[1].second.toVector()[0].toVector().size() < 2) return Value(); - if (!args[1].toVector()[0].getVec2(low_p, low_v) || !args[1].toVector()[0].getVec2(high_p, high_v)) + if (!evalctx->eval_arguments[1].second.toVector()[0].getVec2(low_p, low_v) || !evalctx->eval_arguments[1].second.toVector()[0].getVec2(high_p, high_v)) return Value(); - for (size_t i = 1; i < args[1].toVector().size(); i++) { + for (size_t i = 1; i < evalctx->eval_arguments[1].second.toVector().size(); i++) { double this_p, this_v; - if (args[1].toVector()[i].getVec2(this_p, this_v)) { + if (evalctx->eval_arguments[1].second.toVector()[i].getVec2(this_p, this_v)) { if (this_p <= p && (this_p > low_p || low_p > p)) { low_p = this_p; low_v = this_v; @@ -404,14 +402,14 @@ Value builtin_lookup(const Context *, const std::vector<std::string>&, const std - returns [[0,4],[1,5],[2,6],[8]] */ -Value builtin_search(const Context *, const std::vector<std::string>&, const std::vector<Value> &args) +Value builtin_search(const Context *, const EvalContext *evalctx) { - if (args.size() < 2) return Value(); + if (evalctx->eval_arguments.size() < 2) return Value(); - const Value &findThis = args[0]; - const Value &searchTable = args[1]; - unsigned int num_returns_per_match = (args.size() > 2) ? args[2].toDouble() : 1; - unsigned int index_col_num = (args.size() > 3) ? args[3].toDouble() : 0; + const Value &findThis = evalctx->eval_arguments[0].second; + const Value &searchTable = evalctx->eval_arguments[1].second; + unsigned int num_returns_per_match = (evalctx->eval_arguments.size() > 2) ? evalctx->eval_arguments[2].second.toDouble() : 1; + unsigned int index_col_num = (evalctx->eval_arguments.size() > 3) ? evalctx->eval_arguments[3].second.toDouble() : 0; Value::VectorType returnvec; @@ -499,7 +497,7 @@ Value builtin_search(const Context *, const std::vector<std::string>&, const std #define QUOTE(x__) # x__ #define QUOTED(x__) QUOTE(x__) -Value builtin_version(const Context *, const std::vector<std::string>&, const std::vector<Value> &) +Value builtin_version(const Context *, const EvalContext *evalctx) { Value::VectorType val; val.push_back(Value(double(OPENSCAD_YEAR))); @@ -510,9 +508,9 @@ Value builtin_version(const Context *, const std::vector<std::string>&, const st return Value(val); } -Value builtin_version_num(const Context *ctx, const std::vector<std::string>& call_argnames, const std::vector<Value> &args) +Value builtin_version_num(const Context *ctx, const EvalContext *evalctx) { - Value val = (args.size() == 0) ? builtin_version(ctx, call_argnames, args) : args[0]; + Value val = (evalctx->eval_arguments.size() == 0) ? builtin_version(ctx, evalctx) : evalctx->eval_arguments[0].second; double y, m, d = 0; if (!val.getVec3(y, m, d)) { if (!val.getVec2(y, m)) { |