summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c21
-rw-r--r--main.c9
-rw-r--r--misc.c10
-rw-r--r--test.toc32
-rw-r--r--types.c10
5 files changed, 45 insertions, 37 deletions
diff --git a/cgen.c b/cgen.c
index f73debd..9fde5a6 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1911,6 +1911,7 @@ static void cgen_decl(CGenerator *g, Declaration *d) {
/* declarations where we use a value */
for (int idx = 0, nidents = (int)arr_len(d->idents); idx < nidents; ++idx) {
Identifier i = d->idents[idx];
+ if (ident_eq_str(i, "_")) continue;
Type *type = decl_type_at_index(d, idx);
if (type_is_compileonly(&d->type)) {
continue;
@@ -1969,6 +1970,7 @@ static void cgen_decl(CGenerator *g, Declaration *d) {
arr_foreach(d->idents, Identifier, i) {
Expression e;
+ if (ident_eq_str(*i, "_")) continue;
e.flags = EXPR_FOUND_TYPE;
e.kind = EXPR_IDENT;
e.type = d->type;
@@ -1977,13 +1979,18 @@ static void cgen_decl(CGenerator *g, Declaration *d) {
}
cgen_write(g, "}");
} else {
- /* set it directly */
- Expression e = {0};
- e.kind = EXPR_IDENT;
- e.type = d->type;
- e.flags = EXPR_FOUND_TYPE;
- e.ident = d->idents[0];
- cgen_set(g, &e, NULL, &d->expr, NULL);
+ if (ident_eq_str(d->idents[0], "_")) {
+ cgen_expr(g, &d->expr);
+ cgen_write(g, ";");
+ } else {
+ /* set it directly */
+ Expression e = {0};
+ e.kind = EXPR_IDENT;
+ e.type = d->type;
+ e.flags = EXPR_FOUND_TYPE;
+ e.ident = d->idents[0];
+ cgen_set(g, &e, NULL, &d->expr, NULL);
+ }
}
}
}
diff --git a/main.c b/main.c
index f7d5b02..debaaae 100644
--- a/main.c
+++ b/main.c
@@ -8,13 +8,6 @@
/*
@TODO:
-test:
- _ := 5;
- _ := 6;
-don't allow use of the identifier _, e.g. puti(_+5) ok for fields i think
-use
- - use with struct members (e.g. SuperPoint ::= struct { use p: Point; })
-maybe change to #define check(x) do { if_unlikely(x) return 0; } while (0);
always use pointers in cgen'd non-range for loops (sometimes also indices)
is there a problem where we can get TYPE_UNKNOWN in cgen, triggering an assert(0)?
-simple example, but maybe try other stuff: x := #C("5");
@@ -25,6 +18,8 @@ allow `use ???;` if an error has already occurred
if something gets included into a namespace, and its typing fails, the namespace should still be of type namespace, not ???
make sure you can do a[i] where a is &[5]int or &[]char or something
do we consistently handle x := &some_array_or_slice; x.len
+use
+ - use with struct members (e.g. SuperPoint ::= struct { use p: Point; })
&void
simplify eval macros with val_to_u/i64
#if should not create a block
diff --git a/misc.c b/misc.c
index 4e82ff8..9b21209 100644
--- a/misc.c
+++ b/misc.c
@@ -77,3 +77,13 @@ static char const *indefinite_article(char const *s) {
return "a";
}
+#ifdef __GNUC__
+#define if_likely(x) if (__builtin_expect(x, 1))
+#define if_unlikely(x) if (__builtin_expect(x, 0))
+#else
+#define if_likely if
+#define if_unlikely if
+#endif
+
+#define check(x) do { if_unlikely (!x) return false; } while (0);
+
diff --git a/test.toc b/test.toc
index a30d6ee..ed66392 100644
--- a/test.toc
+++ b/test.toc
@@ -1,28 +1,18 @@
#include "std/io.toc";
-/*
-sum ::= fn(n::=, t::=, a: [n]t) t {
- total : t = 0;
- for x := a {
- total += x;
- }
- total
-}
-
-main ::= fn() {
- t ::= int;
- numbers : [1000]t;
- for x, i : (&t, t) = &numbers {
- *x = i;
- }
- puti(sum(numbers) as int);
+foo ::= fn() int {
+ puts("Hello");
+ 3
}
-*/
-Point ::= struct {
- x, y : int;
+
+bar ::= fn() (int, int) {
+ foo(), foo()
}
main ::= fn() {
- p: Point;
- p.x = 12 + e;
+ _ := 5;
+ _ := 6+_;
+ _ := foo();
+ _,_ := bar();
+ _,_ := bar();
}
diff --git a/types.c b/types.c
index 6cb6e97..2eb64f0 100644
--- a/types.c
+++ b/types.c
@@ -282,6 +282,7 @@ purpose is something like "take address of"
*/
static Status expr_must_lval(Expression *e, char const *purpose) {
/* NOTE: make sure you update eval when you change this */
+ assert(e->flags & EXPR_FOUND_TYPE);
switch (e->kind) {
case EXPR_IDENT: {
Identifier i = e->ident;
@@ -1942,8 +1943,13 @@ static Status types_expr(Typer *tr, Expression *e) {
}
case EXPR_IDENT: {
Block *b = tr->block;
- char *i_str = e->ident_str.str;
- size_t i_len = e->ident_str.len;
+ String i = e->ident_str;
+ char *i_str = i.str;
+ size_t i_len = i.len;
+ if_unlikely (str_eq_cstr(i, "_")) {
+ err_print(e->where, "You cannot use _ as a variable. It is used for ignoring results of function calls, e.g. _, y := function_which_returns_two_things();");
+ return false;
+ }
Identifier final_ident = NULL;
bool undeclared = true;
while (1) { /* for each block we are inside... */