diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-03-13 13:13:12 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-03-13 13:13:12 -0400 |
commit | c9ee9b08a9bdf795d0c389a7c42ab61d36a345f4 (patch) | |
tree | 950bbb4838f9ecba272b79abba17f644a25bd718 | |
parent | d0e85d320c84068b5d4ca68bf18eb0f68c4a6752 (diff) |
typeof!
-rw-r--r-- | cgen.c | 1 | ||||
-rw-r--r-- | eval.c | 1 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | parse.c | 7 | ||||
-rw-r--r-- | test.toc | 33 | ||||
-rw-r--r-- | types.c | 24 | ||||
-rw-r--r-- | types.h | 4 |
7 files changed, 35 insertions, 39 deletions
@@ -1516,6 +1516,7 @@ static void cgen_expr(CGenerator *g, Expression *e) { } handled = true; } break; + case UNARY_TYPEOF: case UNARY_DSIZEOF: case UNARY_DALIGNOF: assert(0); @@ -1153,6 +1153,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) { break; case UNARY_DSIZEOF: case UNARY_DALIGNOF: + case UNARY_TYPEOF: assert(0); return false; } @@ -8,6 +8,8 @@ /* TODO: +varargs len +make new and del functions! where #returns_code (function/struct body is a block, to be evaluated at compile time, which returns the actual statements -- you can use this for implementation of printf) - struct varargs @@ -15,8 +17,6 @@ break continue switch enums -typeof - - make sure you can't do typeof(something_that_is_varargs) unions --- switch to / add as an alternative: libffi @@ -64,6 +64,7 @@ static const char *unary_op_to_str(UnaryOp u) { case UNARY_LEN: return "len"; case UNARY_DSIZEOF: return "#sizeof"; case UNARY_DALIGNOF: return "#alignof"; + case UNARY_TYPEOF: return "typeof"; } assert(0); return ""; @@ -1041,7 +1042,8 @@ static int op_precedence(Keyword op) { case KW_LE: return 3; case KW_GE: return 3; case KW_EQ_EQ: return 3; - case KW_NE: return 3; + case KW_NE: return 3; + case KW_TYPEOF: return 5; case KW_PLUS: return 10; case KW_MINUS: return 20; case KW_AMPERSAND: return 25; @@ -1741,6 +1743,9 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { } op = UNARY_DEL; break; + case KW_TYPEOF: + op = UNARY_TYPEOF; + break; default: is_unary = false; break; @@ -1,37 +1,10 @@ printf ::= #foreign("printf","libc.so.6") fn(#C &"const char", #C ..) #C int; -tprintf ::= fn(fmt: []char, args: ..) { - printf(&fmt[0], args); -}; - -sum ::= fn(x: ..) int { - total := 0; - n := 0; - for a, i := x { - total += a + i - i + 1; - n += 1; - } - total - n -}; - -sumc ::= fn(x:: ..) int { - total := 0; - n := 0; - for a, i := x { - total += a + i - i + 1; - n += 1; - } - total - n -}; -do_printing ::= fn(x::..) { - tprintf("%ld\n",sum(x)); - tprintf("%ld\n",sumc(x)); +f ::= fn(x: int, y: int) int { + x+y }; main ::= fn() { - do_printing(); - do_printing(1,2,3); - do_printing(4); - do_printing(1,10,100,1000,10000); + f(3,4 as typeof f(3,4)); }; @@ -657,8 +657,10 @@ static Status type_of_ident(Typer *tr, Location where, Identifier *ident, Type * typedef Declaration *DeclarationPtr; arr_foreach(tr->in_decls, DeclarationPtr, in_decl) { if (d == *in_decl) { - assert(d->flags & DECL_HAS_EXPR); /* we can only be in decls with an expr */ - if (d->expr.kind != EXPR_FN) { /* it's okay if a function references itself */ + /* d needn't have an expression, because it could be its type that refers to itself */ + if ((d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_FN) { + /* it's okay if a function references itself */ + } else { /* if we've complained about it before when we were figuring out the type, don't complain again */ if (!(d->flags & DECL_ERRORED_ABOUT_SELF_REFERENCE)) { char *s = ident_to_str(i); @@ -2516,7 +2518,7 @@ static Status types_expr(Typer *tr, Expression *e) { case EXPR_UNARY_OP: { Expression *of = e->unary.of; Type *of_type = &of->type; - if (!types_expr(tr, e->unary.of)) return false; + if (!types_expr(tr, of)) return false; if (of_type->kind == TYPE_UNKNOWN) { return true; } @@ -2592,10 +2594,22 @@ static Status types_expr(Typer *tr, Expression *e) { return false; } break; + case UNARY_TYPEOF: { + if (of->type.kind == TYPE_VOID) { + err_print(of->where, "This has type void, but you're trying to apply typeof to it."); + return false; + } + if (type_is_builtin(&of->type, BUILTIN_VARARGS)) { + err_print(of->where, "You can't apply typeof to varargs."); + return false; + } + e->kind = EXPR_TYPE; + e->typeval = &of->type; + t->kind = TYPE_BUILTIN; + t->builtin = BUILTIN_TYPE; + } break; case UNARY_DSIZEOF: case UNARY_DALIGNOF: { - if (!types_expr(tr, of)) - return false; Type *queried_type; if (type_is_builtin(&of->type, BUILTIN_TYPE)) { Value val; @@ -316,6 +316,7 @@ typedef enum { KW_TRUE, KW_FALSE, KW_NMS, + KW_TYPEOF, KW_COUNT } Keyword; @@ -330,7 +331,7 @@ static const char *const keywords[KW_COUNT] = "int", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "float", "f32", "f64", "Type", "Namespace", - "char", "bool", "true", "false", "nms"}; + "char", "bool", "true", "false", "nms", "typeof"}; typedef enum { NUM_LITERAL_INT, @@ -566,6 +567,7 @@ typedef enum { UNARY_DEREF, /* *x */ UNARY_NOT, /* !x */ UNARY_DEL, /* del x */ + UNARY_TYPEOF, /* typeof x */ UNARY_LEN, /* x.len ; replaces BINARY_DOT len when typing */ UNARY_DSIZEOF, UNARY_DALIGNOF |