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
# git-clang-format --style=Google HEAD^
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,
const std::shared_ptr<Expr>& b) {
if (a->type() == Type::Float
&& b->type() == Type::Float) {
if (a->type() == Type::Float && b->type() == Type::Float) {
return std::make_shared<Float>(get_value<Float>(a) + get_value<Float>(b));
}
if (a->type() == Type::Integer
&& b->type() == Type::Integer) {
return std::make_shared<Integer>(get_value<Integer>(a) + get_value<Integer>(b));
if (a->type() == Type::Integer && b->type() == Type::Integer) {
return std::make_shared<Integer>(get_value<Integer>(a) +
get_value<Integer>(b));
}
if (a->type() == Type::Float) {
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() {
// syntax
putenv("quote",
[](auto expr, auto env) {
assert_len(expr, 2);
auto value = get_value<List>(expr);
return value[1];
});
putenv("define",
[](auto expr, auto env) {
assert_len(expr, 3);
auto value = get_value<List>(expr);
assert_type<Type::Symbol>(value[1]);
auto symbol = get_value<Symbol>(value[1]);
if (!is_nil(env->get(symbol))) {
oops("symbol defined: " + symbol);
}
env->put(symbol, eval(value[2], env));
return nil;
});
putenv("set!",
[](auto expr, auto env) {
assert_len(expr, 3);
auto value = get_value<List>(expr);
assert_type<Type::Symbol>(value[1]);
auto symbol = get_value<Symbol>(value[1]);
env->put(symbol, eval(value[2], env));
return nil;
});
putenv("progn",
[](auto expr, auto env) {
auto val = nil;
auto value = get_value<List>(expr);
for (auto i = 1; i < value.size(); ++i) {
val = eval(value[i], env);
}
return val;
});
putenv("if",
[](auto expr, auto env) {
// (if (cond) (then body) (else body))
assert_len(expr, 4);
auto value = get_value<List>(expr);
if (is_true(eval(value[1], env))) {
return eval(value[2], env);
} else {
return eval(value[3], env);
}
});
putenv("while",
[](auto expr, auto env) {
// (while (cond) (loop body))
assert_len(expr, 3);
auto value = get_value<List>(expr);
while (is_true(eval(value[1], env))) {
eval(value[2], env);
}
return nil;
});
putenv("lambda",
[](auto expr, auto env) {
// (lambda (args) (body))
assert_len(expr, 3);
auto lambda =
[expr, parent = env](auto args, auto) {
auto value = get_value<List>(expr);
auto symbols = get_value<List>(value[1]);
// arguments bind
auto args_value = get_value<List>(args);
if (symbols.size() != args_value.size() - 1) {
oops("arguments error");
}
auto env = std::make_shared<Env>(parent);
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));
});
putenv("quote", [](auto expr, auto env) {
assert_len(expr, 2);
auto value = get_value<List>(expr);
return value[1];
});
putenv("define", [](auto expr, auto env) {
assert_len(expr, 3);
auto value = get_value<List>(expr);
assert_type<Type::Symbol>(value[1]);
auto symbol = get_value<Symbol>(value[1]);
if (!is_nil(env->get(symbol))) {
oops("symbol defined: " + symbol);
}
env->put(symbol, eval(value[2], env));
return nil;
});
putenv("set!", [](auto expr, auto env) {
assert_len(expr, 3);
auto value = get_value<List>(expr);
assert_type<Type::Symbol>(value[1]);
auto symbol = get_value<Symbol>(value[1]);
env->put(symbol, eval(value[2], env));
return nil;
});
putenv("progn", [](auto expr, auto env) {
auto val = nil;
auto value = get_value<List>(expr);
for (auto i = 1; i < value.size(); ++i) {
val = eval(value[i], env);
}
return val;
});
putenv("if", [](auto expr, auto env) {
// (if (cond) (then body) (else body))
assert_len(expr, 4);
auto value = get_value<List>(expr);
if (is_true(eval(value[1], env))) {
return eval(value[2], env);
} else {
return eval(value[3], env);
}
});
putenv("while", [](auto expr, auto env) {
// (while (cond) (loop body))
assert_len(expr, 3);
auto value = get_value<List>(expr);
while (is_true(eval(value[1], env))) {
eval(value[2], env);
}
return nil;
});
putenv("lambda", [](auto expr, auto env) {
// (lambda (args) (body))
assert_len(expr, 3);
auto lambda = [expr, parent = env](auto args, auto) {
auto value = get_value<List>(expr);
auto symbols = get_value<List>(value[1]);
// arguments bind
auto args_value = get_value<List>(args);
if (symbols.size() != args_value.size() - 1) {
oops("arguments error");
}
auto env = std::make_shared<Env>(parent);
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
putenv("+",
[](auto expr, auto env) {
assert_len(expr, 3);
auto value = get_value<List>(expr);
return sum(eval(value[1], env), eval(value[2], env));
});
putenv("message",
[](auto expr, auto env) {
auto value = get_value<List>(expr);
for (auto i = 1; i < value.size(); ++i) {
message(eval(value[i], env));
std::cout << std::endl;
}
return nil;
});
putenv("+", [](auto expr, auto env) {
assert_len(expr, 3);
auto value = get_value<List>(expr);
return sum(eval(value[1], env), eval(value[2], env));
});
putenv("message", [](auto expr, auto env) {
auto value = get_value<List>(expr);
for (auto i = 1; i < value.size(); ++i) {
message(eval(value[i], env));
std::cout << std::endl;
}
return nil;
});
}
} // namespace lispoo
} // namespace lispoo

5
src/lispoo.cpp

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

89
src/lispoo.h

@ -1,13 +1,12 @@
#pragma once
#include <iostream>
#include <exception>
#include <string>
#include <vector>
#include <memory>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
namespace lispoo {
@ -28,75 +27,73 @@ enum class Type {
};
class Expr {
public:
public:
virtual Type type() = 0;
};
template <typename T>
class Atom: public Expr {
public:
class Atom : public Expr {
public:
explicit Atom(const T& value) : value_(value) {}
Type type() override { return Type::Atom; }
const T& value() const { return value_; }
private:
private:
T value_;
};
class Symbol: public Atom<std::string> {
public:
class Symbol : public Atom<std::string> {
public:
explicit Symbol(const std::string& value) : Atom(value) {}
Type type() override { return Type::Symbol; }
};
class Integer: public Atom<long> {
public:
class Integer : public Atom<long> {
public:
explicit Integer(const long& value) : Atom(value) {}
Type type() override { return Type::Integer; }
};
class Float: public Atom<double> {
public:
class Float : public Atom<double> {
public:
explicit Float(const double& value) : Atom(value) {}
Type type() override { return Type::Float; }
};
class Null: public Expr {
public:
class Null : public Expr {
public:
Type type() override { return Type::Null; }
};
static const std::shared_ptr<Expr> nil = std::make_shared<Null>();
class List: public Expr {
public:
class List : public Expr {
public:
Type type() override { return Type::List; }
const std::vector<std::shared_ptr<Expr>>& value() const { return value_; }
void append(const std::shared_ptr<Expr>& expr) { value_.emplace_back(expr); }
private:
private:
std::vector<std::shared_ptr<Expr>> value_;
};
class Env;
class Callable: public Expr {
public:
using Fn = std::function<std::shared_ptr<Expr>(const std::shared_ptr<Expr>&,
const std::shared_ptr<Env>& env)>;
class Callable : public Expr {
public:
using Fn = std::function<std::shared_ptr<Expr>(
const std::shared_ptr<Expr>&, const std::shared_ptr<Env>& env)>;
explicit Callable(Fn&& lambda) : lambda_(lambda) {}
Type type() override { return Type::Callable; }
const Fn& value() const {
return lambda_;
}
const Fn& value() const { return lambda_; }
private:
private:
Fn lambda_;
};
// environment
class Env {
public:
public:
Env(const std::shared_ptr<Env>& env) : env_(env) {}
std::shared_ptr<Expr> get(const std::string& symbol) const {
@ -113,20 +110,20 @@ public:
expr_map_[symbol] = expr;
}
private:
private:
std::unordered_map<std::string, std::shared_ptr<Expr>> expr_map_;
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) {
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
inline bool is_par(char ch) {
return ch == '(' || ch == ')';
}
inline bool is_par(char ch) { return ch == '(' || ch == ')'; }
template <typename T>
inline decltype(auto) get_value(const std::shared_ptr<Expr>& expr) {
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;
}
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);
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 type = Type::Symbol;
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) {
case Type::Symbol:
return std::make_shared<Symbol>(token);
return std::make_shared<Symbol>(token);
case Type::Integer:
return std::make_shared<Integer>(std::stol(token));
return std::make_shared<Integer>(std::stol(token));
case Type::Float:
return std::make_shared<Float>(std::stod(token));
return std::make_shared<Float>(std::stod(token));
default:
break;
break;
}
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()) {
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);
}
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) {
oops("syntax error");
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);
}
} // namespace lispoo
} // namespace lispoo

Loading…
Cancel
Save