diff options
Diffstat (limited to 'tis-as.c')
| -rw-r--r-- | tis-as.c | 143 |
1 files changed, 94 insertions, 49 deletions
@@ -25,8 +25,7 @@ enum tok { TOK_NEG, TOK_JMP, TOK_JEZ, TOK_JNZ, TOK_JGZ, TOK_JLZ, TOK_JRO, /* Misc */ - TOK_COMMENT, TOK_LABEL, TOK_XPOS, TOK_YPOS, - TOK_SEP, TOK_NL, TOK_EOF + TOK_COMMENT, TOK_LABEL, TOK_XPOS, TOK_YPOS, TOK_NL, TOK_EOF }; struct tokenizer { @@ -46,20 +45,28 @@ static struct tpu_port stdout_port; static struct tpu_map tpu_map; +static const char *dir_names[] = { + "LEFT", "RIGHT", "UP", "DOWN" +}; + +static const char *status_names[] = { + "IDLE", "RUN", "READ", "WRITE" +}; + static const char *tok_reprs[] = { /* Global */ "'STDIN'", "'STDOUT'", "'TPU'", "'END'", - /* Operands */ - "'ACC'", "'BAK'", "'NIL'", "'LEFT'", "'RIGHT'", "'UP'", - "'DOWN'", "'ANY'", "'LAST'", "<LIT>", "<NAME>", + /* Operands (order like OP_*) */ + "'ACC'", "'BAK'", "'NIL'", "'LEFT'", "'RIGHT'", + "'UP'", "'DOWN'", "'ANY'", "'LAST'", "<LIT>", "<NAME>", - /* Instructions */ + /* Instructions (order like INST_*) */ "'NOP'", "'MOV'", "'SWP'", "'SAV'", "'ADD'", "'SUB'", "'NEG'", "'JMP'", "'JEZ'", "'JNZ'", "'JGZ'", "'JLZ'", "'JRO'", /* Misc */ - "#<COMMENT>", "<LABEL>:", "X<INT>", "Y<INT>", "','", "<NL>", "<EOF>" + "#<COMMENT>", "<LABEL>:", "X<INT>", "Y<INT>", "<NL>", "<EOF>" }; const char *progname = "tis-as"; @@ -106,26 +113,38 @@ tok_next(struct tokenizer *tok) if (feof(tok->file)) return TOK_EOF; s = fgets(tok->linebuf, sizeof(tok->linebuf), tok->file); if (!s && !feof(tok->file)) die("fgets:"); - if (!s) return TOK_EOF; - if (*s && s[strlen(s)-1] != '\n') + if (!s) return TOK_NL; + + len = strlen(s); + if (len && s[len-1] != '\n' && !feof(tok->file)) die("load: line %lu too long", tok->lineno); + if (len && s[len-1] == '\n') s[len-1] = '\0'; + + tok->lineno += 1; + tok->tokstr = s; tok->off = 0; + return TOK_NL; } s = tok->linebuf + tok->off; len = strspn(s, WHITESPACE); tok->off += len; s += len; + tok->tokstr = s; + if (!*s) return TOK_NL; - len = strcspn(s, WHITESPACE); - s[len] = '\0'; + len = strcspn(s, WHITESPACE ","); tok->off += len; - if (!len) return TOK_NL; + printf("> %s\n", s); + if (s[len]) { + s[len] = '\0'; + tok->off += 1; + } if (!strcasecmp(s, "stdin")) { return TOK_STDIN; } else if (!strcasecmp(s, "stdout")) { - return TOK_STDIN; + return TOK_STDOUT; } else if (!strcasecmp(s, "tpu")) { return TOK_TPU; } else if (!strcasecmp(s, "end")) { @@ -150,8 +169,6 @@ tok_next(struct tokenizer *tok) return TOK_LAST; } else if (is_lit(s)) { return TOK_LIT; - } else if (strspn(s, NAMEALPH) == strlen(s)) { - return TOK_NAME; } else if (!strcasecmp(s, "nop")) { return TOK_NOP; } else if (!strcasecmp(s, "mov")) { @@ -179,7 +196,7 @@ tok_next(struct tokenizer *tok) } else if (!strcasecmp(s, "jro")) { return TOK_JRO; } else if (*s == '#') { - tok->off = strlen(s); + tok->off += strlen(tok->linebuf + tok->off); return TOK_COMMENT; } else if (len && strspn(s, NAMEALPH) == len-1 && s[len-1] == ':') { return TOK_LABEL; @@ -187,6 +204,8 @@ tok_next(struct tokenizer *tok) return TOK_XPOS; } else if (*s == 'Y' && atoi(s+1) > 0) { return TOK_YPOS; + } else if (strspn(s, NAMEALPH) == strlen(s)) { + return TOK_NAME; } else { die("load: line %lu, invalid token '%s'", tok->lineno, s); } @@ -211,9 +230,8 @@ tok_next_in(struct tokenizer *tokenizer, ...) va_end(cpy); fprintf(stderr, "tis-as: load: "); - fprintf(stderr, "line %lu, got tok '%s', expected one of ", + fprintf(stderr, "line %lu, got tok %s, expected one of (", tokenizer->lineno, tok_reprs[tok]); - first = true; va_start(ap, tokenizer); while ((arg = va_arg(ap, int)) > 0) { @@ -222,8 +240,8 @@ tok_next_in(struct tokenizer *tokenizer, ...) first = false; } va_end(ap); + fputs(")\n", stderr); - fprintf(stderr, "\n"); exit(1); } @@ -246,7 +264,7 @@ load(const char *fname) file = fopen(fname, "r"); if (!file) die("fopen:"); - tokenizer.lineno = 1; + tokenizer.lineno = 0; tokenizer.file = file; tokenizer.off = 0; tokenizer.tokstr = NULL; @@ -284,6 +302,7 @@ load(const char *fname) case TOK_END: if (!tpu) goto disallowed; tpu = NULL; + tok_next_in(&tokenizer, TOK_NL, -1); break; case TOK_NOP: case TOK_MOV: case TOK_SWP: case TOK_SAV: case TOK_ADD: case TOK_SUB: case TOK_NEG: case TOK_JMP: @@ -292,11 +311,10 @@ load(const char *fname) if (!tpu) goto disallowed; inst = tok_to_inst(tok); - op1_tok = tok_next_in(&tokenizer, TOK_ACC, - TOK_BAK, TOK_UP, TOK_DOWN, - TOK_LEFT, TOK_RIGHT, TOK_NL, -1); + op1_tok = tok_next_in(&tokenizer, TOK_ACC, TOK_BAK, + TOK_NIL, TOK_LEFT, TOK_RIGHT, TOK_UP, TOK_DOWN, + TOK_ANY, TOK_LAST, TOK_LIT, TOK_NAME, TOK_NL, -1); if (op1_tok == TOK_NL) { - tok_next_in(&tokenizer, TOK_NL, -1); tpu_add_inst(tpu, inst, -1, 0, -1, 0); break; } @@ -305,13 +323,12 @@ load(const char *fname) if (op1 == OP_LIT) op1_lit = str2lit(tokenizer.tokstr); - op2_tok = tok_next_in(&tokenizer, TOK_ACC, - TOK_BAK, TOK_UP, TOK_DOWN, - TOK_LEFT, TOK_RIGHT, TOK_NL, -1); + op2_tok = tok_next_in(&tokenizer, TOK_ACC, TOK_BAK, + TOK_NIL, TOK_LEFT, TOK_RIGHT, TOK_UP, TOK_DOWN, + TOK_ANY, TOK_LAST, TOK_LIT, TOK_NAME, TOK_NL, -1); if (op2_tok == TOK_NL) { - tok_next_in(&tokenizer, TOK_NL, -1); - tpu_add_inst(tpu, inst, - (int) op1, op1_lit, -1, 0); + tpu_add_inst(tpu, inst, (int) op1, + op1_lit, -1, 0); break; } @@ -332,6 +349,8 @@ load(const char *fname) tokenizer.lineno); tok_next_in(&tokenizer, TOK_NL, -1); break; + case TOK_NL: + break; default: goto disallowed; } @@ -356,14 +375,14 @@ load(const char *fname) stdin_port.dst_port = port; } - if (link->x == stdout_x && link->y == stdout_x) { + if (link->x == stdout_x && link->y == stdout_y) { port = &link->tpu->ports[DIR_DOWN]; if (port->attached) die("load: stdout port in use"); port->attached = true; port->dst_tpu = NULL; port->dst_port = &stdout_port; - stdout_port.dst_port = port; + stdout_port.attached = true; stdout_port.dst_tpu = NULL; stdout_port.dst_port = port; } @@ -375,34 +394,59 @@ load(const char *fname) fclose(file); + return; + disallowed: - die("load: line %lu, token %s not allowed here", - tokenizer.lineno, tok_reprs[tok]); + if (tok == TOK_NAME) { + die("load: line %lu, unexpected token '%s'", + tokenizer.lineno, tokenizer.tokstr); + } else { + die("load: line %lu, token %s not allowed here", + tokenizer.lineno, tok_reprs[tok]); + } } void run(void) { struct tpu_map_link *link; - struct tpu_inst *inst; - size_t i, pc; + size_t i, k; + int c; + + stdin_port.out = -1; + stdout_port.reading = true; + while (1) { + if (stdin_port.dst_port->reading) { + c = getchar(); + if (c < 0) break; + stdin_port.out = c; + } - /* initial pass to propagate moves */ - for (i = 0; i < TPU_MAP_BUCKETS; i++) { - for (link = tpu_map.buckets[i]; link; link = link->next) { - inst = tpu_current_inst(link->tpu); - if (inst && inst->type == INST_MOV) { - pc = link->tpu->pc; - tpu_exec(link->tpu, inst); - link->tpu->pc = pc; + printf("===\n"); + + for (i = 0; i < TPU_MAP_BUCKETS; i++) { + for (link = tpu_map.buckets[i]; link; link = link->next) { + tpu_step(link->tpu); } } - } - for (i = 0; i < TPU_MAP_BUCKETS; i++) { - for (link = tpu_map.buckets[i]; link; link = link->next) { - inst = tpu_current_inst(link->tpu); - tpu_step(link->tpu); + for (i = 0; i < TPU_MAP_BUCKETS; i++) { + for (link = tpu_map.buckets[i]; link; link = link->next) { + tpu_update_ports(link->tpu); + printf("FINAL %lu %lu: %s\n", link->x, link->y, + status_names[link->tpu->status]); + for (k = 0; k < 4; k++) { + if (link->tpu->ports[k].in >= 0) + printf("%lu %lu %5s: %i\n", + link->x, link->y, dir_names[k], + link->tpu->ports[k].in); + } + } + } + + if (stdout_port.dst_port->out >= 0) { + putchar(stdout_port.dst_port->out); + stdout_port.dst_port->out = -1; } } } @@ -419,3 +463,4 @@ main(int argc, const char **argv) run(); } + |
