mlisp/ml.h

231 lines
5.4 KiB
C++

#pragma once
#include <map>
#include <string>
#include <vector>
#include <sstream>
#include <exception>
const std::string VERSION = "ml 0.3 (" __DATE__ " " __TIME__ ")";
const std::string STDLIB_LOADER =
R"(
(do (define ___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, MlValue value);
// Get vector of executables in this scope
std::vector<std::string> get_lambdas_list() 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, MlEnvironment const &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;
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 &);
class MlValue {
public:
// Constructs a nil value
MlValue();
// Constructs an integer
MlValue(long i);
// Constructs a floating point value
MlValue(double f);
// Constructs a bool value
MlValue(bool b);
// Constructs a list
MlValue(const std::vector<MlValue> &list);
// Construct a quoted value
static MlValue quote(const MlValue &quoted);
// Construct an atom
static MlValue atom(const std::string &s);
// Construct a string
static MlValue string(const std::string &s);
// Construct a nil
static MlValue nil();
// Construct a lambda function
MlValue(const std::vector<MlValue> &params, MlValue ret, MlEnvironment const &env);
// Construct a builtin function
MlValue(const std::string &name, Builtin b);
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_builtin() const;
bool is_number() const;
bool is_string() const;
bool is_list() const;
// Get the boolean value of this value.
bool as_bool() const;
// Get this item's integer value
long as_int() const;
// Get this item's floating point value
double as_float() const;
// Get this item's string value
std::string as_string() const;
// Get this item's atom value
std::string as_atom() const;
// Get this item's list value
std::vector<MlValue> as_list() const;
// Push an item to the end of this list
void push(MlValue val);
// Push an item from the end of this list
MlValue pop();
// Cast this to an integer value
MlValue cast_to_int() const;
// Cast this to a floating point value
MlValue cast_to_float() const;
// Cast this to a string
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:
enum {
QUOTE,
ATOM,
INT,
FLOAT,
LIST,
STRING,
LAMBDA,
BUILTIN,
NIL
} type;
union {
long i;
double f;
Builtin b;
} stack_data;
std::string str;
std::vector<MlValue> list;
MlEnvironment lambda_scope;
};