summaryrefslogtreecommitdiff
path: root/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'ast.c')
-rw-r--r--ast.c113
1 files changed, 73 insertions, 40 deletions
diff --git a/ast.c b/ast.c
index a6f308d..c2ea654 100644
--- a/ast.c
+++ b/ast.c
@@ -12,27 +12,37 @@ void ast_free(AST *ast){
assert(ast);
switch(ast->type){
case AST_LIST:
- assert(ast->l.len>=0);
- for(int i=0;i<ast->l.len;i++){
- assert(ast->l.nodes[i]);
- ast_free(ast->l.nodes[i]);
+ assert(ast->li.len>=0);
+ for(int i=0;i<ast->li.len;i++){
+ assert(ast->li.nodes[i]);
+ ast_free(ast->li.nodes[i]);
}
break;
+ case AST_LAMBDA:
+ assert(ast->la.cfunc||ast->la.body);
+ if(ast->la.body)ast_free(ast->la.body);
+ break;
+
case AST_WORD:
- assert(ast->w.word);
- free(ast->w.word);
+ assert(ast->wo.word);
+ free(ast->wo.word);
break;
case AST_STRING:
- assert(ast->S.str);
- free(ast->S.str);
+ assert(ast->st.str);
+ free(ast->st.str);
break;
case AST_NUMBER:
case AST_SYMBOL:
break;
+ case AST_QUOTED:
+ assert(ast->qu.ast);
+ ast_free(ast->qu.ast);
+ break;
+
default:
assert(false);
}
@@ -44,32 +54,36 @@ AST* ast_copy(const AST *ast){
assert(ast);
switch(ast->type){
case AST_LIST:{
- assert(ast->l.len>=0);
- assert(ast->l.nodes);
- AST **nodes=malloc(ast->l.len,AST*);
- for(int i=0;i<ast->l.len;i++)nodes[i]=ast_copy(ast->l.nodes[i]);
- AST *l=ast_list(ast->l.len,nodes);
- l->l.quoted=ast->l.quoted;
- return l;
+ assert(ast->li.len>=0);
+ assert(ast->li.nodes);
+ AST **nodes=malloc(ast->li.len,AST*);
+ for(int i=0;i<ast->li.len;i++)nodes[i]=ast_copy(ast->li.nodes[i]);
+ return ast_list(ast->li.len,nodes);
}
+ case AST_LAMBDA:
+ return ast_lambda(ast->la.cfunc,ast->la.body?ast_copy(ast->la.body):NULL);
+
case AST_WORD:
- assert(ast->w.word);
- return ast_word(copystring(ast->w.word));
+ assert(ast->wo.word);
+ return ast_word(copystring(ast->wo.word));
case AST_NUMBER:
- return ast_number(ast->n.num);
+ return ast_number(ast->nu.num);
case AST_STRING:
- return ast_string(copybufasstring(ast->S.str,ast->S.len),ast->S.len);
+ return ast_string(copybufasstring(ast->st.str,ast->st.len),ast->st.len);
case AST_SYMBOL:{
- assert(ast->s.name);
- AST *sym=ast_symbol(ast->s.name);
- sym->s.symid=ast->s.symid;
+ assert(ast->sy.name);
+ AST *sym=ast_symbol(ast->sy.name);
+ sym->sy.symid=ast->sy.symid;
return sym;
}
+ case AST_QUOTED:
+ return ast_quoted(ast_copy(ast->qu.ast));
+
default:
assert(false);
}
@@ -114,22 +128,21 @@ static void ast_stringify_(const AST *ast,Buffer *buf){
assert(buf);
switch(ast->type){
case AST_LIST:
- if(ast->l.quoted)buf_append(buf,"'",1);
buf_append(buf,"(",1);
- for(int i=0;i<ast->l.len;i++){
+ for(int i=0;i<ast->li.len;i++){
if(i!=0)buf_append(buf," ",1);
- ast_stringify_(ast->l.nodes[i],buf);
+ ast_stringify_(ast->li.nodes[i],buf);
}
buf_append(buf,")",1);
break;
case AST_WORD:
- buf_append(buf,ast->w.word,strlen(ast->w.word));
+ buf_append(buf,ast->wo.word,strlen(ast->wo.word));
break;
case AST_NUMBER:{
char *s;
- int len=asprintf(&s,"%g",ast->n.num);
+ int len=asprintf(&s,"%g",ast->nu.num);
if(!s)outofmem();
buf_append(buf,s,len);
free(s);
@@ -138,8 +151,8 @@ static void ast_stringify_(const AST *ast,Buffer *buf){
case AST_STRING:{
buf_append(buf,"\"",1);
- const char *str=ast->S.str;
- for(int i=0;i<ast->S.len;i++){
+ const char *str=ast->st.str;
+ for(int i=0;i<ast->st.len;i++){
if(str[i]>=32&&str[i]<=126)buf_append(buf,str+i,1);
else switch(str[i]){
case '\n': buf_append(buf,"\\n",2); break;
@@ -164,7 +177,12 @@ static void ast_stringify_(const AST *ast,Buffer *buf){
case AST_SYMBOL:
buf_append(buf,"'",1);
- buf_append(buf,ast->s.name,strlen(ast->s.name));
+ buf_append(buf,ast->sy.name,strlen(ast->sy.name));
+ break;
+
+ case AST_QUOTED:
+ buf_append(buf,"'",1);
+ ast_stringify_(ast->qu.ast,buf);
break;
default:
@@ -185,10 +203,17 @@ AST* ast_list(int len,AST **nodes){
assert(nodes);
AST *ast=malloc(1,AST);
ast->type=AST_LIST;
- ast->l.len=len;
- ast->l.nodes=malloc(len,AST*);
- memcpy(ast->l.nodes,nodes,len*sizeof(AST*));
- ast->l.quoted=false;
+ ast->li.len=len;
+ ast->li.nodes=nodes;
+ return ast;
+}
+
+AST* ast_lambda(lambdafunc_t cfunc,AST *body){
+ assert(cfunc||body);
+ AST *ast=malloc(1,AST);
+ ast->type=AST_LAMBDA;
+ ast->la.cfunc=cfunc;
+ ast->la.body=body;
return ast;
}
@@ -196,22 +221,22 @@ AST* ast_word(char *word){
assert(word);
AST *ast=malloc(1,AST);
ast->type=AST_WORD;
- ast->w.word=word;
+ ast->wo.word=word;
return ast;
}
AST* ast_number(double num){
AST *ast=malloc(1,AST);
ast->type=AST_NUMBER;
- ast->n.num=num;
+ ast->nu.num=num;
return ast;
}
AST* ast_string(char *str,int len){
AST *ast=malloc(1,AST);
ast->type=AST_STRING;
- ast->S.str=str;
- ast->S.len=len;
+ ast->st.str=str;
+ ast->st.len=len;
return ast;
}
@@ -219,7 +244,15 @@ AST* ast_symbol(char *name){
assert(name);
AST *ast=malloc(1,AST);
ast->type=AST_SYMBOL;
- ast->s.name=name;
- ast->s.symid=-1;
+ ast->sy.name=name;
+ ast->sy.symid=-1;
+ return ast;
+}
+
+AST* ast_quoted(AST *contents){
+ assert(contents);
+ AST *ast=malloc(1,AST);
+ ast->type=AST_QUOTED;
+ ast->qu.ast=contents;
return ast;
}