From 99482d4c7c185beb1b72426896366ebf031ca939 Mon Sep 17 00:00:00 2001 From: Robert Bendun Date: Sun, 21 Aug 2022 17:29:37 +0200 Subject: [PATCH] Improved examples; multiplication = repeat operator --- examples/mozart.mq | 8 -------- examples/rick.mq | 10 ++++++++++ examples/sandattack.mq | 18 +++++++++++------- src/builtin_functions.cc | 14 ++++++-------- src/builtin_operators.cc | 34 +++++++++++++++++++++++++++++++++- 5 files changed, 60 insertions(+), 24 deletions(-) delete mode 100644 examples/mozart.mq create mode 100644 examples/rick.mq diff --git a/examples/mozart.mq b/examples/mozart.mq deleted file mode 100644 index 5ef621a..0000000 --- a/examples/mozart.mq +++ /dev/null @@ -1,8 +0,0 @@ -oct 2; -bpm 120; -par (f#) (c# 4 (1/2)); -par (g#) [d# 4 (1/2); (g# 3 (5/16)]; -par (f) (d# 4 (1/2)); -par (a#) [f 4 (1/2); a# 4 (1/16); f# 4 (1/16); f 4 (1/16); c# 4 (1/16)]; -par (f#) (c# 4 (1/2)); -par (g#) (d# 4 (1/2)); diff --git a/examples/rick.mq b/examples/rick.mq new file mode 100644 index 0000000..01d8fbb --- /dev/null +++ b/examples/rick.mq @@ -0,0 +1,10 @@ +bpm 120; len hn; oct 2; + +play [ + f# & c# 4; + par g# [d# 4; g# 3 (5/16)]; + f & d# 4; + par a# [oct 4; f; len sn; a#; f#; f; c#]; + f# & c# 4; + g# & d# 4; +]; diff --git a/examples/sandattack.mq b/examples/sandattack.mq index d8da6cd..3a05ee7 100644 --- a/examples/sandattack.mq +++ b/examples/sandattack.mq @@ -1,9 +1,13 @@ bpm 150; +len sn; + +play [ + oct 3; 4 * h; h 3 en; + oct 3; 6 * h; h 3 en; + oct 4; 7 * e; + oct 4; 6 * d; + oct 3; a; a; 5 * h; + oct 3; 7 * h; + oct 4; 2 * d; 4 * (h 3); h 3 en +]; -play (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/8)); -play (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/8)); -play (e 4 (1/16)) (e 4 (1/16)) (e 4 (1/16)) (e 4 (1/16)) (e 4 (1/16)) (e 4 (1/16)) (e 4 (1/8)); -play (d 4 (1/16)) (d 4 (1/16)) (d 4 (1/16)) (d 4 (1/16)) (d 4 (1/16)) (d 4 (1/16)) (d 4 (1/8)); -play (a 3 (1/16)) (a 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/8)); -play (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/8)); -play (d 4 (1/16)) (d 4 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/16)) (h 3 (1/8)); diff --git a/src/builtin_functions.cc b/src/builtin_functions.cc index ac0f4c9..b833dca 100644 --- a/src/builtin_functions.cc +++ b/src/builtin_functions.cc @@ -210,14 +210,6 @@ static auto builtin_program_change(Interpreter &i, std::vector args) -> R }; } -static Result action_play(Interpreter &i, Value v) -{ - if (v.type == Value::Type::Music) { - Try(i.play(std::move(v).chord)); - } - return {}; -} - /// Plays sequentialy notes walking into arrays and evaluation blocks /// /// @invariant default_action is play one @@ -241,6 +233,12 @@ static inline Result sequential_play(Interpreter &i, Value v) return {}; } +static Result action_play(Interpreter &i, Value v) +{ + Try(sequential_play(i, std::move(v))); + return {}; +} + template> static inline Result builtin_play(Interpreter &i, Container args) { diff --git a/src/builtin_operators.cc b/src/builtin_operators.cc index 8560ca7..06073f8 100644 --- a/src/builtin_operators.cc +++ b/src/builtin_operators.cc @@ -132,13 +132,45 @@ static Result comparison_operator(Interpreter&, std::vector args) return Value::from(Binary_Predicate{}(args.front(), args.back())); } +static Result multiplication_operator(Interpreter &i, std::vector args) +{ + using MN = Shape; + using NM = Shape; + + Number repeat; Chord what; bool typechecked = false; + + // TODO add automatic symetry resolution for cases like this + if (NM::typecheck(args)) { typechecked = true; std::tie(repeat, what) = NM::move_from(args); } + else if (MN::typecheck(args)) { typechecked = true; std::tie(what, repeat) = MN::move_from(args); } + + if (typechecked) { + return Value::from(Array { + .elements = std::vector( + repeat.floor().as_int(), Value::from(std::move(what)) + ) + }); + } + + // If binary_operator returns an error that lists all possible overloads + // of this operator we must inject overloads that we provided above + auto result = binary_operator, '*'>(i, std::move(args)); + if (!result.has_value()) { + auto &details = result.error().details; + if (auto p = std::get_if(&details)) { + p->possibilities.push_back("(repeat: number, what: music) -> array of music"); + p->possibilities.push_back("(what: music, repeat: number) -> array of music"); + } + } + return result; +} + using Operator_Entry = std::tuple; /// Operators definition table static constexpr auto Operators = std::array { Operator_Entry { "+", plus_minus_operator> }, Operator_Entry { "-", plus_minus_operator> }, - Operator_Entry { "*", binary_operator, '*'> }, + Operator_Entry { "*", multiplication_operator }, Operator_Entry { "/", binary_operator, '/'> }, Operator_Entry { "<", comparison_operator> },