summaryrefslogtreecommitdiff
path: root/interpreter.c
diff options
context:
space:
mode:
Diffstat (limited to 'interpreter.c')
-rw-r--r--interpreter.c125
1 files changed, 119 insertions, 6 deletions
diff --git a/interpreter.c b/interpreter.c
index 333b8c9..05e5d2c 100644
--- a/interpreter.c
+++ b/interpreter.c
@@ -4,6 +4,7 @@
#include <assert.h>
#include "interpreter.h"
+#include "inter_builtins.h"
#include "util.h"
@@ -85,36 +86,148 @@ void inter_destroy(InterState *is){
static void intern_symbols(InterState *is,AST *ast){
switch(ast->type){
case AST_LIST:
- for(int i=0;i<ast->l.len;i++)intern_symbols(is,ast->l.nodes[i]);
+ for(int i=0;i<ast->li.len;i++)intern_symbols(is,ast->li.nodes[i]);
break;
case AST_SYMBOL:{
- if(ast->s.symid>=0&&ast->s.symid<is->ss.len&&strcmp(ast->s.name,is->ss.syms[ast->s.symid])==0){
+ if(ast->sy.symid>=0&&ast->sy.symid<is->ss.len&&strcmp(ast->sy.name,is->ss.syms[ast->sy.symid])==0){
break;
}
int i;
for(i=0;i<is->ss.len;i++){
- if(strcmp(is->ss.syms[i],ast->s.name)==0)break;
+ if(strcmp(is->ss.syms[i],ast->sy.name)==0)break;
}
if(i<is->ss.len){
- ast->s.symid=i;
+ ast->sy.symid=i;
break;
}
if(is->ss.len==is->ss.sz){
is->ss.sz*=2;
is->ss.syms=realloc(is->ss.syms,is->ss.sz,char*);
}
- is->ss.syms[is->ss.len++]=copystring(ast->s.name);
+ is->ss.syms[is->ss.len++]=copystring(ast->sy.name);
break;
}
+ case AST_QUOTED:
+ intern_symbols(is,ast->qu.ast);
+ break;
+
case AST_WORD:
case AST_NUMBER:
case AST_STRING:
break;
+
+ default:
+ assert(false);
+ }
+}
+
+static const AST* find_var(const InterState *is,const char *name){
+ int h=namehash(name,VMAP_HASHSZ);
+ for(const Scope *scope=is->scope;scope;scope=scope->next){
+ for(const Vllist *ll=scope->vmap[h];ll;ll=ll->next){
+ if(strcmp(name,ll->name)==0)return ll->value;
+ }
+ }
+ return NULL;
+}
+
+InterRet ir_ast(AST *ast){
+ InterRet ir={ast,NULL};
+ return ir;
+}
+
+InterRet ir_err(char *errstr){
+ InterRet ir={NULL,errstr};
+ return ir;
+}
+
+InterRet ir_err_c(const char *errstr){
+ return ir_err(copystring(errstr));
+}
+
+static InterRet interpret(InterState *is,const AST *ast){
+ switch(ast->type){
+ case AST_LIST:{
+ if(ast->li.len==0){
+ return ir_ast(ast_copy(ast));
+ }
+ assert(ast->li.len>0);
+ AST *nodes[ast->li.len];
+ for(int i=0;i<ast->li.len;i++){
+ InterRet ir=interpret(is,ast->li.nodes[i]);;
+ if(ir.errstr){
+ while(i-->0)ast_free(nodes[i]);
+ return ir;
+ }
+ nodes[i]=ir.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");
+ }
+
+#define NOT_IMPLEMENTED false
+ if(nodes[0]->la.body)assert(NOT_IMPLEMENTED);
+
+ return nodes[0]->la.cfunc(is,ast->li.len-1,nodes+1);
+ }
+
+ case AST_SYMBOL:
+ return ir_ast(ast_copy(ast));
+
+ case AST_WORD:{
+ const AST *cv=find_var(is,ast->wo.word);
+ if(cv)return ir_ast(ast_copy(cv));
+ char *errstr;
+ asprintf(&errstr,"Unknown variable '%s'",ast->wo.word);
+ if(!errstr)outofmem();
+ return ir_err(errstr);
+ }
+
+ case AST_NUMBER:
+ return ir_ast(ast_copy(ast));
+
+ case AST_STRING:
+ return ir_ast(ast_copy(ast));
+
+ case AST_QUOTED:
+ return ir_ast(ast_copy(ast->qu.ast));
+
+ default:
+ assert(false);
}
}
-void inter_runcode(InterState *is,AST *ast){
+void inter_register(InterState *is,const char *name,lambdafunc_t cfunc){
+ assert(is->scope);
+ int h=namehash(name,VMAP_HASHSZ);
+ Vllist *ll=malloc(1,Vllist);
+ ll->name=copystring(name);
+ ll->value=ast_lambda(cfunc,NULL);
+ ll->next=is->scope->vmap[h];
+ is->scope->vmap[h]=ll;
+}
+
+void inter_register_prelude(InterState *is){
+ inter_register(is,"do",builtin_do);
+ inter_register(is,"print",builtin_print);
+ inter_register(is,"+",builtin_sum);
+ inter_register(is,"-",builtin_difference);
+ inter_register(is,"*",builtin_product);
+ inter_register(is,"/",builtin_quotient);
+ inter_register(is,"%",builtin_remainder);
+ inter_register(is,"sum",builtin_sum);
+ inter_register(is,"difference",builtin_difference);
+ inter_register(is,"product",builtin_product);
+ inter_register(is,"quotient",builtin_quotient);
+ inter_register(is,"remainder",builtin_remainder);
+}
+
+InterRet inter_runcode(InterState *is,AST *ast){
intern_symbols(is,ast);
+
+ return interpret(is,ast);
}