diff --git a/examples/church.mq b/examples/church.mq deleted file mode 100644 index dbec7cf..0000000 --- a/examples/church.mq +++ /dev/null @@ -1,34 +0,0 @@ --- PAIR definition -pair := [x y | [z | z x y]]; -car := [pair | pair [x y | x]]; -cdr := [pair | pair [x y | y]]; - -x := pair 100 200; -say (car x); -say (cdr x); - --- LIST definition -null := pair true true; -is_empty := car; -head := [list | car (cdr list)]; -tail := [list | cdr (cdr list)]; -cons := [head tail | pair false (pair head tail)]; - -for_each := [list iterator | - if (is_empty list) [ nil ] [ - iterator (head list); - for_each (tail list) iterator ]]; - -map := [list iterator | - if (is_empty list) [ null ] [| - cons (iterator (head list)) (map (tail list) iterator) ]]; - -foldr := [list init folder | - if (is_empty list) - [ init ] - [ foldr (tail list) (folder (head list) init) folder ]]; - -range := [start stop | if (start >= stop) [cons start null] [cons start (range (start+1) stop)]]; - -xs := range 1 5; -say (foldr xs 1 [x y|x*y]); diff --git a/examples/common-array-operations.mq b/examples/common-array-operations.mq index c425034..1e2ad91 100644 --- a/examples/common-array-operations.mq +++ b/examples/common-array-operations.mq @@ -1,4 +1,5 @@ -map := [fn array | var result = []; for array [v | result = result & [fn v] ]; result]; -drop := [n arr | arr.(range n (len arr))]; -take := [n arr | arr.(up n)]; -filter := [predicate arr | arr.(map predicate arr)]; +map := (fn array | result := (); for array (v | result = result & (| fn v) ); result); +drop := (n arr | arr.(range n (len arr))); +take := (n arr | arr.(up n)); +filter := (predicate arr | arr.(map predicate arr)); + diff --git a/examples/factorial.mq b/examples/factorial.mq index 0954d71..6b9f0d8 100644 --- a/examples/factorial.mq +++ b/examples/factorial.mq @@ -5,26 +5,26 @@ using Musique programming language ---------------------------------------------------------------------------- -- Calculate factorial using recursive approach -factorial_recursive := [n | +factorial_recursive := (n | if (n <= 1) - [1] - [n * (factorial_recursive (n-1))] -]; + (| 1) + (| n * (factorial_recursive (n-1))) +); -- Calculate factorial using iterative approach -factorial_iterative := [n | +factorial_iterative := (n | x := 1; - for (range 1 (n+1)) [i|x *= i]; + for (range 1 (n+1)) (i | x *= i); x -]; +); -- Calculate factorial using composition of functions -factorial := [n| fold (1 + up n) 1 '*]; +factorial := (n | fold (1 + up n) 1 '*); -- Gather all functions into array, and iterate over it -- This allows to reduce repeatition of this test case -for [factorial_recursive; factorial_iterative; factorial] [ factorial | - for (up 10) [ n | +for (factorial_recursive; factorial_iterative; factorial) ( factorial | + for (up 10) ( n | say (factorial (n)); - ]; -]; + ) +); diff --git a/examples/fib.mq b/examples/fib.mq index 102bd9a..8e00df6 100644 --- a/examples/fib.mq +++ b/examples/fib.mq @@ -1 +1,5 @@ -fib := [n | if (n <= 1) [ n ] [ fib (n-1) + fib (n-2) ] ]; +fib := (n | + if (n <= 1) + (| n) + (| fib (n-1) + fib (n-2)) +); diff --git a/examples/for-elise.mq b/examples/for-elise.mq index 4527a60..a68058b 100644 --- a/examples/for-elise.mq +++ b/examples/for-elise.mq @@ -4,12 +4,12 @@ WIP implemntation ---------------------------------------------- oct 5; bpm 72; len (1/16); -subsection1 := [ +subsection1 := ( sim (a 4 en) (a 2 e 3 a 3); - play [oct 4; c e a]; + play (oct 4; c e a); sim (b 4 en) (e 2 e 3 g# 3); - play [oct 4; e g# b]; + play (oct 4; e g# b); sim (c 5 en) (a 2 e 3 a 3); play (e 4 e 5 d# 5); @@ -21,22 +21,22 @@ subsection1 := [ sim (b 4 en) (e 2 e 3 g# 3); play (d 4 c 5 b 4); -]; +); -section1 := [ n | - play (e d#); +section1 := ( n | + play e d#; play (e d# e b 4 d c); call subsection1; if (n == 1) - [ sim (a 4 qn) (a 2 e 3 a 3); ] - [ sim (a 4 en) (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) - ] -]; + ) +); -section2 := [ n | +section2 := ( n | sim (e 5 den) (c 3 g 3 c 4); play (g 4 f e); @@ -55,10 +55,10 @@ section2 := [ n | call subsection1; if (n == 1) - [ sim (a 4 en) (a 2 e 3 a 3) + ( sim (a 4 en) (a 2 e 3 a 3) ; play (b 4 c 5 d 5) - ] -]; + ) +); section1 1; section1 2; diff --git a/examples/permutations.mq b/examples/permutations.mq index 2a33e45..8873cd1 100644 --- a/examples/permutations.mq +++ b/examples/permutations.mq @@ -1,11 +1,11 @@ -factorial := [n | if (n < 2) [1] [factorial (n-1) * n]]; +factorial := (n | fold (1 + up n) '*); -for_all_permutations := [array fun | - iter := [start stop x | if (start >= stop) [x] [iter (start+1) stop (fun x)]]; - iter 0 (factorial (len array)) array -]; -for_all_permutations (flat 1 2 3 4 5) [array| - say array; - permute array -]; +list_all_permutations := ( array | + for (up (factorial (len array))) (| + say array; + array = permute array; + ); +); + +list_all_permutations (1 + up 5); diff --git a/examples/random-rythm.mq b/examples/random-rythm.mq index b7eae41..f6c23ea 100644 --- a/examples/random-rythm.mq +++ b/examples/random-rythm.mq @@ -1,5 +1,6 @@ -for (up 10) [ n | +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/examples/rhythm-of-primes.mq b/examples/rhythm-of-primes.mq index 6f67af9..7a90dab 100644 --- a/examples/rhythm-of-primes.mq +++ b/examples/rhythm-of-primes.mq @@ -25,9 +25,9 @@ play c d c e (c & d) c d (c & e) -------------------------------------------------------------- -Length := 20; +Length := 40; -cmajor := [c;d;e;f;g]; +cmajor := (c;d;e;f;g); scale := reverse cmajor; primes := nprimes (len scale); indicies := up (len scale); @@ -35,4 +35,6 @@ indicies := up (len scale); oct 3; len (1/16); -for (2 + up Length) [ i | play (chord scale.(indicies.(i % primes == 0))); ]; +for (2 + up Length) ( i | + play (chord scale.(indicies.(i % primes == 0))); +); diff --git a/examples/rick.mq b/examples/rick.mq deleted file mode 100644 index 01d8fbb..0000000 --- a/examples/rick.mq +++ /dev/null @@ -1,10 +0,0 @@ -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 3a05ee7..5822446 100644 --- a/examples/sandattack.mq +++ b/examples/sandattack.mq @@ -1,7 +1,7 @@ bpm 150; len sn; -play [ +play ( oct 3; 4 * h; h 3 en; oct 3; 6 * h; h 3 en; oct 4; 7 * e; @@ -9,5 +9,5 @@ play [ oct 3; a; a; 5 * h; oct 3; 7 * h; oct 4; 2 * d; 4 * (h 3); h 3 en -]; +); diff --git a/examples/variables.mq b/examples/variables.mq deleted file mode 100644 index 8719f9a..0000000 --- a/examples/variables.mq +++ /dev/null @@ -1,2 +0,0 @@ -x := 10; -say (x + 1) diff --git a/musique/lexer/lexer.cc b/musique/lexer/lexer.cc index fa8ca08..442c4f4 100644 --- a/musique/lexer/lexer.cc +++ b/musique/lexer/lexer.cc @@ -88,10 +88,8 @@ auto Lexer::next_token() -> Result> } switch (peek()) { - case '(': consume(); return Token { Token::Type::Open_Paren, finish(), token_location }; - case ')': consume(); return Token { Token::Type::Close_Paren, finish(), token_location }; - case '[': consume(); return Token { Token::Type::Open_Block, finish(), token_location }; - case ']': consume(); return Token { Token::Type::Close_Block, finish(), token_location }; + case '(': consume(); return Token { Token::Type::Open_Block, finish(), token_location }; + case ')': consume(); return Token { Token::Type::Close_Block, finish(), token_location }; case ';': consume(); return Token { Token::Type::Expression_Separator, finish(), token_location }; case '|': @@ -258,12 +256,10 @@ std::ostream& operator<<(std::ostream& os, Token::Type type) switch (type) { case Token::Type::Chord: return os << "CHORD"; case Token::Type::Close_Block: return os << "CLOSE BLOCK"; - case Token::Type::Close_Paren: return os << "CLOSE PAREN"; case Token::Type::Expression_Separator: return os << "EXPRESSION SEPARATOR"; case Token::Type::Keyword: return os << "KEYWORD"; case Token::Type::Numeric: return os << "NUMERIC"; case Token::Type::Open_Block: return os << "OPEN BLOCK"; - case Token::Type::Open_Paren: return os << "OPEN PAREN"; case Token::Type::Operator: return os << "OPERATOR"; case Token::Type::Parameter_Separator: return os << "PARAMETER SEPARATOR"; case Token::Type::Symbol: return os << "SYMBOL"; @@ -275,13 +271,11 @@ std::string_view type_name(Token::Type type) { switch (type) { case Token::Type::Chord: return "chord"; - case Token::Type::Close_Block: return "]"; - case Token::Type::Close_Paren: return ")"; + case Token::Type::Close_Block: return ")"; case Token::Type::Expression_Separator: return "|"; case Token::Type::Keyword: return "keyword"; case Token::Type::Numeric: return "numeric"; - case Token::Type::Open_Block: return "["; - case Token::Type::Open_Paren: return "("; + case Token::Type::Open_Block: return "("; case Token::Type::Operator: return "operator"; case Token::Type::Parameter_Separator: return "parameter separator"; case Token::Type::Symbol: return "symbol"; diff --git a/musique/lexer/token.hh b/musique/lexer/token.hh index 407bbe2..638f4b6 100644 --- a/musique/lexer/token.hh +++ b/musique/lexer/token.hh @@ -19,8 +19,6 @@ struct Token Expression_Separator, ///< ";" separates expressions. Used mainly to separate calls, like `foo 1 2; bar 3 4` Open_Block, ///< "[" delimits anonymous block of code (potentially a function) Close_Block, ///< "]" delimits anonymous block of code (potentially a function) - Open_Paren, ///< "(" used in arithmetic or as function invocation sarrounding - Close_Paren ///< ")" used in arithmetic or as function invocation sarrounding }; /// Type of token diff --git a/musique/parser/parser.cc b/musique/parser/parser.cc index 3398280..38abd13 100644 --- a/musique/parser/parser.cc +++ b/musique/parser/parser.cc @@ -68,13 +68,11 @@ Result Parser::parse(std::string_view source, std::string_view filename, un auto const result = parser.parse_sequence(); if (result.has_value() && parser.token_id < parser.tokens.size()) { - if (parser.expect(Token::Type::Close_Paren) || parser.expect(Token::Type::Close_Block)) { + if (parser.expect(Token::Type::Close_Block)) { auto const tok = parser.consume(); return Error { .details = errors::Closing_Token_Without_Opening { - .type = tok.type == Token::Type::Close_Paren - ? errors::Closing_Token_Without_Opening::Paren - : errors::Closing_Token_Without_Opening::Block + errors::Closing_Token_Without_Opening::Paren }, .location = tok.location }; @@ -287,30 +285,15 @@ Result Parser::parse_atomic_expression() if (is_lambda) { return Ast::lambda(opening.location, std::move(ast), std::move(parameters)); } else { + ensure(ast.type == Ast::Type::Sequence, "I dunno if this is a valid assumption tbh"); + if (ast.arguments.size() == 1) { + return std::move(ast.arguments.front()); + } return Ast::block(opening.location, std::move(ast)); } }); } - case Token::Type::Open_Paren: - { - consume(); - auto ast = Try(parse_sequence()); - if (not expect(Token::Type::Close_Paren)) { - auto const& token = Try(peek()); - return Error { - .details = errors::internal::Unexpected_Token { - .type = type_name(token.type), - .source = token.source, - .when = "waiting for closing paren ')'" - }, - .location = token.location - }; - } - consume(); - return ast; - } - break; case Token::Type::Operator: return Error { .details = errors::Wrong_Arity_Of { diff --git a/musique/value/chord.cc b/musique/value/chord.cc index 7ff6884..6bd4c42 100644 --- a/musique/value/chord.cc +++ b/musique/value/chord.cc @@ -121,6 +121,9 @@ Result Chord::operator()(Interpreter& interpreter, std::vector arg std::move(current.begin(), current.end(), std::back_inserter(array)); ensure(not array.empty(), "At least *this should be in this array"); + if (array.size() == 1) { + return array.front(); + } return array; } diff --git a/musique/value/number.hh b/musique/value/number.hh index 1b7a915..ead16f4 100644 --- a/musique/value/number.hh +++ b/musique/value/number.hh @@ -56,6 +56,10 @@ struct Number std::ostream& operator<<(std::ostream& os, Number const& num); -template<> struct std::hash { std::size_t operator()(Number const&) const; }; +template<> +struct std::hash +{ + std::size_t operator()(Number const&) const; +}; #endif