From 0d339ae7bf88443df5968d605aeca146dd78e0c3 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Wed, 24 Aug 2016 22:51:28 +0200 Subject: If; logical operators --- ast.c | 21 ++++++++++++++++++++ fibo.lysp | 17 ++++++++++++++++ if.lysp | 7 +++++++ inter_builtins.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- inter_builtins.h | 10 ++++++++++ interpreter.c | 26 ++++++++++++++++++++++-- 6 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 fibo.lysp create mode 100644 if.lysp 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 #include #include @@ -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;itype){ + 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;i0)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); } -- cgit v1.2.3