Early text-based snapshot system

This commit is contained in:
Robert Bendun 2022-11-11 19:24:45 +01:00
parent 89b3519c24
commit 268455532b
4 changed files with 145 additions and 0 deletions

View File

@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `<note><octave>` notation like `c4` that mimics [scientific notation](https://en.wikipedia.org/wiki/Scientific_pitch_notation)
- operator pretty printing while printing values
- macros: builtin functions that takes AST and produces value
- early text-based snapshot system available via `:snap` command inside interactive session
### Changed

View File

@ -277,3 +277,132 @@ std::optional<Error> ensure_midi_connection_available(Interpreter &i, std::strin
}
return {};
}
static void snapshot(std::ostream& out, Note const& note) {
if (note.length) {
out << "(" << note << ")";
} else {
out << note;
}
}
static void snapshot(std::ostream &out, Ast const& ast) {
switch (ast.type) {
break; case Ast::Type::Sequence:
{
for (auto const& a : ast.arguments) {
snapshot(out, a);
out << ", ";
}
}
break; case Ast::Type::Block:
ensure(ast.arguments.size() == 1, "Block can contain only one node which contains its body");
out << "(";
snapshot(out, ast.arguments.front());
out << ")";
break; case Ast::Type::Lambda:
out << "(";
for (auto i = 0u; i+1 < ast.arguments.size(); ++i) {
ensure(ast.arguments[i].type == Ast::Type::Literal, "Lambda arguments should be an identifiers");
out << ast.arguments[i].token.source << " ";
}
out << "|";
snapshot(out, ast.arguments.back());
out << ")";
break; case Ast::Type::Variable_Declaration:
ensure(ast.arguments.size() == 2, "Variable declaration snapshots only support single lhs variables");
ensure(ast.arguments.front().type == Ast::Type::Literal, "Expected first value to be an identifier");
out << ast.arguments[0].token.source << " := ";
return snapshot(out, ast.arguments.back());
break; case Ast::Type::Literal:
out << ast.token.source;
break; case Ast::Type::Binary:
out << "(";
snapshot(out, ast.arguments[0]);
out << ") ";
out << ast.token.source;
out << " (";
snapshot(out, ast.arguments[1]);
out << ")";
break; case Ast::Type::Call:
out << "(";
for (auto const& a : ast.arguments) {
out << "(";
snapshot(out, a);
out << ") ";
}
out << ")";
}
}
static void snapshot(std::ostream& out, Value const& value) {
std::visit(Overloaded{
[&](Nil) { out << "nil"; },
[&](Bool const& b) {
out << (b ? "true" : "false");
},
[&](Number const& n) {
out << "(" << n.num << "/" << n.den << ")";
},
[&](Array const& array) {
out << "(flat (";
for (auto const& nested : array.elements) {
snapshot(out, nested);
out << ", ";
}
out << "))";
},
[&](Chord const& chord) {
if (chord.notes.size() == 1) {
auto note = chord.notes.front();
snapshot(out, note);
} else {
out << "(chord ";
for (auto const &note : chord.notes) {
snapshot(out, note);
out << " ";
}
out << ")";
}
},
[&](Symbol const& symbol) {
out << "'" << symbol;
},
[&](Block const& block) {
out << "(";
for (auto const& param : block.parameters) {
out << param << ' ';
}
out << "| ";
snapshot(out, block.body);
out << ")";
},
[](Intrinsic const&) { unreachable(); },
[](Macro const&) { unreachable(); }
}, value.data);
}
void Interpreter::snapshot(std::ostream& out)
{
auto const& ctx = context_stack.back();
out << ", oct " << int(ctx.octave) << '\n';
out << ", len (" << ctx.length.num << "/" << ctx.length.den << ")\n";
out << ", bpm " << ctx.bpm << '\n';
for (auto current = env.get(); current; current = current->parent.get()) {
for (auto const& [name, value] : current->variables) {
if (std::holds_alternative<Intrinsic>(value.data) || std::holds_alternative<Macro>(value.data)) {
continue;
}
out << ", " << name << " := ";
::snapshot(out, value);
out << '\n';
}
}
out << std::flush;
}

View File

@ -51,6 +51,9 @@ struct Interpreter
///
/// Invoked during construction
void register_builtin_operators();
/// Dumps snapshot of interpreter into stream
void snapshot(std::ostream& out);
};
std::optional<Error> ensure_midi_connection_available(Interpreter&, std::string_view operation_name);

View File

@ -314,6 +314,18 @@ static Result<bool> handle_repl_session_commands(std::string_view input, Runner
return runner.run(eternal_sources.back(), path);
}
},
Command {
"snap",
+[](Runner &runner, std::optional<std::string_view> arg) -> std::optional<Error> {
std::ostream *out = &std::cout;
std::fstream file;
if (arg.has_value() && arg->size()) {
file.open(std::string(*arg));
}
runner.interpreter.snapshot(*out);
return std::nullopt;
}
},
};
if (input.starts_with('!')) {