206 lines
5.4 KiB
C++
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 "ed); // 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> ¶ms, 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;
|
|
};
|