diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-04-24 15:34:14 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-04-24 15:34:14 -0400 |
commit | 2de90e47312b8a7de69712015590fc7fbd3d9b0a (patch) | |
tree | cd5576b9d5e8ba4c041389781cc678de040dfe74 | |
parent | eb8eca81e997c3fbf454a636b2097629e8e8d0ea (diff) |
fixed problems with using _ as an identifier
-rw-r--r-- | cgen.c | 21 | ||||
-rw-r--r-- | main.c | 9 | ||||
-rw-r--r-- | misc.c | 10 | ||||
-rw-r--r-- | test.toc | 32 | ||||
-rw-r--r-- | types.c | 10 |
5 files changed, 45 insertions, 37 deletions
@@ -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); + } } } } @@ -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 @@ -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); + @@ -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(); } @@ -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... */ |