Working arrays, flat function
This commit is contained in:
parent
64417bf187
commit
6611512b1f
@ -67,6 +67,14 @@ dtn 3/64
|
|||||||
Dostępne funkcje
|
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)
|
if : condition: bool, block: block -> (eval block)
|
||||||
wywołuje block jeśli condition jest:
|
wywołuje block jeśli condition jest:
|
||||||
dla b: bool jest b == true
|
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
|
jeśli condition jest prawdziwe wg zasad wyżej wywołaj then
|
||||||
w innym przypadku wywołaj else
|
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
|
len : block -> number
|
||||||
zwraca ilość elementów (liczbę indeksowalnych pozycji) wewnątrz bloku
|
zwraca ilość elementów (liczbę indeksowalnych pozycji) wewnątrz bloku
|
||||||
Przykład:
|
Przykład:
|
||||||
|
@ -106,12 +106,8 @@ Interpreter::Interpreter()
|
|||||||
|
|
||||||
global.force_define("len", +[](Interpreter &, std::vector<Value> args) -> Result<Value> {
|
global.force_define("len", +[](Interpreter &, std::vector<Value> args) -> Result<Value> {
|
||||||
assert(args.size() == 1, "len only accepts one argument");
|
assert(args.size() == 1, "len only accepts one argument");
|
||||||
assert(args.front().type == Value::Type::Block, "Only blocks can be measure");
|
assert(args.front().type == Value::Type::Block || args.front().type == Value::Type::Array, "Only blocks and arrays can have length");
|
||||||
if (args.front().blk.body.type != Ast::Type::Sequence) {
|
return Value::from(Number(args.front().size()));
|
||||||
return Value::from(Number(1));
|
|
||||||
} else {
|
|
||||||
return Value::from(Number(args.front().blk.body.arguments.size()));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
global.force_define("play", +[](Interpreter &i, std::vector<Value> args) -> Result<Value> {
|
global.force_define("play", +[](Interpreter &i, std::vector<Value> args) -> Result<Value> {
|
||||||
@ -122,6 +118,27 @@ Interpreter::Interpreter()
|
|||||||
return Value{};
|
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::plus<>>();
|
||||||
operators["-"] = binary_operator<std::minus<>>();
|
operators["-"] = binary_operator<std::minus<>>();
|
||||||
operators["*"] = binary_operator<std::multiplies<>>();
|
operators["*"] = binary_operator<std::multiplies<>>();
|
||||||
|
@ -466,6 +466,7 @@ struct Block
|
|||||||
|
|
||||||
Result<Value> operator()(Interpreter &i, std::vector<Value> params);
|
Result<Value> operator()(Interpreter &i, std::vector<Value> params);
|
||||||
Result<Value> index(Interpreter &i, unsigned position);
|
Result<Value> index(Interpreter &i, unsigned position);
|
||||||
|
usize size() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Note
|
struct Note
|
||||||
@ -500,8 +501,13 @@ struct Array
|
|||||||
std::vector<Value> elements;
|
std::vector<Value> elements;
|
||||||
|
|
||||||
Result<Value> index(Interpreter &i, unsigned position);
|
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
|
// TODO Add location
|
||||||
struct Value
|
struct Value
|
||||||
{
|
{
|
||||||
@ -546,6 +552,7 @@ struct Value
|
|||||||
Intrinsic intr;
|
Intrinsic intr;
|
||||||
Block blk;
|
Block blk;
|
||||||
Note note;
|
Note note;
|
||||||
|
Array array;
|
||||||
|
|
||||||
// TODO Most strings should not be allocated by Value, but reference to string allocated previously
|
// 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:
|
// Wrapper for std::string is needed that will allocate only when needed, middle ground between:
|
||||||
@ -557,6 +564,7 @@ struct Value
|
|||||||
bool falsy() const;
|
bool falsy() const;
|
||||||
Result<Value> operator()(Interpreter &i, std::vector<Value> args);
|
Result<Value> operator()(Interpreter &i, std::vector<Value> args);
|
||||||
Result<Value> index(Interpreter &i, unsigned position);
|
Result<Value> index(Interpreter &i, unsigned position);
|
||||||
|
usize size() const;
|
||||||
|
|
||||||
bool operator==(Value const& other) 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;
|
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 Value::from(Note n)
|
||||||
{
|
{
|
||||||
Value v;
|
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::Block: return false; // TODO Reconsider if functions are comparable
|
||||||
case Type::Bool: return b == other.b;
|
case Type::Bool: return b == other.b;
|
||||||
case Type::Music: return note == other.note;
|
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();
|
unreachable();
|
||||||
@ -245,7 +269,7 @@ std::ostream& operator<<(std::ostream& os, Value const& v)
|
|||||||
return os << "<block>";
|
return os << "<block>";
|
||||||
|
|
||||||
case Value::Type::Array:
|
case Value::Type::Array:
|
||||||
unimplemented();
|
return os << v.array;
|
||||||
|
|
||||||
case Value::Type::Music:
|
case Value::Type::Music:
|
||||||
return os << v.note;
|
return os << v.note;
|
||||||
@ -299,6 +323,34 @@ Result<Value> Block::index(Interpreter &i, unsigned position)
|
|||||||
return i.eval((Ast)body.arguments[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)
|
std::optional<Note> Note::from(std::string_view literal)
|
||||||
{
|
{
|
||||||
if (auto note = note_index(literal); note != u8(-1)) {
|
if (auto note = note_index(literal); note != u8(-1)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user