summaryrefslogtreecommitdiff
path: root/prelude.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'prelude.cpp')
-rw-r--r--prelude.cpp108
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);
}