-
Sam Yates authored
Adds a new KineticRewriter visitor that transforms (after semantic analysis) a parsed KINETIC procedure into an equivalent DERIVATIVE procedure. The visitor takes a ProcedureExpression and composes the equivalent procedure, available via the as_procedure() method on the visitor object. Move common functinality for 'local' variable insertion during transformation phase to new files astmanip.?pp. Add Expression method for directly setting scope. Use scope_ptr type alias widely. Implement correct clone() behaviour for DerivativeExpression Implement KineticRewriter transforming visitor class. Add equivalence test for KineticRewriter: the test incorporates a simple ad-hoc algebraic expression simplifier. Add unit test to Parser.parse_binop to exercise bug #94
4e229b01
functionexpander.hpp 2.70 KiB
#pragma once
#include <sstream>
#include "scope.hpp"
#include "visitor.hpp"
// storage for a list of expressions
using call_list_type = std::list<expression_ptr>;
// Make a local declaration and assignment for the given expression,
// and insert at the front and back respectively of the statement list.
// Return the new unique local identifier.
expression_ptr insert_unique_local_assignment(call_list_type& stmts, Expression* e);
// prototype for lowering function calls
call_list_type lower_function_calls(Expression* e);
///////////////////////////////////////////////////////////////////////////////
// visitor that takes function call sites and lowers them to inline assignments
//
// e.g. if called on the following statement
//
// a = 3 + foo(x, y)
//
// the calls_ member will be
//
// LOCAL ll0_
// ll0_ = foo(x,y)
//
// and the original statment is modified to be
//
// a = 3 + ll0_
//
// If the calls_ data is spliced directly before the original statement
// the function call will have been fully lowered
///////////////////////////////////////////////////////////////////////////////
class FunctionCallLowerer : public Visitor {
public:
FunctionCallLowerer(scope_ptr s)
: scope_(s)
{}
void visit(CallExpression *e) override;
void visit(Expression *e) override;
void visit(UnaryExpression *e) override;
void visit(BinaryExpression *e) override;
void visit(NumberExpression *e) override {};
void visit(IdentifierExpression *e) override {};
call_list_type& calls() {
return calls_;
}
call_list_type move_calls() {
return std::move(calls_);
}
~FunctionCallLowerer() {}
private:
template< typename F>
void expand_call(CallExpression* func, F replacer) {
auto id = insert_unique_local_assignment(calls_, func);
// replace the function call in the original expression with the local
// variable which holds the pre-computed value
replacer(std::move(id));
}
call_list_type calls_;
scope_ptr scope_;
};
///////////////////////////////////////////////////////////////////////////////
// visitor that takes function arguments that are not literals of identifiers
// and lowers them to inline assignments
//
// e.g. if called on the following statement
//
// a = foo(2+x, y)
//
// the calls_ member will be
//
// LOCAL ll0_
// ll0_ = 2+x
//
// and the original statment is modified to be
//
// a = foo(ll0_, y)
//
// If the calls_ data is spliced directly before the original statement
// the function arguments will have been fully lowered
///////////////////////////////////////////////////////////////////////////////
call_list_type lower_function_arguments(std::vector<expression_ptr>& args);