b32 is_flags : 1;
};
-struct AstEnumValue { AstTyped_base; AstNumLit* value; };
+struct AstEnumValue { AstTyped_base; AstTyped* value; };
struct AstTypeAlias { AstType_base; AstType* to; };
struct AstTypeRawAlias { AstType_base; Type* to; };
struct AstCompoundType {
Entity_Type_String_Literal,
Entity_Type_File_Contents,
Entity_Type_Enum,
+ Entity_Type_Enum_Value,
Entity_Type_Type_Alias,
Entity_Type_Memory_Reservation_Type,
Entity_Type_Use,
AstFileContents *file_contents;
AstType *type_alias;
AstEnumType *enum_type;
+ AstEnumValue *enum_value;
AstMemRes *mem_res;
AstPolyProc *poly_proc;
AstPolyQuery *poly_query;
}
// NOTE: Returns 1 if the conversion was successful.
-b32 convert_numlit_to_type(AstNumLit* num, Type* type) {
+b32 convert_numlit_to_type(AstNumLit* num, Type* to_type) {
if (num->type == NULL)
num->type = type_build_from_ast(context.ast_alloc, num->type_node);
assert(num->type);
- if (types_are_compatible(num->type, type)) return 1;
- if (!type_is_numeric(type)) return 0;
+ if (types_are_compatible(num->type, to_type)) return 1;
+ if (!type_is_numeric(to_type)) return 0;
+
+ Type *type = to_type;
+ if (type->kind == Type_Kind_Enum) type = type->Enum.backing;
if (num->type->Basic.kind == Basic_Kind_Int_Unsized) {
if (type->Basic.flags & Basic_Flag_Unsigned) {
u64 value = (u64) num->value.l;
if (type->Basic.size == 8) {
- num->type = type;
+ num->type = to_type;
return 1;
}
switch (type->Basic.size) {
case 1: if (value <= 255) {
- num->type = type;
+ num->type = to_type;
return 1;
}
case 2: if (value <= 65535) {
- num->type = type;
+ num->type = to_type;
return 1;
}
case 4: if (value <= 4294967295) {
- num->type = type;
+ num->type = to_type;
return 1;
}
}
switch (type->Basic.size) {
case 1: if (-128ll <= value && value <= 127ll) {
num->value.i = (i32) value;
- num->type = type;
+ num->type = to_type;
return 1;
} break;
case 2: if (-32768ll <= value && value <= 32767ll) {
num->value.i = (i32) value;
- num->type = type;
+ num->type = to_type;
return 1;
} break;
case 4: if (-2147483648ll <= value && value <= 2147483647ll) {
num->value.i = (i32) value;
- num->type = type;
+ num->type = to_type;
return 1;
} break;
- case 8: { num->type = type;
+ case 8: { num->type = to_type;
return 1;
} break;
}
return 0;
}
- num->type = type;
+ num->type = to_type;
num->value.f = (f32) num->value.l;
return 1;
}
return 0;
}
- num->type = type;
+ num->type = to_type;
num->value.d = (f64) num->value.l;
return 1;
}
num->value.f = (f32) num->value.d;
}
- num->type = type;
+ num->type = to_type;
return 1;
}
else if (num->type->Basic.kind == Basic_Kind_F32) {
if (type->Basic.kind == Basic_Kind_F64) {
num->value.d = (f64) num->value.f;
- num->type = type;
+ num->type = to_type;
return 1;
}
}
resolve_expression_type(ent->expr);
break;
+ case Entity_Type_Enum_Value:
+ cs = check_expression(&ent->enum_value->value);
+ break;
+
case Entity_Type_Type_Alias:
if (ent->type_alias->kind == Ast_Kind_Struct_Type)
cs = check_struct((AstStructType *) ent->type_alias);
break;
}
+ case Ast_Kind_Enum_Value: {
+ ent.type = Entity_Type_Enum_Value;
+ ent.state = Entity_State_Check_Types;
+ ent.enum_value = (AstEnumValue *) node;
+ ENTITY_INSERT(ent);
+ break;
+ }
+
case Ast_Kind_Use: {
if (((AstUse *) node)->expr->kind == Ast_Kind_Package) {
ent.state = Entity_State_Resolve_Symbols;
if (consume_token_if_next(parser, ':')) {
expect_token(parser, ':');
-
- // TODO: Make this work for any expression.
- evalue->value = parse_int_literal(parser);
+ evalue->value = parse_expression(parser, 0);
}
expect_token(parser, ';');
AstTyped* expr = (AstTyped *) strip_aliases((AstNode *) (*fa)->expr);
+ b32 force_a_lookup = 0;
+ if (expr->kind == Ast_Kind_Enum_Type) {
+ force_a_lookup = 1;
+ }
+
AstNode* resolution = try_symbol_resolve_from_node((AstNode *) expr, (*fa)->token);
if (resolution) *((AstNode **) fa) = resolution;
else if (expr->kind == Ast_Kind_Package) {
return Symres_Yield_Macro;
}
}
+ else if (force_a_lookup) {
+ if (context.cycle_detected) {
+ onyx_report_error((*fa)->token->pos, "'%b' does not exist here. This is a bad error message.",
+ (*fa)->token->text,
+ (*fa)->token->length);
+ return Symres_Error;
+ }
+
+ return Symres_Yield_Macro;
+ }
return Symres_Success;
}
if (enum_node->backing->kind == Ast_Kind_Symbol) SYMRES(symbol, (AstNode **) &enum_node->backing);
if (enum_node->backing == NULL) return Symres_Error;
- enum_node->backing_type = type_build_from_ast(context.ast_alloc, enum_node->backing);
- enum_node->scope = scope_create(context.ast_alloc, NULL, enum_node->token->pos);
+ if (enum_node->scope == NULL) {
+ enum_node->backing_type = type_build_from_ast(context.ast_alloc, enum_node->backing);
+ enum_node->scope = scope_create(context.ast_alloc, curr_scope, enum_node->token->pos);
- type_build_from_ast(context.ast_alloc, (AstType *) enum_node);
+ type_build_from_ast(context.ast_alloc, (AstType *) enum_node);
+ }
+
+ scope_enter(enum_node->scope);
u64 next_assign_value = enum_node->is_flags ? 1 : 0;
bh_arr_each(AstEnumValue *, value, enum_node->values) {
- symbol_introduce(enum_node->scope, (*value)->token, (AstNode *) *value);
+ if ((*value)->flags & Ast_Flag_Has_Been_Checked) continue;
+
(*value)->type = enum_node->etcache;
+ (*value)->flags |= Ast_Flag_Comptime;
if ((*value)->value != NULL) {
- // HACK
- resolve_expression_type((AstTyped *) (*value)->value);
- if (type_is_small_integer((*value)->value->type)) {
- next_assign_value = (*value)->value->value.i;
- } else if (type_is_integer((*value)->value->type)) {
- next_assign_value = (*value)->value->value.l;
+ SYMRES(expression, &(*value)->value);
+
+ if ((*value)->value->kind == Ast_Kind_NumLit) {
+ AstNumLit *n_value = (AstNumLit *) (*value)->value;
+ resolve_expression_type((AstTyped *) n_value);
+
+ if (type_is_small_integer(n_value->type)) {
+ next_assign_value = n_value->value.i;
+ } else if (type_is_integer(n_value->type)) {
+ next_assign_value = n_value->value.l;
+ } else {
+ onyx_report_error((*value)->token->pos, "expected numeric integer literal for enum initialization, got '%s'", type_get_name(n_value->type));
+ return Symres_Error;
+ }
+
+ n_value->type = enum_node->etcache;
+
} else {
- onyx_report_error((*value)->token->pos, "expected numeric integer literal for enum initialization");
- return Symres_Error;
- }
+ if ((*value)->entity == NULL) {
+ add_entities_for_node(NULL, (AstNode *) (*value), enum_node->scope, NULL);
+ }
+
+ if (context.cycle_detected) {
+ onyx_report_error((*value)->token->pos, "Expected compile time known value for enum initialization.");
+ return Symres_Error;
+ }
- (*value)->value->type = enum_node->etcache;
+ return Symres_Yield_Macro;
+ }
} else {
AstNumLit* num = make_int_literal(context.ast_alloc, next_assign_value);
num->type = enum_node->etcache;
- (*value)->value = num;
+ (*value)->value = (AstTyped *) num;
}
- (*value)->flags |= Ast_Flag_Comptime;
+ symbol_introduce(enum_node->scope, (*value)->token, (AstNode *) (*value));
+
+ (*value)->flags |= Ast_Flag_Comptime | Ast_Flag_Has_Been_Checked;
if (enum_node->is_flags) {
next_assign_value <<= 1;
next_assign_value++;
}
}
+
+ scope_leave();
+
+ // HACK this ensure that you can only lookup symbols in an Enum that are actually defined in the enum.
+ // However, during the symbol resolution of the values in an enum, they need to be able to see the
+ // enclosing scope.
+ enum_node->scope->parent = NULL;
+
return Symres_Success;
}
b32 type_is_small_integer(Type* type) {
if (type == NULL) return 0;
+ if (type->kind == Type_Kind_Enum) return type_is_small_integer(type->Enum.backing);
if (type->kind != Type_Kind_Basic) return 0;
return type->Basic.kind >= Basic_Kind_I8 && type->Basic.kind <= Basic_Kind_U32;
b32 type_is_integer(Type* type) {
if (type == NULL) return 0;
+ if (type->kind == Type_Kind_Enum) return type_is_integer(type->Enum.backing);
if (type->kind != Type_Kind_Basic) return 0;
return (type->Basic.kind >= Basic_Kind_I8 && type->Basic.kind <= Basic_Kind_U64)
case Ast_Kind_Enum_Value: {
AstEnumValue* ev = (AstEnumValue *) expr;
+ AstNumLit * num = (AstNumLit *) ev->value;
+ assert(num->kind == Ast_Kind_NumLit);
+
WasmType backing_type = onyx_type_to_wasm_type(ev->type);
- if (backing_type == WASM_TYPE_INT32) WID(WI_I32_CONST, ev->value->value.i);
- else if (backing_type == WASM_TYPE_INT64) WID(WI_I64_CONST, ev->value->value.l);
+ if (backing_type == WASM_TYPE_INT32) WID(WI_I32_CONST, num->value.i);
+ else if (backing_type == WASM_TYPE_INT64) WID(WI_I64_CONST, num->value.l);
else onyx_report_error(ev->token->pos, "Invalid backing type for enum.");
break;
}
PATCH;
bh_buffer_write_u64(&table_buffer, name_loc);
bh_buffer_write_u64(&table_buffer, (*value)->token->length);
- bh_buffer_write_u64(&table_buffer, (*value)->value->value.l);
+
+ assert((*value)->value->kind == Ast_Kind_NumLit);
+ AstNumLit *num = (AstNumLit *) (*value)->value;
+ bh_buffer_write_u64(&table_buffer, num->value.l);
}
u32 name_base = table_buffer.length;
compose(10.0f, dumb, (ABC) => ABC + 3) |> println();
- double :: (x) => x * 2;
- convert :: (x: $T, $TO: type_expr) => cast(TO) x;
- add :: (x: $T, y: T) => x + y;
- map :: (x: $T, f: (T) -> $R) => f(x);
+ double :: macro (x) => x * 2;
+ convert :: macro (x: $T, $TO: type_expr) => cast(TO) x;
+ add :: macro (x: $T, y: T) => x + y;
+ map :: macro (x: $T, f: (T) -> $R) => f(x);
5 |> double()
|> map((x) => x * 3)