Working arrays, flat function
This commit is contained in:
parent
64417bf187
commit
6611512b1f
@ -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:
|
||||
|
@ -106,12 +106,8 @@ Interpreter::Interpreter()
|
||||
|
||||
global.force_define("len", +[](Interpreter &, std::vector<Value> args) -> Result<Value> {
|
||||
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<Value> args) -> Result<Value> {
|
||||
@ -122,6 +118,27 @@ Interpreter::Interpreter()
|
||||
return Value{};
|
||||
});
|
||||
|
||||
global.force_define("flat", +[](Interpreter &i, std::vector<Value> args) -> Result<Value> {
|
||||
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<std::plus<>>();
|
||||
operators["-"] = binary_operator<std::minus<>>();
|
||||
operators["*"] = binary_operator<std::multiplies<>>();
|
||||
|
@ -466,6 +466,7 @@ struct Block
|
||||
|
||||
Result<Value> operator()(Interpreter &i, std::vector<Value> params);
|
||||
Result<Value> index(Interpreter &i, unsigned position);
|
||||
usize size() const;
|
||||
};
|
||||
|
||||
struct Note
|
||||
@ -500,8 +501,13 @@ struct Array
|
||||
std::vector<Value> elements;
|
||||
|
||||
Result<Value> 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<Value> operator()(Interpreter &i, std::vector<Value> args);
|
||||
Result<Value> index(Interpreter &i, unsigned position);
|
||||
usize size() const;
|
||||
|
||||
bool operator==(Value const& other) const;
|
||||
};
|
||||
|
56
src/value.cc
56
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 << "<block>";
|
||||
|
||||
case Value::Type::Array:
|
||||
unimplemented();
|
||||
return os << v.array;
|
||||
|
||||
case Value::Type::Music:
|
||||
return os << v.note;
|
||||
@ -299,6 +323,34 @@ Result<Value> 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<Value> 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> Note::from(std::string_view literal)
|
||||
{
|
||||
if (auto note = note_index(literal); note != u8(-1)) {
|
||||
|
Loading…
Reference in New Issue
Block a user