Value printing improved

This commit is contained in:
Robert Bendun 2022-09-23 13:18:55 +02:00
parent 857f8f3b52
commit d9c0468729
5 changed files with 99 additions and 10 deletions

View File

@ -6,6 +6,7 @@ Obj= \
context.o \ context.o \
environment.o \ environment.o \
errors.o \ errors.o \
format.o \
interpreter.o \ interpreter.o \
lexer.o \ lexer.o \
lines.o \ lines.o \

View File

@ -6,9 +6,9 @@
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <functional> #include <functional>
#include <iostream>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <ostream>
#include <span> #include <span>
#include <string_view> #include <string_view>
#include <variant> #include <variant>
@ -784,7 +784,7 @@ struct Block
Result<Value> operator()(Interpreter &i, std::vector<Value> params); Result<Value> operator()(Interpreter &i, std::vector<Value> params);
/// Indexing block /// Indexing block
Result<Value> index(Interpreter &i, unsigned position); Result<Value> index(Interpreter &i, unsigned position) const;
/// Count of elements in block /// Count of elements in block
usize size() const; usize size() const;
@ -845,7 +845,7 @@ struct Array
std::vector<Value> elements; std::vector<Value> elements;
/// Index element of an array /// Index element of an array
Result<Value> index(Interpreter &i, unsigned position); Result<Value> index(Interpreter &i, unsigned position) const;
/// Count of elements /// Count of elements
usize size() const; usize size() const;
@ -923,7 +923,7 @@ struct Value
Result<Value> operator()(Interpreter &i, std::vector<Value> args); Result<Value> operator()(Interpreter &i, std::vector<Value> args);
/// Index contained value if it can be called /// Index contained value if it can be called
Result<Value> index(Interpreter &i, unsigned position); Result<Value> index(Interpreter &i, unsigned position) const;
/// Return elements count of contained value if it can be measured /// Return elements count of contained value if it can be measured
usize size() const; usize size() const;
@ -1137,4 +1137,22 @@ template<> struct std::hash<Ast> { std::size_t operator()(Ast const&) cons
template<> struct std::hash<Number> { std::size_t operator()(Number const&) const; }; template<> struct std::hash<Number> { std::size_t operator()(Number const&) const; };
template<> struct std::hash<Value> { std::size_t operator()(Value const&) const; }; template<> struct std::hash<Value> { std::size_t operator()(Value const&) const; };
struct Value_Formatter
{
enum Context
{
Free,
Inside_Block
};
Context context = Free;
unsigned indent = 0;
Value_Formatter nest(Context nested = Free) const;
Result<void> format(std::ostream& os, Interpreter &interpreter, Value const& value);
};
Result<std::string> format(Interpreter &i, Value const& value);
#endif #endif

70
src/format.cc Normal file
View File

@ -0,0 +1,70 @@
#include <musique.hh>
#include <sstream>
Result<std::string> format(Interpreter &i, Value const& value)
{
std::stringstream ss;
Try(Value_Formatter{}.format(ss, i, value));
return ss.str();
}
Value_Formatter Value_Formatter::nest(Context nested) const
{
return Value_Formatter { .context = nested, .indent = indent + 2 };
}
std::optional<Error> Value_Formatter::format(std::ostream& os, Interpreter &interpreter, Value const& value)
{
switch (value.type) {
break; case Value::Type::Nil:
os << "nil";
break; case Value::Type::Symbol:
os << value.s;
break; case Value::Type::Bool:
os << std::boolalpha << value.b;
break; case Value::Type::Number:
if (auto n = value.n.simplify(); n.den == 1) {
os << n.num << '/' << n.den;
} else {
os << n.num;
}
break; case Value::Type::Intrinsic:
for (auto const& [key, val] : Env::global->variables) {
if (val.type == Value::Type::Intrinsic && val.intr == value.intr) {
os << "<intrinsic '" << key << "'>";
return {};
}
}
os << "<intrinsic>";
break; case Value::Type::Array:
os << '[';
for (auto i = 0u; i < value.array.elements.size(); ++i) {
if (i > 0) {
os << "; ";
}
Try(nest(Inside_Block).format(os, interpreter, value.array.elements[i]));
}
os << ']';
break; case Value::Type::Block:
os << '[';
for (auto i = 0u; i < value.blk.size(); ++i) {
if (i > 0) {
os << "; ";
}
Try(nest(Inside_Block).format(os, interpreter, Try(value.index(interpreter, i))));
}
os << ']';
break; case Value::Type::Music:
os << value.chord;
}
return {};
}

View File

@ -126,9 +126,9 @@ struct Runner
midi_input_event_loop.detach(); midi_input_event_loop.detach();
} }
Env::global->force_define("say", +[](Interpreter&, std::vector<Value> args) -> Result<Value> { Env::global->force_define("say", +[](Interpreter &interpreter, std::vector<Value> args) -> Result<Value> {
for (auto it = args.begin(); it != args.end(); ++it) { for (auto it = args.begin(); it != args.end(); ++it) {
std::cout << *it; Try(format(interpreter, *it));
if (std::next(it) != args.end()) if (std::next(it) != args.end())
std::cout << ' '; std::cout << ' ';
} }
@ -162,7 +162,7 @@ struct Runner
return {}; return {};
} }
if (auto result = Try(interpreter.eval(std::move(ast))); output && result.type != Value::Type::Nil) { if (auto result = Try(interpreter.eval(std::move(ast))); output && result.type != Value::Type::Nil) {
std::cout << result << std::endl; std::cout << Try(format(interpreter, result)) << std::endl;
} }
return {}; return {};
} }

View File

@ -169,7 +169,7 @@ Result<Value> Value::operator()(Interpreter &i, std::vector<Value> args)
} }
} }
Result<Value> Value::index(Interpreter &i, unsigned position) Result<Value> Value::index(Interpreter &i, unsigned position) const
{ {
switch (type) { switch (type) {
case Type::Block: case Type::Block:
@ -361,7 +361,7 @@ static inline Result<void> guard_index(unsigned index, unsigned size)
} }
// TODO Add memoization // TODO Add memoization
Result<Value> Block::index(Interpreter &i, unsigned position) Result<Value> Block::index(Interpreter &i, unsigned position) const
{ {
assert(parameters.size() == 0, "cannot index into block with parameters (for now)"); assert(parameters.size() == 0, "cannot index into block with parameters (for now)");
if (body.type != Ast::Type::Sequence) { if (body.type != Ast::Type::Sequence) {
@ -378,7 +378,7 @@ usize Block::size() const
return body.type == Ast::Type::Sequence ? body.arguments.size() : 1; return body.type == Ast::Type::Sequence ? body.arguments.size() : 1;
} }
Result<Value> Array::index(Interpreter &, unsigned position) Result<Value> Array::index(Interpreter &, unsigned position) const
{ {
Try(guard_index(position, elements.size())); Try(guard_index(position, elements.size()));
return elements[position]; return elements[position];