Added file as function commandline switch
This commit is contained in:
parent
346c66a8f4
commit
6c631dc075
@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
* `:quit` REPL command that mirrors `:exit` command
|
* `:quit` REPL command that mirrors `:exit` command
|
||||||
* Virtual MIDI output port creation as default action (--output connects to existing one)
|
* Virtual MIDI output port creation as default action (--output connects to existing one)
|
||||||
* Added build instructions
|
* Added build instructions
|
||||||
|
* `-f` commandline argument that will turn file into deffered function
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <musique/pretty.hh>
|
#include <musique/pretty.hh>
|
||||||
#include <musique/try.hh>
|
#include <musique/try.hh>
|
||||||
#include <musique/unicode.hh>
|
#include <musique/unicode.hh>
|
||||||
|
#include <musique/value/block.hh>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -76,6 +77,9 @@ static T pop(std::span<char const*> &span)
|
|||||||
" -I,--interactive,--repl\n"
|
" -I,--interactive,--repl\n"
|
||||||
" enables interactive mode even when another code was passed\n"
|
" enables interactive mode even when another code was passed\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" -f,--as-function FILENAME\n"
|
||||||
|
" deffer file execution and turn it into a file\n"
|
||||||
|
"\n"
|
||||||
" --ast\n"
|
" --ast\n"
|
||||||
" prints ast for given code\n"
|
" prints ast for given code\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -119,6 +123,37 @@ static void trim(std::string_view &s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string filename_to_function_name(std::string_view filename)
|
||||||
|
{
|
||||||
|
if (filename == "-") {
|
||||||
|
return "stdin";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto stem = fs::path(filename).stem().string();
|
||||||
|
auto stem_view = std::string_view(stem);
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
auto is_first = unicode::First_Character::Yes;
|
||||||
|
while (!stem_view.empty()) {
|
||||||
|
auto [rune, next_stem] = utf8::decode(stem_view);
|
||||||
|
if (!unicode::is_identifier(rune, is_first)) {
|
||||||
|
if (rune != ' ' && rune != '-') {
|
||||||
|
// TODO Nicer error
|
||||||
|
std::cerr << "[ERROR] Failed to construct function name from filename " << stem
|
||||||
|
<< "\n due to presence of invalid character: " << utf8::Print{rune} << "(U+" << std::hex << rune << ")\n"
|
||||||
|
<< std::flush;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
name += '_';
|
||||||
|
} else {
|
||||||
|
name += stem_view.substr(0, stem_view.size() - next_stem.size());
|
||||||
|
}
|
||||||
|
stem_view = next_stem;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
/// Runs interpreter on given source code
|
/// Runs interpreter on given source code
|
||||||
struct Runner
|
struct Runner
|
||||||
{
|
{
|
||||||
@ -160,6 +195,29 @@ struct Runner
|
|||||||
Runner& operator=(Runner const&) = delete;
|
Runner& operator=(Runner const&) = delete;
|
||||||
Runner& operator=(Runner &&) = delete;
|
Runner& operator=(Runner &&) = delete;
|
||||||
|
|
||||||
|
/// Consider given input file as new definition of parametless function
|
||||||
|
///
|
||||||
|
/// Useful for deffering execution of files to the point when all configuration of midi devices
|
||||||
|
/// is beeing known as working.
|
||||||
|
std::optional<Error> deffered_file(std::string_view source, std::string_view filename)
|
||||||
|
{
|
||||||
|
auto ast = Try(Parser::parse(source, filename, repl_line_number));
|
||||||
|
if (ast_only_mode) {
|
||||||
|
dump(ast);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto name = filename_to_function_name(filename);
|
||||||
|
|
||||||
|
Block block;
|
||||||
|
block.location = ast.location;
|
||||||
|
block.body = std::move(ast);
|
||||||
|
block.context = Env::global;
|
||||||
|
std::cout << "Defined function " << name << " as file " << filename << std::endl;
|
||||||
|
Env::global->force_define(std::move(name), Value(std::move(block)));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
/// Run given source
|
/// Run given source
|
||||||
std::optional<Error> run(std::string_view source, std::string_view filename, bool output = false)
|
std::optional<Error> run(std::string_view source, std::string_view filename, bool output = false)
|
||||||
{
|
{
|
||||||
@ -286,7 +344,12 @@ static std::optional<Error> Main(std::span<char const*> args)
|
|||||||
/// Describes all arguments that will be run
|
/// Describes all arguments that will be run
|
||||||
struct Run
|
struct Run
|
||||||
{
|
{
|
||||||
bool is_file = true;
|
enum Type
|
||||||
|
{
|
||||||
|
File,
|
||||||
|
Argument,
|
||||||
|
Deffered_File
|
||||||
|
} type;
|
||||||
std::string_view argument;
|
std::string_view argument;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -299,7 +362,7 @@ static std::optional<Error> Main(std::span<char const*> args)
|
|||||||
std::string_view arg = pop(args);
|
std::string_view arg = pop(args);
|
||||||
|
|
||||||
if (arg == "-" || !arg.starts_with('-')) {
|
if (arg == "-" || !arg.starts_with('-')) {
|
||||||
runnables.push_back({ .is_file = true, .argument = std::move(arg) });
|
runnables.push_back({ .type = Run::File, .argument = std::move(arg) });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +376,16 @@ static std::optional<Error> Main(std::span<char const*> args)
|
|||||||
std::cerr << "musique: error: option " << arg << " requires an argument" << std::endl;
|
std::cerr << "musique: error: option " << arg << " requires an argument" << std::endl;
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
runnables.push_back({ .is_file = false, .argument = pop(args) });
|
runnables.push_back({ .type = Run::Argument, .argument = pop(args) });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg == "-f" || arg == "--as-function") {
|
||||||
|
if (args.empty()) {
|
||||||
|
std::cerr << "musique: error: option " << arg << " requires an argument" << std::endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
runnables.push_back({ .type = Run::Deffered_File, .argument = pop(args) });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,8 +418,8 @@ static std::optional<Error> Main(std::span<char const*> args)
|
|||||||
|
|
||||||
Runner runner{output_port};
|
Runner runner{output_port};
|
||||||
|
|
||||||
for (auto const& [is_file, argument] : runnables) {
|
for (auto const& [type, argument] : runnables) {
|
||||||
if (!is_file) {
|
if (type == Run::Argument) {
|
||||||
Lines::the.add_line("<arguments>", argument, repl_line_number);
|
Lines::the.add_line("<arguments>", argument, repl_line_number);
|
||||||
Try(runner.run(argument, "<arguments>"));
|
Try(runner.run(argument, "<arguments>"));
|
||||||
repl_line_number++;
|
repl_line_number++;
|
||||||
@ -355,7 +427,6 @@ static std::optional<Error> Main(std::span<char const*> args)
|
|||||||
}
|
}
|
||||||
auto path = argument;
|
auto path = argument;
|
||||||
if (path == "-") {
|
if (path == "-") {
|
||||||
path = "<stdin>";
|
|
||||||
eternal_sources.emplace_back(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>());
|
eternal_sources.emplace_back(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>());
|
||||||
} else {
|
} else {
|
||||||
if (not fs::exists(path)) {
|
if (not fs::exists(path)) {
|
||||||
@ -367,7 +438,11 @@ static std::optional<Error> Main(std::span<char const*> args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Lines::the.add_file(std::string(path), eternal_sources.back());
|
Lines::the.add_file(std::string(path), eternal_sources.back());
|
||||||
Try(runner.run(eternal_sources.back(), path));
|
if (type == Run::File) {
|
||||||
|
Try(runner.run(eternal_sources.back(), path));
|
||||||
|
} else {
|
||||||
|
Try(runner.deffered_file(eternal_sources.back(), argument));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runnables.empty() || enable_repl) {
|
if (runnables.empty() || enable_repl) {
|
||||||
@ -442,4 +517,5 @@ int main(int argc, char const** argv)
|
|||||||
std::cerr << result.value() << std::flush;
|
std::cerr << result.value() << std::flush;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user