version 0.2

try, throw implemented
help screen updates
some code reorganisation
readme and doc updates
This commit is contained in:
2021-06-10 23:26:14 +02:00
parent b50e9ba128
commit f594437b61
7 changed files with 227 additions and 105 deletions

145
ml.cpp
View File

@@ -1351,6 +1351,11 @@ namespace builtin {
if (args.size() != 2)
throw MlError(MlValue("/", divide), env, args.size() > 2 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
if ((args[1].get_type_name() == "int" && args[1] == 0l) ||
(args[1].get_type_name() == "float" && args[1] == 0.0))
throw std::invalid_argument("divide by zero.");
return args[0] / args[1];
}
@@ -1846,17 +1851,6 @@ namespace builtin {
return acc;
}
MlValue threads_join(std::vector<MlValue> args, MlEnvironment &env) {
if (args.size() != 0)
throw MlError(MlValue("threads_join", threads_join), env, TOO_MANY_ARGS);
std::lock_guard<std::mutex> lockGuard(register_mutex);
for (auto &th : threads_register)
if (th.joinable()) th.join();
return MlValue::nil();
}
MlValue thread_sleep(std::vector<MlValue> args, MlEnvironment &env) {
eval_args(args, env);
@@ -1866,48 +1860,51 @@ namespace builtin {
std::this_thread::sleep_for(std::chrono::milliseconds(args[0].as_int()));
return args[0];
}
}
void repl(MlEnvironment &env) {
std::string code;
std::string input;
MlValue tmp;
std::vector<MlValue> parsed;
MlValue threads_join(std::vector<MlValue> args, MlEnvironment &env) {
if (args.size() != 0)
throw MlError(MlValue("threads-join", threads_join), env, TOO_MANY_ARGS);
setup_linenoise(env);
while (true) {
char *line = linenoise(">>> ");
if (line == nullptr) break;
linenoise_line_read(line);
input = std::string(line);
if (input == "!quit" || input == "!q")
break;
else if (input == "!env" || input == "!e")
std::cout << env << std::endl;
else if (input == "!export" || input == "!x") {
std::cout << "File to export to: ";
std::getline(std::cin, input);
write_file_contents(input, code);
} else if (input != "") {
try {
tmp = run(input, env);
std::cout << " => " << tmp.debug() << std::endl;
code += input + "\n";
} catch (MlError &e) {
std::cerr << e.description() << std::endl;
MlPerfMon::instance().clear_callstack();
} catch (std::exception &e) {
std::cerr << e.what() << std::endl;
}
}
std::lock_guard<std::mutex> lockGuard(register_mutex);
for (auto &th : threads_register)
if (th.joinable()) th.join();
return MlValue::nil();
}
MlValue try_block(std::vector<MlValue> args, MlEnvironment &env) {
if (args.size() < 2 || args.size() > 3)
throw MlError(MlValue("try", try_block), env, args.size() > 3 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
MlValue value;
size_t cs_posisition; // unroll stack position to state when try begun to prevent "forgotten" entries in case of exception
// try block
try {
cs_posisition = MlPerfMon::instance().get_callstack_position();
value = args[0].eval(env);
// catch block
} catch (std::exception &e) {
MlPerfMon::instance().restore_callstack_position(cs_posisition);
env.set("ml-exception", MlValue::string(e.what()));
value = args[1].eval(env);
}
// finally block
if (args.size() == 3) {
args[2].eval(env);
}
return value;
}
MlValue throw_exception(std::vector<MlValue> args, MlEnvironment &env) {
if (args.size() != 1)
throw MlError(MlValue("throw", throw_exception), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
throw std::runtime_error(args[0].as_string());
}
close_linenoise();
}
void load_std_lib(MlEnvironment &env) {
@@ -2037,6 +2034,10 @@ MlValue MlEnvironment::get(const std::string &name) const {
if (name == "thread-sleep") return MlValue("thread-sleep", builtin::thread_sleep);
if (name == "threads-join") return MlValue("threads-join", builtin::threads_join);
// Exceptions
if (name == "try") return MlValue("try", builtin::try_block);
if (name == "throw") return MlValue("throw", builtin::throw_exception);
std::map<std::string, MlValue>::const_iterator itr = defs.find(name);
if (itr != defs.end()) return itr->second;
else if (parent_scope != nullptr) {
@@ -2061,6 +2062,50 @@ std::vector<std::string> MlEnvironment::get_lambdas_list() const {
return lambdas;
}
void repl(MlEnvironment &env) {
std::string code;
std::string input;
MlValue tmp;
std::vector<MlValue> parsed;
setup_linenoise(env);
while (true) {
char *line = linenoise(">>> ");
if (line == nullptr) break;
linenoise_line_read(line);
input = std::string(line);
if (input == "!quit" || input == "!q")
break;
else if (input == "!env" || input == "!e")
std::cout << env << std::endl;
else if (input == "!export" || input == "!x") {
std::cout << "File to export to: ";
std::getline(std::cin, input);
write_file_contents(input, code);
} else if (input != "") {
try {
tmp = run(input, env);
std::cout << " => " << tmp.debug() << std::endl;
code += input + "\n";
} catch (MlError &e) {
std::cerr << e.description() << std::endl;
MlPerfMon::instance().clear_callstack();
} catch (std::exception &e) {
std::cerr << e.what() << std::endl;
}
}
}
close_linenoise();
}
bool cmdOptionExists(char **begin, char **end, const std::string &option) { return std::find(begin, end, option) != end; }
std::vector<std::string> getCmdOption(char *argv[], int argc, const std::string &option) {
@@ -2092,7 +2137,7 @@ int main(int argc, char *argv[]) {
}
// help
if (cmdOptionExists(argv, argv + argc, "-h")) {
std::cout << "Usage:\n\t-h print this help\n\t-f source_file - executes code in file\n\t-c code - runs passed code\n\t-i runs repl\n\t-b skip stdlib loading\n\t-p prints profile info at the end\n\t-v prints version string\n\n";
std::cout << "Usage:\n\t-h print this help\n\t-b skip stdlib loading\n\t-c code - runs code passed on command line\n\t-f source_file - executes code in file\n\t-i runs repl\n\t-p prints profile info at the end\n\t-v prints version string\n\n";
return 0;
}
// version