harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 555bd4914dcf770a15733efdd20dd39149a8a89c
parent aa6d14a8ef21b29376b73e95065c9a44e5960ff6
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri,  3 Sep 2021 10:50:41 +0200

all: basic first-class type riggings

Diffstat:
Minclude/ast.h | 7++++++-
Minclude/expr.h | 6++++++
Minclude/types.h | 1+
Msrc/check.c | 8++++++++
Msrc/eval.c | 6++++++
Msrc/gen.c | 5+++++
Msrc/lex.c | 1+
Msrc/parse.c | 42++++++++++++++++++++++++++++++++----------
Msrc/qinstr.c | 2++
Msrc/qtype.c | 3+++
Msrc/type_store.c | 5+++++
Msrc/typedef.c | 3+++
Msrc/types.c | 12++++++++++++
13 files changed, 90 insertions(+), 11 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -317,6 +317,10 @@ struct ast_expression_tuple { struct ast_expression_tuple *next; }; +struct ast_expression_type { + struct ast_type *type; +}; + struct ast_expression_unarithm { enum unarithm_operator op; struct ast_expression *operand; @@ -324,7 +328,7 @@ struct ast_expression_unarithm { struct ast_expression { struct location loc; - enum expr_type type; + enum expr_type type; // TODO: Rename me to "kind", and "_type" to "type" union { struct ast_expression_access access; struct ast_expression_alloc alloc; @@ -352,6 +356,7 @@ struct ast_expression { struct ast_expression_struct _struct; struct ast_expression_switch _switch; struct ast_expression_tuple tuple; + struct ast_expression_type _type; struct ast_expression_unarithm unarithm; }; }; diff --git a/include/expr.h b/include/expr.h @@ -36,6 +36,7 @@ enum expr_type { EXPR_STRUCT, EXPR_SWITCH, EXPR_TUPLE, + EXPR_TYPE, EXPR_UNARITHM, EXPR_YIELD, }; @@ -322,6 +323,10 @@ struct expression_tuple { struct expression_tuple *next; }; +struct expression_type { + const struct type *type; +}; + enum unarithm_operator { UN_ADDRESS, // & UN_BNOT, // ~ @@ -367,6 +372,7 @@ struct expression { struct expression_switch _switch; struct expression_struct _struct; struct expression_slice slice; + struct expression_type _type; struct expression_tuple tuple; struct expression_unarithm unarithm; void *user; diff --git a/include/types.h b/include/types.h @@ -39,6 +39,7 @@ enum type_storage { STORAGE_TAGGED, STORAGE_TUPLE, STORAGE_UNION, + STORAGE_TYPE, }; struct type; diff --git a/src/check.c b/src/check.c @@ -661,6 +661,7 @@ type_promote(struct type_store *store, case STORAGE_STRUCT: case STORAGE_TAGGED: case STORAGE_TUPLE: + case STORAGE_TYPE: case STORAGE_UINTPTR: case STORAGE_UNION: case STORAGE_VOID: @@ -1482,6 +1483,7 @@ check_expr_constant(struct context *ctx, case STORAGE_SLICE: case STORAGE_TAGGED: case STORAGE_TUPLE: + case STORAGE_TYPE: case STORAGE_STRUCT: case STORAGE_UNION: assert(0); // Invariant @@ -2779,6 +2781,8 @@ check_expression(struct context *ctx, case EXPR_TUPLE: check_expr_tuple(ctx, aexpr, expr, hint); break; + case EXPR_TYPE: + assert(0); // TODO case EXPR_UNARITHM: check_expr_unarithm(ctx, aexpr, expr, hint); break; @@ -3111,6 +3115,8 @@ type_is_specified(struct context *ctx, const struct ast_type *atype) } } return true; + case STORAGE_TYPE: + assert(0); // TODO } assert(0); // Unreachable } @@ -3296,6 +3302,8 @@ expr_is_specified(struct context *ctx, const struct ast_expression *aexpr) } } return true; + case EXPR_TYPE: + return type_is_specified(ctx, aexpr->_type.type); case EXPR_UNARITHM: return expr_is_specified(ctx, aexpr->unarithm.operand); case EXPR_YIELD: diff --git a/src/eval.c b/src/eval.c @@ -89,6 +89,7 @@ itrunc(const struct type *type, uintmax_t val) case STORAGE_STRUCT: case STORAGE_TAGGED: case STORAGE_TUPLE: + case STORAGE_TYPE: case STORAGE_UNION: case STORAGE_VOID: assert(0); @@ -346,6 +347,7 @@ eval_const(struct context *ctx, struct expression *in, struct expression *out) case STORAGE_POINTER: case STORAGE_RUNE: case STORAGE_SIZE: + case STORAGE_TYPE: case STORAGE_U16: case STORAGE_U32: case STORAGE_U64: @@ -456,6 +458,8 @@ eval_cast(struct context *ctx, struct expression *in, struct expression *out) case STORAGE_TUPLE: case STORAGE_UNION: assert(0); // Invariant + case STORAGE_TYPE: + assert(0); // TODO case STORAGE_VOID: break; // no-op } @@ -536,6 +540,7 @@ constant_default(struct context *ctx, struct expression *v) assert(0); // TODO case STORAGE_ALIAS: case STORAGE_FUNCTION: + case STORAGE_TYPE: assert(0); // Invariant case STORAGE_VOID: break; // no-op @@ -731,6 +736,7 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out) case EXPR_PROPAGATE: case EXPR_RETURN: case EXPR_SWITCH: + case EXPR_TYPE: // XXX: Should this work? case EXPR_YIELD: // Excluded from translation-compatible subset return EVAL_INVALID; diff --git a/src/gen.c b/src/gen.c @@ -1335,6 +1335,8 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr) assert(from->storage == STORAGE_SLICE); pushi(ctx->current, &qresult, Q_COPY, &qvalue, NULL); break; + case STORAGE_TYPE: + assert(0); // TODO case STORAGE_ALIAS: case STORAGE_BOOL: case STORAGE_FCONST: @@ -2607,6 +2609,8 @@ gen_expr(struct gen_context *ctx, const struct expression *expr) return gen_expr_return(ctx, expr); case EXPR_SWITCH: return gen_expr_switch_with(ctx, expr, NULL); + case EXPR_TYPE: + assert(0); // TODO case EXPR_UNARITHM: return gen_expr_unarithm(ctx, expr); case EXPR_SLICE: @@ -3129,6 +3133,7 @@ gen_data_item(struct gen_context *ctx, struct expression *expr, } break; case STORAGE_UNION: + case STORAGE_TYPE: assert(0); // TODO case STORAGE_ALIAS: case STORAGE_FCONST: diff --git a/src/lex.c b/src/lex.c @@ -1137,6 +1137,7 @@ token_str(const struct token *tok) case STORAGE_STRUCT: case STORAGE_TAGGED: case STORAGE_TUPLE: + case STORAGE_TYPE: case STORAGE_UNION: case STORAGE_VOID: assert(0); diff --git a/src/parse.c b/src/parse.c @@ -369,6 +369,9 @@ parse_primitive_type(struct lexer *lexer) case T_STR: type->storage = STORAGE_STRING; break; + case T_TYPE: + type->storage = STORAGE_TYPE; + break; case T_F32: type->storage = STORAGE_F32; break; @@ -613,24 +616,25 @@ parse_type(struct lexer *lexer) struct ast_type *type = NULL; bool noreturn = false, nullable = false, unwrap = false; switch (lex(lexer, &tok)) { - case T_I8: + case T_BOOL: + case T_CHAR: + case T_F32: + case T_F64: case T_I16: case T_I32: case T_I64: - case T_U8: + case T_I8: + case T_INT: + case T_RUNE: + case T_SIZE: + case T_STR: + case T_TYPE: case T_U16: case T_U32: case T_U64: - case T_INT: + case T_U8: case T_UINT: - case T_SIZE: case T_UINTPTR: - case T_CHAR: - case T_RUNE: - case T_STR: - case T_F32: - case T_F64: - case T_BOOL: case T_VOID: unlex(lexer, &tok); type = parse_primitive_type(lexer); @@ -816,6 +820,7 @@ parse_constant(struct lexer *lexer) case STORAGE_TAGGED: case STORAGE_TUPLE: case STORAGE_UNION: + case STORAGE_TYPE: assert(0); // Handled in a different nonterminal } return exp; @@ -1129,6 +1134,20 @@ parse_measurement_expression(struct lexer *lexer) } static struct ast_expression * +parse_type_expression(struct lexer *lexer) +{ + struct ast_expression *exp = mkexpr(&lexer->loc); + exp->type = EXPR_TYPE; + struct token tok; + lex(lexer, &tok); + + want(lexer, T_LPAREN, NULL); + exp->_type.type = parse_type(lexer); + want(lexer, T_RPAREN, NULL); + return exp; +} + +static struct ast_expression * parse_call_expression(struct lexer *lexer, struct ast_expression *lvalue) { struct token tok; @@ -1462,6 +1481,9 @@ parse_builtin_expression(struct lexer *lexer) case T_OFFSET: unlex(lexer, &tok); return parse_measurement_expression(lexer); + case T_TYPE: + unlex(lexer, &tok); + return parse_type_expression(lexer); default: unlex(lexer, &tok); break; diff --git a/src/qinstr.c b/src/qinstr.c @@ -57,6 +57,7 @@ store_for_type(struct gen_context *ctx, const struct type *type) break; case STORAGE_POINTER: case STORAGE_UINTPTR: + case STORAGE_TYPE: switch (ctx->arch.ptr->stype) { case Q_LONG: return Q_STOREL; @@ -124,6 +125,7 @@ load_for_type(struct gen_context *ctx, const struct type *type) break; case STORAGE_POINTER: case STORAGE_UINTPTR: + case STORAGE_TYPE: switch (ctx->arch.ptr->stype) { case Q_LONG: return Q_LOADL; diff --git a/src/qtype.c b/src/qtype.c @@ -175,6 +175,7 @@ aggregate_lookup(struct gen_context *ctx, const struct type *type) case STORAGE_SIZE: case STORAGE_UINTPTR: case STORAGE_POINTER: + case STORAGE_TYPE: case STORAGE_NULL: case STORAGE_F32: case STORAGE_F64: @@ -215,6 +216,7 @@ qtype_lookup(struct gen_context *ctx, case STORAGE_UINTPTR: case STORAGE_POINTER: case STORAGE_NULL: + case STORAGE_TYPE: return ctx->arch.ptr; case STORAGE_F32: return &qbe_single; @@ -259,6 +261,7 @@ type_is_aggregate(const struct type *type) case STORAGE_I8: case STORAGE_INT: case STORAGE_POINTER: + case STORAGE_TYPE: case STORAGE_NULL: case STORAGE_RUNE: case STORAGE_SIZE: diff --git a/src/type_store.c b/src/type_store.c @@ -123,6 +123,7 @@ builtin_type_for_storage(enum type_storage storage, bool is_const) case STORAGE_STRUCT: case STORAGE_TAGGED: case STORAGE_TUPLE: + case STORAGE_TYPE: case STORAGE_UNION: case STORAGE_ENUM: return NULL; @@ -702,6 +703,10 @@ type_init_from_atype(struct type_store *store, type->pointer.referent = type_store_lookup_atype( store, atype->pointer.referent); break; + case STORAGE_TYPE: + type->size = 8; // XXX: ARCH + type->align = 8; + break; case STORAGE_SLICE: type->size = 24; // XXX: ARCH type->align = 8; diff --git a/src/typedef.c b/src/typedef.c @@ -141,6 +141,7 @@ emit_const(const struct expression *expr, FILE *out) case STORAGE_FUNCTION: case STORAGE_POINTER: case STORAGE_TAGGED: + case STORAGE_TYPE: assert(0); // Invariant } } @@ -315,6 +316,8 @@ emit_type(const struct type *type, FILE *out) } fprintf(out, ")"); break; + case STORAGE_TYPE: + assert(0); // TODO case STORAGE_FCONST: case STORAGE_ICONST: assert(0); // Invariant diff --git a/src/types.c b/src/types.c @@ -150,6 +150,8 @@ type_storage_unparse(enum type_storage storage) return "tagged union"; case STORAGE_TUPLE: return "tuple"; + case STORAGE_TYPE: + return "type"; case STORAGE_U16: return "u16"; case STORAGE_U32: @@ -183,6 +185,7 @@ type_is_integer(const struct type *type) case STORAGE_STRUCT: case STORAGE_TAGGED: case STORAGE_TUPLE: + case STORAGE_TYPE: case STORAGE_UNION: case STORAGE_BOOL: case STORAGE_NULL: @@ -226,6 +229,7 @@ type_is_numeric(const struct type *type) case STORAGE_STRUCT: case STORAGE_TAGGED: case STORAGE_TUPLE: + case STORAGE_TYPE: case STORAGE_UNION: case STORAGE_BOOL: case STORAGE_CHAR: @@ -278,6 +282,7 @@ type_storage_is_signed(enum type_storage storage) case STORAGE_STRUCT: case STORAGE_TAGGED: case STORAGE_TUPLE: + case STORAGE_TYPE: case STORAGE_UNION: case STORAGE_BOOL: case STORAGE_CHAR: @@ -340,6 +345,7 @@ bool storage_is_flexible(enum type_storage storage) case STORAGE_STRUCT: case STORAGE_TAGGED: case STORAGE_TUPLE: + case STORAGE_TYPE: case STORAGE_U16: case STORAGE_U32: case STORAGE_U64: @@ -447,6 +453,9 @@ type_hash(const struct type *type) hash = fnv1a_u32(hash, type_hash(tuple->type)); } break; + case STORAGE_TYPE: + // Does not require any additional information + break; } return hash; } @@ -566,6 +575,8 @@ type_is_assignable(const struct type *to, const struct type *from) case STORAGE_ICONST: case STORAGE_FCONST: assert(0); // Invariant + case STORAGE_TYPE: + assert(0); // TODO case STORAGE_I8: case STORAGE_I16: case STORAGE_I32: @@ -712,6 +723,7 @@ type_is_castable(const struct type *to, const struct type *from) switch (from->storage) { case STORAGE_FCONST: case STORAGE_ICONST: + case STORAGE_TYPE: assert(0); // TODO case STORAGE_I8: case STORAGE_I16: