From deaceaf3143c9800fb705fdd1851afffee91ad55 Mon Sep 17 00:00:00 2001 From: mar77i Date: Mon, 18 Nov 2024 18:25:19 +0100 Subject: [PATCH] more useful accessors --- growable.c | 4 +- growable.h | 4 +- parser.c | 33 +++++++------- parser.h | 4 +- runtime.c | 121 +++++++++++++++++++++++---------------------------- runtime.h | 2 +- shitscript.c | 27 +++++++----- shitscript.h | 11 ++++- 8 files changed, 105 insertions(+), 101 deletions(-) diff --git a/growable.c b/growable.c index 3a0decf..a05dfc2 100644 --- a/growable.c +++ b/growable.c @@ -35,6 +35,6 @@ int growable_grow(struct growable *g, size_t len) { return 0; } -void growable_cleanup(struct growable *g) { - free(g->data); +void growable_cleanup(const struct growable g) { + free(g.data); } diff --git a/growable.h b/growable.h index b5e9f89..ae98ae9 100644 --- a/growable.h +++ b/growable.h @@ -15,8 +15,8 @@ struct growable { ((struct growable){ .item_size = (is), .len = 0, .allo = 0, .data = NULL }) int growable_grow(struct growable *g, size_t len); -void growable_cleanup(struct growable *g); +void growable_cleanup(const struct growable g); -#define GROWABLE_AT(g, t, i) ((t*)(g).data)[i] +#define GROWABLE_AT(g, t, i) (((t*)(g).data)[i]) #endif // GROWABLE_H diff --git a/parser.c b/parser.c index a0fe82f..d22a72f 100644 --- a/parser.c +++ b/parser.c @@ -6,7 +6,6 @@ #include #include "growable.h" -#include "shitscript.h" #include "parser.h" static inline int read_number(struct ast_item *ai) { @@ -20,7 +19,8 @@ static inline int read_number(struct ast_item *ai) { } ai->u.i = new_value; } - ungetc(c, stdin); + if (c != EOF) + ungetc(c, stdin); return 0; } @@ -32,13 +32,14 @@ static inline int read_ident_or_keyword(int c, struct ast_item *ai) { ((char*)s.data)[s.len++] = c; c = getc(stdin); } while (isalnum(c) || c == '_'); - ungetc(c, stdin); + if (c != EOF) + ungetc(c, stdin); if (growable_grow(&s, s.len + 1) < 0) return -1; ((char*)s.data)[s.len++] = '\0'; if (strcasecmp(s.data, "goto") == 0) { ai->type = AST_ITEM_GOTO; - growable_cleanup(&s); + growable_cleanup(s); return 0; } ai->type = AST_ITEM_IDENT; @@ -46,7 +47,7 @@ static inline int read_ident_or_keyword(int c, struct ast_item *ai) { return 0; } -int parse_input(struct growable *ast_items, struct growable *markers) { +int parse_input(struct program *p) { int c; struct ast_item ai; while ((c = getc(stdin)) != EOF) { @@ -65,19 +66,19 @@ int parse_input(struct growable *ast_items, struct growable *markers) { ai.type = AST_ITEM_SEMICOLON; goto add_item; case ':': - if (ast_items->len == 0 || ( - (struct ast_item*)ast_items->data - )[ast_items->len - 1].type != AST_ITEM_IDENT) { + if ( + p->ast_items.len == 0 + || GET_ITEM(*p, p->ast_items.len - 1).type != AST_ITEM_IDENT + ) { fprintf(stderr, "Error: Identifier expected before ':'\n"); return -1; } - if (growable_grow(markers, markers->len + 1) < 0) + if (growable_grow(&p->markers, p->markers.len + 1) < 0) return -1; - GROWABLE_AT( - *markers, struct ast_marker, markers->len++ - ) = (struct ast_marker){ - GROWABLE_AT(*ast_items, struct ast_item, --ast_items->len).u.s, - ast_items->len, + p->ast_items.len--; + GET_MARKER(*p, p->markers.len++) = (struct ast_marker){ + GET_ITEM(*p, p->ast_items.len).u.s, + p->ast_items.len, }; continue; case '*': @@ -102,9 +103,9 @@ int parse_input(struct growable *ast_items, struct growable *markers) { fprintf(stderr, "Error: invalid input: '%c' (0x%02x)\n", c, c & 0xff); return -1; add_item: - if (growable_grow(ast_items, ast_items->len + 1) < 0) + if (growable_grow(&p->ast_items, p->ast_items.len + 1) < 0) return -1; - memcpy(&((struct ast_item*)ast_items->data)[ast_items->len++], &ai, sizeof ai); + memcpy(&GET_ITEM(*p, p->ast_items.len++), &ai, sizeof ai); } if (ferror(stdin)) { fprintf(stderr, "Error: read error.\n"); diff --git a/parser.h b/parser.h index c1d4806..9189ab9 100644 --- a/parser.h +++ b/parser.h @@ -4,6 +4,8 @@ #ifndef PARSER_H #define PARSER_H -int parse_input(struct growable *ast_items, struct growable *markers); +#include "shitscript.h" + +int parse_input(struct program *p); #endif // PARSER_H diff --git a/runtime.c b/runtime.c index 17fd532..d8389eb 100644 --- a/runtime.c +++ b/runtime.c @@ -21,15 +21,17 @@ struct scope_item { struct scope_value value; }; +#define GET_SCOPE_ITEM(s, i) (GROWABLE_AT((s), struct scope_item, (i))) + enum evaluate_until { UNTIL_SEMICOLON, }; static inline int maybe_resolve_int( + const struct program p, struct growable *scope, - struct growable markers, - intmax_t *result, - struct ast_item ai + struct ast_item ai, + intmax_t *result ) { size_t i; if (ai.type == AST_ITEM_INT) { @@ -40,40 +42,42 @@ static inline int maybe_resolve_int( return -1; } for (i = 0; i < scope->len; i++) - if (strcmp(((struct scope_item*)scope->data)[i].name, ai.u.s) == 0) + if (strcmp(GET_SCOPE_ITEM(*scope, i).name, ai.u.s) == 0) goto found_in_scope; - for (i = 0; i < markers.len; i++) - if (strcmp(((struct ast_marker*)markers.data)[i].name, ai.u.s) == 0) { - *result = ((struct ast_marker*)markers.data)[i].pos; + for (i = 0; i < p.markers.len; i++) + if (strcmp(GET_MARKER(p, i).name, ai.u.s) == 0) { + *result = GET_MARKER(p, i).pos; return 0; } fprintf(stderr, "Error: unknown identifier: '%s'\n", ai.u.s); return -1; found_in_scope: - if (((struct scope_item*)scope->data)[i].value.type != VALUE_TYPE_INT) { + if (GET_SCOPE_ITEM(*scope, i).value.type != VALUE_TYPE_INT) { fprintf(stderr, "Error: invalid type: '%s'\n", ai.u.s); return -1; } - *result = ((struct scope_item*)scope->data)[i].value.u.i; + *result = GET_SCOPE_ITEM(*scope, i).value.u.i; return 0; } static inline int evaluate_arith( - struct growable ast_items, + const struct program p, + struct growable *scope, size_t *stmt, enum evaluate_until until, - intmax_t *result, - struct growable *scope, - struct growable markers + intmax_t *result ) { - intmax_t accu = 0, other = 0; - if (maybe_resolve_int(scope, markers, &accu, ((struct ast_item*)ast_items.data)[*stmt]) < 0) + intmax_t accu = 0, other; + if (maybe_resolve_int(p, scope, GET_ITEM(p, *stmt), &accu) < 0) return -1; (*stmt)++; - if (until == UNTIL_SEMICOLON && ((struct ast_item*)ast_items.data)[*stmt].type == AST_ITEM_SEMICOLON) + if ( + until == UNTIL_SEMICOLON + && GET_ITEM(p, *stmt).type == AST_ITEM_SEMICOLON + ) goto done; for (;;) { - if (*stmt + 1 >= ast_items.len) { + if (*stmt + 1 >= p.ast_items.len) { switch (until) { case UNTIL_SEMICOLON: fprintf(stderr, "Error: semicolon expected.\n"); @@ -81,35 +85,32 @@ static inline int evaluate_arith( } return -1; } - if (((struct ast_item*)ast_items.data)[*stmt].type == AST_ITEM_PLUS) { - if (maybe_resolve_int(scope, markers, &other, ((struct ast_item*)ast_items.data)[*stmt + 1]) < 0) - return -1; - (*stmt) += 2; + other = 0; + if (maybe_resolve_int(p, scope, GET_ITEM(p, *stmt + 1), &other) < 0) + return -1; + switch (GET_ITEM(p, *stmt).type) { + case AST_ITEM_PLUS: accu += other; - } else if (((struct ast_item*)ast_items.data)[*stmt].type == AST_ITEM_MINUS) { - if (maybe_resolve_int(scope, markers, &other, ((struct ast_item*)ast_items.data)[*stmt + 1]) < 0) - return -1; - (*stmt) += 2; + break; + case AST_ITEM_MINUS: accu -= other; - } else if (((struct ast_item*)ast_items.data)[*stmt].type == AST_ITEM_MULTIPLY) { - if (maybe_resolve_int(scope, markers, &other, ((struct ast_item*)ast_items.data)[*stmt + 1]) < 0) - return -1; - (*stmt) += 2; + break; + case AST_ITEM_MULTIPLY: accu *= other; - } else if (((struct ast_item*)ast_items.data)[*stmt].type == AST_ITEM_DIVIDE) { - if (maybe_resolve_int(scope, markers, &other, ((struct ast_item*)ast_items.data)[*stmt + 1]) < 0) - return -1; - (*stmt) += 2; + break; + case AST_ITEM_DIVIDE: accu /= other; - } else { + break; + default: fprintf(stderr, "Error: unknown operator: "); - ast_item_dump(((struct ast_item*)ast_items.data)[*stmt], stderr); + ast_item_dump(stderr, GET_ITEM(p, *stmt)); fputc('\n', stderr); return -1; } + (*stmt) += 2; if ( until == UNTIL_SEMICOLON - && ((struct ast_item*)ast_items.data)[*stmt].type == AST_ITEM_SEMICOLON + && GET_ITEM(p, *stmt).type == AST_ITEM_SEMICOLON ) goto done; } @@ -124,71 +125,57 @@ static inline int assign_value( size_t i; printf("assigning %s value %"PRIdMAX"\n", name, value.u.i); for (i = 0; i < scope->len; i++) { - if (strcmp(((struct scope_item*)scope->data)[i].name, name) == 0) { - ((struct scope_item*)scope->data)[i].value = value; + if (strcmp(GET_SCOPE_ITEM(*scope, i).name, name) == 0) { + GET_SCOPE_ITEM(*scope, i).value = value; return 0; } } if (growable_grow(scope, scope->len + 1) < 0) return -1; - ((struct scope_item*)scope->data)[scope->len++] = (struct scope_item){ - name, value - }; + GET_SCOPE_ITEM(*scope, scope->len++) = (struct scope_item){ name, value }; return 0; } -int evaluate_statement( - const struct growable ast_items, - const struct growable markers, - size_t *stmt, - struct growable *scope -) { +int evaluate_statement(const struct program p, struct growable *scope, size_t *stmt) { size_t tmp; struct scope_value value = { .type = VALUE_TYPE_INT }; + struct ast_item *item = &GET_ITEM(p, *stmt); if ( - ((struct ast_item*)ast_items.data)[*stmt].type == AST_ITEM_IDENT - && *stmt + 1 < ast_items.len - && ((struct ast_item*)ast_items.data)[*stmt + 1].type == AST_ITEM_ASSIGN + item->type == AST_ITEM_IDENT + && *stmt + 1 < p.ast_items.len + && GET_ITEM(p, *stmt + 1).type == AST_ITEM_ASSIGN ) { tmp = *stmt; *stmt += 2; - if ( - evaluate_arith( - ast_items, stmt, UNTIL_SEMICOLON, &value.u.i, scope, markers - ) < 0 - ) + if (evaluate_arith(p, scope, stmt, UNTIL_SEMICOLON, &value.u.i) < 0) return -1; (*stmt)++; - if (assign_value(scope, ((struct ast_item*)ast_items.data)[tmp].u.s, value) < 0) + if (assign_value(scope, GET_ITEM(p, tmp).u.s, value) < 0) return -1; - } else if (((struct ast_item*)ast_items.data)[*stmt].type == AST_ITEM_GOTO) { + } else if (item->type == AST_ITEM_GOTO) { (*stmt)++; - if ( - evaluate_arith( - ast_items, stmt, UNTIL_SEMICOLON, &value.u.i, scope, markers - ) < 0 - ) + if (evaluate_arith(p, scope, stmt, UNTIL_SEMICOLON, &value.u.i) < 0) return -1; *stmt = value.u.i; printf("goto %zu\n", *stmt); } else { fprintf(stderr, "Error: canot execute: "); - ast_item_dump(((struct ast_item*)ast_items.data)[*stmt], stderr); + ast_item_dump(stderr, *item); fputc('\n', stderr); return -1; } return 0; } -int run_ast_items(const struct growable ast_items, const struct growable markers) { +int run_ast_items(const struct program p) { struct growable scope = EMPTY_GROWABLE(sizeof (struct scope_item)); size_t stmt = 0; int ret = -1; - while (stmt < ast_items.len) - if (evaluate_statement(ast_items, markers, &stmt, &scope) < 0) + while (stmt < p.ast_items.len) + if (evaluate_statement(p, &scope, &stmt) < 0) goto error; ret = 0; error: - growable_cleanup(&scope); + growable_cleanup(scope); return ret; } diff --git a/runtime.h b/runtime.h index 8ee99d8..2d2bc59 100644 --- a/runtime.h +++ b/runtime.h @@ -8,6 +8,6 @@ #include "shitscript.h" -int run_ast_items(struct growable ast_items, struct growable markers); +int run_ast_items(const struct program p); #endif // RUNTIME_H diff --git a/shitscript.c b/shitscript.c index 212869c..28d4478 100644 --- a/shitscript.c +++ b/shitscript.c @@ -8,7 +8,7 @@ #include "runtime.h" #include "shitscript.h" -void ast_item_dump(const struct ast_item ai, FILE *fh) { +void ast_item_dump(FILE *fh, const struct ast_item ai) { switch (ai.type) { case AST_ITEM_PLUS: fprintf(fh, "AST_ITEM_PLUS"); @@ -49,20 +49,25 @@ void ast_item_cleanup(struct ast_item ai) { int main(void) { size_t i; - struct growable ast_items = EMPTY_GROWABLE(sizeof (struct ast_item)); - struct growable markers = EMPTY_GROWABLE(sizeof (struct ast_marker)); + struct program p = { + .ast_items = EMPTY_GROWABLE(sizeof (struct ast_item)), + .markers = EMPTY_GROWABLE(sizeof (struct ast_marker)), + .buffer = EMPTY_GROWABLE(sizeof (char)), + }; int ret = EXIT_FAILURE; - if (parse_input(&ast_items, &markers) < 0) + if (parse_input(&p) < 0) goto error; - if (run_ast_items(ast_items, markers) < 0) + growable_cleanup(p.buffer); + // p.buffer = EMPTY_GROWABLE(sizeof char); + if (run_ast_items(p) < 0) goto error; ret = EXIT_SUCCESS; error: - for (i = 0; i < ast_items.len; i++) - ast_item_cleanup(((struct ast_item*)ast_items.data)[i]); - for (i = 0; i < markers.len; i++) - free(((struct ast_marker*)markers.data)[i].name); - growable_cleanup(&ast_items); - growable_cleanup(&markers); + for (i = 0; i < p.ast_items.len; i++) + ast_item_cleanup(GET_ITEM(p, i)); + for (i = 0; i < p.markers.len; i++) + free(GET_MARKER(p, i).name); + growable_cleanup(p.ast_items); + growable_cleanup(p.markers); return ret; } diff --git a/shitscript.h b/shitscript.h index 55f619a..64dddaa 100644 --- a/shitscript.h +++ b/shitscript.h @@ -31,6 +31,15 @@ struct ast_marker { size_t pos; }; -void ast_item_dump(const struct ast_item ai, FILE *fh); +struct program { + struct growable ast_items; + struct growable markers; + struct growable buffer; +}; + +#define GET_ITEM(p, i) (GROWABLE_AT((p).ast_items, struct ast_item, (i))) +#define GET_MARKER(p, i) (GROWABLE_AT((p).markers, struct ast_marker, (i))) + +void ast_item_dump(FILE *fh, const struct ast_item ai); #endif // SHITSCRIPT_H -- 2.47.0