Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <vector>
- #include <unordered_map>
- #include <typeinfo>
- #include <string>
- #include <assert.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- using std::unordered_map;
- using std::vector;
- using std::make_pair;
- class Env;
- class Print;
- class Error {
- };
- template<typename T>
- class Ref
- {
- public:
- Ref() : t_(nullptr) {}
- Ref(T *t) :
- t_(t)
- {
- t_->ref();
- }
- Ref(T &t)
- : t_(&t)
- {
- }
- template<typename U> Ref(Ref<U> &ru) :
- t_(&*ru)
- {
- t_->ref();
- }
- T &operator*() const {
- return *t_;
- }
- T *operator->() const
- {
- return t_;
- }
- operator T &() const
- {
- return *t_;
- }
- operator T *() const {
- return t_;
- }
- private:
- T *t_;
- };
- class Node
- {
- public:
- template<typename T, typename ...Args>
- static
- Ref<T> make(Args ...args)
- {
- return new T(args...);
- }
- template<typename To, typename From>
- static To *cast(From *from) {
- To *ret = dynamic_cast<To *>(from);
- if (!ret) throw Error();
- return ret;
- }
- void ref() {
- refs++;
- }
- void deref() {
- assert(refs > 0);
- if (--refs > 0) return;
- delete this;
- }
- virtual void print(Print &) const = 0;
- virtual Ref<Node> eval(Env &) {
- return this;
- }
- virtual Ref<Node> apply(vector<Node *>, Env &) {
- throw Error();
- }
- private:
- int refs;
- };
- enum class Token {
- RightParen,
- };
- class Print
- {
- public:
- Print(FILE *file) :
- file_(file)
- {
- }
- void atom(char const *format, ...)
- {
- }
- void token(Token t) {
- print_space_if_required(t);
- switch (t) {
- case Token::RightParen:
- fputc(')', file_);
- break;
- }
- last_token_ = t;
- }
- private:
- void print_space_if_required(Token t) {
- switch (last_token_) {
- }
- }
- FILE *file_;
- Token last_token_;
- };
- class Symbol : public Node {
- public:
- Symbol(char const *s)
- : s_(s) {}
- void print(Print &print) const {
- print.atom("%s", s_.c_str());
- }
- size_t hash() const {
- return std::hash<std::string>()(s_);
- }
- private:
- std::string s_;
- };
- size_t hash_symbol(Symbol const &sym) {
- return sym.hash();
- }
- class Env : public Node {
- public:
- virtual void define(Symbol &, Node *) = 0;
- void define(char const *s, Node *value) {
- define(Node::make<Symbol>(s), value);
- }
- };
- class Lexer
- {
- public:
- Lexer(FILE *file) :
- file_(file)
- {
- }
- private:
- FILE *file_;
- };
- Ref<Node> parse(Lexer &) {
- }
- class GlobalEnv : public Env
- {
- virtual void print(Print &print) const
- {
- print.atom("#(%s", typeid(*this).name());
- for (auto const &i : vars_) {
- i.first->print(print);
- i.second->print(print);
- }
- print.token(Token::RightParen);
- }
- virtual void define(Symbol &name, Node *value)
- {
- vars_.insert(make_pair<Ref<Symbol>, Ref<Node>>(name, value));
- }
- private:
- unordered_map<Ref<Symbol>, Ref<Node>, &hash_symbol> vars_;
- };
- class Primitive : public Node {
- public:
- typedef Ref<Node> (*ApplyFunc)(vector<Node *>, Env &);
- Primitive(char const *name, ApplyFunc af)
- : name_(name),
- apply_func_(af)
- {
- }
- void print(Print &print) const {
- print.atom("#(%s", typeid(*this).name());
- print.atom("%s", name_);
- print.token(Token::RightParen);
- }
- private:
- char const *name_;
- ApplyFunc apply_func_;
- };
- void add_primitive(Env &env, char const *name, Primitive::ApplyFunc func)
- {
- env.define(name, Node::make<Primitive>(name, func));
- }
- Ref<Node> apply_define(vector<Node *> args, Env &env) {
- Ref<Node> value;
- Symbol *name;
- switch (args.size()) {
- case 2:
- value = args[1]->eval(env);
- case 1:
- name = Node::cast<Symbol>(args[0]);
- break;
- default:
- throw Error();
- }
- env.define(*name, value);
- }
- Ref<Env> make_global_env()
- {
- auto ret = Node::make<GlobalEnv>();
- add_primitive(ret, "__define", apply_define);
- return ret;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement