2021-08-19 13:28:15 +02:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "FN_multi_function_procedure_builder.hh"
|
|
|
|
|
|
|
|
namespace blender::fn {
|
|
|
|
|
|
|
|
void MFInstructionCursor::insert(MFProcedure &procedure, MFInstruction *new_instruction)
|
|
|
|
{
|
|
|
|
if (instruction_ == nullptr) {
|
|
|
|
if (is_entry_) {
|
|
|
|
procedure.set_entry(*new_instruction);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* The cursors points at nothing, nothing to do. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
switch (instruction_->type()) {
|
|
|
|
case MFInstructionType::Call: {
|
|
|
|
static_cast<MFCallInstruction *>(instruction_)->set_next(new_instruction);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MFInstructionType::Branch: {
|
|
|
|
MFBranchInstruction &branch_instruction = *static_cast<MFBranchInstruction *>(
|
|
|
|
instruction_);
|
|
|
|
if (branch_output_) {
|
|
|
|
branch_instruction.set_branch_true(new_instruction);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
branch_instruction.set_branch_false(new_instruction);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MFInstructionType::Destruct: {
|
|
|
|
static_cast<MFDestructInstruction *>(instruction_)->set_next(new_instruction);
|
|
|
|
break;
|
|
|
|
}
|
2021-08-19 14:06:43 +02:00
|
|
|
case MFInstructionType::Dummy: {
|
|
|
|
static_cast<MFDummyInstruction *>(instruction_)->set_next(new_instruction);
|
|
|
|
break;
|
|
|
|
}
|
2021-08-22 20:16:27 +02:00
|
|
|
case MFInstructionType::Return: {
|
|
|
|
/* It shouldn't be possible to build a cursor that points to a return instruction. */
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
break;
|
|
|
|
}
|
2021-08-19 13:28:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-19 13:46:19 +02:00
|
|
|
void MFProcedureBuilder::add_destruct(MFVariable &variable)
|
2021-08-19 13:28:15 +02:00
|
|
|
{
|
|
|
|
MFDestructInstruction &instruction = procedure_->new_destruct_instruction();
|
|
|
|
instruction.set_variable(&variable);
|
2021-08-19 15:33:35 +02:00
|
|
|
this->link_to_cursors(&instruction);
|
2021-08-19 13:28:15 +02:00
|
|
|
cursors_ = {MFInstructionCursor{instruction}};
|
|
|
|
}
|
|
|
|
|
2021-08-19 13:46:19 +02:00
|
|
|
void MFProcedureBuilder::add_destruct(Span<MFVariable *> variables)
|
2021-08-19 13:28:15 +02:00
|
|
|
{
|
|
|
|
for (MFVariable *variable : variables) {
|
2021-08-19 13:46:19 +02:00
|
|
|
this->add_destruct(*variable);
|
2021-08-19 13:28:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-22 20:16:27 +02:00
|
|
|
MFReturnInstruction &MFProcedureBuilder::add_return()
|
|
|
|
{
|
|
|
|
MFReturnInstruction &instruction = procedure_->new_return_instruction();
|
|
|
|
this->link_to_cursors(&instruction);
|
|
|
|
cursors_ = {};
|
|
|
|
return instruction;
|
|
|
|
}
|
|
|
|
|
2021-08-20 14:29:01 +02:00
|
|
|
MFCallInstruction &MFProcedureBuilder::add_call_with_no_variables(const MultiFunction &fn)
|
2021-08-19 13:28:15 +02:00
|
|
|
{
|
|
|
|
MFCallInstruction &instruction = procedure_->new_call_instruction(fn);
|
2021-08-19 15:33:35 +02:00
|
|
|
this->link_to_cursors(&instruction);
|
2021-08-19 13:28:15 +02:00
|
|
|
cursors_ = {MFInstructionCursor{instruction}};
|
|
|
|
return instruction;
|
|
|
|
}
|
|
|
|
|
2021-08-20 14:29:01 +02:00
|
|
|
MFCallInstruction &MFProcedureBuilder::add_call_with_all_variables(
|
|
|
|
const MultiFunction &fn, Span<MFVariable *> param_variables)
|
2021-08-19 13:28:15 +02:00
|
|
|
{
|
2021-08-20 14:29:01 +02:00
|
|
|
MFCallInstruction &instruction = this->add_call_with_no_variables(fn);
|
|
|
|
instruction.set_params(param_variables);
|
2021-08-19 13:28:15 +02:00
|
|
|
return instruction;
|
|
|
|
}
|
|
|
|
|
2021-08-20 14:29:01 +02:00
|
|
|
Vector<MFVariable *> MFProcedureBuilder::add_call(const MultiFunction &fn,
|
|
|
|
Span<MFVariable *> input_and_mutable_variables)
|
2021-08-19 13:28:15 +02:00
|
|
|
{
|
|
|
|
Vector<MFVariable *> output_variables;
|
2021-08-20 14:29:01 +02:00
|
|
|
MFCallInstruction &instruction = this->add_call_with_no_variables(fn);
|
2021-08-19 13:28:15 +02:00
|
|
|
for (const int param_index : fn.param_indices()) {
|
|
|
|
const MFParamType param_type = fn.param_type(param_index);
|
|
|
|
switch (param_type.interface_type()) {
|
|
|
|
case MFParamType::Input:
|
|
|
|
case MFParamType::Mutable: {
|
|
|
|
MFVariable *variable = input_and_mutable_variables.first();
|
|
|
|
instruction.set_param_variable(param_index, variable);
|
|
|
|
input_and_mutable_variables = input_and_mutable_variables.drop_front(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MFParamType::Output: {
|
|
|
|
MFVariable &variable = procedure_->new_variable(param_type.data_type());
|
|
|
|
instruction.set_param_variable(param_index, &variable);
|
|
|
|
output_variables.append(&variable);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* All passed in variables should have been dropped in the loop above. */
|
|
|
|
BLI_assert(input_and_mutable_variables.is_empty());
|
|
|
|
return output_variables;
|
|
|
|
}
|
|
|
|
|
2021-08-19 13:46:19 +02:00
|
|
|
MFProcedureBuilder::Branch MFProcedureBuilder::add_branch(MFVariable &condition)
|
2021-08-19 13:28:15 +02:00
|
|
|
{
|
|
|
|
MFBranchInstruction &instruction = procedure_->new_branch_instruction();
|
|
|
|
instruction.set_condition(&condition);
|
2021-08-19 15:33:35 +02:00
|
|
|
this->link_to_cursors(&instruction);
|
|
|
|
/* Clear cursors because this builder ends here. */
|
|
|
|
cursors_.clear();
|
2021-08-19 13:28:15 +02:00
|
|
|
|
2021-08-19 13:44:15 +02:00
|
|
|
Branch branch{*procedure_, *procedure_};
|
2021-08-19 13:28:15 +02:00
|
|
|
branch.branch_true.set_cursor(MFInstructionCursor{instruction, true});
|
|
|
|
branch.branch_false.set_cursor(MFInstructionCursor{instruction, false});
|
|
|
|
return branch;
|
|
|
|
}
|
|
|
|
|
2021-08-19 15:33:35 +02:00
|
|
|
MFProcedureBuilder::Loop MFProcedureBuilder::add_loop()
|
|
|
|
{
|
|
|
|
MFDummyInstruction &loop_begin = procedure_->new_dummy_instruction();
|
|
|
|
MFDummyInstruction &loop_end = procedure_->new_dummy_instruction();
|
|
|
|
this->link_to_cursors(&loop_begin);
|
|
|
|
cursors_ = {MFInstructionCursor{loop_begin}};
|
|
|
|
|
|
|
|
Loop loop;
|
|
|
|
loop.begin = &loop_begin;
|
|
|
|
loop.end = &loop_end;
|
|
|
|
|
|
|
|
return loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MFProcedureBuilder::add_loop_continue(Loop &loop)
|
|
|
|
{
|
|
|
|
this->link_to_cursors(loop.begin);
|
|
|
|
/* Clear cursors because this builder ends here. */
|
|
|
|
cursors_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MFProcedureBuilder::add_loop_break(Loop &loop)
|
|
|
|
{
|
|
|
|
this->link_to_cursors(loop.end);
|
|
|
|
/* Clear cursors because this builder ends here. */
|
|
|
|
cursors_.clear();
|
|
|
|
}
|
|
|
|
|
2021-08-19 13:28:15 +02:00
|
|
|
} // namespace blender::fn
|