mirror of https://github.com/vitalif/openscad
Simple implementation of tail-recursion elimination.
parent
2e8d93d5be
commit
a820487032
|
@ -121,6 +121,13 @@ void Context::set_constant(const std::string &name, const Value &value)
|
|||
set_constant(name, ValuePtr(value));
|
||||
}
|
||||
|
||||
void Context::apply_variables(const Context &other)
|
||||
{
|
||||
for (ValueMap::const_iterator it = other.variables.begin();it != other.variables.end();it++) {
|
||||
set_variable((*it).first, (*it).second);
|
||||
}
|
||||
}
|
||||
|
||||
ValuePtr Context::lookup_variable(const std::string &name, bool silent) const
|
||||
{
|
||||
if (!this->ctx_stack) {
|
||||
|
|
|
@ -26,6 +26,7 @@ public:
|
|||
void set_constant(const std::string &name, const ValuePtr &value);
|
||||
void set_constant(const std::string &name, const Value &value);
|
||||
|
||||
void apply_variables(const Context &other);
|
||||
ValuePtr lookup_variable(const std::string &name, bool silent = false) const;
|
||||
bool has_local_variable(const std::string &name) const;
|
||||
|
||||
|
|
65
src/func.cc
65
src/func.cc
|
@ -84,6 +84,11 @@ std::string AbstractFunction::dump(const std::string &indent, const std::string
|
|||
return dump.str();
|
||||
}
|
||||
|
||||
Function::Function(const char *name, AssignmentList &definition_arguments, Expression *expr)
|
||||
: name(name), definition_arguments(definition_arguments), expr(expr)
|
||||
{
|
||||
}
|
||||
|
||||
Function::~Function()
|
||||
{
|
||||
delete expr;
|
||||
|
@ -113,6 +118,66 @@ std::string Function::dump(const std::string &indent, const std::string &name) c
|
|||
return dump.str();
|
||||
}
|
||||
|
||||
class FunctionTailRecursion : public Function
|
||||
{
|
||||
private:
|
||||
bool invert;
|
||||
ExpressionFunctionCall *call; // memory owned by the main expression
|
||||
Expression *endexpr; // memory owned by the main expression
|
||||
|
||||
public:
|
||||
FunctionTailRecursion(const char *name, AssignmentList &definition_arguments, Expression *expr, ExpressionFunctionCall *call, Expression *endexpr, bool invert);
|
||||
virtual ~FunctionTailRecursion();
|
||||
|
||||
virtual ValuePtr evaluate(const Context *ctx, const EvalContext *evalctx) const;
|
||||
};
|
||||
|
||||
FunctionTailRecursion::FunctionTailRecursion(const char *name, AssignmentList &definition_arguments, Expression *expr, ExpressionFunctionCall *call, Expression *endexpr, bool invert)
|
||||
: Function(name, definition_arguments, expr), invert(invert), call(call), endexpr(endexpr)
|
||||
{
|
||||
}
|
||||
|
||||
FunctionTailRecursion::~FunctionTailRecursion()
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr FunctionTailRecursion::evaluate(const Context *ctx, const EvalContext *evalctx) const
|
||||
{
|
||||
if (!expr) return ValuePtr::undefined;
|
||||
|
||||
Context c(ctx);
|
||||
c.setVariables(definition_arguments, evalctx);
|
||||
|
||||
EvalContext ec(&c, call->call_arguments);
|
||||
while (invert ^ expr->first->evaluate(&c)) {
|
||||
Context tmp;
|
||||
tmp.setVariables(definition_arguments, &ec);
|
||||
c.apply_variables(tmp);
|
||||
}
|
||||
|
||||
ValuePtr result = endexpr->evaluate(&c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Function * Function::create(const char *name, AssignmentList &definition_arguments, Expression *expr)
|
||||
{
|
||||
if (dynamic_cast<ExpressionTernary *>(expr)) {
|
||||
ExpressionFunctionCall *f1 = dynamic_cast<ExpressionFunctionCall *>(expr->second);
|
||||
ExpressionFunctionCall *f2 = dynamic_cast<ExpressionFunctionCall *>(expr->third);
|
||||
if (f1 && !f2) {
|
||||
if (name == f1->funcname) {
|
||||
return new FunctionTailRecursion(name, definition_arguments, expr, f1, expr->third, false);
|
||||
}
|
||||
} else if (f2 && !f1) {
|
||||
if (name == f2->funcname) {
|
||||
return new FunctionTailRecursion(name, definition_arguments, expr, f2, expr->second, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Function(name, definition_arguments, expr);
|
||||
}
|
||||
|
||||
BuiltinFunction::~BuiltinFunction()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -38,13 +38,16 @@ public:
|
|||
class Function : public AbstractFunction
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
AssignmentList definition_arguments;
|
||||
|
||||
Expression *expr;
|
||||
|
||||
Function() { }
|
||||
Function(const char *name, AssignmentList &definition_arguments, Expression *expr);
|
||||
virtual ~Function();
|
||||
|
||||
virtual ValuePtr evaluate(const Context *ctx, const EvalContext *evalctx) const;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
|
||||
static Function * create(const char *name, AssignmentList &definition_arguments, Expression *expr);
|
||||
};
|
||||
|
|
|
@ -166,9 +166,7 @@ statement:
|
|||
}
|
||||
| TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr
|
||||
{
|
||||
Function *func = new Function();
|
||||
func->definition_arguments = *$4;
|
||||
func->expr = $8;
|
||||
Function *func = Function::create($2, *$4, $8);
|
||||
scope_stack.top()->functions[$2] = func;
|
||||
free($2);
|
||||
delete $4;
|
||||
|
|
Loading…
Reference in New Issue