commit c84e09c24fcd1c9c93671254fb919cfb0c5e538b
parent b8a1f1badee3a45e7b35eb3879539b5e9b2616e7
Author: Eyal Sawady <ecs@d2evs.net>
Date: Tue, 22 Dec 2020 23:21:52 -0500
parse: implement enum types
Diffstat:
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
}