harec

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

commit c84e09c24fcd1c9c93671254fb919cfb0c5e538b
parent b8a1f1badee3a45e7b35eb3879539b5e9b2616e7
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Tue, 22 Dec 2020 23:21:52 -0500

parse: implement enum types

Diffstat:
Minclude/ast.h | 2+-
Minclude/types.h | 1+
Msrc/check.c | 1+
Msrc/lex.c | 1+
Msrc/parse.c | 125++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/qtype.c | 5+++++
Msrc/type_store.c | 8+++++++-
Msrc/types.c | 4++++
8 files changed, 119 insertions(+), 28 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -31,7 +31,7 @@ struct ast_list_type { struct ast_enum_field { const char *name; struct ast_expression *value; - struct enum_field *next; + struct ast_enum_field *next; }; struct ast_enum_type { diff --git a/include/types.h b/include/types.h @@ -8,6 +8,7 @@ enum type_storage { // Scalar types TYPE_STORAGE_BOOL, TYPE_STORAGE_CHAR, + TYPE_STORAGE_ENUM, TYPE_STORAGE_F32, TYPE_STORAGE_F64, TYPE_STORAGE_I8, diff --git a/src/check.c b/src/check.c @@ -180,6 +180,7 @@ check_expr_constant(struct context *ctx, case TYPE_STORAGE_STRING: assert(0); // TODO case TYPE_STORAGE_CHAR: + case TYPE_STORAGE_ENUM: case TYPE_STORAGE_UINTPTR: case TYPE_STORAGE_VOID: case TYPE_STORAGE_ALIAS: diff --git a/src/lex.c b/src/lex.c @@ -1022,6 +1022,7 @@ token_str(const struct token *tok) case TYPE_STORAGE_ARRAY: case TYPE_STORAGE_BOOL: case TYPE_STORAGE_CHAR: + case TYPE_STORAGE_ENUM: case TYPE_STORAGE_FUNCTION: case TYPE_STORAGE_POINTER: case TYPE_STORAGE_SLICE: diff --git a/src/parse.c b/src/parse.c @@ -264,57 +264,129 @@ parse_prototype(struct parser *par, struct ast_function_type *type) } static void -parse_type(struct parser *par, struct ast_type *type) -{ - trenter(TR_PARSE, "type"); +parse_integer_type(struct parser *par, enum type_storage *storage) { + trenter(TR_PARSE, "integer"); struct token tok = {0}; switch (lex(par->lex, &tok)) { - case T_CONST: - type->flags |= TYPE_CONST; - break; - default: - unlex(par->lex, &tok); - break; - } - switch (lex(par->lex, &tok)) { case T_I8: - type->storage = TYPE_STORAGE_I8; + *storage = TYPE_STORAGE_I8; break; case T_I16: - type->storage = TYPE_STORAGE_I16; + *storage = TYPE_STORAGE_I16; break; case T_I32: - type->storage = TYPE_STORAGE_I32; + *storage = TYPE_STORAGE_I32; break; case T_I64: - type->storage = TYPE_STORAGE_I64; + *storage = TYPE_STORAGE_I64; break; case T_U8: - type->storage = TYPE_STORAGE_U8; + *storage = TYPE_STORAGE_U8; break; case T_U16: - type->storage = TYPE_STORAGE_U16; + *storage = TYPE_STORAGE_U16; break; case T_U32: - type->storage = TYPE_STORAGE_U32; + *storage = TYPE_STORAGE_U32; break; case T_U64: - type->storage = TYPE_STORAGE_U64; + *storage = TYPE_STORAGE_U64; break; case T_INT: - type->storage = TYPE_STORAGE_INT; + *storage = TYPE_STORAGE_INT; break; case T_UINT: - type->storage = TYPE_STORAGE_UINT; + *storage = TYPE_STORAGE_UINT; break; case T_SIZE: - type->storage = TYPE_STORAGE_SIZE; + *storage = TYPE_STORAGE_SIZE; break; case T_UINTPTR: - type->storage = TYPE_STORAGE_UINTPTR; + *storage = TYPE_STORAGE_UINTPTR; break; case T_CHAR: - type->storage = TYPE_STORAGE_CHAR; + *storage = TYPE_STORAGE_CHAR; + break; + default: + assert(0); + } + trleave(TR_PARSE, "%s", type_storage_unparse(*storage)); +} + +static struct ast_expression *parse_simple_expression(struct parser *par); + +static void +parse_enum_type(struct parser *par, struct ast_enum_type *type) +{ + trenter(TR_PARSE, "enum"); + struct token tok = {0}; + switch (lex(par->lex, &tok)) { + case T_LBRACE: + type->storage = TYPE_STORAGE_INT; + unlex(par->lex, &tok); + break; + default: + unlex(par->lex, &tok); + parse_integer_type(par, &type->storage); + break; + } + want(par, T_LBRACE, NULL); + struct ast_enum_field **next = &type->values; + while (tok.token != T_RBRACE) { + *next = calloc(1, sizeof(struct ast_enum_field)); + want(par, T_NAME, &tok); + (*next)->name = tok.name; + if (lex(par->lex, &tok) == T_EQUAL) { + (*next)->value = parse_simple_expression(par); + trace(TR_PARSE, "%s = [expr]", (*next)->name); + } else { + unlex(par->lex, &tok); + trace(TR_PARSE, "%s = [generated]", (*next)->name); + } + next = &(*next)->next; + switch (lex(par->lex, &tok)) { + case T_COMMA: + if (lex(par->lex, &tok) != T_RBRACE) { + unlex(par->lex, &tok); + } + case T_RBRACE: + break; + default: + synassert(false, &tok, T_COMMA, T_RBRACE, T_EOF); + } + } + trleave(TR_PARSE, NULL); +} + +static void +parse_type(struct parser *par, struct ast_type *type) +{ + trenter(TR_PARSE, "type"); + struct token tok = {0}; + switch (lex(par->lex, &tok)) { + case T_CONST: + type->flags |= TYPE_CONST; + break; + default: + unlex(par->lex, &tok); + break; + } + switch (lex(par->lex, &tok)) { + case T_I8: + case T_I16: + case T_I32: + case T_I64: + case T_U8: + case T_U16: + case T_U32: + case T_U64: + case T_INT: + case T_UINT: + case T_SIZE: + case T_UINTPTR: + case T_CHAR: + unlex(par->lex, &tok); + parse_integer_type(par, &type->storage); break; case T_RUNE: type->storage = TYPE_STORAGE_RUNE; @@ -335,7 +407,9 @@ parse_type(struct parser *par, struct ast_type *type) type->storage = TYPE_STORAGE_VOID; break; case T_ENUM: - assert(0); // TODO: Enums + type->storage = TYPE_STORAGE_ENUM; + parse_enum_type(par, &type->_enum); + break; case T_NULLABLE: type->pointer.flags |= PTR_NULLABLE; want(par, T_TIMES, NULL); @@ -372,7 +446,6 @@ parse_type(struct parser *par, struct ast_type *type) } static struct ast_expression *parse_complex_expression(struct parser *par); -static struct ast_expression *parse_simple_expression(struct parser *par); static struct ast_expression * parse_access(struct parser *par) diff --git a/src/qtype.c b/src/qtype.c @@ -35,6 +35,7 @@ qstype_for_type(const struct type *type) case TYPE_STORAGE_VOID: return Q__VOID; case TYPE_STORAGE_ALIAS: + case TYPE_STORAGE_ENUM: assert(0); // TODO case TYPE_STORAGE_ARRAY: case TYPE_STORAGE_SLICE: @@ -82,6 +83,8 @@ qxtype_for_type(const struct type *type) case TYPE_STORAGE_UNION: case TYPE_STORAGE_FUNCTION: return qstype_for_type(type); + case TYPE_STORAGE_ENUM: + assert(0); // TODO } assert(0); } @@ -116,6 +119,7 @@ qtype_for_type(struct gen_context *ctx, const struct type *type, bool extended) return qtype_for_xtype(qstype_for_type(type)); case TYPE_STORAGE_ALIAS: case TYPE_STORAGE_ARRAY: + case TYPE_STORAGE_ENUM: case TYPE_STORAGE_SLICE: case TYPE_STORAGE_STRING: case TYPE_STORAGE_STRUCT: @@ -134,6 +138,7 @@ type_is_aggregate(const struct type *type) switch (type->storage) { case TYPE_STORAGE_BOOL: case TYPE_STORAGE_CHAR: + case TYPE_STORAGE_ENUM: case TYPE_STORAGE_F32: case TYPE_STORAGE_F64: case TYPE_STORAGE_I16: diff --git a/src/type_store.c b/src/type_store.c @@ -44,16 +44,18 @@ builtin_type_for_storage(enum type_storage storage, bool is_const) case TYPE_STORAGE_VOID: // const void and void are the same type return is_const ? &builtin_type_void : &builtin_type_void; - case TYPE_STORAGE_POINTER: case TYPE_STORAGE_ALIAS: case TYPE_STORAGE_ARRAY: case TYPE_STORAGE_FUNCTION: + case TYPE_STORAGE_POINTER: case TYPE_STORAGE_SLICE: case TYPE_STORAGE_STRING: case TYPE_STORAGE_STRUCT: case TYPE_STORAGE_TAGGED_UNION: case TYPE_STORAGE_UNION: return NULL; + case TYPE_STORAGE_ENUM: + assert(0); // TODO } assert(0); // Unreachable } @@ -95,6 +97,7 @@ atype_hash(struct type_store *store, const struct ast_type *type) hash = djb2(hash, atype_hash(store, param->type)); } break; + case TYPE_STORAGE_ENUM: case TYPE_STORAGE_POINTER: case TYPE_STORAGE_SLICE: case TYPE_STORAGE_STRING: @@ -143,6 +146,7 @@ type_hash(struct type_store *store, const struct type *type) hash = djb2(hash, type_hash(store, param->type)); } break; + case TYPE_STORAGE_ENUM: case TYPE_STORAGE_POINTER: case TYPE_STORAGE_SLICE: case TYPE_STORAGE_STRING: @@ -192,6 +196,7 @@ type_eq_atype(struct type_store *store, return true; case TYPE_STORAGE_ALIAS: case TYPE_STORAGE_ARRAY: + case TYPE_STORAGE_ENUM: assert(0); // TODO case TYPE_STORAGE_FUNCTION: if (!type_eq_atype(store, type->func.result, atype->func.result) @@ -254,6 +259,7 @@ type_init_from_atype(struct type_store *store, assert(0); // Invariant case TYPE_STORAGE_ALIAS: case TYPE_STORAGE_ARRAY: + case TYPE_STORAGE_ENUM: assert(0); // TODO case TYPE_STORAGE_FUNCTION: type->func.result = diff --git a/src/types.c b/src/types.c @@ -14,6 +14,8 @@ type_storage_unparse(enum type_storage storage) return "bool"; case TYPE_STORAGE_CHAR: return "char"; + case TYPE_STORAGE_ENUM: + return "enum"; case TYPE_STORAGE_F32: return "f32"; case TYPE_STORAGE_F64: @@ -97,6 +99,8 @@ type_is_signed(const struct type *type) case TYPE_STORAGE_F32: case TYPE_STORAGE_F64: return true; + case TYPE_STORAGE_ENUM: + assert(0); // TODO } assert(0); // Unreachable }