changes here, changes there

This commit is contained in:
2021-02-16 19:53:39 +01:00
parent c1532e78b1
commit 4b93f39375
9 changed files with 332 additions and 121 deletions

137
ml.cpp
View File

@@ -1,6 +1,7 @@
#include "ml.h"
#include "ml_io.h"
#include "ml_date.h"
#include "csvparser.h"
#include "sslclient.h"
@@ -30,7 +31,7 @@
#define BAD_CAST "cannot cast"
#define ATOM_NOT_DEFINED "atom not defined"
#define EVAL_EMPTY_LIST "evaluated empty list"
#define INTERNAL_ERROR "interal virtual machine error"
#define INTERNAL_ERROR "internal virtual machine error"
#define INDEX_OUT_OF_RANGE "index out of range"
#define MALFORMED_PROGRAM "malformed program"
@@ -1057,16 +1058,9 @@ namespace builtin {
eval_args(args, env);
if (args.size() != 2)
throw MlError(MlValue("write-file", write_file), env,
args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
throw MlError(MlValue("write-file", write_file), env, args.size() > 2 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
std::ofstream f;
// The first argument is the file name
f.open(args[0].as_string().c_str());
// The second argument is the contents of the file to write
MlValue result = MlValue((f << args[1].as_string()) ? 1 : 0);
f.close();
return result;
return MlValue(write_file_contents(args[0].as_string(), args[1].as_string()));
}
// Read URL to (code content)
@@ -1097,12 +1091,13 @@ namespace builtin {
}
// Parse JSON string
MlValue read_json(std::vector<MlValue> args, MlEnvironment &env) {
MlValue parse_json(std::vector<MlValue> args, MlEnvironment &env) {
eval_args(args, env);
// TODO add support for more params specifying options
if (args.size() != 1)
throw MlError(MlValue("read-json", read_json), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
throw MlError(MlValue("parse-json", parse_json), env,
args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
std::string str = args[0].as_string();
std::string err;
@@ -1116,48 +1111,59 @@ namespace builtin {
return json.ivalualize();
}
// get current time as secs from epoch
MlValue get_universal_time(std::vector<MlValue> args, MlEnvironment &env) {
eval_args(args, env);
if (args.size() != 0)
throw MlError(MlValue("get-universal-time", get_universal_time), env, TOO_MANY_ARGS);
return MlValue(now());
}
MlValue date_to_str(std::vector<MlValue> args, MlEnvironment &env) {
eval_args(args, env);
if (args.size() != 2)
throw MlError(MlValue("date_to_str", date_to_str), env,
args.size() > 2 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
return MlValue::string(date_to_string(args[0].as_int(), args[1].as_string()));
}
MlValue str_to_date(std::vector<MlValue> args, MlEnvironment &env) {
eval_args(args, env);
if (args.size() != 2)
throw MlError(MlValue("str-to-date", str_to_date), env,
args.size() > 2 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
return MlValue(string_to_date(args[0].as_string(), args[1].as_string()));
}
MlValue date_add(std::vector<MlValue> args, MlEnvironment &env) {
eval_args(args, env);
if (args.size() != 3)
throw MlError(MlValue("date-add", date_add), env, args.size() > 3 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
return MlValue(add_to_date(args[0].as_int(), args[1].as_int(), args[2].as_string()));
}
// Execute system command
MlValue system_cmd(std::vector<MlValue> args, MlEnvironment &env) {
eval_args(args, env);
// TODO add support for more params constructing options as one string
// TODO add support for stderr
if (args.size() != 1)
throw MlError(MlValue("system-cmd", system_cmd), env,
args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
std::string cmd = args[0].as_string();
std::string cmd_output;
int stat;
// TODO better parameter here
// TODO handle reading of stderr
// https://stackoverflow.com/questions/478898/how-do-i-execute-a-command-and-get-the-output-of-the-command-within-c-using-po
// https://jineshkj.wordpress.com/2006/12/22/how-to-capture-stdin-stdout-and-stderr-of-child-program/
char buffer[128];
FILE *pipe = popen(cmd.c_str(), "r");
if (!pipe)
throw std::runtime_error("popen() failed!");
try {
while (!std::feof(pipe)) {
if (std::fgets(buffer, 128, pipe) != nullptr)
cmd_output += buffer;
}
} catch (...) {
stat = pclose(pipe);
throw;
}
stat = pclose(pipe);
int cmd_retval = WEXITSTATUS(stat);
// TODO add helper function for this
std::vector<MlValue> lst;
lst.push_back(MlValue(cmd_retval));
lst.push_back(MlValue::string(cmd_output));
return lst;
return exec_system_cmd(args[0].as_string());
}
// list directory
MlValue ls_dir(std::vector<MlValue> args, MlEnvironment &env) {
eval_args(args, env);
@@ -1172,7 +1178,7 @@ namespace builtin {
MlValue is_file(std::vector<MlValue> args, MlEnvironment &env) {
eval_args(args, env);
// TODO add suppor for more params and list params
// TODO add support for more params and list params
if (args.size() != 1)
throw MlError(MlValue("is-file?", is_file), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
@@ -1183,7 +1189,7 @@ namespace builtin {
MlValue is_dir(std::vector<MlValue> args, MlEnvironment &env) {
eval_args(args, env);
// TODO add suppor for more params and list params
// TODO add support for more params and list params
if (args.size() != 1)
throw MlError(MlValue("is-dir?", is_dir), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
@@ -1583,10 +1589,7 @@ void repl(MlEnvironment &env) {
std::cout << "File to export to: ";
std::getline(std::cin, input);
std::ofstream f;
f.open(input.c_str(), std::ofstream::out);
f << code;
f.close();
write_file_contents(input, code);
} else if (input != "") {
try {
tmp = run(input, env);
@@ -1601,6 +1604,16 @@ void repl(MlEnvironment &env) {
}
}
// load lisp std library
void load_std_lib(MlEnvironment &env) {
// TODO iterate through dir with files
std::string filename = "stdlib/stdlib.lisp";
MlEnvironment e;
MlValue result = run(read_file_contents(filename), e);
env.combine(e);
}
// Does this environment, or its parent environment, have a variable?
bool MlEnvironment::has(std::string name) const {
// Find the value in the map
@@ -1653,9 +1666,7 @@ MlValue MlEnvironment::get(const std::string &name) const {
if (name == "insert") return MlValue("insert", builtin::insert);
if (name == "index") return MlValue("index", builtin::index);
if (name == "remove") return MlValue("remove", builtin::remove);
if (name == "len") return MlValue("len", builtin::len);
if (name == "push") return MlValue("push", builtin::push);
if (name == "pop") return MlValue("pop", builtin::pop);
if (name == "head") return MlValue("head", builtin::head);
@@ -1676,15 +1687,23 @@ MlValue MlEnvironment::get(const std::string &name) const {
if (name == "input") return MlValue("input", builtin::input);
if (name == "random") return MlValue("random", builtin::random);
if (name == "include") return MlValue("include", builtin::include);
if (name == "parse-csv") return MlValue("parse-csv", builtin::parse_csv);
if (name == "read-file") return MlValue("read-file", builtin::read_file);
if (name == "write-file") return MlValue("write-file", builtin::write_file);
if (name == "read-url") return MlValue("read-url", builtin::read_url);
if (name == "read-json") return MlValue("read-json", builtin::read_json);
if (name == "system-cmd") return MlValue("system-cmd", builtin::system_cmd);
if (name == "ls-dir") return MlValue("ls-dir", builtin::ls_dir);
if (name == "is-file?") return MlValue("is-file?", builtin::is_file);
if (name == "is-dir?") return MlValue("is-der?", builtin::is_dir);
if (name == "is-dir?") return MlValue("is-dir?", builtin::is_dir);
// parsing operations
if (name == "parse-csv") return MlValue("parse-csv", builtin::parse_csv);
if (name == "parse-json") return MlValue("parse-json", builtin::parse_json);
// Datetime operations
if (name == "get-universal-time") return MlValue("get-universal-time", builtin::get_universal_time);
if (name == "date-to-str") return MlValue("date-to-str", builtin::date_to_str);
if (name == "str-to-date") return MlValue("str-to-date", builtin::str_to_date);
if (name == "date-add") return MlValue("date-add", builtin::date_add);
// String operations
if (name == "debug") return MlValue("debug", builtin::debug);
@@ -1709,16 +1728,6 @@ MlValue MlEnvironment::get(const std::string &name) const {
throw MlError(MlValue::atom(name), *this, ATOM_NOT_DEFINED);
}
// load lisp std library
void load_std_lib(MlEnvironment &env) {
// TODO iterate through dir with files
std::string filename = "stdlib/stdlib.lisp";
MlEnvironment e;
MlValue result = run(read_file_contents(filename), e);
env.combine(e);
}
int main(int argc, const char **argv) {
MlEnvironment env;
std::vector<MlValue> args;