diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-23 14:50:28 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-23 14:50:28 -0400 |
commit | e540f6475c1306370c5faf15fc3a0c1e46ba3caf (patch) | |
tree | d278d93f44c3fb01d4abf70873356a618d3ae7f6 | |
parent | f97d401c3bade9f053055f411be25ef6d6b8041b (diff) |
started writing bf interpreter; found a few bugs
-rw-r--r-- | cgen.c | 6 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | tests/bf.toc | 86 | ||||
-rw-r--r-- | tokenizer.c | 2 | ||||
-rw-r--r-- | types.c | 22 | ||||
-rw-r--r-- | types.h | 4 |
6 files changed, 107 insertions, 14 deletions
@@ -868,14 +868,16 @@ static bool cgen_expr(CGenerator *g, Expression *e) { } } break; case EXPR_IF: - cgen_ident_id(g, e->if_.c.id); + if (e->type.kind != TYPE_VOID) + cgen_ident_id(g, e->if_.c.id); break; case EXPR_WHILE: if (e->type.kind != TYPE_VOID) cgen_ident_id(g, e->while_.c.id); break; case EXPR_BLOCK: - cgen_ident_id(g, e->block_ret_id); + if (e->type.kind != TYPE_VOID) + cgen_ident_id(g, e->block_ret_id); break; case EXPR_CALL: cgen_write(g, "("); @@ -1,6 +1,7 @@ /* TODO: bf interpreter (& other tests) +pointer arithmetic compile time arrays, slices unicode variable names make sure initializers for global variables are compile-time constants diff --git a/tests/bf.toc b/tests/bf.toc new file mode 100644 index 0000000..d0ca413 --- /dev/null +++ b/tests/bf.toc @@ -0,0 +1,86 @@ +getstdin @= fn() []char { + contents : []char; + contents_sz : int; + contents_len : int; + buffer : [1024]char; + while #C("fgets(buffer, 1024, stdin)") { + buffer_len : int; + while buffer[buffer_len] { + buffer_len = buffer_len + 1; + } + if contents_sz < buffer_len { + old_contents := contents; + contents_sz = 2*contents_sz + 1024; + contents = new(char, contents_sz); + i := 0; + while i < contents_len { + contents[i] = old_contents[i]; + i = i + 1; + } + del(old_contents); + } + i := 0; + while i < buffer_len { + contents[contents_len] = buffer[i]; + contents_len = contents_len + 1; + i = i + 1; + } + } + contents[contents_len] = 0 as char; + contents +}; + +main @= fn() { + code := getstdin(); + tape_sz := 100; + tape := new(int, tape_sz); + ptr := tape_sz / 2; + i := 0; + while code[i] { + if code[i] == '+' { + tape[ptr] = tape[ptr]+1; + } elif code[i] == '-' { + tape[ptr] = tape[ptr]-1; + } elif code[i] == '>' { + ptr = ptr + 1; + if ptr >= tape_sz { + // TODO + } + } elif code[i] == '<' { + ptr = ptr - 1; + if ptr < 0 { + // TODO + } + } elif code[i] == '[' { + if !tape[ptr] { + // jump past matching ] + level := 0; + i = i + 1; + while level >= 0 { + level = level + (if code[i] == '[' { 1 } elif code[i] == ']' { -1 } else {0}); + i = i + 1; + } + i = i + 1; + } + } elif code[i] == ']' { + if tape[ptr] { + // jump to right after matching [ + level := 0; + i = i - 1; + while level <= 0 { + level = level + (if code[i] == '[' { 1 } elif code[i] == ']' { -1 } else {0}); + i = i - 1; + } + i = i + 1; + } + } elif code[i] == '.' { + c := tape[ptr] as char; + #C("putc(c, stdout)"); + } elif code[i] == ',' { + c : char = #C("getc(stdin)"); + tape[ptr] = c as int; + } + i = i + 1; + } + +};
\ No newline at end of file diff --git a/tokenizer.c b/tokenizer.c index 1a4f5dd..2e6bb4d 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -1,5 +1,5 @@ static const char *keywords[KW_COUNT] = - {";", ":", "@", ",", "(", ")", "{", "}", "[", "]", "==", "!=", "<", "<=", ">", ">=", + {";", ":", "@", ",", "(", ")", "{", "}", "[", "]", "==", "!=", "<=", "<", ">=", ">", "+", "-", "*", "!", "&", "/", "=", "if", "elif", "else", "while", "return", "fn", "as", @@ -917,19 +917,23 @@ static bool types_expr(Typer *tr, Expression *e) { case BINARY_GE: case BINARY_EQ: case BINARY_NE: { - bool match = true; + bool valid = true; if (e->binary.op != BINARY_SET) { /* numerical binary ops */ if (lhs_type->kind != rhs_type->kind) { - match = false; + valid = false; } else if (lhs_type->kind != TYPE_BUILTIN) { - match = false; - } else if (!type_builtin_is_numerical(lhs_type->builtin) || !type_builtin_is_numerical(rhs_type->builtin)) { - match = false; + valid = false; + } else { + if (e->binary.op == BINARY_EQ || e->binary.op == BINARY_NE) { + } else if (!type_builtin_is_numerical(lhs_type->builtin) || !type_builtin_is_numerical(rhs_type->builtin)) { + valid = false; + } } + } - if (!type_eq(lhs_type, rhs_type)) match = false; - if (match) { + if (!type_eq(lhs_type, rhs_type)) valid = false; + if (valid) { switch (e->binary.op) { case BINARY_SET: /* type of x = y is always void */ @@ -965,12 +969,12 @@ static bool types_expr(Typer *tr, Expression *e) { } break; } } - if (!match) { + if (!valid) { char *s1, *s2; s1 = type_to_str(lhs_type); s2 = type_to_str(rhs_type); const char *op = binary_op_to_str(e->binary.op); - err_print(e->where, "Mismatched types to operator %s: %s and %s", op, s1, s2); + err_print(e->where, "Invalid types to operator %s: %s and %s", op, s1, s2); return false; } break; @@ -148,10 +148,10 @@ typedef enum { KW_RSQUARE, KW_EQEQ, KW_NE, - KW_LT, KW_LE, - KW_GT, + KW_LT, KW_GE, + KW_GT, KW_PLUS, KW_MINUS, KW_ASTERISK, |