diff options
| author | peter <peter@pmikkelsen.com> | 2026-08-25 20:56:55 +0000 |
|---|---|---|
| committer | peter <peter@pmikkelsen.com> | 2026-08-25 20:56:55 +0000 |
| commit | 86a65e695b9dc1fb7a20094204339f5bf168fb92 (patch) | |
| tree | c4ab839a70c830097103d33797fedf01261d1800 | |
| parent | 956cfb9ac26f44d05ffc446f30f84174865685a4 (diff) | |
Start working on modules, including a built-in "boot" module
FossilOrigin-Name: 4829dbeb2071fe0be41ded66a61ba2e156119a47def8a23415b8227a00d53ce7
| -rw-r--r-- | CMakeLists.txt | 12 | ||||
| -rw-r--r-- | src/include/aplwc.h | 3 | ||||
| -rw-r--r-- | src/lib/aplwc_internal.h | 15 | ||||
| -rw-r--r-- | src/lib/boot.aplwc | 13 | ||||
| -rw-r--r-- | src/lib/main.c | 43 | ||||
| -rw-r--r-- | src/lib/module.c | 65 | ||||
| -rw-r--r-- | src/lib/string.c | 4 | ||||
| -rw-r--r-- | src/lib/syntax.c | 48 | ||||
| -rw-r--r-- | tests/aplwc_new.c | 5 |
9 files changed, 188 insertions, 20 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f59b019..d3450d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,13 +48,25 @@ target_link_options(common INTERFACE ) add_library(aplwc + ${CMAKE_CURRENT_BINARY_DIR}/generated_headers/boot.h src/lib/eval.c src/lib/main.c src/lib/memory.c + src/lib/module.c src/lib/string.c src/lib/syntax.c ) target_link_libraries(aplwc PRIVATE common) +target_include_directories(aplwc PRIVATE + "${CMAKE_CURRENT_BINARY_DIR}/generated_headers/" +) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/generated_headers/boot.h" + COMMAND xxd -i -n boot_src "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/boot.aplwc" "${CMAKE_CURRENT_BINARY_DIR}/generated_headers/boot.h" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/lib/boot.aplwc" + COMMENT "Generate boot.h from boot.aplwc" +) add_executable(aplwc-repl src/bin/main.c diff --git a/src/include/aplwc.h b/src/include/aplwc.h index 58db819..a22bd8d 100644 --- a/src/include/aplwc.h +++ b/src/include/aplwc.h @@ -28,7 +28,8 @@ void aplwc_free_line(struct aplwc_line *); struct aplwc_value *aplwc_eval(struct aplwc_line *); void aplwc_free_value(struct aplwc_value *); const char *aplwc_value_string(struct aplwc_value *); +enum aplwc_rc aplwc_load_module(struct aplwc *, const char *, const char *, int n); -#define APLWC_MIN_MEM (64) +#define APLWC_MIN_MEM (2048) #endif /* APLWC_H */ diff --git a/src/lib/aplwc_internal.h b/src/lib/aplwc_internal.h index 33feafb..b027073 100644 --- a/src/lib/aplwc_internal.h +++ b/src/lib/aplwc_internal.h @@ -36,7 +36,13 @@ enum token_tag { TOKEN_TAG_NEWLINE, TOKEN_TAG_NUMBER, TOKEN_TAG_LEFT_ARROW, - TOKEN_TAG_DIAMOND + TOKEN_TAG_DIAMOND, + TOKEN_TAG_KEYWORD, + TOKEN_TAG_TEXT, + TOKEN_TAG_DEL, + TOKEN_TAG_LEFT_PAREN, + TOKEN_TAG_RIGHT_PAREN, + TOKEN_TAG_IBEAM }; struct token { @@ -77,11 +83,14 @@ void memory_free_token_list(struct memory *, struct token_list *); void memory_free_aplwc_value(struct memory *, struct aplwc_value *); /* string.c */ -struct string *chars_to_string(struct aplwc *, const char *); +struct string *chars_to_string(struct aplwc *, const char *, int len); uint32_t string_char(struct string *, size_t); size_t char_length(struct string *, size_t); /* syntax.c */ -struct token_list *scan_line(struct aplwc *, struct string *); +struct token_list *scan_string(struct aplwc *, struct string *, int); + +/* module.c */ +enum aplwc_rc load_module(struct aplwc *, struct string *, struct token_list *); #endif /* APLWC_INTERNAL_H */ diff --git a/src/lib/boot.aplwc b/src/lib/boot.aplwc new file mode 100644 index 0000000..6248427 --- /dev/null +++ b/src/lib/boot.aplwc @@ -0,0 +1,13 @@ +:module Boot +:symbol plus '+' +:symbol minus '-' +:export '+' '-' + +∇ r←a plus b + r←a (1⌶) b +∇ + +∇ r←a minus b + r←a (2⌶) b +∇ + diff --git a/src/lib/main.c b/src/lib/main.c index e9d33cb..ae17f34 100644 --- a/src/lib/main.c +++ b/src/lib/main.c @@ -1,4 +1,5 @@ #include "aplwc_internal.h" +#include "boot.h" enum aplwc_rc aplwc_new(struct aplwc **p, uint8_t *data, size_t size) @@ -12,7 +13,7 @@ aplwc_new(struct aplwc **p, uint8_t *data, size_t size) return APLWC_OUT_OF_MEMORY; (*p)->memory = m; - return APLWC_OK; + return aplwc_load_module(*p, "Boot", (const char *)boot_src, boot_src_len); } void @@ -70,11 +71,11 @@ aplwc_read(struct aplwc *aplwc, const char *line) struct token_list *tokens; struct aplwc_line *ret; - text = chars_to_string(aplwc, line); + text = chars_to_string(aplwc, line, -1); if(text == NULL) return NULL; - tokens = scan_line(aplwc, text); + tokens = scan_string(aplwc, text, 1); if(tokens == NULL) return NULL; @@ -124,3 +125,39 @@ aplwc_value_string(struct aplwc_value *value) 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; + + namestr = NULL; + text = NULL; + tokens = NULL; + + namestr = chars_to_string(aplwc, name, -1); + if(namestr == NULL) + goto error; + + text = chars_to_string(aplwc, src, srclen); + if(text == NULL) + goto error; + + tokens = scan_string(aplwc, text, 0); + if(tokens == NULL) + goto error; + + if(load_module(aplwc, namestr, tokens) == APLWC_OK) + return APLWC_OK; + else{ +error: + if(tokens != NULL) + memory_free_token_list(&aplwc->memory, tokens); + if(text != NULL) + memory_free_string(&aplwc->memory, text); + if(namestr != NULL) + memory_free_string(&aplwc->memory, namestr); + return aplwc_last_error(aplwc); + } +} diff --git a/src/lib/module.c b/src/lib/module.c new file mode 100644 index 0000000..4ce9f8c --- /dev/null +++ b/src/lib/module.c @@ -0,0 +1,65 @@ +#include "aplwc_internal.h" + +static int +read_keyword_decl(struct token_list *tokens, size_t offset) +{ + int len; + + for(len = 1; (offset + len) < tokens->length; len++) + if(tokens->tokens[offset+len].tag == TOKEN_TAG_NEWLINE) + break; + return len; +} + +static int +read_function_decl(struct token_list *tokens, size_t offset) +{ + int len; + + for(len = 1; (offset + len) < tokens->length; len++) + if(tokens->tokens[offset+len].tag == TOKEN_TAG_DEL) + break; + return len; +} + +static int +read_decl(struct token_list *tokens, size_t offset) +{ + UNUSED_PARAMETER(tokens); + UNUSED_PARAMETER(offset); + + switch(tokens->tokens[offset].tag){ + case TOKEN_TAG_NEWLINE: + return 0; + case TOKEN_TAG_KEYWORD: + return read_keyword_decl(tokens, offset); + case TOKEN_TAG_DEL: + return read_function_decl(tokens, offset); + default: + return -1; + } +} + +static enum aplwc_rc +read_decls(struct token_list *tokens) +{ + size_t offset; + int skip; + + for(offset = 0; offset < tokens->length; offset++){ + skip = read_decl(tokens, offset); + if(skip == -1) + return APLWC_INVALID_SYNTAX; + offset += skip; + } + return APLWC_OK; +} + +enum aplwc_rc +load_module(struct aplwc *aplwc, struct string *name, struct token_list *tokens) +{ + UNUSED_PARAMETER(aplwc); + UNUSED_PARAMETER(name); + + return read_decls(tokens); +} diff --git a/src/lib/string.c b/src/lib/string.c index 123e81b..ecac9d7 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -1,7 +1,7 @@ #include "aplwc_internal.h" struct string * -chars_to_string(struct aplwc *aplwc, const char *chars) +chars_to_string(struct aplwc *aplwc, const char *chars, int len) { const uint8_t *utf8; size_t bytecount, charcount; @@ -12,7 +12,7 @@ chars_to_string(struct aplwc *aplwc, const char *chars) utf8 = (const uint8_t *)chars; seqlen = extra = 0; - for(bytecount = 0, charcount = 0; utf8[bytecount]; bytecount++){ + for(bytecount = 0, charcount = 0; ((bytecount < (unsigned int)len) || (len == -1)) && utf8[bytecount]; bytecount++){ b = utf8[bytecount]; if(extra == 0){ c = 0; diff --git a/src/lib/syntax.c b/src/lib/syntax.c index c3452f2..f930973 100644 --- a/src/lib/syntax.c +++ b/src/lib/syntax.c @@ -59,6 +59,11 @@ single_sym(struct scan_state *state, struct token *token) switch(peek(state)){ case 0x2190: token->tag = TOKEN_TAG_LEFT_ARROW; break; case 0x22C4: token->tag = TOKEN_TAG_DIAMOND; break; + case 0x2207: token->tag = TOKEN_TAG_DEL; break; + case 0x2336: token->tag = TOKEN_TAG_IBEAM; break; + case '\n': token->tag = TOKEN_TAG_NEWLINE; break; + case '(': token->tag = TOKEN_TAG_LEFT_PAREN; break; + case ')': token->tag = TOKEN_TAG_RIGHT_PAREN; break; default: return 0; } @@ -83,6 +88,21 @@ identifier(struct scan_state *state, struct token *token) return 1; } +static int +keyword(struct scan_state *state, struct token *token) +{ + uint32_t c; + if(peek(state) != ':') + return 0; + + do + c = advance(state); + while(is_letter(c)); + + token->tag = TOKEN_TAG_KEYWORD; + return 1; +} + static int number(struct scan_state *state, struct token *token) { @@ -125,14 +145,25 @@ number(struct scan_state *state, struct token *token) return 1; } -static int -newline(struct scan_state *state, struct token *token) +static int +text(struct scan_state *state, struct token *token) { - if(peek(state) != '\n') + uint32_t c; + + c = peek(state); + if(c != '\'') return 0; - advance(state); - token->tag = TOKEN_TAG_NEWLINE; + do + c = advance(state); + while((c != '\n') && (c != 0) && (c != '\'')); + + if(c == '\'') + advance(state); + else + return 0; + + token->tag = TOKEN_TAG_TEXT; return 1; } @@ -143,8 +174,9 @@ next_token(struct scan_state *state, struct token *token) int (*scans[])(struct scan_state *, struct token *token) = { single_sym, identifier, + keyword, number, - newline + text, }; skip_space(state); @@ -198,7 +230,7 @@ scan(struct string *text, struct token_list *tokens) } struct token_list * -scan_line(struct aplwc *aplwc, struct string *text) +scan_string(struct aplwc *aplwc, struct string *text, int oneline) { enum aplwc_rc rc; struct token_list *tokens; @@ -218,7 +250,7 @@ scan_line(struct aplwc *aplwc, struct string *text) tokens->length = n; scan(text, tokens); - for(i = 0; i < n; i++){ + for(i = 0; oneline && (i < n); i++){ if(tokens->tokens[i].tag != TOKEN_TAG_NEWLINE) continue; diff --git a/tests/aplwc_new.c b/tests/aplwc_new.c index 55e742f..8d57ecd 100644 --- a/tests/aplwc_new.c +++ b/tests/aplwc_new.c @@ -11,15 +11,14 @@ main(void) for(i = 0; i < 32; i++){ for(j = 0; j <= sizeof(data)-i; j++){ ret = aplwc_new(&aplwc, data+i, j); + aplwc_destroy(aplwc); if(ret){ if(ret != APLWC_OUT_OF_MEMORY) return 1; - if(aplwc != NULL) - return 1; if(j >= APLWC_MIN_MEM) return 1; + break; } - aplwc_destroy(aplwc); } } |