diff --git a/examples/factorial.mq b/examples/factorial.mq index 6b9f0d8..a3af654 100644 --- a/examples/factorial.mq +++ b/examples/factorial.mq @@ -7,8 +7,8 @@ using Musique programming language -- Calculate factorial using recursive approach factorial_recursive := (n | if (n <= 1) - (| 1) - (| n * (factorial_recursive (n-1))) + 1 + (n * (factorial_recursive (n-1))) ); -- Calculate factorial using iterative approach diff --git a/examples/fib.mq b/examples/fib.mq index 8e00df6..7874a17 100644 --- a/examples/fib.mq +++ b/examples/fib.mq @@ -1,5 +1,5 @@ fib := (n | if (n <= 1) - (| n) - (| fib (n-1) + fib (n-2)) + n + (fib (n-1) + fib (n-2)) ); diff --git a/examples/for-elise.mq b/examples/for-elise.mq index a68058b..12dce7d 100644 --- a/examples/for-elise.mq +++ b/examples/for-elise.mq @@ -30,7 +30,7 @@ section1 := ( n | call subsection1; if (n == 1) - (| sim (a 4 qn) (a 2 e 3 a 3) ) + ( sim (a 4 qn) (a 2 e 3 a 3) ) ( sim (a 4 en) (a 2 e 3 a 3) ; play (b 4 c 5 d 5) ) diff --git a/examples/random-rythm.mq b/examples/random-rythm.mq index f6c23ea..db7d9de 100644 --- a/examples/random-rythm.mq +++ b/examples/random-rythm.mq @@ -1,6 +1,6 @@ for (up 10) ( n | snd := c + (shuffle (up 12)).0; - oct := if (n % 2 == 0) (| 3 ) (| 4 ); + oct := if (n % 2 == 0) 3 4; say snd oct; play (snd oct qn); ); diff --git a/musique/interpreter/builtin_functions.cc b/musique/interpreter/builtin_functions.cc index 74f2af2..9329b8f 100644 --- a/musique/interpreter/builtin_functions.cc +++ b/musique/interpreter/builtin_functions.cc @@ -579,7 +579,7 @@ static Result builtin_scan(Interpreter &interpreter, std::vector a } /// Execute blocks depending on condition -static Result builtin_if(Interpreter &i, std::vector args) { +static Result builtin_if(Interpreter &i, std::span args) { static constexpr auto guard = Guard<2> { .name = "if", .possibilities = { @@ -592,12 +592,10 @@ static Result builtin_if(Interpreter &i, std::vector args) { return guard.yield_error(); } - if (args.front().truthy()) { - auto fun = Try(guard.match(args[1])); - return (*fun)(i, {}); + if (Try(i.eval((Ast)args.front())).truthy()) { + return i.eval((Ast)args[1]); } else if (args.size() == 3) { - auto fun = Try(guard.match(args[2])); - return (*fun)(i, {}); + return i.eval((Ast)args[2]); } return Value{}; diff --git a/musique/interpreter/interpreter.cc b/musique/interpreter/interpreter.cc index 5866b6b..6b68746 100644 --- a/musique/interpreter/interpreter.cc +++ b/musique/interpreter/interpreter.cc @@ -167,6 +167,10 @@ Result Interpreter::eval(Ast &&ast) auto call_location = ast.arguments.front().location; Value func = Try(eval(std::move(ast.arguments.front()))); + if (auto macro = std::get_if(&func.data)) { + return (*macro)(*this, std::span(ast.arguments).subspan(1)); + } + std::vector values; values.reserve(ast.arguments.size()); for (auto& a : std::span(ast.arguments).subspan(1)) { diff --git a/musique/value/value.hh b/musique/value/value.hh index ea0ad22..21d3fc3 100644 --- a/musique/value/value.hh +++ b/musique/value/value.hh @@ -19,6 +19,8 @@ struct Nil using Bool = bool; using Symbol = std::string; +using Macro = Result(*)(Interpreter &i, std::span); + /// Representation of any value in language struct Value { @@ -52,7 +54,8 @@ struct Value Intrinsic, Block, Array, - Chord + Chord, + Macro > data = Nil{}; Value(); @@ -71,6 +74,10 @@ struct Value { } + inline Value(Macro m) : data(m) + { + } + /// Returns truth judgment for current type, used primarly for if function bool truthy() const;