Initial Commit

This commit is contained in:
2014-05-20 15:32:21 +01:00
commit 46bbd52885
30 changed files with 2029 additions and 0 deletions

190
lval.c Normal file
View File

@@ -0,0 +1,190 @@
#include <stdlib.h>
#include "lang.h"
#include "util.h"
lval* lval_new(int type) {
lval* val = calloc(1,sizeof(lval));
val->type = type;
return val;
}
lval* lval_num(double_t x) {
lval* val = lval_new(LVAL_NUM);
val->data.num = x;
return val;
}
lval* lval_sym(char* x) {
lval* val = lval_new(LVAL_SYM);
val->data.sym = strdup(x);
return val;
}
lval* lval_s_expr() {
lval* val = lval_new(LVAL_S_EXPR);
val->cell_count = 0;
val->cell_list = NULL;
return val;
}
lval* lval_q_expr() {
lval* val = lval_new(LVAL_Q_EXPR);
val->cell_count = 0;
val->cell_list = NULL;
return val;
}
lval* lval_func(lbuiltin func, char* name) {
lval* val = lval_new(LVAL_FUNC);
val->data.func.call = func;
val->data.func.name = strdup(name);
return val;
}
lval* lval_exit() {
lval* val = lval_new(LVAL_EXIT);
return val;
}
lval* lval_add(lval* val, lval* x) {
val->cell_count++;
val->cell_list = realloc(val->cell_list, sizeof(lval*)*val->cell_count);
val->cell_list[val->cell_count-1] = x;
return val;
}
lval* lval_pop(lval* val, int index) {
//Get the item
lval* x = val->cell_list[index];
//Re-create the list ignoring the index we are extracting
lval** newList = NULL;
if (val->cell_count-1 > 0) {
newList = calloc(val->cell_count-1, sizeof(lval*));
int k = 0;
for(int i=0; i < val->cell_count; i++) {
if (i == index) {
continue;
}
newList[k++] = val->cell_list[i];
}
}
val->cell_count--;
free(val->cell_list);
val->cell_list = newList;
return x;
}
lval* lval_take(lval* val, int i) {
lval* x = lval_pop(val, i);
lval_delete(val);
return x;
}
lval* lval_join(lval* a, lval* b) {
while(b->cell_count > 0) {
lval_add(a, lval_pop(b,0));
}
lval_delete(b);
return a;
}
void lval_delete(lval* val) {
switch(val->type) {
case LVAL_NUM: break;
case LVAL_EXIT: break;
case LVAL_FUNC: free(val->data.func.name); break;
case LVAL_SYM: free(val->data.sym); break;
case LVAL_ERR:
if (val->data.err.detail != NULL) {
free(val->data.err.detail);
}
break;
case LVAL_Q_EXPR:
case LVAL_S_EXPR:
for (int i = 0; i < val->cell_count; i++) {
lval_delete(val->cell_list[i]);
}
if (val->cell_count > 0) {
free(val->cell_list);
}
break;
}
free(val);
}
lval* lval_copy(lval* current) {
lval* new = lval_new(current->type);
switch(current->type) {
case LVAL_FUNC:
new->data.func.call = current->data.func.call;
new->data.func.name = strdup(current->data.func.name);
break;
case LVAL_NUM: new->data.num = current->data.num; break;
case LVAL_EXIT: break;
case LVAL_SYM: new->data.sym = strdup(current->data.sym); break;
case LVAL_ERR:
new->data.err.num = current->data.err.num;
new->data.err.detail = current->data.err.detail == NULL ? NULL : strdup(current->data.err.detail);
break;
case LVAL_Q_EXPR:
case LVAL_S_EXPR:
new->cell_count = current->cell_count;
if (new->cell_count == 0) {
new->cell_list = NULL;
} else {
new->cell_list = calloc(new->cell_count, sizeof(lval*));
for(int i=0; i < new->cell_count; i++) {
new->cell_list[i] = lval_copy(current->cell_list[i]);
}
}
break;
}
return new;
}
lval* lval_err(VAL_ERROR err){
return lval_err_detail(err, NULL);
}
lval* lval_err_detail(VAL_ERROR err, char* format, ...){
lval* val = lval_new(LVAL_ERR);
val->data.err.num = err;
va_list va;
va_start(va, format);
val->data.err.detail = calloc(512, sizeof(char));
vsnprintf(val->data.err.detail, 511, format, va);
if (strlen(val->data.err.detail) == 0) {
free(val->data.err.detail);
val->data.err.detail = NULL;
} else {
val->data.err.detail = realloc(val->data.err.detail, strlen(val->data.err.detail)+1);
}
va_end(va);
return val;
}
char* lval_str_name(VAL_TYPE type) {
switch(type) {
case LVAL_ERR: return "Error";
case LVAL_FUNC: return "Function";
case LVAL_NUM: return "Numeric";
case LVAL_Q_EXPR: return "Q-Expression";
case LVAL_SYM: return "Symbol";
case LVAL_S_EXPR: return "S-Expression";
default: return "UNKNOWN";
}
}