Compare commits
15
Commits
21f0d8fbd8
...
ba7281b6f1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba7281b6f1 | ||
|
|
b9feb8e8b6 | ||
|
|
e39862fe9f | ||
|
|
93af6151fa | ||
|
|
9b14ea974a | ||
|
|
25d6f45329 | ||
|
|
835669c4eb | ||
|
|
22920cb810 | ||
|
|
3d5a2e3fbe | ||
|
|
088c5f0248 | ||
|
|
03918b036d | ||
|
|
5f49f08eea | ||
|
|
ed9fa1698e | ||
|
|
f35fea9fa4 | ||
|
|
6e1557ff8c |
@@ -103,3 +103,7 @@ add_dependencies(test4 ${PROJECT})
|
|||||||
add_custom_target(test5
|
add_custom_target(test5
|
||||||
COMMAND env STEP=step_env MAL_IMPL=js ../vendor/mal/runtest.py --deferrable --optional ../vendor/mal/tests/step5_tco.mal -- ./${PROJECT})
|
COMMAND env STEP=step_env MAL_IMPL=js ../vendor/mal/runtest.py --deferrable --optional ../vendor/mal/tests/step5_tco.mal -- ./${PROJECT})
|
||||||
add_dependencies(test5 ${PROJECT})
|
add_dependencies(test5 ${PROJECT})
|
||||||
|
|
||||||
|
add_custom_target(test6
|
||||||
|
COMMAND env STEP=step_env MAL_IMPL=js ../vendor/mal/runtest.py --deferrable --optional ../vendor/mal/tests/step6_file.mal -- ./${PROJECT})
|
||||||
|
add_dependencies(test6 ${PROJECT})
|
||||||
|
|||||||
+20
-5
@@ -16,15 +16,23 @@
|
|||||||
|
|
||||||
namespace blaze {
|
namespace blaze {
|
||||||
|
|
||||||
void Collection::add(ASTNodePtr node)
|
void Collection::add(ValuePtr node)
|
||||||
{
|
{
|
||||||
|
if (node == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_nodes.push_back(node);
|
m_nodes.push_back(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
void HashMap::addElement(const std::string& key, ASTNodePtr value)
|
void HashMap::add(const std::string& key, ValuePtr value)
|
||||||
{
|
{
|
||||||
|
if (value == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_elements.emplace(key, value);
|
m_elements.emplace(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +66,7 @@ Symbol::Symbol(const std::string& symbol)
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
Value::Value(State state)
|
Constant::Constant(State state)
|
||||||
: m_state(state)
|
: m_state(state)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -73,18 +81,25 @@ Function::Function(const std::string& name, FunctionType function)
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
Lambda::Lambda(std::vector<std::string> bindings, ASTNodePtr body, EnvironmentPtr env)
|
Lambda::Lambda(std::vector<std::string> bindings, ValuePtr body, EnvironmentPtr env)
|
||||||
: m_bindings(bindings)
|
: m_bindings(bindings)
|
||||||
, m_body(body)
|
, m_body(body)
|
||||||
, m_env(env)
|
, m_env(env)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
Atom::Atom(ValuePtr pointer)
|
||||||
|
: m_value(pointer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blaze
|
} // namespace blaze
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
void Formatter<blaze::ASTNodePtr>::format(Builder& builder, blaze::ASTNodePtr value) const
|
void Formatter<blaze::ValuePtr>::format(Builder& builder, blaze::ValuePtr value) const
|
||||||
{
|
{
|
||||||
blaze::Printer printer;
|
blaze::Printer printer;
|
||||||
return Formatter<std::string>::format(builder, printer.printNoErrorCheck(value));
|
return Formatter<std::string>::format(builder, printer.printNoErrorCheck(value));
|
||||||
|
|||||||
@@ -23,9 +23,9 @@
|
|||||||
|
|
||||||
namespace blaze {
|
namespace blaze {
|
||||||
|
|
||||||
class ASTNode {
|
class Value {
|
||||||
public:
|
public:
|
||||||
virtual ~ASTNode() = default;
|
virtual ~Value() = default;
|
||||||
|
|
||||||
std::string className() const { return typeid(*this).name(); }
|
std::string className() const { return typeid(*this).name(); }
|
||||||
|
|
||||||
@@ -39,34 +39,36 @@ public:
|
|||||||
virtual bool isString() const { return false; }
|
virtual bool isString() const { return false; }
|
||||||
virtual bool isKeyword() const { return false; }
|
virtual bool isKeyword() const { return false; }
|
||||||
virtual bool isNumber() const { return false; }
|
virtual bool isNumber() const { return false; }
|
||||||
virtual bool isValue() const { return false; }
|
virtual bool isConstant() const { return false; }
|
||||||
virtual bool isSymbol() const { return false; }
|
virtual bool isSymbol() const { return false; }
|
||||||
|
virtual bool isCallable() const { return false; }
|
||||||
virtual bool isFunction() const { return false; }
|
virtual bool isFunction() const { return false; }
|
||||||
virtual bool isLambda() const { return false; }
|
virtual bool isLambda() const { return false; }
|
||||||
|
virtual bool isAtom() const { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ASTNode() {}
|
Value() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
class Collection : public ASTNode {
|
class Collection : public Value {
|
||||||
public:
|
public:
|
||||||
virtual ~Collection() = default;
|
virtual ~Collection() = default;
|
||||||
|
|
||||||
virtual bool isCollection() const override { return true; }
|
void add(ValuePtr node);
|
||||||
|
|
||||||
void add(ASTNodePtr node);
|
const std::list<ValuePtr>& nodes() const { return m_nodes; }
|
||||||
|
|
||||||
const std::list<ASTNodePtr>& nodes() const { return m_nodes; }
|
|
||||||
size_t size() const { return m_nodes.size(); }
|
size_t size() const { return m_nodes.size(); }
|
||||||
bool empty() const { return m_nodes.size() == 0; }
|
bool empty() const { return m_nodes.size() == 0; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Collection() {}
|
Collection() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::list<ASTNodePtr> m_nodes;
|
virtual bool isCollection() const override { return true; }
|
||||||
|
|
||||||
|
std::list<ValuePtr> m_nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
@@ -77,6 +79,7 @@ public:
|
|||||||
List() = default;
|
List() = default;
|
||||||
virtual ~List() = default;
|
virtual ~List() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
virtual bool isList() const override { return true; }
|
virtual bool isList() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,51 +91,52 @@ public:
|
|||||||
Vector() = default;
|
Vector() = default;
|
||||||
virtual ~Vector() = default;
|
virtual ~Vector() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
virtual bool isVector() const override { return true; }
|
virtual bool isVector() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// {}
|
// {}
|
||||||
class HashMap final : public ASTNode {
|
class HashMap final : public Value {
|
||||||
public:
|
public:
|
||||||
HashMap() = default;
|
HashMap() = default;
|
||||||
virtual ~HashMap() = default;
|
virtual ~HashMap() = default;
|
||||||
|
|
||||||
virtual bool isHashMap() const override { return true; }
|
void add(const std::string& key, ValuePtr value);
|
||||||
|
|
||||||
void addElement(const std::string& key, ASTNodePtr value);
|
const std::unordered_map<std::string, ValuePtr>& elements() const { return m_elements; }
|
||||||
|
|
||||||
const std::unordered_map<std::string, ASTNodePtr>& elements() const { return m_elements; }
|
|
||||||
size_t size() const { return m_elements.size(); }
|
size_t size() const { return m_elements.size(); }
|
||||||
bool empty() const { return m_elements.size() == 0; }
|
bool empty() const { return m_elements.size() == 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, ASTNodePtr> m_elements;
|
virtual bool isHashMap() const override { return true; }
|
||||||
|
|
||||||
|
std::unordered_map<std::string, ValuePtr> m_elements;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// "string"
|
// "string"
|
||||||
class String final : public ASTNode {
|
class String final : public Value {
|
||||||
public:
|
public:
|
||||||
explicit String(const std::string& data);
|
String(const std::string& data);
|
||||||
virtual ~String() = default;
|
virtual ~String() = default;
|
||||||
|
|
||||||
virtual bool isString() const override { return true; }
|
|
||||||
|
|
||||||
const std::string& data() const { return m_data; }
|
const std::string& data() const { return m_data; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_data;
|
virtual bool isString() const override { return true; }
|
||||||
|
|
||||||
|
const std::string m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// :keyword
|
// :keyword
|
||||||
class Keyword final : public ASTNode {
|
class Keyword final : public Value {
|
||||||
public:
|
public:
|
||||||
explicit Keyword(const std::string& data);
|
Keyword(const std::string& data);
|
||||||
virtual ~Keyword() = default;
|
virtual ~Keyword() = default;
|
||||||
|
|
||||||
virtual bool isKeyword() const override { return true; }
|
virtual bool isKeyword() const override { return true; }
|
||||||
@@ -140,28 +144,28 @@ public:
|
|||||||
const std::string& keyword() const { return m_data; }
|
const std::string& keyword() const { return m_data; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_data;
|
const std::string m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// 123
|
// 123
|
||||||
class Number final : public ASTNode {
|
class Number final : public Value {
|
||||||
public:
|
public:
|
||||||
explicit Number(int64_t number);
|
Number(int64_t number);
|
||||||
virtual ~Number() = default;
|
virtual ~Number() = default;
|
||||||
|
|
||||||
virtual bool isNumber() const override { return true; }
|
|
||||||
|
|
||||||
int64_t number() const { return m_number; }
|
int64_t number() const { return m_number; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t m_number { 0 };
|
virtual bool isNumber() const override { return true; }
|
||||||
|
|
||||||
|
const int64_t m_number { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// true, false, nil
|
// true, false, nil
|
||||||
class Value final : public ASTNode {
|
class Constant final : public Value {
|
||||||
public:
|
public:
|
||||||
enum State : uint8_t {
|
enum State : uint8_t {
|
||||||
Nil,
|
Nil,
|
||||||
@@ -169,69 +173,99 @@ public:
|
|||||||
False,
|
False,
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Value(State state);
|
Constant(State state);
|
||||||
virtual ~Value() = default;
|
virtual ~Constant() = default;
|
||||||
|
|
||||||
virtual bool isValue() const override { return true; }
|
|
||||||
|
|
||||||
State state() const { return m_state; }
|
State state() const { return m_state; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
State m_state;
|
virtual bool isConstant() const override { return true; }
|
||||||
|
|
||||||
|
const State m_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// Symbols
|
// Symbols
|
||||||
class Symbol final : public ASTNode {
|
class Symbol final : public Value {
|
||||||
public:
|
public:
|
||||||
explicit Symbol(const std::string& symbol);
|
Symbol(const std::string& symbol);
|
||||||
virtual ~Symbol() = default;
|
virtual ~Symbol() = default;
|
||||||
|
|
||||||
virtual bool isSymbol() const override { return true; }
|
|
||||||
|
|
||||||
const std::string& symbol() const { return m_symbol; }
|
const std::string& symbol() const { return m_symbol; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_symbol;
|
virtual bool isSymbol() const override { return true; }
|
||||||
|
|
||||||
|
const std::string m_symbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
using FunctionType = std::function<ASTNodePtr(std::list<ASTNodePtr>)>;
|
class Callable : public Value {
|
||||||
|
|
||||||
class Function final : public ASTNode {
|
|
||||||
public:
|
public:
|
||||||
explicit Function(const std::string& name, FunctionType function);
|
virtual ~Callable() = default;
|
||||||
virtual ~Function() = default;
|
|
||||||
|
|
||||||
virtual bool isFunction() const override { return true; }
|
protected:
|
||||||
|
Callable() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool isCallable() const override { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
using FunctionType = std::function<ValuePtr(std::list<ValuePtr>)>;
|
||||||
|
|
||||||
|
class Function final : public Callable {
|
||||||
|
public:
|
||||||
|
Function(const std::string& name, FunctionType function);
|
||||||
|
virtual ~Function() = default;
|
||||||
|
|
||||||
const std::string& name() const { return m_name; }
|
const std::string& name() const { return m_name; }
|
||||||
FunctionType function() const { return m_function; }
|
FunctionType function() const { return m_function; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual bool isFunction() const override { return true; }
|
||||||
|
|
||||||
const std::string m_name;
|
const std::string m_name;
|
||||||
FunctionType m_function;
|
const FunctionType m_function;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
class Lambda final : public ASTNode {
|
class Lambda final : public Callable {
|
||||||
public:
|
public:
|
||||||
Lambda(std::vector<std::string> bindings, ASTNodePtr body, EnvironmentPtr env);
|
Lambda(std::vector<std::string> bindings, ValuePtr body, EnvironmentPtr env);
|
||||||
virtual ~Lambda() = default;
|
virtual ~Lambda() = default;
|
||||||
|
|
||||||
virtual bool isLambda() const override { return true; }
|
|
||||||
|
|
||||||
std::vector<std::string> bindings() const { return m_bindings; }
|
std::vector<std::string> bindings() const { return m_bindings; }
|
||||||
ASTNodePtr body() const { return m_body; }
|
ValuePtr body() const { return m_body; }
|
||||||
EnvironmentPtr env() const { return m_env; }
|
EnvironmentPtr env() const { return m_env; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> m_bindings;
|
virtual bool isLambda() const override { return true; }
|
||||||
ASTNodePtr m_body;
|
|
||||||
EnvironmentPtr m_env;
|
const std::vector<std::string> m_bindings;
|
||||||
|
const ValuePtr m_body;
|
||||||
|
const EnvironmentPtr m_env;
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
class Atom final : public Value {
|
||||||
|
public:
|
||||||
|
Atom() = default;
|
||||||
|
Atom(ValuePtr pointer);
|
||||||
|
virtual ~Atom() = default;
|
||||||
|
|
||||||
|
ValuePtr reset(ValuePtr value) { return m_value = value; }
|
||||||
|
ValuePtr deref() const { return m_value; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool isAtom() const override { return true; }
|
||||||
|
|
||||||
|
ValuePtr m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
@@ -246,37 +280,43 @@ std::shared_ptr<T> makePtr(Args&&... args)
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<Collection>() const { return isCollection(); }
|
inline bool Value::fastIs<Collection>() const { return isCollection(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<List>() const { return isList(); }
|
inline bool Value::fastIs<List>() const { return isList(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<Vector>() const { return isVector(); }
|
inline bool Value::fastIs<Vector>() const { return isVector(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<HashMap>() const { return isHashMap(); }
|
inline bool Value::fastIs<HashMap>() const { return isHashMap(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<String>() const { return isString(); }
|
inline bool Value::fastIs<String>() const { return isString(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<Keyword>() const { return isKeyword(); }
|
inline bool Value::fastIs<Keyword>() const { return isKeyword(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<Number>() const { return isNumber(); }
|
inline bool Value::fastIs<Number>() const { return isNumber(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<Value>() const { return isValue(); }
|
inline bool Value::fastIs<Constant>() const { return isConstant(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<Symbol>() const { return isSymbol(); }
|
inline bool Value::fastIs<Symbol>() const { return isSymbol(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<Function>() const { return isFunction(); }
|
inline bool Value::fastIs<Callable>() const { return isCallable(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<Lambda>() const { return isLambda(); }
|
inline bool Value::fastIs<Function>() const { return isFunction(); }
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool Value::fastIs<Lambda>() const { return isLambda(); }
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool Value::fastIs<Atom>() const { return isAtom(); }
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
} // namespace blaze
|
} // namespace blaze
|
||||||
@@ -284,6 +324,6 @@ inline bool ASTNode::fastIs<Lambda>() const { return isLambda(); }
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct ruc::format::Formatter<blaze::ASTNodePtr> : public Formatter<std::string> {
|
struct ruc::format::Formatter<blaze::ValuePtr> : public Formatter<std::string> {
|
||||||
void format(Builder& builder, blaze::ASTNodePtr value) const;
|
void format(Builder& builder, blaze::ValuePtr value) const;
|
||||||
};
|
};
|
||||||
|
|||||||
+3
-3
@@ -29,7 +29,7 @@ EnvironmentPtr Environment::create(EnvironmentPtr outer)
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnvironmentPtr Environment::create(const ASTNodePtr lambda, std::list<ASTNodePtr> arguments)
|
EnvironmentPtr Environment::create(const ValuePtr lambda, std::list<ValuePtr> arguments)
|
||||||
{
|
{
|
||||||
auto lambda_casted = std::static_pointer_cast<Lambda>(lambda);
|
auto lambda_casted = std::static_pointer_cast<Lambda>(lambda);
|
||||||
auto env = create(lambda_casted->env());
|
auto env = create(lambda_casted->env());
|
||||||
@@ -75,7 +75,7 @@ bool Environment::exists(const std::string& symbol)
|
|||||||
return m_values.find(symbol) != m_values.end();
|
return m_values.find(symbol) != m_values.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Environment::set(const std::string& symbol, ASTNodePtr value)
|
ValuePtr Environment::set(const std::string& symbol, ValuePtr value)
|
||||||
{
|
{
|
||||||
if (exists(symbol)) {
|
if (exists(symbol)) {
|
||||||
m_values.erase(symbol);
|
m_values.erase(symbol);
|
||||||
@@ -86,7 +86,7 @@ ASTNodePtr Environment::set(const std::string& symbol, ASTNodePtr value)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Environment::get(const std::string& symbol)
|
ValuePtr Environment::get(const std::string& symbol)
|
||||||
{
|
{
|
||||||
if (exists(symbol)) {
|
if (exists(symbol)) {
|
||||||
return m_values[symbol];
|
return m_values[symbol];
|
||||||
|
|||||||
+4
-4
@@ -21,17 +21,17 @@ public:
|
|||||||
// Factory functions instead of constructors because it can fail in the bindings/arguments case
|
// Factory functions instead of constructors because it can fail in the bindings/arguments case
|
||||||
static EnvironmentPtr create();
|
static EnvironmentPtr create();
|
||||||
static EnvironmentPtr create(EnvironmentPtr outer);
|
static EnvironmentPtr create(EnvironmentPtr outer);
|
||||||
static EnvironmentPtr create(const ASTNodePtr lambda, std::list<ASTNodePtr> arguments);
|
static EnvironmentPtr create(const ValuePtr lambda, std::list<ValuePtr> arguments);
|
||||||
|
|
||||||
bool exists(const std::string& symbol);
|
bool exists(const std::string& symbol);
|
||||||
ASTNodePtr set(const std::string& symbol, ASTNodePtr value);
|
ValuePtr set(const std::string& symbol, ValuePtr value);
|
||||||
ASTNodePtr get(const std::string& symbol);
|
ValuePtr get(const std::string& symbol);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Environment() {}
|
Environment() {}
|
||||||
|
|
||||||
EnvironmentPtr m_outer { nullptr };
|
EnvironmentPtr m_outer { nullptr };
|
||||||
std::unordered_map<std::string, ASTNodePtr> m_values;
|
std::unordered_map<std::string, ValuePtr> m_values;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blaze
|
} // namespace blaze
|
||||||
|
|||||||
+21
-21
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
namespace blaze {
|
namespace blaze {
|
||||||
|
|
||||||
Eval::Eval(ASTNodePtr ast, EnvironmentPtr env)
|
Eval::Eval(ValuePtr ast, EnvironmentPtr env)
|
||||||
: m_ast(ast)
|
: m_ast(ast)
|
||||||
, m_env(env)
|
, m_env(env)
|
||||||
{
|
{
|
||||||
@@ -29,7 +29,7 @@ Eval::Eval(ASTNodePtr ast, EnvironmentPtr env)
|
|||||||
|
|
||||||
void Eval::eval()
|
void Eval::eval()
|
||||||
{
|
{
|
||||||
m_ast_stack = std::stack<ASTNodePtr>();
|
m_ast_stack = std::stack<ValuePtr>();
|
||||||
m_env_stack = std::stack<EnvironmentPtr>();
|
m_env_stack = std::stack<EnvironmentPtr>();
|
||||||
m_ast_stack.push(m_ast);
|
m_ast_stack.push(m_ast);
|
||||||
m_env_stack.push(m_env);
|
m_env_stack.push(m_env);
|
||||||
@@ -37,9 +37,9 @@ void Eval::eval()
|
|||||||
m_ast = evalImpl();
|
m_ast = evalImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Eval::evalImpl()
|
ValuePtr Eval::evalImpl()
|
||||||
{
|
{
|
||||||
ASTNodePtr ast = nullptr;
|
ValuePtr ast = nullptr;
|
||||||
EnvironmentPtr env = nullptr;
|
EnvironmentPtr env = nullptr;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -117,13 +117,13 @@ ASTNodePtr Eval::evalImpl()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Eval::evalAst(ASTNodePtr ast, EnvironmentPtr env)
|
ValuePtr Eval::evalAst(ValuePtr ast, EnvironmentPtr env)
|
||||||
{
|
{
|
||||||
if (ast == nullptr || env == nullptr) {
|
if (ast == nullptr || env == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNode* ast_raw_ptr = ast.get();
|
Value* ast_raw_ptr = ast.get();
|
||||||
if (is<Symbol>(ast_raw_ptr)) {
|
if (is<Symbol>(ast_raw_ptr)) {
|
||||||
auto result = env->get(std::static_pointer_cast<Symbol>(ast)->symbol());
|
auto result = env->get(std::static_pointer_cast<Symbol>(ast)->symbol());
|
||||||
if (!result) {
|
if (!result) {
|
||||||
@@ -139,7 +139,7 @@ ASTNodePtr Eval::evalAst(ASTNodePtr ast, EnvironmentPtr env)
|
|||||||
for (auto node : nodes) {
|
for (auto node : nodes) {
|
||||||
m_ast_stack.push(node);
|
m_ast_stack.push(node);
|
||||||
m_env_stack.push(env);
|
m_env_stack.push(env);
|
||||||
ASTNodePtr eval_node = evalImpl();
|
ValuePtr eval_node = evalImpl();
|
||||||
if (eval_node == nullptr) {
|
if (eval_node == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -153,11 +153,11 @@ ASTNodePtr Eval::evalAst(ASTNodePtr ast, EnvironmentPtr env)
|
|||||||
for (auto& element : elements) {
|
for (auto& element : elements) {
|
||||||
m_ast_stack.push(element.second);
|
m_ast_stack.push(element.second);
|
||||||
m_env_stack.push(env);
|
m_env_stack.push(env);
|
||||||
ASTNodePtr element_node = evalImpl();
|
ValuePtr element_node = evalImpl();
|
||||||
if (element_node == nullptr) {
|
if (element_node == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
result->addElement(element.first, element_node);
|
result->add(element.first, element_node);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ ASTNodePtr Eval::evalAst(ASTNodePtr ast, EnvironmentPtr env)
|
|||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Eval::evalDef(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
ValuePtr Eval::evalDef(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
|
||||||
{
|
{
|
||||||
if (nodes.size() != 2) {
|
if (nodes.size() != 2) {
|
||||||
Error::the().add(format("wrong number of arguments: def!, {}", nodes.size()));
|
Error::the().add(format("wrong number of arguments: def!, {}", nodes.size()));
|
||||||
@@ -184,7 +184,7 @@ ASTNodePtr Eval::evalDef(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
|||||||
std::string symbol = std::static_pointer_cast<Symbol>(first_argument)->symbol();
|
std::string symbol = std::static_pointer_cast<Symbol>(first_argument)->symbol();
|
||||||
m_ast_stack.push(second_argument);
|
m_ast_stack.push(second_argument);
|
||||||
m_env_stack.push(env);
|
m_env_stack.push(env);
|
||||||
ASTNodePtr value = evalImpl();
|
ValuePtr value = evalImpl();
|
||||||
|
|
||||||
// Dont overwrite symbols after an error
|
// Dont overwrite symbols after an error
|
||||||
if (Error::the().hasAnyError()) {
|
if (Error::the().hasAnyError()) {
|
||||||
@@ -195,7 +195,7 @@ ASTNodePtr Eval::evalDef(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
|||||||
return env->set(symbol, value);
|
return env->set(symbol, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Eval::evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
void Eval::evalLet(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
|
||||||
{
|
{
|
||||||
if (nodes.size() != 2) {
|
if (nodes.size() != 2) {
|
||||||
Error::the().add(format("wrong number of arguments: let*, {}", nodes.size()));
|
Error::the().add(format("wrong number of arguments: let*, {}", nodes.size()));
|
||||||
@@ -212,7 +212,7 @@ void Eval::evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the nodes out of the List or Vector
|
// Get the nodes out of the List or Vector
|
||||||
std::list<ASTNodePtr> binding_nodes;
|
std::list<ValuePtr> binding_nodes;
|
||||||
auto bindings = std::static_pointer_cast<Collection>(first_argument);
|
auto bindings = std::static_pointer_cast<Collection>(first_argument);
|
||||||
binding_nodes = bindings->nodes();
|
binding_nodes = bindings->nodes();
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ void Eval::evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
|||||||
std::string key = std::static_pointer_cast<Symbol>(*it)->symbol();
|
std::string key = std::static_pointer_cast<Symbol>(*it)->symbol();
|
||||||
m_ast_stack.push(*std::next(it));
|
m_ast_stack.push(*std::next(it));
|
||||||
m_env_stack.push(let_env);
|
m_env_stack.push(let_env);
|
||||||
ASTNodePtr value = evalImpl();
|
ValuePtr value = evalImpl();
|
||||||
let_env->set(key, value);
|
let_env->set(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ void Eval::evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
|||||||
return; // TCO
|
return; // TCO
|
||||||
}
|
}
|
||||||
|
|
||||||
void Eval::evalDo(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
void Eval::evalDo(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
|
||||||
{
|
{
|
||||||
if (nodes.size() == 0) {
|
if (nodes.size() == 0) {
|
||||||
Error::the().add(format("wrong number of arguments: do, {}", nodes.size()));
|
Error::the().add(format("wrong number of arguments: do, {}", nodes.size()));
|
||||||
@@ -267,7 +267,7 @@ void Eval::evalDo(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
|||||||
return; // TCO
|
return; // TCO
|
||||||
}
|
}
|
||||||
|
|
||||||
void Eval::evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
void Eval::evalIf(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
|
||||||
{
|
{
|
||||||
if (nodes.size() != 2 && nodes.size() != 3) {
|
if (nodes.size() != 2 && nodes.size() != 3) {
|
||||||
Error::the().add(format("wrong number of arguments: if, {}", nodes.size()));
|
Error::the().add(format("wrong number of arguments: if, {}", nodes.size()));
|
||||||
@@ -276,13 +276,13 @@ void Eval::evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
|||||||
|
|
||||||
auto first_argument = *nodes.begin();
|
auto first_argument = *nodes.begin();
|
||||||
auto second_argument = *std::next(nodes.begin());
|
auto second_argument = *std::next(nodes.begin());
|
||||||
auto third_argument = (nodes.size() == 3) ? *std::next(std::next(nodes.begin())) : makePtr<Value>(Value::Nil);
|
auto third_argument = (nodes.size() == 3) ? *std::next(std::next(nodes.begin())) : makePtr<Constant>(Constant::Nil);
|
||||||
|
|
||||||
m_ast_stack.push(first_argument);
|
m_ast_stack.push(first_argument);
|
||||||
m_env_stack.push(env);
|
m_env_stack.push(env);
|
||||||
auto first_evaluated = evalImpl();
|
auto first_evaluated = evalImpl();
|
||||||
if (!is<Value>(first_evaluated.get())
|
if (!is<Constant>(first_evaluated.get())
|
||||||
|| std::static_pointer_cast<Value>(first_evaluated)->state() == Value::True) {
|
|| std::static_pointer_cast<Constant>(first_evaluated)->state() == Constant::True) {
|
||||||
m_ast_stack.push(second_argument);
|
m_ast_stack.push(second_argument);
|
||||||
m_env_stack.push(env);
|
m_env_stack.push(env);
|
||||||
return; // TCO
|
return; // TCO
|
||||||
@@ -309,7 +309,7 @@ void Eval::evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
|||||||
AST_CHECK(type, value) \
|
AST_CHECK(type, value) \
|
||||||
auto variable = std::static_pointer_cast<type>(value);
|
auto variable = std::static_pointer_cast<type>(value);
|
||||||
|
|
||||||
ASTNodePtr Eval::evalFn(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
ValuePtr Eval::evalFn(const std::list<ValuePtr>& nodes, EnvironmentPtr env)
|
||||||
{
|
{
|
||||||
ARG_COUNT_CHECK("fn*", nodes.size() != 2, nodes.size());
|
ARG_COUNT_CHECK("fn*", nodes.size() != 2, nodes.size());
|
||||||
|
|
||||||
@@ -329,7 +329,7 @@ ASTNodePtr Eval::evalFn(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env)
|
|||||||
return makePtr<Lambda>(bindings, second_argument, env);
|
return makePtr<Lambda>(bindings, second_argument, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Eval::apply(std::shared_ptr<List> evaluated_list)
|
ValuePtr Eval::apply(std::shared_ptr<List> evaluated_list)
|
||||||
{
|
{
|
||||||
if (evaluated_list == nullptr) {
|
if (evaluated_list == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
+12
-12
@@ -18,27 +18,27 @@ class List;
|
|||||||
|
|
||||||
class Eval {
|
class Eval {
|
||||||
public:
|
public:
|
||||||
Eval(ASTNodePtr ast, EnvironmentPtr env);
|
Eval(ValuePtr ast, EnvironmentPtr env);
|
||||||
virtual ~Eval() = default;
|
virtual ~Eval() = default;
|
||||||
|
|
||||||
void eval();
|
void eval();
|
||||||
|
|
||||||
ASTNodePtr ast() const { return m_ast; }
|
ValuePtr ast() const { return m_ast; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTNodePtr evalImpl();
|
ValuePtr evalImpl();
|
||||||
ASTNodePtr evalAst(ASTNodePtr ast, EnvironmentPtr env);
|
ValuePtr evalAst(ValuePtr ast, EnvironmentPtr env);
|
||||||
ASTNodePtr evalDef(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
|
ValuePtr evalDef(const std::list<ValuePtr>& nodes, EnvironmentPtr env);
|
||||||
void evalLet(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
|
void evalLet(const std::list<ValuePtr>& nodes, EnvironmentPtr env);
|
||||||
void evalDo(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
|
void evalDo(const std::list<ValuePtr>& nodes, EnvironmentPtr env);
|
||||||
void evalIf(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
|
void evalIf(const std::list<ValuePtr>& nodes, EnvironmentPtr env);
|
||||||
ASTNodePtr evalFn(const std::list<ASTNodePtr>& nodes, EnvironmentPtr env);
|
ValuePtr evalFn(const std::list<ValuePtr>& nodes, EnvironmentPtr env);
|
||||||
ASTNodePtr apply(std::shared_ptr<List> evaluated_list);
|
ValuePtr apply(std::shared_ptr<List> evaluated_list);
|
||||||
|
|
||||||
ASTNodePtr m_ast;
|
ValuePtr m_ast;
|
||||||
EnvironmentPtr m_env;
|
EnvironmentPtr m_env;
|
||||||
|
|
||||||
std::stack<ASTNodePtr> m_ast_stack;
|
std::stack<ValuePtr> m_ast_stack;
|
||||||
std::stack<EnvironmentPtr> m_env_stack;
|
std::stack<EnvironmentPtr> m_env_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -13,8 +13,8 @@ namespace blaze {
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// Types
|
// Types
|
||||||
|
|
||||||
class ASTNode;
|
class Value;
|
||||||
typedef std::shared_ptr<ASTNode> ASTNodePtr;
|
typedef std::shared_ptr<Value> ValuePtr;
|
||||||
|
|
||||||
class Environment;
|
class Environment;
|
||||||
typedef std::shared_ptr<Environment> EnvironmentPtr;
|
typedef std::shared_ptr<Environment> EnvironmentPtr;
|
||||||
@@ -22,6 +22,9 @@ typedef std::shared_ptr<Environment> EnvironmentPtr;
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// Functions
|
// Functions
|
||||||
|
|
||||||
|
extern ValuePtr read(std::string_view input);
|
||||||
|
ValuePtr eval(ValuePtr ast, EnvironmentPtr env);
|
||||||
|
|
||||||
extern void installFunctions(EnvironmentPtr env);
|
extern void installFunctions(EnvironmentPtr env);
|
||||||
|
|
||||||
} // namespace blaze
|
} // namespace blaze
|
||||||
|
|||||||
+211
-42
@@ -7,6 +7,7 @@
|
|||||||
#include <memory> // std::static_pointer_cast
|
#include <memory> // std::static_pointer_cast
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "ruc/file.h"
|
||||||
#include "ruc/format/format.h"
|
#include "ruc/format/format.h"
|
||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
@@ -34,7 +35,7 @@
|
|||||||
static struct FUNCTION_STRUCT_NAME(unique) \
|
static struct FUNCTION_STRUCT_NAME(unique) \
|
||||||
FUNCTION_STRUCT_NAME(unique)( \
|
FUNCTION_STRUCT_NAME(unique)( \
|
||||||
symbol, \
|
symbol, \
|
||||||
[](std::list<ASTNodePtr> nodes) -> ASTNodePtr lambda);
|
[](std::list<ValuePtr> nodes) -> ValuePtr lambda);
|
||||||
|
|
||||||
#define ADD_FUNCTION(symbol, lambda) ADD_FUNCTION_IMPL(__LINE__, symbol, lambda);
|
#define ADD_FUNCTION(symbol, lambda) ADD_FUNCTION_IMPL(__LINE__, symbol, lambda);
|
||||||
|
|
||||||
@@ -129,36 +130,36 @@ ADD_FUNCTION(
|
|||||||
|
|
||||||
// // -----------------------------------------
|
// // -----------------------------------------
|
||||||
|
|
||||||
#define NUMBER_COMPARE(operator) \
|
#define NUMBER_COMPARE(operator) \
|
||||||
{ \
|
{ \
|
||||||
bool result = true; \
|
bool result = true; \
|
||||||
\
|
\
|
||||||
if (nodes.size() < 2) { \
|
if (nodes.size() < 2) { \
|
||||||
Error::the().add(format("wrong number of arguments: {}, {}", #operator, nodes.size() - 1)); \
|
Error::the().add(format("wrong number of arguments: {}, {}", #operator, nodes.size())); \
|
||||||
return nullptr; \
|
return nullptr; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
for (auto node : nodes) { \
|
for (auto node : nodes) { \
|
||||||
if (!is<Number>(node.get())) { \
|
if (!is<Number>(node.get())) { \
|
||||||
Error::the().add(format("wrong argument type: number, '{}'", node)); \
|
Error::the().add(format("wrong argument type: number, '{}'", node)); \
|
||||||
return nullptr; \
|
return nullptr; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* Start with the first number */ \
|
/* Start with the first number */ \
|
||||||
int64_t number = std::static_pointer_cast<Number>(nodes.front())->number(); \
|
int64_t number = std::static_pointer_cast<Number>(nodes.front())->number(); \
|
||||||
\
|
\
|
||||||
/* Skip the first node */ \
|
/* Skip the first node */ \
|
||||||
for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) { \
|
for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) { \
|
||||||
int64_t current_number = std::static_pointer_cast<Number>(*it)->number(); \
|
int64_t current_number = std::static_pointer_cast<Number>(*it)->number(); \
|
||||||
if (!(number operator current_number)) { \
|
if (!(number operator current_number)) { \
|
||||||
result = false; \
|
result = false; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
number = current_number; \
|
number = current_number; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
return makePtr<Value>((result) ? Value::True : Value::False); \
|
return makePtr<Constant>((result) ? Constant::True : Constant::False); \
|
||||||
}
|
}
|
||||||
|
|
||||||
ADD_FUNCTION("<", NUMBER_COMPARE(<));
|
ADD_FUNCTION("<", NUMBER_COMPARE(<));
|
||||||
@@ -185,6 +186,10 @@ ADD_FUNCTION(
|
|||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
|
if (nodes.size() == 0) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto node : nodes) {
|
for (auto node : nodes) {
|
||||||
if (!is<List>(node.get())) {
|
if (!is<List>(node.get())) {
|
||||||
result = false;
|
result = false;
|
||||||
@@ -192,7 +197,7 @@ ADD_FUNCTION(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return makePtr<Value>((result) ? Value::True : Value::False);
|
return makePtr<Constant>((result) ? Constant::True : Constant::False);
|
||||||
});
|
});
|
||||||
|
|
||||||
ADD_FUNCTION(
|
ADD_FUNCTION(
|
||||||
@@ -212,21 +217,21 @@ ADD_FUNCTION(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return makePtr<Value>((result) ? Value::True : Value::False);
|
return makePtr<Constant>((result) ? Constant::True : Constant::False);
|
||||||
});
|
});
|
||||||
|
|
||||||
ADD_FUNCTION(
|
ADD_FUNCTION(
|
||||||
"count",
|
"count",
|
||||||
{
|
{
|
||||||
if (nodes.size() != 1) {
|
if (nodes.size() != 1) {
|
||||||
Error::the().add(format("wrong number of arguments: count, {}", nodes.size() - 1));
|
Error::the().add(format("wrong number of arguments: count, {}", nodes.size()));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto first_argument = nodes.front();
|
auto first_argument = nodes.front();
|
||||||
|
|
||||||
size_t result = 0;
|
size_t result = 0;
|
||||||
if (is<Value>(first_argument.get()) && std::static_pointer_cast<Value>(nodes.front())->state() == Value::Nil) {
|
if (is<Constant>(first_argument.get()) && std::static_pointer_cast<Constant>(nodes.front())->state() == Constant::Nil) {
|
||||||
// result = 0
|
// result = 0
|
||||||
}
|
}
|
||||||
else if (is<Collection>(first_argument.get())) {
|
else if (is<Collection>(first_argument.get())) {
|
||||||
@@ -274,7 +279,7 @@ ADD_FUNCTION("pr-str", PRINTER_STRING(true, " "));
|
|||||||
} \
|
} \
|
||||||
print("\n"); \
|
print("\n"); \
|
||||||
\
|
\
|
||||||
return makePtr<Value>(Value::Nil); \
|
return makePtr<Constant>(Constant::Nil); \
|
||||||
}
|
}
|
||||||
|
|
||||||
ADD_FUNCTION("prn", PRINTER_PRINT(true));
|
ADD_FUNCTION("prn", PRINTER_PRINT(true));
|
||||||
@@ -286,12 +291,12 @@ ADD_FUNCTION(
|
|||||||
"=",
|
"=",
|
||||||
{
|
{
|
||||||
if (nodes.size() < 2) {
|
if (nodes.size() < 2) {
|
||||||
Error::the().add(format("wrong number of arguments: =, {}", nodes.size() - 1));
|
Error::the().add(format("wrong number of arguments: =, {}", nodes.size()));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<bool(ASTNodePtr, ASTNodePtr)> equal =
|
std::function<bool(ValuePtr, ValuePtr)> equal =
|
||||||
[&equal](ASTNodePtr lhs, ASTNodePtr rhs) -> bool {
|
[&equal](ValuePtr lhs, ValuePtr rhs) -> bool {
|
||||||
if ((is<List>(lhs.get()) || is<Vector>(lhs.get()))
|
if ((is<List>(lhs.get()) || is<Vector>(lhs.get()))
|
||||||
&& (is<List>(rhs.get()) || is<Vector>(rhs.get()))) {
|
&& (is<List>(rhs.get()) || is<Vector>(rhs.get()))) {
|
||||||
auto lhs_nodes = std::static_pointer_cast<Collection>(lhs)->nodes();
|
auto lhs_nodes = std::static_pointer_cast<Collection>(lhs)->nodes();
|
||||||
@@ -342,8 +347,8 @@ ADD_FUNCTION(
|
|||||||
&& std::static_pointer_cast<Number>(lhs)->number() == std::static_pointer_cast<Number>(rhs)->number()) {
|
&& std::static_pointer_cast<Number>(lhs)->number() == std::static_pointer_cast<Number>(rhs)->number()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (is<Value>(lhs.get()) && is<Value>(rhs.get())
|
if (is<Constant>(lhs.get()) && is<Constant>(rhs.get())
|
||||||
&& std::static_pointer_cast<Value>(lhs)->state() == std::static_pointer_cast<Value>(rhs)->state()) {
|
&& std::static_pointer_cast<Constant>(lhs)->state() == std::static_pointer_cast<Constant>(rhs)->state()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (is<Symbol>(lhs.get()) && is<Symbol>(rhs.get())
|
if (is<Symbol>(lhs.get()) && is<Symbol>(rhs.get())
|
||||||
@@ -364,9 +369,173 @@ ADD_FUNCTION(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return makePtr<Value>((result) ? Value::True : Value::False);
|
return makePtr<Constant>((result) ? Constant::True : Constant::False);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"read-string",
|
||||||
|
{
|
||||||
|
if (nodes.size() != 1) {
|
||||||
|
Error::the().add(format("wrong number of arguments: read-string, {}", nodes.size()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is<String>(nodes.front().get())) {
|
||||||
|
Error::the().add(format("wrong argument type: string, '{}'", nodes.front()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string input = std::static_pointer_cast<String>(nodes.front())->data();
|
||||||
|
|
||||||
|
return read(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"slurp",
|
||||||
|
{
|
||||||
|
if (nodes.size() != 1) {
|
||||||
|
Error::the().add(format("wrong number of arguments: slurp, {}", nodes.size()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is<String>(nodes.front().get())) {
|
||||||
|
Error::the().add(format("wrong argument type: string, '{}'", nodes.front()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string path = std::static_pointer_cast<String>(nodes.front())->data();
|
||||||
|
|
||||||
|
auto file = ruc::File(path);
|
||||||
|
|
||||||
|
return makePtr<String>(file.data());
|
||||||
|
});
|
||||||
|
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"eval",
|
||||||
|
{
|
||||||
|
if (nodes.size() != 1) {
|
||||||
|
Error::the().add(format("wrong number of arguments: eval, {}", nodes.size()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eval(nodes.front(), nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
// (atom 1)
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"atom",
|
||||||
|
{
|
||||||
|
if (nodes.size() != 1) {
|
||||||
|
Error::the().add(format("wrong number of arguments: atom, {}", nodes.size()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return makePtr<Atom>(nodes.front());
|
||||||
|
});
|
||||||
|
|
||||||
|
// (atom? myatom 2 "foo")
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"atom?",
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
if (nodes.size() == 0) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto node : nodes) {
|
||||||
|
if (!is<Atom>(node.get())) {
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return makePtr<Constant>((result) ? Constant::True : Constant::False);
|
||||||
|
});
|
||||||
|
|
||||||
|
// (deref myatom)
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"deref",
|
||||||
|
{
|
||||||
|
if (nodes.size() != 1) {
|
||||||
|
Error::the().add(format("wrong number of arguments: deref, {}", nodes.size()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is<Atom>(nodes.front().get())) {
|
||||||
|
Error::the().add(format("wrong argument type: atom, '{}'", nodes.front()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::static_pointer_cast<Atom>(nodes.front())->deref();
|
||||||
|
});
|
||||||
|
|
||||||
|
// (reset! myatom 2)
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"reset!",
|
||||||
|
{
|
||||||
|
if (nodes.size() != 2) {
|
||||||
|
Error::the().add(format("wrong number of arguments: reset!, {}", nodes.size()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is<Atom>(nodes.front().get())) {
|
||||||
|
Error::the().add(format("wrong argument type: atom, '{}'", nodes.front()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto atom = std::static_pointer_cast<Atom>(*nodes.begin());
|
||||||
|
auto value = *std::next(nodes.begin());
|
||||||
|
|
||||||
|
atom->reset(value);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// (swap! myatom (fn* [x] (+ 1 x)))
|
||||||
|
ADD_FUNCTION(
|
||||||
|
"swap!",
|
||||||
|
{
|
||||||
|
if (nodes.size() < 2) {
|
||||||
|
Error::the().add(format("wrong number of arguments: reset!, {}", nodes.size()));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto first_argument = *nodes.begin();
|
||||||
|
auto second_argument = *std::next(nodes.begin());
|
||||||
|
|
||||||
|
if (!is<Atom>(first_argument.get())) {
|
||||||
|
Error::the().add(format("wrong argument type: atom, '{}'", first_argument));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is<Callable>(second_argument.get())) {
|
||||||
|
Error::the().add(format("wrong argument type: function, '{}'", second_argument));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto atom = std::static_pointer_cast<Atom>(first_argument);
|
||||||
|
|
||||||
|
// Remove atom and function from the argument list, add atom value
|
||||||
|
nodes.pop_front();
|
||||||
|
nodes.pop_front();
|
||||||
|
nodes.push_front(atom->deref());
|
||||||
|
|
||||||
|
ValuePtr value = nullptr;
|
||||||
|
if (is<Function>(second_argument.get())) {
|
||||||
|
auto function = std::static_pointer_cast<Function>(second_argument)->function();
|
||||||
|
value = function(nodes);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto lambda = std::static_pointer_cast<Lambda>(second_argument);
|
||||||
|
value = eval(lambda->body(), Environment::create(lambda, nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
return atom->reset(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
void installFunctions(EnvironmentPtr env)
|
void installFunctions(EnvironmentPtr env)
|
||||||
{
|
{
|
||||||
for (const auto& [name, lambda] : s_functions) {
|
for (const auto& [name, lambda] : s_functions) {
|
||||||
|
|||||||
@@ -128,8 +128,6 @@ bool Lexer::consumeString()
|
|||||||
|
|
||||||
static std::unordered_set<char> exit = {
|
static std::unordered_set<char> exit = {
|
||||||
'"',
|
'"',
|
||||||
'\r',
|
|
||||||
'\n',
|
|
||||||
'\0',
|
'\0',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+17
-11
@@ -29,7 +29,7 @@ Printer::~Printer()
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
std::string Printer::print(ASTNodePtr node, bool print_readably)
|
std::string Printer::print(ValuePtr node, bool print_readably)
|
||||||
{
|
{
|
||||||
if (Error::the().hasAnyError()) {
|
if (Error::the().hasAnyError()) {
|
||||||
init();
|
init();
|
||||||
@@ -40,7 +40,7 @@ std::string Printer::print(ASTNodePtr node, bool print_readably)
|
|||||||
return printNoErrorCheck(node, print_readably);
|
return printNoErrorCheck(node, print_readably);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Printer::printNoErrorCheck(ASTNodePtr node, bool print_readably)
|
std::string Printer::printNoErrorCheck(ValuePtr node, bool print_readably)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ void Printer::init()
|
|||||||
m_print = "";
|
m_print = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Printer::printImpl(ASTNodePtr node, bool print_readably)
|
void Printer::printImpl(ValuePtr node, bool print_readably)
|
||||||
{
|
{
|
||||||
auto printSpacing = [this]() -> void {
|
auto printSpacing = [this]() -> void {
|
||||||
if (!m_first_node && !m_previous_node_is_list) {
|
if (!m_first_node && !m_previous_node_is_list) {
|
||||||
@@ -70,7 +70,7 @@ void Printer::printImpl(ASTNodePtr node, bool print_readably)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ASTNode* node_raw_ptr = node.get();
|
Value* node_raw_ptr = node.get();
|
||||||
if (is<Collection>(node_raw_ptr)) {
|
if (is<Collection>(node_raw_ptr)) {
|
||||||
printSpacing();
|
printSpacing();
|
||||||
m_print += (is<List>(node_raw_ptr)) ? '(' : '[';
|
m_print += (is<List>(node_raw_ptr)) ? '(' : '[';
|
||||||
@@ -90,10 +90,10 @@ void Printer::printImpl(ASTNodePtr node, bool print_readably)
|
|||||||
m_previous_node_is_list = true;
|
m_previous_node_is_list = true;
|
||||||
auto elements = std::static_pointer_cast<HashMap>(node)->elements();
|
auto elements = std::static_pointer_cast<HashMap>(node)->elements();
|
||||||
for (auto it = elements.begin(); it != elements.end(); ++it) {
|
for (auto it = elements.begin(); it != elements.end(); ++it) {
|
||||||
m_print += format("{} ", it->first.front() == 0x7f ? ":" + it->first.substr(1) : it->first); // 127
|
m_print += format("{} ", (it->first.front() == 0x7f) ? ":" + it->first.substr(1) : '"' + it->first + '"'); // 127
|
||||||
printImpl(it->second, print_readably);
|
printImpl(it->second, print_readably);
|
||||||
|
|
||||||
if (isLast(it, elements)) {
|
if (!isLast(it, elements)) {
|
||||||
m_print += ' ';
|
m_print += ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,13 +119,13 @@ void Printer::printImpl(ASTNodePtr node, bool print_readably)
|
|||||||
printSpacing();
|
printSpacing();
|
||||||
m_print += format("{}", std::static_pointer_cast<Number>(node)->number());
|
m_print += format("{}", std::static_pointer_cast<Number>(node)->number());
|
||||||
}
|
}
|
||||||
else if (is<Value>(node_raw_ptr)) {
|
else if (is<Constant>(node_raw_ptr)) {
|
||||||
printSpacing();
|
printSpacing();
|
||||||
std::string value;
|
std::string value;
|
||||||
switch (std::static_pointer_cast<Value>(node)->state()) {
|
switch (std::static_pointer_cast<Constant>(node)->state()) {
|
||||||
case Value::Nil: value = "nil"; break;
|
case Constant::Nil: value = "nil"; break;
|
||||||
case Value::True: value = "true"; break;
|
case Constant::True: value = "true"; break;
|
||||||
case Value::False: value = "false"; break;
|
case Constant::False: value = "false"; break;
|
||||||
}
|
}
|
||||||
m_print += format("{}", value);
|
m_print += format("{}", value);
|
||||||
}
|
}
|
||||||
@@ -141,6 +141,12 @@ void Printer::printImpl(ASTNodePtr node, bool print_readably)
|
|||||||
printSpacing();
|
printSpacing();
|
||||||
m_print += format("#<user-function>({:p})", node_raw_ptr);
|
m_print += format("#<user-function>({:p})", node_raw_ptr);
|
||||||
}
|
}
|
||||||
|
else if (is<Atom>(node_raw_ptr)) {
|
||||||
|
printSpacing();
|
||||||
|
m_print += "(atom ";
|
||||||
|
printImpl(std::static_pointer_cast<Atom>(node)->deref(), print_readably);
|
||||||
|
m_print += ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Printer::printError()
|
void Printer::printError()
|
||||||
|
|||||||
+3
-3
@@ -17,12 +17,12 @@ public:
|
|||||||
Printer();
|
Printer();
|
||||||
virtual ~Printer();
|
virtual ~Printer();
|
||||||
|
|
||||||
std::string print(ASTNodePtr node, bool print_readably = true);
|
std::string print(ValuePtr node, bool print_readably = true);
|
||||||
std::string printNoErrorCheck(ASTNodePtr node, bool print_readably = true);
|
std::string printNoErrorCheck(ValuePtr node, bool print_readably = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
void printImpl(ASTNodePtr node, bool print_readably = true);
|
void printImpl(ValuePtr node, bool print_readably = true);
|
||||||
void printError();
|
void printError();
|
||||||
|
|
||||||
bool m_first_node { true };
|
bool m_first_node { true };
|
||||||
|
|||||||
+22
-22
@@ -56,7 +56,7 @@ void Reader::read()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readImpl()
|
ValuePtr Reader::readImpl()
|
||||||
{
|
{
|
||||||
if (m_tokens.size() == 0) {
|
if (m_tokens.size() == 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -124,7 +124,7 @@ ASTNodePtr Reader::readImpl()
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readSpliceUnquote()
|
ValuePtr Reader::readSpliceUnquote()
|
||||||
{
|
{
|
||||||
ignore(); // ~@
|
ignore(); // ~@
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ ASTNodePtr Reader::readSpliceUnquote()
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readList()
|
ValuePtr Reader::readList()
|
||||||
{
|
{
|
||||||
ignore(); // (
|
ignore(); // (
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ ASTNodePtr Reader::readList()
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readVector()
|
ValuePtr Reader::readVector()
|
||||||
{
|
{
|
||||||
ignore(); // [
|
ignore(); // [
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ ASTNodePtr Reader::readVector()
|
|||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readHashMap()
|
ValuePtr Reader::readHashMap()
|
||||||
{
|
{
|
||||||
ignore(); // {
|
ignore(); // {
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ ASTNodePtr Reader::readHashMap()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string keyString = is<String>(key.get()) ? std::static_pointer_cast<String>(key)->data() : std::static_pointer_cast<Keyword>(key)->keyword();
|
std::string keyString = is<String>(key.get()) ? std::static_pointer_cast<String>(key)->data() : std::static_pointer_cast<Keyword>(key)->keyword();
|
||||||
hash_map->addElement(keyString, value);
|
hash_map->add(keyString, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // }
|
if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // }
|
||||||
@@ -207,7 +207,7 @@ ASTNodePtr Reader::readHashMap()
|
|||||||
return hash_map;
|
return hash_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readQuote()
|
ValuePtr Reader::readQuote()
|
||||||
{
|
{
|
||||||
ignore(); // '
|
ignore(); // '
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ ASTNodePtr Reader::readQuote()
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readQuasiQuote()
|
ValuePtr Reader::readQuasiQuote()
|
||||||
{
|
{
|
||||||
ignore(); // `
|
ignore(); // `
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ ASTNodePtr Reader::readQuasiQuote()
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readUnquote()
|
ValuePtr Reader::readUnquote()
|
||||||
{
|
{
|
||||||
ignore(); // ~
|
ignore(); // ~
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ ASTNodePtr Reader::readUnquote()
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readWithMeta()
|
ValuePtr Reader::readWithMeta()
|
||||||
{
|
{
|
||||||
ignore(); // ^
|
ignore(); // ^
|
||||||
|
|
||||||
@@ -268,15 +268,15 @@ ASTNodePtr Reader::readWithMeta()
|
|||||||
|
|
||||||
auto list = makePtr<List>();
|
auto list = makePtr<List>();
|
||||||
list->add(makePtr<Symbol>("with-meta"));
|
list->add(makePtr<Symbol>("with-meta"));
|
||||||
ASTNodePtr first = readImpl();
|
ValuePtr first = readImpl();
|
||||||
ASTNodePtr second = readImpl();
|
ValuePtr second = readImpl();
|
||||||
list->add(second);
|
list->add(second);
|
||||||
list->add(first);
|
list->add(first);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readDeref()
|
ValuePtr Reader::readDeref()
|
||||||
{
|
{
|
||||||
ignore(); // @
|
ignore(); // @
|
||||||
|
|
||||||
@@ -292,19 +292,19 @@ ASTNodePtr Reader::readDeref()
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readString()
|
ValuePtr Reader::readString()
|
||||||
{
|
{
|
||||||
std::string symbol = consume().symbol;
|
std::string symbol = consume().symbol;
|
||||||
|
|
||||||
return makePtr<String>(symbol);
|
return makePtr<String>(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readKeyword()
|
ValuePtr Reader::readKeyword()
|
||||||
{
|
{
|
||||||
return makePtr<Keyword>(consume().symbol);
|
return makePtr<Keyword>(consume().symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNodePtr Reader::readValue()
|
ValuePtr Reader::readValue()
|
||||||
{
|
{
|
||||||
Token token = consume();
|
Token token = consume();
|
||||||
char* end_ptr = nullptr;
|
char* end_ptr = nullptr;
|
||||||
@@ -314,13 +314,13 @@ ASTNodePtr Reader::readValue()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (token.symbol == "nil") {
|
if (token.symbol == "nil") {
|
||||||
return makePtr<Value>(Value::Nil);
|
return makePtr<Constant>(Constant::Nil);
|
||||||
}
|
}
|
||||||
else if (token.symbol == "true") {
|
else if (token.symbol == "true") {
|
||||||
return makePtr<Value>(Value::True);
|
return makePtr<Constant>(Constant::True);
|
||||||
}
|
}
|
||||||
else if (token.symbol == "false") {
|
else if (token.symbol == "false") {
|
||||||
return makePtr<Value>(Value::False);
|
return makePtr<Constant>(Constant::False);
|
||||||
}
|
}
|
||||||
|
|
||||||
return makePtr<Symbol>(token.symbol);
|
return makePtr<Symbol>(token.symbol);
|
||||||
@@ -372,11 +372,11 @@ void Reader::dump()
|
|||||||
dumpImpl(m_node);
|
dumpImpl(m_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reader::dumpImpl(ASTNodePtr node)
|
void Reader::dumpImpl(ValuePtr node)
|
||||||
{
|
{
|
||||||
std::string indentation = std::string(m_indentation * 2, ' ');
|
std::string indentation = std::string(m_indentation * 2, ' ');
|
||||||
|
|
||||||
ASTNode* node_raw_ptr = node.get();
|
Value* node_raw_ptr = node.get();
|
||||||
if (is<Collection>(node_raw_ptr)) {
|
if (is<Collection>(node_raw_ptr)) {
|
||||||
auto nodes = std::static_pointer_cast<List>(node)->nodes();
|
auto nodes = std::static_pointer_cast<List>(node)->nodes();
|
||||||
print("{}", indentation);
|
print("{}", indentation);
|
||||||
@@ -406,7 +406,7 @@ void Reader::dumpImpl(ASTNodePtr node)
|
|||||||
print(fg(ruc::format::TerminalColor::Yellow), "NumberNode");
|
print(fg(ruc::format::TerminalColor::Yellow), "NumberNode");
|
||||||
print(" <{}>", node);
|
print(" <{}>", node);
|
||||||
}
|
}
|
||||||
else if (is<Value>(node_raw_ptr)) {
|
else if (is<Constant>(node_raw_ptr)) {
|
||||||
print("{}", indentation);
|
print("{}", indentation);
|
||||||
print(fg(ruc::format::TerminalColor::Yellow), "ValueNode");
|
print(fg(ruc::format::TerminalColor::Yellow), "ValueNode");
|
||||||
print(" <{}>", node);
|
print(" <{}>", node);
|
||||||
|
|||||||
+16
-16
@@ -25,7 +25,7 @@ public:
|
|||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
|
|
||||||
ASTNodePtr node() { return m_node; }
|
ValuePtr node() { return m_node; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isEOF() const;
|
bool isEOF() const;
|
||||||
@@ -35,21 +35,21 @@ private:
|
|||||||
void ignore();
|
void ignore();
|
||||||
void retreat();
|
void retreat();
|
||||||
|
|
||||||
ASTNodePtr readImpl();
|
ValuePtr readImpl();
|
||||||
ASTNodePtr readSpliceUnquote(); // ~@
|
ValuePtr readSpliceUnquote(); // ~@
|
||||||
ASTNodePtr readList(); // ()
|
ValuePtr readList(); // ()
|
||||||
ASTNodePtr readVector(); // []
|
ValuePtr readVector(); // []
|
||||||
ASTNodePtr readHashMap(); // {}
|
ValuePtr readHashMap(); // {}
|
||||||
ASTNodePtr readQuote(); // '
|
ValuePtr readQuote(); // '
|
||||||
ASTNodePtr readQuasiQuote(); // `
|
ValuePtr readQuasiQuote(); // `
|
||||||
ASTNodePtr readUnquote(); // ~
|
ValuePtr readUnquote(); // ~
|
||||||
ASTNodePtr readWithMeta(); // ^
|
ValuePtr readWithMeta(); // ^
|
||||||
ASTNodePtr readDeref(); // @
|
ValuePtr readDeref(); // @
|
||||||
ASTNodePtr readString(); // "foobar"
|
ValuePtr readString(); // "foobar"
|
||||||
ASTNodePtr readKeyword(); // :keyword
|
ValuePtr readKeyword(); // :keyword
|
||||||
ASTNodePtr readValue(); // number, "nil", "true", "false", symbol
|
ValuePtr readValue(); // number, "nil", "true", "false", symbol
|
||||||
|
|
||||||
void dumpImpl(ASTNodePtr node);
|
void dumpImpl(ValuePtr node);
|
||||||
|
|
||||||
size_t m_index { 0 };
|
size_t m_index { 0 };
|
||||||
size_t m_indentation { 0 };
|
size_t m_indentation { 0 };
|
||||||
@@ -59,7 +59,7 @@ private:
|
|||||||
bool m_invalid_syntax { false };
|
bool m_invalid_syntax { false };
|
||||||
bool m_is_unbalanced { false };
|
bool m_is_unbalanced { false };
|
||||||
|
|
||||||
ASTNodePtr m_node { nullptr };
|
ValuePtr m_node { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blaze
|
} // namespace blaze
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@
|
|||||||
#include "readline.h"
|
#include "readline.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
static blaze::EnvironmentPtr s_outer_env = blaze::Environment::create();
|
static blaze::EnvironmentPtr s_outer_env = blaze::Environment::create();
|
||||||
|
|
||||||
static auto cleanup(int signal) -> void;
|
static auto cleanup(int signal) -> void;
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <csignal> // std::signal
|
||||||
|
#include <cstdlib> // std::exit
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ruc/argparser.h"
|
||||||
|
#include "ruc/format/color.h"
|
||||||
|
|
||||||
|
#include "ast.h"
|
||||||
|
#include "environment.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "eval.h"
|
||||||
|
#include "forward.h"
|
||||||
|
#include "lexer.h"
|
||||||
|
#include "printer.h"
|
||||||
|
#include "reader.h"
|
||||||
|
#include "readline.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
namespace blaze {
|
||||||
|
|
||||||
|
static EnvironmentPtr s_outer_env = Environment::create();
|
||||||
|
|
||||||
|
static auto cleanup(int signal) -> void
|
||||||
|
{
|
||||||
|
print("\033[0m\n");
|
||||||
|
std::exit(signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto read(std::string_view input) -> ValuePtr
|
||||||
|
{
|
||||||
|
Lexer lexer(input);
|
||||||
|
lexer.tokenize();
|
||||||
|
if (Settings::the().get("dump-lexer") == "1") {
|
||||||
|
lexer.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
Reader reader(std::move(lexer.tokens()));
|
||||||
|
reader.read();
|
||||||
|
if (Settings::the().get("dump-reader") == "1") {
|
||||||
|
reader.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
return reader.node();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto eval(ValuePtr ast, EnvironmentPtr env) -> ValuePtr
|
||||||
|
{
|
||||||
|
if (env == nullptr) {
|
||||||
|
env = s_outer_env;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eval eval(ast, env);
|
||||||
|
eval.eval();
|
||||||
|
|
||||||
|
return eval.ast();
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto print(ValuePtr exp) -> std::string
|
||||||
|
{
|
||||||
|
Printer printer;
|
||||||
|
|
||||||
|
return printer.print(exp, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto rep(std::string_view input, EnvironmentPtr env) -> std::string
|
||||||
|
{
|
||||||
|
Error::the().clearErrors();
|
||||||
|
Error::the().setInput(input);
|
||||||
|
|
||||||
|
return print(eval(read(input), env));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string_view lambdaTable[] = {
|
||||||
|
"(def! not (fn* (cond) (if cond false true)))",
|
||||||
|
"(def! load-file (fn* (filename) \
|
||||||
|
(eval (read-string (str \"(do \" (slurp filename) \"\nnil)\")))))",
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto installLambdas(EnvironmentPtr env) -> void
|
||||||
|
{
|
||||||
|
for (auto function : lambdaTable) {
|
||||||
|
rep(function, env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void
|
||||||
|
{
|
||||||
|
auto list = makePtr<List>();
|
||||||
|
if (arguments.size() > 1) {
|
||||||
|
for (auto it = arguments.begin() + 1; it != arguments.end(); ++it) {
|
||||||
|
list->add(makePtr<String>(*it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env->set("*ARGV*", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blaze
|
||||||
|
|
||||||
|
auto main(int argc, char* argv[]) -> int
|
||||||
|
{
|
||||||
|
bool dump_lexer = false;
|
||||||
|
bool dump_reader = false;
|
||||||
|
bool pretty_print = false;
|
||||||
|
std::string_view history_path = "~/.blaze-history";
|
||||||
|
std::vector<std::string> arguments;
|
||||||
|
|
||||||
|
// CLI arguments
|
||||||
|
ruc::ArgParser arg_parser;
|
||||||
|
arg_parser.addOption(dump_lexer, 'l', "dump-lexer", nullptr, nullptr);
|
||||||
|
arg_parser.addOption(dump_reader, 'r', "dump-reader", nullptr, nullptr);
|
||||||
|
arg_parser.addOption(pretty_print, 'c', "color", nullptr, nullptr);
|
||||||
|
arg_parser.addOption(history_path, 'h', "history-path", nullptr, nullptr, nullptr, ruc::ArgParser::Required::Yes);
|
||||||
|
arg_parser.addArgument(arguments, "arguments", nullptr, nullptr, ruc::ArgParser::Required::No);
|
||||||
|
arg_parser.parse(argc, argv);
|
||||||
|
|
||||||
|
// Set settings
|
||||||
|
blaze::Settings::the().set("dump-lexer", dump_lexer ? "1" : "0");
|
||||||
|
blaze::Settings::the().set("dump-reader", dump_reader ? "1" : "0");
|
||||||
|
blaze::Settings::the().set("pretty-print", pretty_print ? "1" : "0");
|
||||||
|
|
||||||
|
// Signal callbacks
|
||||||
|
std::signal(SIGINT, blaze::cleanup);
|
||||||
|
std::signal(SIGTERM, blaze::cleanup);
|
||||||
|
|
||||||
|
installFunctions(blaze::s_outer_env);
|
||||||
|
installLambdas(blaze::s_outer_env);
|
||||||
|
makeArgv(blaze::s_outer_env, arguments);
|
||||||
|
|
||||||
|
if (arguments.size() > 0) {
|
||||||
|
rep(format("(load-file \"{}\")", arguments.front()), blaze::s_outer_env);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blaze::Readline readline(pretty_print, history_path);
|
||||||
|
|
||||||
|
std::string input;
|
||||||
|
while (readline.get(input)) {
|
||||||
|
if (pretty_print) {
|
||||||
|
print("\033[0m");
|
||||||
|
}
|
||||||
|
print("{}\n", rep(input, blaze::s_outer_env));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pretty_print) {
|
||||||
|
print("\033[0m");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user