Overhaul of chord call semantics to support easy sequencing
This commit is contained in:
parent
98a88c3acc
commit
676f41909f
@ -2,12 +2,12 @@ var C = chord (c 3 1) (g 3 1) (c 4 1);
|
|||||||
var G = chord (g 3 1) (d 4 1) (g 4 1);
|
var G = chord (g 3 1) (d 4 1) (g 4 1);
|
||||||
|
|
||||||
oct 5;
|
oct 5;
|
||||||
par (C) e e f g;
|
par C e e f g;
|
||||||
par (G) g f e d;
|
par G g f e d;
|
||||||
par (C) c c d e;
|
par C c c d e;
|
||||||
par (G) (e 5 (3/8)) (d 5 (1/8)) (d 5 (1/2));
|
par G (e 5 (3/8) d 5 (1/8) d 5 (1/2));
|
||||||
par (C) e e f g;
|
par C e e f g;
|
||||||
par (G) g f e d;
|
par G g f e d;
|
||||||
par (C) c c d e;
|
par C c c d e;
|
||||||
par (G) (d 5 (1/2)) (c 5 (1/8));
|
par G (d 5 (1/2) c 5 (1/8));
|
||||||
par (C) (c 5 1);
|
par C (c 5 1);
|
||||||
|
@ -811,6 +811,9 @@ struct Chord
|
|||||||
static Chord from(std::string_view source);
|
static Chord from(std::string_view source);
|
||||||
|
|
||||||
bool operator==(Chord const&) const = default;
|
bool operator==(Chord const&) const = default;
|
||||||
|
|
||||||
|
/// Fill length and octave or sequence multiple chords
|
||||||
|
Result<Value> operator()(Interpreter &i, std::vector<Value> args);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, Chord const& chord);
|
std::ostream& operator<<(std::ostream& os, Chord const& chord);
|
||||||
|
62
src/value.cc
62
src/value.cc
@ -161,22 +161,7 @@ Result<Value> Value::operator()(Interpreter &i, std::vector<Value> args)
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::Intrinsic: return intr(i, std::move(args));
|
case Type::Intrinsic: return intr(i, std::move(args));
|
||||||
case Type::Block: return blk(i, std::move(args));
|
case Type::Block: return blk(i, std::move(args));
|
||||||
case Type::Music:
|
case Type::Music: return chord(i, std::move(args));
|
||||||
{
|
|
||||||
assert(args.size() == 1 || args.size() == 2, "music value can be called only in form note <octave> [<length>]"); // TODO(assert)
|
|
||||||
assert(args[0].type == Type::Number, "expected octave to be a number"); // TODO(assert)
|
|
||||||
|
|
||||||
assert(args.size() == 2 ? args[1].type == Type::Number : true, "expected length to be a number"); // TODO(assert)
|
|
||||||
for (auto ¬e : chord.notes) {
|
|
||||||
note.octave = args[0].n.as_int();
|
|
||||||
if (args.size() == 2) {
|
|
||||||
note.length = args[1].n;
|
|
||||||
}
|
|
||||||
note.simplify_inplace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return Error {
|
return Error {
|
||||||
.details = errors::Not_Callable { .type = type_name(type) },
|
.details = errors::Not_Callable { .type = type_name(type) },
|
||||||
@ -509,6 +494,51 @@ Chord Chord::from(std::string_view source)
|
|||||||
return chord;
|
return chord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<Value> Chord::operator()(Interpreter&, std::vector<Value> args)
|
||||||
|
{
|
||||||
|
std::vector<Value> array;
|
||||||
|
Chord *current = this;
|
||||||
|
enum State {
|
||||||
|
Waiting_For_Octave,
|
||||||
|
Waiting_For_Length,
|
||||||
|
Waiting_For_Note
|
||||||
|
} state = Waiting_For_Octave;
|
||||||
|
|
||||||
|
for (auto &arg : args) {
|
||||||
|
if (arg.type == Value::Type::Number) {
|
||||||
|
switch (state) {
|
||||||
|
break; case Waiting_For_Octave:
|
||||||
|
std::for_each(current->notes.begin(), current->notes.end(),
|
||||||
|
[&arg](Note &n) { n.octave = arg.n.floor().as_int(); });
|
||||||
|
state = Waiting_For_Length;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
break; case Waiting_For_Length:
|
||||||
|
std::for_each(current->notes.begin(), current->notes.end(),
|
||||||
|
[&arg](Note &n) { n.length = arg.n; });
|
||||||
|
state = Waiting_For_Note;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
unimplemented();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.type == Value::Type::Music) {
|
||||||
|
if (array.empty()) {
|
||||||
|
array.push_back(Value::from(std::move(*current)));
|
||||||
|
}
|
||||||
|
array.push_back(std::move(arg));
|
||||||
|
current = &array.back().chord;
|
||||||
|
state = Waiting_For_Octave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array.empty()
|
||||||
|
? Value::from(*current)
|
||||||
|
: Value::from(Array{array});
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, Chord const& chord)
|
std::ostream& operator<<(std::ostream& os, Chord const& chord)
|
||||||
{
|
{
|
||||||
if (chord.notes.size() == 1) {
|
if (chord.notes.size() == 1) {
|
||||||
|
Loading…
Reference in New Issue
Block a user