From 1194d23d65d424e760fa972aa2decc1650497a1b Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Sat, 23 May 2020 19:27:06 -0400 Subject: started fixing tests; found bug --- parse.c | 23 +++++--- test.toc | 68 +++++++++++++++++++++-- tests/bf.toc | 148 ++++++++++++++++++++++++++----------------------- tests/control_flow.toc | 2 +- tests/std/io.toc | 8 ++- tests/std/mem.toc | 4 +- tests/types.toc | 6 +- types.c | 6 +- 8 files changed, 172 insertions(+), 93 deletions(-) diff --git a/parse.c b/parse.c index ce2a9eb..33e8fe2 100644 --- a/parse.c +++ b/parse.c @@ -153,6 +153,12 @@ static inline bool type_is_float(Type *t) { return t->kind == TYPE_BUILTIN && type_builtin_is_float(t->builtin); } +static inline void mklocation(Location *l, File *f, Token *start, Token *end) { + l->file = f; + l->start = (U32)(start - f->tokens); + l->end = (U32)(end - f->tokens); +} + /* returns -1 on failure */ static int kw_to_builtin_type(Keyword kw) { switch (kw) { @@ -850,8 +856,11 @@ static Status parse_block(Parser *p, Block *b, U8 flags) { break; } if (t->token->kind == TOKEN_EOF) { - tokr_err(t, "Expected '}' to close function body."); - ret = false; + /* sometimes we skip to the end of the file to give up on parsing, so if there's already been an error, don't give this one. */ + if (ret) { + tokr_err(t, "Expected '}' to close function body."); + ret = false; + } goto end; } @@ -1222,9 +1231,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { #if 0 { Location where; - where.file = p->file; - where.start = t->token; - where.end = end; + mklocation(&where, p->file, t->token, end); printf("PARSING "); fprint_location(stdout, where); } @@ -2543,8 +2550,10 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { stmt_expr: s->kind = STMT_EXPR; Token *end = expr_find_end(p, 0); - if (!end) { - tokr_err(t, "No semicolon found at end of statement."); + if (!end || !token_is_kw(end, KW_SEMICOLON)) { + Location loc; + mklocation(&loc, p->file, t->token, end); + err_print(loc, "No semicolon found at end of statement."); tokr_skip_to_eof(t); return false; } diff --git a/test.toc b/test.toc index 00b42d1..73d1ad1 100644 --- a/test.toc +++ b/test.toc @@ -1,14 +1,70 @@ +#include "tests/std/io.toc", io; +#include "tests/std/mem.toc"; + +z ::= nms { + Foo ::= struct(f ::= fn() int { return 7; }) { + x: int; + } + + Bar ::= fn() &(struct { x, y: int; f ::= fn() int { return 13; } } ) { + x : u64; + return &x as &void; + } + + + foo ::= fn() total : int = 0 { + f: Foo(); + total += f.f(); + total += Bar().f(); + } +} + main ::= fn() { - a ::= foo(3); - b := foo(5); + nums := news(int, 10); + for x, i := &nums { + *x = i*i; + } + l := slice_to_ll(nums); + p := &l; + while p { + io.puti(p.head); + p = p.tail; + } + f: Foo; + f.k = -173; + f.b = new(Bar); + f.b.f.b = new(Bar); + f.b.f.b.f.k = 9; + io.puti(f.k); + io.puti(f.b.f.k); + io.puti(f.b.f.b.f.k); + x := z.foo(); + y ::= z.foo(); + io.puti(x); + io.puti(y); } -foo ::= fn(x: int) int { - if x == 3 { - return 7; +slice_to_ll ::= fn(t::=, slice: []t) use ll: LinkedList(t) { + head = slice[0]; + if slice.len == 1 { + tail = null; } else { - return #C("3*x"); + tail = new(LinkedList(t)); + *tail = slice_to_ll(slice[1:]); } } +LinkedList ::= struct (of :: Type) { + head: of; + tail: &LinkedList(of); +} + +Foo ::= struct { + k: int; + b: &Bar; +} + +Bar ::= struct { + f: Foo; +} diff --git a/tests/bf.toc b/tests/bf.toc index 83fb291..3d4ed36 100644 --- a/tests/bf.toc +++ b/tests/bf.toc @@ -16,51 +16,51 @@ extern void exit(int); contents_len : int; buffer : [1024]char; while #C("fgets(buffer, 1024, fp)") { - buffer_len : int; - while buffer[buffer_len] { - buffer_len = buffer_len + 1; - } - if contents_sz < contents_len + buffer_len { - old_contents := contents; - contents_sz = 2*contents_sz + 1024; - contents = news(char, contents_sz); - i := 0; - while i < contents_len { - contents[i] = old_contents[i]; - i = i + 1; - } - dels(old_contents); - } - i := 0; - while i < buffer_len { - contents[contents_len] = buffer[i]; - contents_len = contents_len + 1; - i = i + 1; - } + buffer_len : int; + while buffer[buffer_len] { + buffer_len = buffer_len + 1; + } + if contents_sz < contents_len + buffer_len { + old_contents := contents; + contents_sz = 2*contents_sz + 1024; + contents = news(char, contents_sz); + i := 0; + while i < contents_len { + contents[i] = old_contents[i]; + i = i + 1; + } + dels(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 + return contents; }; runfile ::= fn(filename: []char) { - #C("extern int putchar(int c);"); - code := readfile(filename); - tape_sz := 3; - tape := news(int, tape_sz); - ptr := tape_sz / 2; - i := 0; - while code[i] { - // puti(ptr); - // puti(tape_sz); - 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 { - // extend to the right - newtape := news(int, 2*tape_sz); + #C("extern int putchar(int c);"); + code := readfile(filename); + tape_sz := 3; + tape := news(int, tape_sz); + ptr := tape_sz / 2; + i := 0; + while code[i] { + // puti(ptr); + // puti(tape_sz); + 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 { + // extend to the right + newtape := news(int, 2*tape_sz); j := 0; while j < tape_sz { newtape[j] = tape[j]; @@ -69,12 +69,12 @@ runfile ::= fn(filename: []char) { tape_sz = tape_sz * 2; dels(tape); tape = newtape; - } - } elif code[i] == '<' { - ptr = ptr - 1; - if ptr < 0 { - // extend to the left - newtape := news(int, 2*tape_sz); + } + } elif code[i] == '<' { + ptr = ptr - 1; + if ptr < 0 { + // extend to the left + newtape := news(int, 2*tape_sz); j := 0; while j < tape_sz { newtape[j+tape_sz] = tape[j]; @@ -84,36 +84,44 @@ runfile ::= fn(filename: []char) { dels(tape); tape = newtape; ptr = ptr + tape_sz; - } - } elif code[i] == '[' { - if !tape[ptr] { - // jump to matching ] + } + } elif code[i] == '[' { + if !tape[ptr] { + // jump to matching ] level := 0; while level >= 0 { - i = i + 1; - level = level + (if code[i] == '[' { 1 } elif code[i] == ']' { -1 } else {0}); + i = i + 1; + if code[i] == '[' { + level += 1; + } elif code[i] == ']' { + level -= 1; + } } - } - } elif code[i] == ']' { - if tape[ptr] { - // jump to matching [ + } + } elif code[i] == ']' { + if tape[ptr] { + // jump to matching [ level := 0; while level <= 0 { - i = i - 1; - level = level + (if code[i] == '[' { 1 } elif code[i] == ']' { -1 } else {0}); + i = i - 1; + if code[i] == '[' { + level += 1; + } elif code[i] == ']' { + level -= 1; + } } - } - } elif code[i] == '.' { - c := tape[ptr] as char; - #C("putchar(c);"); - } elif code[i] == ',' { - // Input doesn't really work, because you - // need to send an EOF to end the program. - } - i = i + 1; - } - dels(tape); - dels(code); + } + } elif code[i] == '.' { + c := tape[ptr] as char; + #C("putchar(c);"); + } elif code[i] == ',' { + // Input doesn't really work, because you + // need to send an EOF to end the program. + } + i = i + 1; + } + dels(tape); + dels(code); }; main ::= fn() { diff --git a/tests/control_flow.toc b/tests/control_flow.toc index f54a8bc..012978d 100644 --- a/tests/control_flow.toc +++ b/tests/control_flow.toc @@ -21,7 +21,7 @@ f ::= fn() int { return total; } } - 0 + return 0; } main ::= fn() { diff --git a/tests/std/io.toc b/tests/std/io.toc index 2b9e999..c274631 100644 --- a/tests/std/io.toc +++ b/tests/std/io.toc @@ -32,7 +32,13 @@ writei ::= fn(x: int) { if x == 0 { toc_putchar('0'); } else { - abs ::= fn(x: int) int { if x < 0 { -x } else { x } }; + abs ::= fn(x: int) int { + if x < 0 { + return -x; + } else { + return x; + } + }; scan_digit := 1000000000000000000; started := false; while scan_digit > 0 { diff --git a/tests/std/mem.toc b/tests/std/mem.toc index ef4e638..9ea9b12 100644 --- a/tests/std/mem.toc +++ b/tests/std/mem.toc @@ -5,14 +5,14 @@ calloc ::= #foreign("calloc", base.libc) fn(#C size_t, #C size_t) #C &"void"; free ::= #foreign("free", base.libc) fn(#C &"void"); new ::= fn(t :: Type) &t { - calloc(1, (sizeof t) as #C size_t) + return calloc(1, (sizeof t) as #C size_t); } news ::= fn(t :: Type, n : int) []t { s: []t; s.data = calloc(n as #C size_t, (sizeof t) as #C size_t); s.len = n; - s + return s; } // TODO(eventually): use type information to make this just one function diff --git a/tests/types.toc b/tests/types.toc index 7e56f91..25c38d5 100644 --- a/tests/types.toc +++ b/tests/types.toc @@ -2,13 +2,13 @@ #include "std/mem.toc"; z ::= nms { - Foo ::= struct(f ::= fn() int { 7 }) { + Foo ::= struct(f ::= fn() int { return 7; }) { x: int; } - Bar ::= fn() &(struct { x, y: int; f ::= fn() int { 13 } } ) { + Bar ::= fn() &(struct { x, y: int; f ::= fn() int { return 13; } } ) { x : u64; - &x as &void + return &x as &void; } diff --git a/types.c b/types.c index d8928e5..17ed62c 100644 --- a/types.c +++ b/types.c @@ -3582,16 +3582,16 @@ top: if (header->flags & DECL_USE) { if (ident_eq_str(header->idents[0], "_")) { err_print(header->where, "You have to name your for loop variable in order to use it (sorry)."); - return false; + goto for_fail; } if (!use_ident(tr, header->idents[0], val_type, header->where)) { - return false; + goto for_fail; } } + typer_block_exit(tr); if (!types_block(tr, &fo->body)) goto for_fail; - typer_block_exit(tr); } break; for_fail: if (in_header) -- cgit v1.2.3