mlisp/ml.h

206 lines
5.4 KiB
C++

#pragma once
#include <map>
#include <string>
#include <vector>
#include <sstream>
#include <exception>
#ifdef NDEBUG
const std::string VERSION = "ml 0.5.1 (" __DATE__ " " __TIME__ "), Release";
#else
const std::string VERSION = "ml 0.5.1 (" __DATE__ " " __TIME__ "), Debug";
#endif
const std::string STDLIB_LOADER =
R"(
(do (def ___lib_path "/usr/local/var/mlisp")
(if (is-dir? ___lib_path)
(for file (ls-dir ___lib_path)
(if (string-regex? file "^stdlib\.lsp$")
(include (+ ___lib_path "/" file)))
)))
)";
// Forward declaration for MlEnvironment class definition
class MlValue;
// An instance of a function's scope.
class MlEnvironment {
public:
// Default constructor
MlEnvironment() : parent_scope(nullptr) {}
// Does this environment, or its parent environment,
// have this atom in scope?
// This is only used to determine which atoms to capture when
// creating a lambda function.
bool has(const std::string &name) const;
// Get the value associated with this name in this scope
MlValue get(const std::string &name) const;
// Set the value associated with this name in this scope
void set(const std::string &name, MlValue value);
// Set the value associated with this name in this scope and parent scopes
// and if not exists sets in this scope
void setX(const std::string &name, const MlValue& value);
// Get vector of executables in this scope
std::vector<std::string> get_lambdas_list(const std::string &token) const;
void combine(MlEnvironment const &other);
void set_parent_scope(MlEnvironment *parent) {
parent_scope = parent;
}
// Output this scope in readable form to a stream.
friend std::ostream &operator<<(std::ostream &os, MlEnvironment const &v);
private:
// The definitions in the scope.
std::map<std::string, MlValue> defs;
MlEnvironment *parent_scope;
};
// An exception thrown by the lisp
class MlError : public std::exception {
public:
MlError() = delete;
// Create an error with the value that caused the error,
// the scope where the error was found, and the message.
MlError(const MlValue &v, const MlEnvironment &env, const char *msg);
// Copy constructor is needed to prevent double frees
MlError(MlError const &other);
~MlError();
// Get the printable error description.
std::string description() const;
const char * what() const noexcept override;
private:
MlValue *cause;
MlEnvironment env;
const char *msg;
};
// The type for a builtin function, which takes a list of values,
// and the environment to run the function in.
typedef MlValue (*Builtin)(std::vector<MlValue>, MlEnvironment &);
// friend class
class MlPerfMon;
class MlValue {
public:
enum Type {
QUOTE,
ATOM,
INT,
FLOAT,
LIST,
STRING,
LAMBDA,
MACRO,
BUILTIN,
NIL,
TRUE
} type;
public:
MlValue(); // Constructs a nil value
MlValue(long i);
MlValue(double f);
MlValue(bool b);
MlValue(std::vector<MlValue> list); // Constructs a list
MlValue(const std::vector<std::string> &slist); // Constructs a list from vector of strings
static MlValue quote(const MlValue &quoted); // Construct a quoted value
static MlValue atom(const std::string &s);
static MlValue string(const std::string &s);
static MlValue nil();
MlValue(const std::vector<MlValue> &params, MlValue ret, MlEnvironment const &env, const Type ftype); // Construct a lambda or macro function
MlValue(const std::string &name, Builtin b); // Construct a builtin function
std::vector<std::string> get_used_atoms();
// Apply this as a function to a list of arguments in a given environment.
MlValue apply(std::vector<MlValue> args, MlEnvironment &env);
// Evaluate this value as lisp code.
MlValue eval(MlEnvironment &env);
bool is_nil() const;
bool is_builtin() const;
bool is_macro() const;
bool is_number() const;
bool is_string() const;
bool is_list() const;
bool as_bool() const;
long as_int() const;
double as_float() const;
std::string as_string() const;
std::string as_atom() const;
std::vector<MlValue> as_list() const;
// Push an item to the end of this list
void push(const MlValue& val);
// Push an item from the end of this list
MlValue pop();
MlValue cast_to_int() const;
MlValue cast_to_float() const;
MlValue cast_to_string() const;
bool operator==(MlValue other) const;
bool operator!=(const MlValue &other) const;
bool operator>=(const MlValue &other) const;
bool operator<=(const MlValue &other) const;
bool operator>(const MlValue &other) const;
bool operator<(const MlValue &other) const;
MlValue operator+(const MlValue &other) const;
MlValue operator-(const MlValue &other) const;
MlValue operator*(const MlValue &other) const;
MlValue operator/(const MlValue &other) const;
MlValue operator%(const MlValue &other) const;
// Get the name of the type of this value
std::string get_type_name() const;
std::string display() const;
std::string debug() const;
friend std::ostream &operator<<(std::ostream &os, MlValue const &v);
private:
union {
long i;
double f;
Builtin b;
} stack_data;
std::string str;
std::vector<MlValue> list;
MlEnvironment lambda_scope;
friend class MlPerfMon;
};