/* * Copyright (C) 2026 Peter Mikkelsen * * This file is part of aplwc. * * Aplwc is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Aplwc is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with aplwc. If not, see . */ #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->modules = NULL; 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; } void aplwc_read(struct aplwc *aplwc, const char *linestr, AplwcLine *lineptr) { struct string *text; struct token_list *tokens; struct aplwc_line *line; MEMPTRS(aplwc, 2); aplwc_clear_line(lineptr); 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; memory_root_new(aplwc, line, &lineptr->ref); end: MEMPTRS_EXIT(aplwc); } void aplwc_free_line(AplwcLine *line) { memory_root_free(&line->ref); } void 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) memory_root_new(aplwc, v, &value->ref); } 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); }