Implemented many missing test cases
This commit is contained in:
parent
23a230c9d3
commit
0a00080d2d
@ -112,7 +112,7 @@ static Result<Value> plus_minus_operator(Interpreter &interpreter, std::vector<V
|
||||
|
||||
|
||||
template<typename Binary_Operation>
|
||||
static Result<Value> binary_operator(Interpreter&, std::vector<Value> args)
|
||||
static Result<Value> binary_operator(Interpreter& interpreter, std::vector<Value> args)
|
||||
{
|
||||
using NN = Shape<Value::Type::Number, Value::Type::Number>;
|
||||
|
||||
@ -121,6 +121,10 @@ static Result<Value> binary_operator(Interpreter&, std::vector<Value> args)
|
||||
return Value::from(Binary_Operation{}(lhs, rhs));
|
||||
}
|
||||
|
||||
if (may_be_vectorized(args)) {
|
||||
return vectorize(binary_operator<Binary_Operation>, interpreter, args);
|
||||
}
|
||||
|
||||
unreachable();
|
||||
}
|
||||
|
||||
|
@ -20,20 +20,33 @@ void test_seconds_compute(
|
||||
}
|
||||
|
||||
suite context_suite = [] {
|
||||
"Context duration resolution"_test = [] {
|
||||
test_seconds_compute(60, Number(2,1), 8);
|
||||
test_seconds_compute(60, Number(1,1), 4);
|
||||
test_seconds_compute(60, Number(1,2), 2);
|
||||
test_seconds_compute(60, Number(1,4), 1);
|
||||
"Context"_test = [] {
|
||||
should("resolve note duration length to seconds") = [] {
|
||||
test_seconds_compute(60, Number(2,1), 8);
|
||||
test_seconds_compute(60, Number(1,1), 4);
|
||||
test_seconds_compute(60, Number(1,2), 2);
|
||||
test_seconds_compute(60, Number(1,4), 1);
|
||||
|
||||
test_seconds_compute(96, Number(2,1), 5);
|
||||
test_seconds_compute(96, Number(1,1), 2.5);
|
||||
test_seconds_compute(96, Number(1,2), 1.25);
|
||||
test_seconds_compute(96, Number(1,4), 0.625);
|
||||
test_seconds_compute(96, Number(2,1), 5);
|
||||
test_seconds_compute(96, Number(1,1), 2.5);
|
||||
test_seconds_compute(96, Number(1,2), 1.25);
|
||||
test_seconds_compute(96, Number(1,4), 0.625);
|
||||
|
||||
test_seconds_compute(120, Number(2,1), 4);
|
||||
test_seconds_compute(120, Number(1,1), 2);
|
||||
test_seconds_compute(120, Number(1,2), 1);
|
||||
test_seconds_compute(120, Number(1,4), 0.5);
|
||||
test_seconds_compute(120, Number(2,1), 4);
|
||||
test_seconds_compute(120, Number(1,1), 2);
|
||||
test_seconds_compute(120, Number(1,2), 1);
|
||||
test_seconds_compute(120, Number(1,4), 0.5);
|
||||
};
|
||||
|
||||
should("fill notes with default context values") = [] {
|
||||
Context ctx;
|
||||
ctx.length = Number(1, 42);
|
||||
ctx.octave = 8;
|
||||
|
||||
expect(eq(ctx.fill({ .base = 0 }), Note { .base = 0, .octave = 8, .length = Number(1, 42) }));
|
||||
expect(eq(ctx.fill({ .base = 0, .length = Number(4) }), Note { .base = 0, .octave = 8, .length = Number(4) }));
|
||||
expect(eq(ctx.fill({ .base = 0, .octave = 1 }), Note { .base = 0, .octave = 1, .length = Number(1, 42) }));
|
||||
expect(eq(ctx.fill({ .base = 0, .octave = 1, .length = Number(4) }), Note { .base = 0, .octave = 1, .length = Number(4) }));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -36,10 +36,10 @@ void expect_alternative(
|
||||
suite intepreter_test = [] {
|
||||
"Interpreter"_test = [] {
|
||||
should("evaluate literals") = [] {
|
||||
evaluates_to(Value::from(false), "false");
|
||||
evaluates_to(Value::from(true), "true");
|
||||
evaluates_to(Value::from(false), "false");
|
||||
evaluates_to(Value::from(true), "true");
|
||||
evaluates_to(Value::from(Number(10)), "10");
|
||||
evaluates_to(Value{}, "nil");
|
||||
evaluates_to(Value{}, "nil");
|
||||
};
|
||||
|
||||
should("evaluate arithmetic") = [] {
|
||||
@ -104,5 +104,76 @@ suite intepreter_test = [] {
|
||||
should("allow assigning result of function calls to a variable") = [] {
|
||||
evaluates_to(Value::from(Number(42)), "var x = [i|i] 42; x");
|
||||
};
|
||||
|
||||
should("support array programming") = [] {
|
||||
evaluates_to(Value::from(Array { .elements = {{
|
||||
Value::from(Number(2)),
|
||||
Value::from(Number(4)),
|
||||
Value::from(Number(6)),
|
||||
Value::from(Number(8))
|
||||
}}}), "2 * [1;2;3;4]");
|
||||
|
||||
evaluates_to(Value::from(Array { .elements = {{
|
||||
Value::from(Note { .base = 1 }),
|
||||
Value::from(Note { .base = 2 }),
|
||||
Value::from(Note { .base = 3 }),
|
||||
Value::from(Note { .base = 4 })
|
||||
}}}), "c + [1;2;3;4]");
|
||||
};
|
||||
|
||||
should("support number - music operations") = [] {
|
||||
evaluates_to(Value::from(Chord { .notes = { Note { .base = 0 }, Note { .base = 3 }, Note { .base = 6 } } }),
|
||||
"c#47 - 1");
|
||||
|
||||
evaluates_to(Value::from(Chord { .notes = { Note { .base = 2 }, Note { .base = 6 }, Note { .base = 9 } } }),
|
||||
"c47 + 2");
|
||||
|
||||
evaluates_to(Value::from(Chord { .notes = { Note { .base = 2 }, Note { .base = 6 }, Note { .base = 9 } } }),
|
||||
"2 + c47");
|
||||
};
|
||||
|
||||
should("support direct chord creation") = [] {
|
||||
evaluates_to(Value::from(Chord { .notes = { Note { .base = 0 }, Note { .base = 4 }, Note { .base = 7 } } }),
|
||||
"chord [c;e;g]");
|
||||
|
||||
evaluates_to(Value::from(Chord { .notes = { Note { .base = 0 }, Note { .base = 4 }, Note { .base = 7 } } }),
|
||||
"chord c e g");
|
||||
|
||||
evaluates_to(Value::from(Chord { .notes = { Note { .base = 0 }, Note { .base = 4 }, Note { .base = 7 } } }),
|
||||
"chord [c;e] g");
|
||||
};
|
||||
|
||||
should("support if builtin") = [] {
|
||||
evaluates_to(Value::from(Number(10)), "if true [10] [20]");
|
||||
evaluates_to(Value::from(Number(20)), "if false [10] [20]");
|
||||
evaluates_to(Value{}, "if false [10]");
|
||||
};
|
||||
|
||||
should("support eager array creation") = [] {
|
||||
evaluates_to(Value::from(Array { .elements = {{ Value::from(Number(10)), Value::from(Number(20)), Value::from(Number(30)) }}}),
|
||||
"flat 10 20 30");
|
||||
|
||||
evaluates_to(Value::from(Array { .elements = {{ Value::from(Number(10)), Value::from(Number(20)), Value::from(Number(30)) }}}),
|
||||
"flat [10;20] 30");
|
||||
|
||||
evaluates_to(Value::from(Array { .elements = {{ Value::from(Number(10)), Value::from(Number(20)), Value::from(Number(30)) }}}),
|
||||
"flat (flat 10 20) 30");
|
||||
};
|
||||
|
||||
should("support indexing") = [] {
|
||||
evaluates_to(Value::from(Number(10)), "[5;10;15].1");
|
||||
evaluates_to(Value::from(Number(10)), "(flat 5 10 15).1");
|
||||
};
|
||||
|
||||
should("support size") = [] {
|
||||
evaluates_to(Value::from(Number(3)), "len [5;10;15]");
|
||||
evaluates_to(Value::from(Number(3)), "len (flat 5 10 15)");
|
||||
};
|
||||
|
||||
should("support call like octave and len setting") = [] {
|
||||
evaluates_to(Value::from(Chord { .notes = {{ Note { .base = 0, .octave = 5, .length = Number(10) }}}}), "c 5 10");
|
||||
evaluates_to(Value::from(Chord { .notes = {{ Note { .base = 0, .octave = 5, .length = Number(10) }}}}), "(c 4 8) 5 10");
|
||||
evaluates_to(Value::from(Chord { .notes = {{ Note { .base = 0, .octave = 5 }}}}), "c 5");
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -67,6 +67,24 @@ static void test_note_resolution(
|
||||
}
|
||||
}
|
||||
|
||||
static void test_note_resolution(
|
||||
std::string_view name,
|
||||
std::string_view expected = {},
|
||||
reflection::source_location sl = reflection::source_location::current())
|
||||
{
|
||||
if (expected.empty())
|
||||
expected = name;
|
||||
|
||||
auto const maybe_note = Note::from(name);
|
||||
expect(maybe_note.has_value(), sl) << "Note::from didn't recognized " << name << " as a note";
|
||||
if (maybe_note) {
|
||||
auto note = *maybe_note;
|
||||
std::stringstream ss;
|
||||
ss << note;
|
||||
expect(eq(expected, ss.str())) << "Different string representation then expected";
|
||||
}
|
||||
}
|
||||
|
||||
suite value_test = [] {
|
||||
"Value"_test = [] {
|
||||
should("be properly created using Value::from") = [] {
|
||||
@ -151,5 +169,20 @@ suite value_test = [] {
|
||||
test_note_resolution("c##########", 70);
|
||||
test_note_resolution("cbbbbbbbbbb", 50);
|
||||
};
|
||||
|
||||
should("Preserve note when printing") = [] {
|
||||
test_note_resolution("c");
|
||||
test_note_resolution("c#");
|
||||
test_note_resolution("d");
|
||||
test_note_resolution("d#");
|
||||
test_note_resolution("e");
|
||||
test_note_resolution("f");
|
||||
test_note_resolution("f#");
|
||||
test_note_resolution("g");
|
||||
test_note_resolution("g#");
|
||||
test_note_resolution("a");
|
||||
test_note_resolution("a#");
|
||||
test_note_resolution("b");
|
||||
};
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user