summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-08-24 22:51:28 +0200
committertomsmeding <tom.smeding@gmail.com>2016-08-24 22:51:28 +0200
commit0d339ae7bf88443df5968d605aeca146dd78e0c3 (patch)
tree31263fc97c77059696a7fd2470ff40120b510ed8
parent43d1244d4d3f5680c84ed840eb8876292c3fd49c (diff)
If; logical operatorsHEADmaster
-rw-r--r--ast.c21
-rw-r--r--fibo.lysp17
-rw-r--r--if.lysp7
-rw-r--r--inter_builtins.c60
-rw-r--r--inter_builtins.h10
-rw-r--r--interpreter.c26
6 files changed, 135 insertions, 6 deletions
diff --git a/ast.c b/ast.c
index 7456ee3..07e2006 100644
--- a/ast.c
+++ b/ast.c
@@ -142,6 +142,27 @@ static void ast_stringify_(const AST *ast,Buffer *buf){
buf_append(buf,")",1);
break;
+ case AST_LAMBDA:
+ buf_append(buf,"[[lambda ",9);
+ if(ast->la.cfunc)buf_append(buf,"cfunc]]",7);
+ else {
+ buf_append(buf,"body ",5);
+ ast_stringify_(ast->la.body,buf);
+ buf_append(buf,"]]",2);
+ }
+ break;
+
+ case AST_LAMBDAARG:{
+ buf_append(buf,"[[lambdaArg ",12);
+ char *s;
+ int len=asprintf(&s,"%d",ast->ar.idx);
+ if(!s)outofmem();
+ buf_append(buf,s,len);
+ free(s);
+ buf_append(buf,"]]",2);
+ break;
+ }
+
case AST_WORD:
buf_append(buf,ast->wo.word,strlen(ast->wo.word));
break;
diff --git a/fibo.lysp b/fibo.lysp
new file mode 100644
index 0000000..09fe16b
--- /dev/null
+++ b/fibo.lysp
@@ -0,0 +1,17 @@
+(do
+ (define 'fibo '(n)
+ '(if (= n 0) 0
+ '(if (= n 1) 1
+ '(+ (fibo (- n 2)) (fibo (- n 1)))
+ )
+ )
+ )
+ (print (fibo 1))
+ (print (fibo 2))
+ (print (fibo 3))
+ (print (fibo 4))
+ (print (fibo 5))
+ (print (fibo 6))
+ (print (fibo 7))
+ (print (fibo 8))
+)
diff --git a/if.lysp b/if.lysp
new file mode 100644
index 0000000..d322d74
--- /dev/null
+++ b/if.lysp
@@ -0,0 +1,7 @@
+(do
+ (define 'n '() 0)
+ (if (= (n) 1)
+ '(do (print "ja") 42)
+ '(do (print "nee") 10)
+ )
+)
diff --git a/inter_builtins.c b/inter_builtins.c
index ba00935..b4bcf22 100644
--- a/inter_builtins.c
+++ b/inter_builtins.c
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE //asprintf
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -7,33 +8,84 @@
#include "interpreter.h"
#include "util.h"
+extern InterRet interpret(InterState *is,const AST *ast);
+
+
InterRet builtin_do(InterState *is,int nargs,AST **args){
assert(args);
InterRet ir;
for(int i=0;i<nargs;i++){
assert(args[i]);
- ir=inter_runcode(is,args[i]);
+ ir=interpret(is,args[i]);
if(ir.errstr)return ir;
if(i<nargs-1)ast_free(ir.ast);
}
return ir;
}
+InterRet builtin_if(InterState *is,int nargs,AST **args){
+ assert(args);
+ if(nargs!=2&&nargs!=3){
+ char *buf;
+ asprintf(&buf,"Builtin 'if' needs 2 or 3 arguments, got %d",nargs);
+ if(!buf)outofmem();
+ return ir_err(buf);
+ }
+ bool cond;
+ switch(args[0]->type){
+ case AST_LIST: cond=args[0]->li.len!=0; break;
+ case AST_LAMBDAARG: assert(false);
+ case AST_WORD: assert(false);
+ case AST_NUMBER: cond=args[0]->nu.num!=0; break;
+ case AST_STRING: cond=args[0]->st.len!=0; break;
+ default:
+ return ir_err_c("Invalid node type in condition of builtin 'if'");
+ }
+ if(cond)return interpret(is,args[1]);
+ else if(nargs==3)return interpret(is,args[2]);
+ else return ir_ast(ast_list(0,malloc(1,AST*)));
+}
+
InterRet builtin_print(InterState *is,int nargs,AST **args){
(void)is;
assert(args);
for(int i=0;i<nargs;i++){
assert(args[i]);
- char *s=ast_stringify(args[i]);
if(i>0)putchar(' ');
- printf("%s",s);
- free(s);
+ if(args[i]->type==AST_STRING){
+ fwrite(args[i]->st.str,1,args[i]->st.len,stdout);
+ } else {
+ char *s=ast_stringify(args[i]);
+ printf("%s",s);
+ free(s);
+ }
}
putchar('\n');
return ir_ast(ast_list(0,malloc(1,AST*)));
}
+#define BUILTIN_LOGICAL_OP(op,name) \
+ InterRet builtin_##name(InterState *is,int nargs,AST **args){ \
+ (void)is; \
+ assert(args); \
+ if(nargs!=2||args[0]->type!=AST_NUMBER||args[1]->type!=AST_NUMBER){ \
+ return ir_err_c("Logical operator '" #op "' expects two number arguments"); \
+ } \
+ return ir_ast(ast_number(args[0]->nu.num op args[1]->nu.num)); \
+ }
+
+
+BUILTIN_LOGICAL_OP(==,equals);
+BUILTIN_LOGICAL_OP(>,greater);
+BUILTIN_LOGICAL_OP(>=,greaterequals);
+BUILTIN_LOGICAL_OP(<,less);
+BUILTIN_LOGICAL_OP(<=,lessequals);
+
+
+#undef BUILTIN_LOGICAL_OP
+
+
#define BUILTIN_ARITH_OP(op,name,defval,expr) \
InterRet builtin_##name(InterState *is,int nargs,AST **args){ \
(void)is; \
diff --git a/inter_builtins.h b/inter_builtins.h
index c9a4bdc..e843b5e 100644
--- a/inter_builtins.h
+++ b/inter_builtins.h
@@ -4,10 +4,20 @@
#include "interpreter.h"
InterRet builtin_do(InterState *is,int nargs,AST **args);
+InterRet builtin_if(InterState *is,int nargs,AST **args);
+
InterRet builtin_print(InterState *is,int nargs,AST **args);
+
+InterRet builtin_equals(InterState *is,int nargs,AST **args);
+InterRet builtin_greater(InterState *is,int nargs,AST **args);
+InterRet builtin_greaterequals(InterState *is,int nargs,AST **args);
+InterRet builtin_less(InterState *is,int nargs,AST **args);
+InterRet builtin_lessequals(InterState *is,int nargs,AST **args);
+
InterRet builtin_sum(InterState *is,int nargs,AST **args);
InterRet builtin_difference(InterState *is,int nargs,AST **args);
InterRet builtin_product(InterState *is,int nargs,AST **args);
InterRet builtin_quotient(InterState *is,int nargs,AST **args);
InterRet builtin_remainder(InterState *is,int nargs,AST **args);
+
InterRet builtin_define(InterState *is,int nargs,AST **args);
diff --git a/interpreter.c b/interpreter.c
index 9f389c1..f5fb3dc 100644
--- a/interpreter.c
+++ b/interpreter.c
@@ -182,7 +182,8 @@ static char* replace_arguments(AST *ast,int nargs,AST **args){
return NULL;
}
-static InterRet interpret(InterState *is,const AST *ast){
+InterRet interpret(InterState *is,const AST *ast){
+ //fprintf(stderr,"Interpreting %s\n",ast_stringify(ast));
switch(ast->type){
case AST_LIST:{
if(ast->li.len==0){
@@ -200,10 +201,15 @@ static InterRet interpret(InterState *is,const AST *ast){
}
if(nodes[0]->type!=AST_LAMBDA){
- fprintf(stderr,"type = %d\n",nodes[0]->type);
return ir_err_c("First node in evaluated list not a function");
}
+ /*AST *temp=ast_list(ast->li.len,nodes);
+ char *ss=ast_stringify(temp);
+ free(temp);
+ fprintf(stderr,"Function call: %s\n",ss);
+ free(ss);*/
+
if(nodes[0]->la.body){
char *errstr=replace_arguments(nodes[0]->la.body,ast->li.len-1,nodes+1);
if(errstr)return ir_err(errstr);
@@ -257,7 +263,22 @@ void inter_register(InterState *is,const char *name,lambdafunc_t cfunc){
void inter_register_prelude(InterState *is){
inter_register(is,"do",builtin_do);
+ inter_register(is,"?",builtin_if);
+ inter_register(is,"if",builtin_if);
+
inter_register(is,"print",builtin_print);
+
+ inter_register(is,"=",builtin_equals);
+ inter_register(is,">",builtin_greater);
+ inter_register(is,">=",builtin_greaterequals);
+ inter_register(is,"<",builtin_less);
+ inter_register(is,"<=",builtin_lessequals);
+ inter_register(is,"equals",builtin_equals);
+ inter_register(is,"greater",builtin_greater);
+ inter_register(is,"greaterequals",builtin_greaterequals);
+ inter_register(is,"less",builtin_less);
+ inter_register(is,"lessequals",builtin_lessequals);
+
inter_register(is,"+",builtin_sum);
inter_register(is,"-",builtin_difference);
inter_register(is,"*",builtin_product);
@@ -268,6 +289,7 @@ void inter_register_prelude(InterState *is){
inter_register(is,"product",builtin_product);
inter_register(is,"quotient",builtin_quotient);
inter_register(is,"remainder",builtin_remainder);
+
inter_register(is,"define",builtin_define);
}