summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parse.c23
-rw-r--r--test.toc68
-rw-r--r--tests/bf.toc148
-rw-r--r--tests/control_flow.toc2
-rw-r--r--tests/std/io.toc8
-rw-r--r--tests/std/mem.toc4
-rw-r--r--tests/types.toc6
-rw-r--r--types.c6
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)