#include "aplwc_internal.h" #include "boot.h" struct aplwc * aplwc_new(struct aplwc_fns fns, enum aplwc_rc *rcp) { enum aplwc_rc rc; struct aplwc *aplwc; size_t size; aplwc = NULL; if(fns.alloc == NULL){ rc = APLWC_OUT_OF_MEMORY; goto end; } aplwc = fns.alloc(sizeof(*aplwc), sizeof(*aplwc), &size); if(aplwc == NULL){ rc = APLWC_OUT_OF_MEMORY; goto end; } aplwc->fns = fns; memory_init(aplwc); rc = aplwc_load_module(aplwc, "Boot", (const char *)boot_src, boot_src_len); end: if(rc != APLWC_OK) aplwc_destroy(aplwc); assert(rcp); *rcp = rc; return aplwc; } void aplwc_destroy(struct aplwc *p) { if(p == NULL) return; memory_destroy(p); if(p->fns.dealloc) p->fns.dealloc(p); } const char * aplwc_errstr_rc(enum aplwc_rc rc) { switch(rc){ case APLWC_OK: return ""; case APLWC_OUT_OF_MEMORY: return "Out of memory"; case APLWC_NOT_YET_IMPLEMENTED: return "Not yet implemented"; case APLWC_INVALID_UTF8: return "Invalid UTF-8"; case APLWC_INVALID_SYNTAX: return "Invalid syntax"; default: return "(unable to produce error string)"; } } const char * aplwc_errstr(struct aplwc *aplwc) { enum { BUF_SIZE = 256 }; const char *err; enum aplwc_rc rc; err = NULL; rc = aplwc ? aplwc->last_error : APLWC_RC_LAST+1; err = aplwc_errstr_rc(rc); return err; } enum aplwc_rc aplwc_last_error(struct aplwc *aplwc) { return aplwc->last_error; } AplwcLine aplwc_read(struct aplwc *aplwc, const char *linestr) { struct string *text; struct token_list *tokens; struct aplwc_line *line; AplwcLine ret; MEMPTRS(aplwc, 2); aplwc_clear_line(&ret); if((text = chars_to_string(aplwc, linestr, -1)) == NULL) goto end; MEMPTR(0, text); if((tokens = scan_string(aplwc, text, 1)) == NULL) goto end; MEMPTR(1, tokens); if((aplwc->last_error = check_tokens(tokens)) != APLWC_OK) goto end; if((line = memory_alloc_aplwc_line(aplwc)) == NULL) goto end; line->text = text; line->tokens = tokens; ret.ref = memory_root_new(aplwc, line); end: MEMPTRS_EXIT(aplwc); return ret; } void aplwc_free_line(AplwcLine line) { memory_root_free(line.ref); } AplwcValue aplwc_eval(AplwcLine line) { AplwcValue value; struct aplwc_line *l; struct aplwc_value *v; struct aplwc *aplwc; aplwc = line.ref.aplwc; aplwc_clear_value(&value); l = memory_root_get(line.ref); aplwc->last_error = APLWC_OK; v = eval_line(aplwc, l); if(v) value.ref = memory_root_new(aplwc, v); return value; } void aplwc_free_value(AplwcValue value) { memory_root_free(value.ref); } const char * aplwc_value_string(AplwcValue value) { struct aplwc_value *v; assert(aplwc_valid_value(value)); v = memory_root_get(value.ref); switch(v->tag){ default: return "???"; } } enum aplwc_rc aplwc_load_module(struct aplwc *aplwc, const char *name, const char *src, int srclen) { struct string *text, *namestr; struct token_list *tokens; MEMPTRS(aplwc, 3); if((namestr = chars_to_string(aplwc, name, -1)) == NULL) goto end; MEMPTR(0, namestr); if((text = chars_to_string(aplwc, src, srclen)) == NULL) goto end; MEMPTR(1, text); if((tokens = scan_string(aplwc, text, 0)) == NULL) goto end; MEMPTR(2, tokens); aplwc->last_error = load_module(aplwc, namestr, tokens); end: MEMPTRS_EXIT(aplwc); return aplwc_last_error(aplwc); } void aplwc_clear_value(AplwcValue *v) { clear_ref(&v->ref); } void aplwc_clear_line(AplwcLine *l) { clear_ref(&l->ref); } int aplwc_valid_value(AplwcValue v) { return valid_ref(v.ref); } int aplwc_valid_line(AplwcLine l) { return valid_ref(l.ref); }