2024-01-30 18:09:57 +00:00
|
|
|
#include "Compiler.hpp"
|
2024-01-31 09:23:03 +00:00
|
|
|
|
|
|
|
// signals
|
|
|
|
// -------
|
2024-01-30 18:09:57 +00:00
|
|
|
#include "Constant.hpp"
|
|
|
|
#include "Sine.hpp"
|
2024-01-31 09:23:03 +00:00
|
|
|
#include "Noise.hpp"
|
2024-02-01 03:15:07 +00:00
|
|
|
#include "Add.hpp"
|
|
|
|
#include "Sub.hpp"
|
|
|
|
#include "Mul.hpp"
|
|
|
|
#include "Div.hpp"
|
2024-01-30 18:09:57 +00:00
|
|
|
|
|
|
|
namespace muz
|
|
|
|
{
|
|
|
|
/*explicit*/ Compiler::Compiler(AudioConf const& conf)
|
|
|
|
: m_conf { conf }
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*virtual*/ Compiler::~Compiler()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::unique_ptr<Signal>>
|
|
|
|
Compiler::compile(std::shared_ptr<Node> node)
|
|
|
|
{
|
|
|
|
compile_node(node);
|
|
|
|
|
|
|
|
return std::move(m_outputs);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Compiler::compile_node(std::shared_ptr<Node> node)
|
|
|
|
{
|
|
|
|
switch (node->type())
|
|
|
|
{
|
|
|
|
case NODE_NUM: {
|
|
|
|
float value = std::stof(node->value());
|
|
|
|
push(std::make_unique<Constant>(m_conf, value));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_CMD: {
|
|
|
|
std::string name = node->child(0)->value();
|
|
|
|
|
|
|
|
for (size_t i=1; i<node->size(); i++)
|
|
|
|
{
|
|
|
|
compile_node(node->child(i));
|
|
|
|
}
|
|
|
|
|
2024-01-31 09:23:03 +00:00
|
|
|
execute_cmd(name, node);
|
2024-01-30 18:09:57 +00:00
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_DIR: {
|
|
|
|
std::string name = node->child(0)->value();
|
|
|
|
|
|
|
|
if (name == "@out")
|
|
|
|
{
|
|
|
|
compile_node(node->child(1));
|
|
|
|
m_outputs.push_back(std::move(pop()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-02-01 03:15:07 +00:00
|
|
|
format_error<compile_error>(node->line(),
|
|
|
|
"cannot compile unknown directive '"
|
|
|
|
+ name
|
|
|
|
+ "'.");
|
2024-01-30 18:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
for (size_t i=0; i<node->size(); i++)
|
|
|
|
{
|
|
|
|
compile_node(node->child(i));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-31 09:23:03 +00:00
|
|
|
void Compiler::execute_cmd(std::string const& name,
|
|
|
|
std::shared_ptr<Node> node)
|
|
|
|
{
|
|
|
|
if (name == "sine")
|
|
|
|
{
|
2024-02-01 19:43:41 +00:00
|
|
|
check_cmd_arity(*node, 1);
|
2024-01-31 09:23:03 +00:00
|
|
|
|
2024-02-01 19:43:41 +00:00
|
|
|
auto signal = std::make_unique<Sine>(m_conf, pop());
|
2024-01-31 09:23:03 +00:00
|
|
|
push(std::move(signal));
|
|
|
|
}
|
|
|
|
else if (name == "noise")
|
|
|
|
{
|
|
|
|
check_cmd_arity(*node, 0);
|
|
|
|
auto signal = std::make_unique<Noise>(m_conf);
|
|
|
|
push(std::move(signal));
|
|
|
|
}
|
2024-02-01 03:15:07 +00:00
|
|
|
else if (name == "add")
|
|
|
|
{
|
|
|
|
check_cmd_arity(*node, 2);
|
|
|
|
|
|
|
|
auto rhs = pop();
|
|
|
|
auto lhs = pop();
|
|
|
|
|
|
|
|
auto signal = std::make_unique<Add>(m_conf,
|
|
|
|
std::move(lhs),
|
|
|
|
std::move(rhs));
|
|
|
|
push(std::move(signal));
|
|
|
|
}
|
|
|
|
else if (name == "sub")
|
|
|
|
{
|
|
|
|
check_cmd_arity(*node, 2);
|
|
|
|
|
|
|
|
auto rhs = pop();
|
|
|
|
auto lhs = pop();
|
|
|
|
|
|
|
|
auto signal = std::make_unique<Sub>(m_conf,
|
|
|
|
std::move(lhs),
|
|
|
|
std::move(rhs));
|
|
|
|
push(std::move(signal));
|
|
|
|
}
|
|
|
|
else if (name == "mul")
|
|
|
|
{
|
|
|
|
check_cmd_arity(*node, 2);
|
|
|
|
|
|
|
|
auto rhs = pop();
|
|
|
|
auto lhs = pop();
|
|
|
|
|
|
|
|
auto signal = std::make_unique<Mul>(m_conf,
|
|
|
|
std::move(lhs),
|
|
|
|
std::move(rhs));
|
|
|
|
push(std::move(signal));
|
|
|
|
}
|
|
|
|
else if (name == "div")
|
|
|
|
{
|
|
|
|
check_cmd_arity(*node, 2);
|
|
|
|
|
|
|
|
auto rhs = pop();
|
|
|
|
auto lhs = pop();
|
|
|
|
|
|
|
|
auto signal = std::make_unique<Div>(m_conf,
|
|
|
|
std::move(lhs),
|
|
|
|
std::move(rhs));
|
|
|
|
push(std::move(signal));
|
|
|
|
}
|
2024-01-31 09:23:03 +00:00
|
|
|
else
|
|
|
|
{
|
2024-02-01 03:15:07 +00:00
|
|
|
format_error<compile_error>(node->line(),
|
|
|
|
"cannot compile unknown command '"
|
|
|
|
+ name
|
|
|
|
+ "'.");
|
2024-01-31 09:23:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-30 18:09:57 +00:00
|
|
|
void Compiler::push(std::unique_ptr<Signal> signal)
|
|
|
|
{
|
|
|
|
m_signals.push_back(std::move(signal));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Signal> Compiler::pop()
|
|
|
|
{
|
|
|
|
auto signal = std::move(m_signals.back());
|
|
|
|
m_signals.pop_back();
|
|
|
|
return signal;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Compiler::check_cmd_arity(Node const& node, int arity)
|
|
|
|
{
|
2024-01-30 19:27:30 +00:00
|
|
|
if (node.size() - 1 != static_cast<size_t>(arity))
|
2024-01-30 18:09:57 +00:00
|
|
|
{
|
2024-02-01 03:15:07 +00:00
|
|
|
format_error<compile_error>(node.line(),
|
|
|
|
"arity mismatch for '"
|
|
|
|
+ node.child(0)->value()
|
|
|
|
+ "': expected <"
|
|
|
|
+ std::to_string(arity)
|
|
|
|
+ ">, got <"
|
|
|
|
+ std::to_string(node.size() - 1)
|
|
|
|
+ ">.");
|
|
|
|
|
2024-01-30 18:09:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|