diff options
author | tomsmeding <tom.smeding@gmail.com> | 2016-11-20 21:05:01 +0100 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2016-11-20 21:05:01 +0100 |
commit | 979325946b938be7cbe51f8c20c44e457107979f (patch) | |
tree | f6814eb3af59fea8d2f8fe25117a1c88557ae474 /prelude.cpp | |
parent | 834cb55baadb9dd7c3a4ad096d81259d0868eeb9 (diff) |
Sugar and prelude extension
Diffstat (limited to 'prelude.cpp')
-rw-r--r-- | prelude.cpp | 108 |
1 files changed, 81 insertions, 27 deletions
diff --git a/prelude.cpp b/prelude.cpp index cd51cad..5738844 100644 --- a/prelude.cpp +++ b/prelude.cpp @@ -3,6 +3,7 @@ #include <string> #include "error.h" #include "prelude.h" +#include "sugar.h" using namespace std; @@ -15,7 +16,8 @@ const AST afterBootstrap=AST(R"RAW( (def 'flip \f \a \b (f b a)) (def 'id \x x) (def 'const \x \y x) - (def 'print (. putstr repr))) + (def 'print (. putstr repr)) + (def '$ \f \x (f x))) )RAW"); static AST dofunction(const AST&); @@ -36,23 +38,14 @@ public: return AST::makeString(res); })); - intoEnv.define("putstr",AST::makeNative([](const AST &ast) -> AST { - if(ast.type!=AST::Type::string){ - throw TypeError("Argument to 'putstr' is not a String"); - } - cout<<ast.strval<<endl; - return AST(); - })); + intoEnv.define("putstr",checkedHook("putstr",{AST::Type::string}, + [](Environment&,const AST &ast) -> AST {cout<<ast.strval<<endl; return AST();})); - intoEnv.define("def",[](Environment &env,const AST &arg1) -> AST { - return AST::makeNative([&env,arg1](const AST &arg2) -> AST { - if(arg1.type!=AST::Type::name){ - throw TypeError("First argument to 'def' is not a Name"); - } + intoEnv.define("def",checkedHook("def",{AST::Type::name},{}, + [](Environment &env,const AST &arg1,const AST &arg2) -> AST { env.define(arg1.nameval,arg2); return AST(); - }); - }); + })); intoEnv.define("do",doNative); @@ -62,18 +55,79 @@ public: return res; })); - intoEnv.define2("+",[](Environment&,const AST &arg1,const AST &arg2) -> AST { - if(arg1.type!=arg2.type){ - throw TypeError("Unequal types in '+'"); - } - if(arg1.type==AST::Type::number){ - return AST::makeNumber(arg1.numval+arg2.numval); - } else if(arg1.type==AST::Type::string){ - return AST::makeString(arg1.strval+arg2.strval); - } else { - throw TypeError("Arguments to '+' neither Number nor String"); - } - }); + intoEnv.define("head",checkedHook("head",{AST::Type::tuple}, + [](Environment&,const AST &arg) -> AST { + if(arg.terms.size()==0){ + throw FormError("Empty tuple in 'head'"); + } + return arg.terms[0]; + })); + + intoEnv.define("tail",checkedHook("tail",{AST::Type::tuple}, + [](Environment&,const AST &arg) -> AST { + if(arg.terms.size()==0){ + throw FormError("Empty tuple in 'tail'"); + } + return AST::makeTuple(Terms(arg.terms.begin()+1,arg.terms.end())); + })); + + intoEnv.define("nil",checkedHook("nil",{AST::Type::tuple}, + [](Environment&,const AST &arg) -> AST { + return AST::makeNumber(arg.terms.size()==0); + })); + + intoEnv.define("not",checkedHook("not",{AST::Type::number}, + [](Environment&,const AST &arg) -> AST { + return AST::makeNumber(arg.numval==0); + })); + + intoEnv.define("if",checkedHook("if",{AST::Type::number},{},{}, + [](Environment&,const AST &arg1,const AST &arg2,const AST &arg3) -> AST { + if(arg1.numval!=0){ + return arg2; + } else { + return arg3; + } + })); + + intoEnv.define("+",checkedHook("+",{AST::Type::number,AST::Type::string}, + {AST::Type::number,AST::Type::string}, + [](Environment&,const AST &arg1,const AST &arg2) -> AST { + if(arg1.type!=arg2.type){ + throw TypeError("Unequal types in '+'"); + } + if(arg1.type==AST::Type::number){ + return AST::makeNumber(arg1.numval+arg2.numval); + } else { + return AST::makeString(arg1.strval+arg2.strval); + } + })); + + intoEnv.define("-",checkedHook("-",{AST::Type::number},{AST::Type::number}, + [](Environment&,const AST &arg1,const AST &arg2) -> AST { + return AST::makeNumber(arg1.numval-arg2.numval); + })); + + intoEnv.define("*",checkedHook("*",{AST::Type::number},{AST::Type::number}, + [](Environment&,const AST &arg1,const AST &arg2) -> AST { + return AST::makeNumber(arg1.numval*arg2.numval); + })); + + intoEnv.define("/",checkedHook("/",{AST::Type::number},{AST::Type::number}, + [](Environment&,const AST &arg1,const AST &arg2) -> AST { + return AST::makeNumber(arg1.numval/arg2.numval); + })); + + intoEnv.define("%",checkedHook("%",{AST::Type::number},{AST::Type::number}, + [](Environment&,const AST &arg1,const AST &arg2) -> AST { + return AST::makeNumber(arg1.numval%arg2.numval); + })); + + intoEnv.define("=",checkedHook("=",{AST::Type::number,AST::Type::string}, + {AST::Type::number,AST::Type::string}, + [](Environment&,const AST &arg1,const AST &arg2) -> AST { + return AST::makeNumber(arg1.type==arg2.type&&arg1.numval==arg2.numval); + })); intoEnv.run(afterBootstrap); } |