This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/functions/intern/multi_function_procedure_builder.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

175 lines
5.6 KiB
C++
Raw Normal View History

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;
}
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
}
}
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