#include <string.h>
#include "growable.h"
-#include "shitscript.h"
#include "parser.h"
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;
}
((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;
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) {
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 '*':
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");
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) {
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");
}
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;
}
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;
}
#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");
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;
}