From 6611512b1f6f6210bdd94d87d99cbbf37f2abc08 Mon Sep 17 00:00:00 2001 From: Robert Bendun Date: Tue, 24 May 2022 19:09:37 +0200 Subject: [PATCH] Working arrays, flat function --- doc/cheatsheet.txt | 13 +++++++++++ src/interpreter.cc | 29 +++++++++++++++++++----- src/musique.hh | 8 +++++++ src/value.cc | 56 ++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 98 insertions(+), 8 deletions(-) diff --git a/doc/cheatsheet.txt b/doc/cheatsheet.txt index 44afe39..e1170d7 100644 --- a/doc/cheatsheet.txt +++ b/doc/cheatsheet.txt @@ -67,6 +67,14 @@ dtn 3/64 Dostępne funkcje --------------------------------------------------------------------------- +flat : ...items : any -> array + tworzy tablicę z dostarczonych elementów, rozsypując elementy indeksowalne + przykład: + flat 1 2 3 tworzy tablicę 1, 2, 3 + flat [1;2] 2 3 tworzy tablicę 1, 2, 2, 3 + flat [[1;2]; [3;4]] 5 6 tworzy tablicę [1;2], [3;4], 5, 6 + + if : condition: bool, block: block -> (eval block) wywołuje block jeśli condition jest: dla b: bool jest b == true @@ -78,6 +86,11 @@ if : condition: Bool, then: Block, else: Block -> (eval then or eval else) jeśli condition jest prawdziwe wg zasad wyżej wywołaj then w innym przypadku wywołaj else +len : array -> number + zwraca ilość elementów w tablicy + Przykład: + len (flat 5 6 7) == 3 + len : block -> number zwraca ilość elementów (liczbę indeksowalnych pozycji) wewnątrz bloku Przykład: diff --git a/src/interpreter.cc b/src/interpreter.cc index 85cadad..0ee9d23 100644 --- a/src/interpreter.cc +++ b/src/interpreter.cc @@ -106,12 +106,8 @@ Interpreter::Interpreter() global.force_define("len", +[](Interpreter &, std::vector args) -> Result { assert(args.size() == 1, "len only accepts one argument"); - assert(args.front().type == Value::Type::Block, "Only blocks can be measure"); - if (args.front().blk.body.type != Ast::Type::Sequence) { - return Value::from(Number(1)); - } else { - return Value::from(Number(args.front().blk.body.arguments.size())); - } + assert(args.front().type == Value::Type::Block || args.front().type == Value::Type::Array, "Only blocks and arrays can have length"); + return Value::from(Number(args.front().size())); }); global.force_define("play", +[](Interpreter &i, std::vector args) -> Result { @@ -122,6 +118,27 @@ Interpreter::Interpreter() return Value{}; }); + global.force_define("flat", +[](Interpreter &i, std::vector args) -> Result { + Array array; + for (auto &arg : args) { + switch (arg.type) { + case Value::Type::Array: + std::move(arg.array.elements.begin(), arg.array.elements.end(), std::back_inserter(array.elements)); + break; + + case Value::Type::Block: + for (auto j = 0u; j < arg.blk.size(); ++j) { + array.elements.push_back(Try(arg.blk.index(i, j))); + } + break; + + default: + array.elements.push_back(std::move(arg)); + } + } + return Value::from(std::move(array)); + }); + operators["+"] = binary_operator>(); operators["-"] = binary_operator>(); operators["*"] = binary_operator>(); diff --git a/src/musique.hh b/src/musique.hh index 5261f6d..47c64a0 100644 --- a/src/musique.hh +++ b/src/musique.hh @@ -466,6 +466,7 @@ struct Block Result operator()(Interpreter &i, std::vector params); Result index(Interpreter &i, unsigned position); + usize size() const; }; struct Note @@ -500,8 +501,13 @@ struct Array std::vector elements; Result index(Interpreter &i, unsigned position); + usize size() const; + + bool operator==(Array const&) const = default; }; +std::ostream& operator<<(std::ostream& os, Array const& v); + // TODO Add location struct Value { @@ -546,6 +552,7 @@ struct Value Intrinsic intr; Block blk; Note note; + Array array; // TODO Most strings should not be allocated by Value, but reference to string allocated previously // Wrapper for std::string is needed that will allocate only when needed, middle ground between: @@ -557,6 +564,7 @@ struct Value bool falsy() const; Result operator()(Interpreter &i, std::vector args); Result index(Interpreter &i, unsigned position); + usize size() const; bool operator==(Value const& other) const; }; diff --git a/src/value.cc b/src/value.cc index 110b418..1ff988c 100644 --- a/src/value.cc +++ b/src/value.cc @@ -138,6 +138,14 @@ Value Value::from(Block &&block) return v; } +Value Value::from(Array &&array) +{ + Value v; + v.type = Type::Array; + v.array = std::move(array); + return v; +} + Value Value::from(Note n) { Value v; @@ -217,7 +225,23 @@ bool Value::operator==(Value const& other) const case Type::Block: return false; // TODO Reconsider if functions are comparable case Type::Bool: return b == other.b; case Type::Music: return note == other.note; - case Type::Array: unimplemented(); + case Type::Array: return array == other.array; + } + + unreachable(); +} + +usize Value::size() const +{ + switch (type) { + case Type::Array: + return array.size(); + + case Type::Block: + return blk.size(); + + default: + assert(false, "This type does not support Value::size()"); // TODO(assert) } unreachable(); @@ -245,7 +269,7 @@ std::ostream& operator<<(std::ostream& os, Value const& v) return os << ""; case Value::Type::Array: - unimplemented(); + return os << v.array; case Value::Type::Music: return os << v.note; @@ -299,6 +323,34 @@ Result Block::index(Interpreter &i, unsigned position) return i.eval((Ast)body.arguments[position]); } +usize Block::size() const +{ + return body.type == Ast::Type::Sequence ? body.arguments.size() : 1; +} + +Result Array::index(Interpreter &, unsigned position) +{ + assert(position < elements.size(), "Out of range"); // TODO(assert) + return elements[position]; +} + +usize Array::size() const +{ + return elements.size(); +} + +std::ostream& operator<<(std::ostream& os, Array const& v) +{ + os << '['; + for (auto it = v.elements.begin(); it != v.elements.end(); ++it) { + os << *it; + if (std::next(it) != v.elements.end()) { + os << "; "; + } + } + return os << ']'; +} + std::optional Note::from(std::string_view literal) { if (auto note = note_index(literal); note != u8(-1)) {