Browse Source

fmt code

Signed-off-by: Rain Mark <rain.by.zhou@gmail.com>
main
Rain Mark 4 years ago
parent
commit
964f1a1741
  1. 2
      build.sh
  2. 191
      src/core.h
  3. 5
      src/lispoo.cpp
  4. 89
      src/lispoo.h

2
build.sh

@ -1,3 +1,5 @@
#!/bin/bash #!/bin/bash
# git-clang-format --style=Google HEAD^
g++ -Werror -std=c++20 -Isrc src/lispoo.cpp -o lispoo g++ -Werror -std=c++20 -Isrc src/lispoo.cpp -o lispoo

191
src/core.h

@ -6,13 +6,12 @@ namespace lispoo {
inline std::shared_ptr<Expr> sum(const std::shared_ptr<Expr>& a, inline std::shared_ptr<Expr> sum(const std::shared_ptr<Expr>& a,
const std::shared_ptr<Expr>& b) { const std::shared_ptr<Expr>& b) {
if (a->type() == Type::Float if (a->type() == Type::Float && b->type() == Type::Float) {
&& b->type() == Type::Float) {
return std::make_shared<Float>(get_value<Float>(a) + get_value<Float>(b)); return std::make_shared<Float>(get_value<Float>(a) + get_value<Float>(b));
} }
if (a->type() == Type::Integer if (a->type() == Type::Integer && b->type() == Type::Integer) {
&& b->type() == Type::Integer) { return std::make_shared<Integer>(get_value<Integer>(a) +
return std::make_shared<Integer>(get_value<Integer>(a) + get_value<Integer>(b)); get_value<Integer>(b));
} }
if (a->type() == Type::Float) { if (a->type() == Type::Float) {
return std::make_shared<Float>(get_value<Float>(a) + get_value<Integer>(b)); return std::make_shared<Float>(get_value<Float>(a) + get_value<Integer>(b));
@ -65,103 +64,93 @@ inline std::shared_ptr<Expr> message(const std::shared_ptr<Expr>& expr) {
inline void init() { inline void init() {
// syntax // syntax
putenv("quote", putenv("quote", [](auto expr, auto env) {
[](auto expr, auto env) { assert_len(expr, 2);
assert_len(expr, 2); auto value = get_value<List>(expr);
auto value = get_value<List>(expr); return value[1];
return value[1]; });
}); putenv("define", [](auto expr, auto env) {
putenv("define", assert_len(expr, 3);
[](auto expr, auto env) { auto value = get_value<List>(expr);
assert_len(expr, 3); assert_type<Type::Symbol>(value[1]);
auto value = get_value<List>(expr); auto symbol = get_value<Symbol>(value[1]);
assert_type<Type::Symbol>(value[1]); if (!is_nil(env->get(symbol))) {
auto symbol = get_value<Symbol>(value[1]); oops("symbol defined: " + symbol);
if (!is_nil(env->get(symbol))) { }
oops("symbol defined: " + symbol); env->put(symbol, eval(value[2], env));
} return nil;
env->put(symbol, eval(value[2], env)); });
return nil; putenv("set!", [](auto expr, auto env) {
}); assert_len(expr, 3);
putenv("set!", auto value = get_value<List>(expr);
[](auto expr, auto env) { assert_type<Type::Symbol>(value[1]);
assert_len(expr, 3); auto symbol = get_value<Symbol>(value[1]);
auto value = get_value<List>(expr); env->put(symbol, eval(value[2], env));
assert_type<Type::Symbol>(value[1]); return nil;
auto symbol = get_value<Symbol>(value[1]); });
env->put(symbol, eval(value[2], env)); putenv("progn", [](auto expr, auto env) {
return nil; auto val = nil;
}); auto value = get_value<List>(expr);
putenv("progn", for (auto i = 1; i < value.size(); ++i) {
[](auto expr, auto env) { val = eval(value[i], env);
auto val = nil; }
auto value = get_value<List>(expr); return val;
for (auto i = 1; i < value.size(); ++i) { });
val = eval(value[i], env); putenv("if", [](auto expr, auto env) {
} // (if (cond) (then body) (else body))
return val; assert_len(expr, 4);
}); auto value = get_value<List>(expr);
putenv("if", if (is_true(eval(value[1], env))) {
[](auto expr, auto env) { return eval(value[2], env);
// (if (cond) (then body) (else body)) } else {
assert_len(expr, 4); return eval(value[3], env);
auto value = get_value<List>(expr); }
if (is_true(eval(value[1], env))) { });
return eval(value[2], env); putenv("while", [](auto expr, auto env) {
} else { // (while (cond) (loop body))
return eval(value[3], env); assert_len(expr, 3);
} auto value = get_value<List>(expr);
}); while (is_true(eval(value[1], env))) {
putenv("while", eval(value[2], env);
[](auto expr, auto env) { }
// (while (cond) (loop body)) return nil;
assert_len(expr, 3); });
auto value = get_value<List>(expr); putenv("lambda", [](auto expr, auto env) {
while (is_true(eval(value[1], env))) { // (lambda (args) (body))
eval(value[2], env); assert_len(expr, 3);
} auto lambda = [expr, parent = env](auto args, auto) {
return nil; auto value = get_value<List>(expr);
}); auto symbols = get_value<List>(value[1]);
putenv("lambda", // arguments bind
[](auto expr, auto env) { auto args_value = get_value<List>(args);
// (lambda (args) (body)) if (symbols.size() != args_value.size() - 1) {
assert_len(expr, 3); oops("arguments error");
auto lambda = }
[expr, parent = env](auto args, auto) { auto env = std::make_shared<Env>(parent);
auto value = get_value<List>(expr); for (auto i = 0; i < symbols.size(); ++i) {
auto symbols = get_value<List>(value[1]); auto symbol = get_value<Symbol>(symbols[i]);
// arguments bind env->put(symbol, eval(args_value[i + 1], parent));
auto args_value = get_value<List>(args); }
if (symbols.size() != args_value.size() - 1) { // eval body
oops("arguments error"); return eval(value[2], env);
} };
auto env = std::make_shared<Env>(parent); return std::make_shared<Callable>(std::move(lambda));
for (auto i = 0; i < symbols.size(); ++i) { });
auto symbol = get_value<Symbol>(symbols[i]);
env->put(symbol, eval(args_value[i + 1], parent));
}
// eval body
return eval(value[2], env);
};
return std::make_shared<Callable>(std::move(lambda));
});
// normal builtin function // normal builtin function
putenv("+", putenv("+", [](auto expr, auto env) {
[](auto expr, auto env) { assert_len(expr, 3);
assert_len(expr, 3); auto value = get_value<List>(expr);
auto value = get_value<List>(expr); return sum(eval(value[1], env), eval(value[2], env));
return sum(eval(value[1], env), eval(value[2], env)); });
}); putenv("message", [](auto expr, auto env) {
putenv("message", auto value = get_value<List>(expr);
[](auto expr, auto env) { for (auto i = 1; i < value.size(); ++i) {
auto value = get_value<List>(expr); message(eval(value[i], env));
for (auto i = 1; i < value.size(); ++i) { std::cout << std::endl;
message(eval(value[i], env)); }
std::cout << std::endl; return nil;
} });
return nil;
});
} }
} // namespace lispoo } // namespace lispoo

5
src/lispoo.cpp

@ -1,7 +1,8 @@
#include <lispoo.h>
#include <core.h> #include <core.h>
#include <sstream> #include <lispoo.h>
#include <fstream> #include <fstream>
#include <sstream>
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc != 2) { if (argc != 2) {

89
src/lispoo.h

@ -1,13 +1,12 @@
#pragma once #pragma once
#include <iostream>
#include <exception> #include <exception>
#include <string>
#include <vector>
#include <memory>
#include <functional> #include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map> #include <unordered_map>
#include <vector>
namespace lispoo { namespace lispoo {
@ -28,75 +27,73 @@ enum class Type {
}; };
class Expr { class Expr {
public: public:
virtual Type type() = 0; virtual Type type() = 0;
}; };
template <typename T> template <typename T>
class Atom: public Expr { class Atom : public Expr {
public: public:
explicit Atom(const T& value) : value_(value) {} explicit Atom(const T& value) : value_(value) {}
Type type() override { return Type::Atom; } Type type() override { return Type::Atom; }
const T& value() const { return value_; } const T& value() const { return value_; }
private: private:
T value_; T value_;
}; };
class Symbol: public Atom<std::string> { class Symbol : public Atom<std::string> {
public: public:
explicit Symbol(const std::string& value) : Atom(value) {} explicit Symbol(const std::string& value) : Atom(value) {}
Type type() override { return Type::Symbol; } Type type() override { return Type::Symbol; }
}; };
class Integer: public Atom<long> { class Integer : public Atom<long> {
public: public:
explicit Integer(const long& value) : Atom(value) {} explicit Integer(const long& value) : Atom(value) {}
Type type() override { return Type::Integer; } Type type() override { return Type::Integer; }
}; };
class Float: public Atom<double> { class Float : public Atom<double> {
public: public:
explicit Float(const double& value) : Atom(value) {} explicit Float(const double& value) : Atom(value) {}
Type type() override { return Type::Float; } Type type() override { return Type::Float; }
}; };
class Null: public Expr { class Null : public Expr {
public: public:
Type type() override { return Type::Null; } Type type() override { return Type::Null; }
}; };
static const std::shared_ptr<Expr> nil = std::make_shared<Null>(); static const std::shared_ptr<Expr> nil = std::make_shared<Null>();
class List: public Expr { class List : public Expr {
public: public:
Type type() override { return Type::List; } Type type() override { return Type::List; }
const std::vector<std::shared_ptr<Expr>>& value() const { return value_; } const std::vector<std::shared_ptr<Expr>>& value() const { return value_; }
void append(const std::shared_ptr<Expr>& expr) { value_.emplace_back(expr); } void append(const std::shared_ptr<Expr>& expr) { value_.emplace_back(expr); }
private: private:
std::vector<std::shared_ptr<Expr>> value_; std::vector<std::shared_ptr<Expr>> value_;
}; };
class Env; class Env;
class Callable: public Expr { class Callable : public Expr {
public: public:
using Fn = std::function<std::shared_ptr<Expr>(const std::shared_ptr<Expr>&, using Fn = std::function<std::shared_ptr<Expr>(
const std::shared_ptr<Env>& env)>; const std::shared_ptr<Expr>&, const std::shared_ptr<Env>& env)>;
explicit Callable(Fn&& lambda) : lambda_(lambda) {} explicit Callable(Fn&& lambda) : lambda_(lambda) {}
Type type() override { return Type::Callable; } Type type() override { return Type::Callable; }
const Fn& value() const { const Fn& value() const { return lambda_; }
return lambda_;
}
private: private:
Fn lambda_; Fn lambda_;
}; };
// environment // environment
class Env { class Env {
public: public:
Env(const std::shared_ptr<Env>& env) : env_(env) {} Env(const std::shared_ptr<Env>& env) : env_(env) {}
std::shared_ptr<Expr> get(const std::string& symbol) const { std::shared_ptr<Expr> get(const std::string& symbol) const {
@ -113,20 +110,20 @@ public:
expr_map_[symbol] = expr; expr_map_[symbol] = expr;
} }
private: private:
std::unordered_map<std::string, std::shared_ptr<Expr>> expr_map_; std::unordered_map<std::string, std::shared_ptr<Expr>> expr_map_;
std::shared_ptr<Env> env_; std::shared_ptr<Env> env_;
}; };
static std::shared_ptr<Env> global = std::make_shared<Env>(std::shared_ptr<Env>()); static std::shared_ptr<Env> global =
std::make_shared<Env>(std::shared_ptr<Env>());
inline void putenv(const std::string& symbol, Callable::Fn&& lambda) { inline void putenv(const std::string& symbol, Callable::Fn&& lambda) {
global->put(symbol, std::make_shared<Callable>(std::forward<Callable::Fn>(lambda))); global->put(symbol,
std::make_shared<Callable>(std::forward<Callable::Fn>(lambda)));
} }
// type utils // type utils
inline bool is_par(char ch) { inline bool is_par(char ch) { return ch == '(' || ch == ')'; }
return ch == '(' || ch == ')';
}
template <typename T> template <typename T>
inline decltype(auto) get_value(const std::shared_ptr<Expr>& expr) { inline decltype(auto) get_value(const std::shared_ptr<Expr>& expr) {
return std::static_pointer_cast<T>(expr)->value(); return std::static_pointer_cast<T>(expr)->value();
@ -184,13 +181,15 @@ inline void tokenize(const std::string& str, std::vector<std::string>& tokens) {
continue; continue;
} }
auto s = i; auto s = i;
for (; !(std::isspace(str[i]) || is_par(str[i])); ++i); for (; !(std::isspace(str[i]) || is_par(str[i])); ++i)
;
tokens.emplace_back(str.c_str() + s, i - s); tokens.emplace_back(str.c_str() + s, i - s);
i--; i--;
} }
} }
inline std::shared_ptr<Expr> parse_atom(const std::vector<std::string>& tokens, long& cursor) { inline std::shared_ptr<Expr> parse_atom(const std::vector<std::string>& tokens,
long& cursor) {
auto token = tokens[cursor]; auto token = tokens[cursor];
auto type = Type::Symbol; auto type = Type::Symbol;
if (std::isdigit(token[0]) || token[0] == '-') { if (std::isdigit(token[0]) || token[0] == '-') {
@ -210,18 +209,19 @@ inline std::shared_ptr<Expr> parse_atom(const std::vector<std::string>& tokens,
} }
switch (type) { switch (type) {
case Type::Symbol: case Type::Symbol:
return std::make_shared<Symbol>(token); return std::make_shared<Symbol>(token);
case Type::Integer: case Type::Integer:
return std::make_shared<Integer>(std::stol(token)); return std::make_shared<Integer>(std::stol(token));
case Type::Float: case Type::Float:
return std::make_shared<Float>(std::stod(token)); return std::make_shared<Float>(std::stod(token));
default: default:
break; break;
} }
return nil; return nil;
} }
inline std::shared_ptr<Expr> parse(const std::vector<std::string>& tokens, long& cursor) { inline std::shared_ptr<Expr> parse(const std::vector<std::string>& tokens,
long& cursor) {
if (cursor >= tokens.size()) { if (cursor >= tokens.size()) {
oops("parse error"); oops("parse error");
} }
@ -235,7 +235,8 @@ inline std::shared_ptr<Expr> parse(const std::vector<std::string>& tokens, long&
return parse_atom(tokens, cursor); return parse_atom(tokens, cursor);
} }
inline std::shared_ptr<Expr> eval(const std::shared_ptr<Expr>& expr, const std::shared_ptr<Env>& env) { inline std::shared_ptr<Expr> eval(const std::shared_ptr<Expr>& expr,
const std::shared_ptr<Env>& env) {
if (!expr) { if (!expr) {
oops("syntax error"); oops("syntax error");
return nil; return nil;
@ -262,4 +263,4 @@ inline std::shared_ptr<Expr> eval(const std::shared_ptr<Expr>& expr, const std::
return get_value<Callable>(callable)(expr, env); return get_value<Callable>(callable)(expr, env);
} }
} // namespace lispoo } // namespace lispoo

Loading…
Cancel
Save