Created
December 23, 2013 15:44
-
-
Save shhyou/8099247 to your computer and use it in GitHub Desktop.
A badly-written memory-leaking lambda calculus interpreter in C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<cstdio> | |
#include<map> | |
#include<string> | |
#include<functional> | |
#include<stdexcept> | |
#include<memory> | |
using std::map; | |
using std::string; | |
using std::function; | |
using std::runtime_error; | |
using std::shared_ptr; | |
using std::dynamic_pointer_cast; | |
class Value { | |
public: | |
Value() {} | |
virtual ~Value() {} | |
}; | |
class IntValue : public Value { | |
const int n; | |
public: | |
IntValue(int n_) : n(n_) {} | |
~IntValue() {} | |
int getInt() { return n; } | |
}; | |
class FunValue : public Value { | |
function<shared_ptr<Value>(shared_ptr<Value>)> fn; | |
public: | |
FunValue(function<shared_ptr<Value>(shared_ptr<Value>)> fn_) : fn(fn_) {} | |
~FunValue() {} | |
shared_ptr<Value> apply(shared_ptr<Value> v) { return fn(v); } | |
}; | |
class Expr { | |
Expr(Expr&&) = delete; | |
public: | |
Expr() {} | |
Expr(const Expr&) {} | |
virtual ~Expr() {} | |
virtual shared_ptr<Value> eval(const map<string,shared_ptr<Value>>&) const { | |
throw runtime_error("no evaluation possible"); | |
} | |
}; | |
class Var : public Expr { | |
const string var; | |
public: | |
Var(const string& var_) : var(var_) {} | |
Var(const Var& v) : var(v.var) {} | |
~Var() {} | |
shared_ptr<Value> eval(const map<string,shared_ptr<Value>>& context) const { return context.at(var); } | |
}; | |
class Val : public Expr { | |
const shared_ptr<Value> val; | |
public: | |
Val(Value* val_) : val(val_) {} | |
Val(const Val& v) : val(v.val) {} | |
~Val() {} | |
shared_ptr<Value> eval(const map<string,shared_ptr<Value>>&) const { return val; } | |
}; | |
class Lam : public Expr { | |
const string x; | |
const Expr* const e; | |
public: | |
Lam(const string& x_, const Expr* const e_) : x(x_), e(e_) {} | |
Lam(const Lam& lam) : x(lam.x), e(lam.e) {} | |
~Lam() {} | |
shared_ptr<Value> eval(const map<string,shared_ptr<Value>>& context) const { | |
const string x_(x); | |
const Expr * const e_(e); | |
return shared_ptr<Value>(new FunValue([x_,e_,context](shared_ptr<Value> v) { | |
map<string,shared_ptr<Value>> new_context(context); | |
new_context.insert(make_pair(x_, v)); | |
return e_->eval(new_context); | |
})); | |
} | |
}; | |
class Ap : public Expr { | |
const Expr * const e1, * const e2; | |
public: | |
Ap(const Expr* const e1_, const Expr* const e2_) : e1(e1_), e2(e2_) {} | |
Ap(const Ap& ap) : e1(ap.e1), e2(ap.e2) {} | |
~Ap() {} | |
shared_ptr<Value> eval(const map<string,shared_ptr<Value>>& context) const { | |
shared_ptr<Value> v1 = e1->eval(context); | |
shared_ptr<Value> v2 = e2->eval(context); | |
// throw exception upon type mismatch | |
return dynamic_pointer_cast<FunValue>(v1)->apply(v2); | |
} | |
}; | |
int main() { | |
Expr * e = | |
new Ap(new Lam("x", new Var("x")), | |
new Val(new IntValue(5))); | |
shared_ptr<Value> v = e->eval({}); | |
printf("%d\n", dynamic_pointer_cast<IntValue>(v)->getInt()); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment