summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c6
-rw-r--r--main.c1
-rw-r--r--tests/bf.toc86
-rw-r--r--tokenizer.c2
-rw-r--r--types.c22
-rw-r--r--types.h4
6 files changed, 107 insertions, 14 deletions
diff --git a/cgen.c b/cgen.c
index 5f68221..b5b7ce8 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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, "(");
diff --git a/main.c b/main.c
index 3acb724..419ed04 100644
--- a/main.c
+++ b/main.c
@@ -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",
diff --git a/types.c b/types.c
index 0804a18..ac56693 100644
--- a/types.c
+++ b/types.c
@@ -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;
diff --git a/types.h b/types.h
index c213ff7..b0db0b1 100644
--- a/types.h
+++ b/types.h
@@ -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,