Implemented many missing test cases

This commit is contained in:
Robert Bendun 2022-05-31 13:43:14 +02:00
parent 23a230c9d3
commit 0a00080d2d
4 changed files with 138 additions and 17 deletions

View File

@ -112,7 +112,7 @@ static Result<Value> plus_minus_operator(Interpreter &interpreter, std::vector<V
template<typename Binary_Operation> 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>; 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)); return Value::from(Binary_Operation{}(lhs, rhs));
} }
if (may_be_vectorized(args)) {
return vectorize(binary_operator<Binary_Operation>, interpreter, args);
}
unreachable(); unreachable();
} }

View File

@ -20,20 +20,33 @@ void test_seconds_compute(
} }
suite context_suite = [] { suite context_suite = [] {
"Context duration resolution"_test = [] { "Context"_test = [] {
test_seconds_compute(60, Number(2,1), 8); should("resolve note duration length to seconds") = [] {
test_seconds_compute(60, Number(1,1), 4); test_seconds_compute(60, Number(2,1), 8);
test_seconds_compute(60, Number(1,2), 2); test_seconds_compute(60, Number(1,1), 4);
test_seconds_compute(60, Number(1,4), 1); 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(2,1), 5);
test_seconds_compute(96, Number(1,1), 2.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,2), 1.25);
test_seconds_compute(96, Number(1,4), 0.625); test_seconds_compute(96, Number(1,4), 0.625);
test_seconds_compute(120, Number(2,1), 4); test_seconds_compute(120, Number(2,1), 4);
test_seconds_compute(120, Number(1,1), 2); test_seconds_compute(120, Number(1,1), 2);
test_seconds_compute(120, Number(1,2), 1); test_seconds_compute(120, Number(1,2), 1);
test_seconds_compute(120, Number(1,4), 0.5); 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) }));
};
}; };
}; };

View File

@ -36,10 +36,10 @@ void expect_alternative(
suite intepreter_test = [] { suite intepreter_test = [] {
"Interpreter"_test = [] { "Interpreter"_test = [] {
should("evaluate literals") = [] { should("evaluate literals") = [] {
evaluates_to(Value::from(false), "false"); evaluates_to(Value::from(false), "false");
evaluates_to(Value::from(true), "true"); evaluates_to(Value::from(true), "true");
evaluates_to(Value::from(Number(10)), "10"); evaluates_to(Value::from(Number(10)), "10");
evaluates_to(Value{}, "nil"); evaluates_to(Value{}, "nil");
}; };
should("evaluate arithmetic") = [] { should("evaluate arithmetic") = [] {
@ -104,5 +104,76 @@ suite intepreter_test = [] {
should("allow assigning result of function calls to a variable") = [] { should("allow assigning result of function calls to a variable") = [] {
evaluates_to(Value::from(Number(42)), "var x = [i|i] 42; x"); 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");
};
}; };
}; };

View File

@ -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 = [] { suite value_test = [] {
"Value"_test = [] { "Value"_test = [] {
should("be properly created using Value::from") = [] { should("be properly created using Value::from") = [] {
@ -151,5 +169,20 @@ suite value_test = [] {
test_note_resolution("c##########", 70); test_note_resolution("c##########", 70);
test_note_resolution("cbbbbbbbbbb", 50); 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");
};
}; };
}; };