summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-03-13 13:13:12 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-03-13 13:13:12 -0400
commitc9ee9b08a9bdf795d0c389a7c42ab61d36a345f4 (patch)
tree950bbb4838f9ecba272b79abba17f644a25bd718
parentd0e85d320c84068b5d4ca68bf18eb0f68c4a6752 (diff)
typeof!
-rw-r--r--cgen.c1
-rw-r--r--eval.c1
-rw-r--r--main.c4
-rw-r--r--parse.c7
-rw-r--r--test.toc33
-rw-r--r--types.c24
-rw-r--r--types.h4
7 files changed, 35 insertions, 39 deletions
diff --git a/cgen.c b/cgen.c
index 873c6ec..2bd56b8 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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);
diff --git a/eval.c b/eval.c
index cefb4e6..f73f600 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
}
diff --git a/main.c b/main.c
index 6f35c07..6b7747a 100644
--- a/main.c
+++ b/main.c
@@ -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
diff --git a/parse.c b/parse.c
index f7cdca2..583f637 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
diff --git a/test.toc b/test.toc
index 8709a64..5573554 100644
--- a/test.toc
+++ b/test.toc
@@ -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));
};
diff --git a/types.c b/types.c
index 506dea0..4e9704c 100644
--- a/types.c
+++ b/types.c
@@ -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;
diff --git a/types.h b/types.h
index 5540d16..1734393 100644
--- a/types.h
+++ b/types.h
@@ -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