summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c21
-rw-r--r--decls_cgen.c1
-rw-r--r--eval.c27
-rw-r--r--parse.c70
-rw-r--r--test.toc2
-rw-r--r--types.c35
-rw-r--r--types.h17
7 files changed, 90 insertions, 83 deletions
diff --git a/cgen.c b/cgen.c
index 6ba6cad..e98224b 100644
--- a/cgen.c
+++ b/cgen.c
@@ -101,6 +101,7 @@ static bool cgen_uses_ptr(Type *t) {
case TYPE_SLICE:
case TYPE_VOID:
case TYPE_UNKNOWN:
+ case TYPE_TYPE:
return false;
}
assert(0);
@@ -178,7 +179,8 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) {
err_print(where, "Can't determine type.");
return false;
case TYPE_TUPLE:
- /* We should never try to generate a tuple */
+ case TYPE_TYPE:
+ /* We should never try to generate this type */
assert(0);
return false;
}
@@ -251,6 +253,7 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
+ case TYPE_TYPE:
case TYPE_SLICE:
break;
}
@@ -403,6 +406,7 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
return false;
break;
case TYPE_VOID:
+ case TYPE_TYPE:
assert(0);
return false;
}
@@ -501,6 +505,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
case EXPR_CAST:
case EXPR_NEW:
case EXPR_DIRECT:
+ case EXPR_TYPE:
assert(0);
return false;
}
@@ -710,6 +715,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
case EXPR_IDENT:
case EXPR_FN:
case EXPR_DIRECT:
+ case EXPR_TYPE:
break;
case EXPR_TUPLE:
arr_foreach(e->tuple, Expression, x)
@@ -922,6 +928,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
/* the only time this should happen is if you're stating
a tuple, e.g. 3, 5;, but we've errored about that before
(the comma operator does not exist in toc!) */
+ case EXPR_TYPE:
assert(0);
break;
case EXPR_FN: {
@@ -988,6 +995,7 @@ static void cgen_zero_value(CGenerator *g, Type *t) {
cgen_zero_value(g, t->arr.of);
cgen_write(g, "}");
break;
+ case TYPE_TYPE:
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
@@ -1061,6 +1069,7 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) {
}
break;
case TYPE_FN:
+ case TYPE_TYPE:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
case TYPE_VOID:
@@ -1075,6 +1084,7 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
switch (t->kind) {
case TYPE_TUPLE:
case TYPE_VOID:
+ case TYPE_TYPE:
assert(0);
return false;
case TYPE_UNKNOWN:
@@ -1260,15 +1270,6 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
cgen_write(g, ";");
cgen_nl(g);
break;
- case STMT_TDECL:
- cgen_write(g, "typedef ");
- if (!cgen_type_pre(g, &s->tdecl.type, s->where)) return false;
- cgen_write(g, " ");
- cgen_ident(g, s->tdecl.name);
- if (!cgen_type_post(g, &s->tdecl.type, s->where)) return false;
- cgen_write(g, ";");
- cgen_nl(g);
- break;
case STMT_RET:
if (!cgen_ret(g, s->ret.flags & RET_FLAG_EXPR ? &s->ret.expr : NULL))
return false;
diff --git a/decls_cgen.c b/decls_cgen.c
index 0ef0451..58d8667 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -64,6 +64,7 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
if (!cgen_decls_block(g, &e->fn.body))
return false;
break;
+ case EXPR_TYPE:
case EXPR_DIRECT:
case EXPR_NEW:
case EXPR_IDENT:
diff --git a/eval.c b/eval.c
index fffc833..445e5c8 100644
--- a/eval.c
+++ b/eval.c
@@ -55,6 +55,8 @@ static size_t compiler_sizeof(Type *t) {
return sizeof(Value *);
case TYPE_SLICE:
return sizeof(Slice);
+ case TYPE_TYPE:
+ return sizeof(Type *);
case TYPE_VOID:
case TYPE_UNKNOWN:
return 0;
@@ -90,7 +92,9 @@ static bool val_truthiness(Value *v, Type *t) {
case TYPE_FN: return v->fn != NULL;
case TYPE_ARR: return t->arr.n > 0;
case TYPE_SLICE: return v->slice.n > 0;
- case TYPE_TUPLE: break;
+ case TYPE_TYPE:
+ case TYPE_TUPLE:
+ break;
}
assert(0);
return false;
@@ -158,6 +162,7 @@ static void val_copy(Evaluator *ev, Value *dest, Value *src, Type *t) {
case TYPE_SLICE:
case TYPE_VOID:
case TYPE_UNKNOWN:
+ case TYPE_TYPE:
*dest = *src;
break;
case TYPE_ARR: {
@@ -187,6 +192,7 @@ static void *val_ptr_to_free(Value *v, Type *t) {
case TYPE_SLICE:
case TYPE_VOID:
case TYPE_UNKNOWN:
+ case TYPE_TYPE:
return NULL;
case TYPE_ARR:
return v->arr;
@@ -282,7 +288,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_VOID: assert(0); break;
case TYPE_UNKNOWN: assert(0); break;
case TYPE_TUPLE: assert(0); break;
-
+ case TYPE_TYPE: assert(0); break;
case TYPE_BUILTIN:
switch (to->kind) {
case TYPE_BUILTIN:
@@ -307,6 +313,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_TUPLE:
case TYPE_FN:
case TYPE_ARR:
+ case TYPE_TYPE:
assert(0);
break;
}
@@ -326,6 +333,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_VOID:
case TYPE_ARR:
case TYPE_BUILTIN:
+ case TYPE_TYPE:
assert(0); break;
}
break;
@@ -355,6 +363,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_UNKNOWN:
case TYPE_TUPLE:
case TYPE_VOID:
+ case TYPE_TYPE:
assert(0);
break;
}
@@ -374,6 +383,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_TUPLE:
case TYPE_VOID:
case TYPE_BUILTIN:
+ case TYPE_TYPE:
assert(0); break;
}
break;
@@ -393,6 +403,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_TUPLE:
case TYPE_VOID:
case TYPE_BUILTIN:
+ case TYPE_TYPE:
assert(0); break;
}
break;
@@ -425,6 +436,9 @@ static void eval_deref(Value *v, void *ptr, Type *type) {
case TYPE_SLICE:
v->slice = *(Slice *)ptr;
break;
+ case TYPE_TYPE:
+ v->type = *(Type **)ptr;
+ break;
case TYPE_VOID:
case TYPE_UNKNOWN:
assert(0);
@@ -457,6 +471,9 @@ static void eval_deref_set(void *set, Value *to, Type *type) {
case TYPE_SLICE:
*(Slice *)set = to->slice;
break;
+ case TYPE_TYPE:
+ *(Type **)set = to->type;
+ break;
case TYPE_VOID:
case TYPE_UNKNOWN:
assert(0);
@@ -636,8 +653,8 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
assert(e->binary.lhs->type.kind == TYPE_BUILTIN); \
switch (builtin) { \
eval_binary_bool_op_nums(builtin, op); \
- default:printf("%d\n",(int)builtin); \
- assert(!"Invalid builtin to "#op); break; \
+ default: \
+ assert(!("Invalid builtin to "#op)[0]); break; \
}}
#define eval_binary_bool_op(op) \
@@ -966,6 +983,8 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
v->slice.n = 0;
}
} break;
+ case EXPR_TYPE:
+ v->type = &e->typeval;
}
return true;
}
diff --git a/parse.c b/parse.c
index c3a0694..652f1bc 100644
--- a/parse.c
+++ b/parse.c
@@ -23,6 +23,7 @@ static const char *expr_kind_to_str(ExprKind k) {
case EXPR_BLOCK: return "block";
case EXPR_IDENT: return "identifier";
case EXPR_SLICE: return "slice";
+ case EXPR_TYPE: return "type";
}
assert(0);
return "";
@@ -202,6 +203,8 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) {
written += type_to_str_(t->ptr, buffer + written, bufsize - written);
return written;
}
+ case TYPE_TYPE:
+ return str_copy(buffer, bufsize, "<type>");
}
assert(0);
@@ -1412,46 +1415,30 @@ static bool parse_stmt(Parser *p, Statement *s) {
if (t->token->kind == TOKEN_EOF)
tokr_err(t, "Expected statement.");
s->where = t->token->where;
- if (t->token->kind == TOKEN_KW) {
- switch (t->token->kw) {
- case KW_RETURN: {
- s->kind = STMT_RET;
+ if (token_is_kw(t->token, KW_RETURN)) {
+ s->kind = STMT_RET;
+ t->token++;
+ s->ret.flags = 0;
+ if (token_is_kw(t->token, KW_SEMICOLON)) {
+ /* return with no expr */
t->token++;
- s->ret.flags = 0;
- if (token_is_kw(t->token, KW_SEMICOLON)) {
- /* return with no expr */
- t->token++;
- return true;
- }
- s->ret.flags |= RET_FLAG_EXPR;
- Token *end = expr_find_end(p, 0, NULL);
- if (!end) {
- while (t->token->kind != TOKEN_EOF) t->token++; /* move to end of file */
- return false;
- }
- if (!token_is_kw(end, KW_SEMICOLON)) {
- err_print(end->where, "Expected ';' at end of return statement.");
- t->token = end->kind == TOKEN_EOF ? end : end + 1;
- return false;
- }
- bool success = parse_expr(p, &s->ret.expr, end);
- t->token = end + 1;
- return success;
+ return true;
}
- case KW_NEWTYPE:
- s->kind = STMT_TDECL;
- t->token++;
- if (t->token->kind != TOKEN_IDENT) {
- tokr_err(t, "Expected identifier after \"newtype\".");
- tokr_skip_semicolon(t);
- }
- s->tdecl.name = t->token->ident;
- t->token++;
- if (!parse_type(p, &s->tdecl.type))
- return false;
- return true;
- default: break;
+ s->ret.flags |= RET_FLAG_EXPR;
+ Token *end = expr_find_end(p, 0, NULL);
+ if (!end) {
+ while (t->token->kind != TOKEN_EOF) t->token++; /* move to end of file */
+ return false;
}
+ if (!token_is_kw(end, KW_SEMICOLON)) {
+ err_print(end->where, "Expected ';' at end of return statement.");
+ t->token = end->kind == TOKEN_EOF ? end : end + 1;
+ return false;
+ }
+ bool success = parse_expr(p, &s->ret.expr, end);
+ t->token = end + 1;
+ return success;
+
}
if (is_decl(t)) {
s->kind = STMT_DECL;
@@ -1672,6 +1659,9 @@ static void fprint_expr(FILE *out, Expression *e) {
if (s->to) fprint_expr(out, s->to);
fprintf(out, "]");
} break;
+ case EXPR_TYPE:
+ fprint_type(out, &e->typeval);
+ break;
}
if (parse_printing_after_types) {
fprintf(out, ":");
@@ -1719,12 +1709,6 @@ static void fprint_stmt(FILE *out, Statement *s) {
fprint_expr(out, &s->ret.expr);
fprintf(out, ";\n");
break;
- case STMT_TDECL:
- fprintf(out, "newtype ");
- fprint_ident(out, s->tdecl.name);
- fprintf(out, " ");
- fprint_type(out, &s->tdecl.type);
- break;
}
}
diff --git a/test.toc b/test.toc
index 0304979..7aaeb3a 100644
--- a/test.toc
+++ b/test.toc
@@ -13,7 +13,7 @@ putf @= fn(x: float) {
");
};
-newtype Foo int
+Foo @= int;
main @= fn() {
// x : Foo;
diff --git a/types.c b/types.c
index d2bed5c..f2f4baf 100644
--- a/types.c
+++ b/types.c
@@ -40,6 +40,7 @@ static bool type_eq(Type *a, Type *b) {
switch (a->kind) {
case TYPE_VOID: return true;
case TYPE_UNKNOWN: assert(0); return false;
+ case TYPE_TYPE: return true;
case TYPE_BUILTIN:
return a->builtin == b->builtin;
case TYPE_FN: {
@@ -98,10 +99,6 @@ static bool expr_arr_must_mut(Expression *e) {
err_print(e->where, "Cannot modify a constant array.");
return false;
}
- if (d->flags & DECL_FLAG_PARAM) {
- err_print(e->where, "Parameters are immutable.");
- return false;
- }
} return true;
case EXPR_CAST:
case EXPR_CALL:
@@ -134,6 +131,7 @@ static bool expr_arr_must_mut(Expression *e) {
case EXPR_LITERAL_INT:
case EXPR_BINARY_OP:
case EXPR_DIRECT:
+ case EXPR_TYPE:
break;
}
assert(0);
@@ -186,7 +184,8 @@ static bool expr_must_lval(Expression *e) {
case EXPR_CALL:
case EXPR_DIRECT:
case EXPR_BLOCK:
- case EXPR_SLICE: {
+ case EXPR_SLICE:
+ case EXPR_TYPE: {
err_print(e->where, "Cannot use %s as l-value.", expr_kind_to_str(e->kind));
return false;
}
@@ -353,6 +352,7 @@ static bool type_resolve(Typer *tr, Type *t) {
break;
case TYPE_UNKNOWN:
case TYPE_VOID:
+ case TYPE_TYPE:
case TYPE_BUILTIN:
break;
}
@@ -363,19 +363,14 @@ static bool type_resolve(Typer *tr, Type *t) {
static bool type_can_be_truthy(Type *t) {
switch (t->kind) {
case TYPE_VOID:
- return false;
- case TYPE_UNKNOWN:
- return true;
- case TYPE_BUILTIN:
- return true;
- case TYPE_FN:
- return true;
case TYPE_TUPLE:
- return false;
case TYPE_ARR:
+ case TYPE_TYPE:
return false;
+ case TYPE_FN:
+ case TYPE_UNKNOWN:
+ case TYPE_BUILTIN:
case TYPE_PTR:
- return true;
case TYPE_SLICE:
return true;
}
@@ -394,7 +389,9 @@ static Status type_cast_status(Type *from, Type *to) {
return STATUS_NONE;
switch (from->kind) {
case TYPE_UNKNOWN: return STATUS_NONE;
- case TYPE_VOID: return STATUS_ERR;
+ case TYPE_TYPE:
+ case TYPE_VOID:
+ return STATUS_ERR;
case TYPE_BUILTIN:
switch (from->builtin) {
case BUILTIN_I8:
@@ -412,6 +409,7 @@ static Status type_cast_status(Type *from, Type *to) {
case TYPE_PTR:
return STATUS_WARN;
case TYPE_FN:
+ case TYPE_TYPE:
case TYPE_TUPLE:
case TYPE_SLICE:
case TYPE_ARR:
@@ -917,6 +915,10 @@ static bool types_expr(Typer *tr, Expression *e) {
bool valid = false;
if (o == BINARY_SET) {
valid = type_eq(lhs_type, rhs_type);
+ if (lhs_type->kind == TYPE_TYPE) {
+ err_print(e->where, "Cannot set type.");
+ return false;
+ }
} else {
/* numerical binary ops */
if (lhs_type->kind == rhs_type->kind && lhs_type->kind == TYPE_BUILTIN
@@ -1047,6 +1049,9 @@ static bool types_expr(Typer *tr, Expression *e) {
}
break;
}
+ case EXPR_TYPE:
+ t->kind = TYPE_TYPE;
+ break;
}
e->type.flags |= TYPE_FLAG_RESOLVED;
return true;
diff --git a/types.h b/types.h
index 537c845..4265310 100644
--- a/types.h
+++ b/types.h
@@ -84,6 +84,7 @@ typedef union Value {
void *ptr;
union Value *tuple;
Slice slice;
+ struct Type *type;
} Value;
#define IDECL_FLAG_HAS_VAL 0x01
@@ -241,7 +242,8 @@ typedef enum {
TYPE_TUPLE,
TYPE_ARR,
TYPE_PTR,
- TYPE_SLICE
+ TYPE_SLICE,
+ TYPE_TYPE
} TypeKind;
typedef enum {
@@ -313,7 +315,8 @@ typedef enum {
EXPR_BLOCK,
EXPR_TUPLE,
EXPR_DIRECT,
- EXPR_SLICE
+ EXPR_SLICE,
+ EXPR_TYPE
} ExprKind;
typedef enum {
@@ -441,6 +444,7 @@ typedef struct Expression {
IdentID block_ret_id;
};
struct Expression *tuple;
+ Type typeval;
};
} Expression;
@@ -471,8 +475,7 @@ typedef struct Declaration {
typedef enum {
STMT_DECL,
STMT_EXPR,
- STMT_RET,
- STMT_TDECL
+ STMT_RET
} StatementKind;
#define RET_FLAG_EXPR 0x01
@@ -481,18 +484,12 @@ typedef struct {
Expression expr;
} Return;
-typedef struct {
- Identifier name;
- Type type;
-} TypeDecl;
-
#define STMT_FLAG_VOIDED_EXPR 0x01 /* the "4;" in fn () { 4; } is a voided expression, but the "4" in fn () int { 4 } is not */
typedef struct Statement {
Location where;
StatementKind kind;
U16 flags;
union {
- TypeDecl tdecl;
Declaration decl;
Expression expr;
Return ret;