mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Use heuristic to determine the type to convert to for compile time types. Added parsing for generic
This commit is contained in:
@@ -87,8 +87,6 @@ const char *decl_to_name(Decl *decl)
|
||||
return "function";
|
||||
case DECL_GENERIC:
|
||||
return "generic";
|
||||
case DECL_GENFUNC:
|
||||
TODO
|
||||
case DECL_INTERFACE:
|
||||
return "interface";
|
||||
case DECL_MACRO:
|
||||
@@ -180,7 +178,6 @@ Decl *decl_new_with_type(TokenId name, DeclKind decl_type, Visibility visibility
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_IMPORT:
|
||||
case DECL_MACRO:
|
||||
case DECL_GENFUNC:
|
||||
case DECL_GENERIC:
|
||||
case DECL_CT_IF:
|
||||
case DECL_CT_ELSE:
|
||||
@@ -914,8 +911,8 @@ void fprint_decl_recursive(Context *context, FILE *file, Decl *decl, int indent)
|
||||
indent--;
|
||||
DUMPAST(decl->macro_decl.body);
|
||||
DUMPEND();
|
||||
case DECL_GENFUNC:
|
||||
DUMPF("(macro %s", decl->name);
|
||||
case DECL_GENERIC:
|
||||
DUMPF("(generic %s", decl->name);
|
||||
DUMPTI(decl->macro_decl.rtype);
|
||||
indent++;
|
||||
DUMP("(params");
|
||||
@@ -963,16 +960,6 @@ void fprint_decl_recursive(Context *context, FILE *file, Decl *decl, int indent)
|
||||
DUMPF("(enum-constant %s", decl->name);
|
||||
DUMPEXPR(decl->enum_constant.expr);
|
||||
DUMPEND();
|
||||
case DECL_GENERIC:
|
||||
DUMPF("(generic %s\n", decl->name);
|
||||
indent++;
|
||||
DUMP("(params");
|
||||
DUMPDECLS(decl->generic_decl.parameters);
|
||||
DUMP("(cases");
|
||||
DUMPASTS(decl->generic_decl.cases);
|
||||
DUMPE();
|
||||
indent--;
|
||||
DUMPEND();
|
||||
case DECL_TYPEDEF:
|
||||
DUMPF("(typedef %s", decl->name);
|
||||
if (decl->typedef_decl.is_func)
|
||||
|
||||
@@ -183,7 +183,6 @@ static void register_generic_decls(Module *module, Decl **decls)
|
||||
case DECL_DISTINCT:
|
||||
case DECL_ENUM:
|
||||
case DECL_GENERIC:
|
||||
case DECL_GENFUNC:
|
||||
case DECL_INTERFACE:
|
||||
case DECL_ERR:
|
||||
case DECL_FUNC:
|
||||
|
||||
@@ -428,10 +428,10 @@ typedef struct
|
||||
{
|
||||
bool failable : 1;
|
||||
Decl **parameters;
|
||||
Decl **body_parameters;
|
||||
TypeInfo *type_parent; // May be null
|
||||
TypeInfo *rtype; // May be null!
|
||||
struct Ast_ *body;
|
||||
Decl **body_parameters;
|
||||
TokenId block_parameter;
|
||||
} MacroDecl;
|
||||
|
||||
@@ -1236,6 +1236,7 @@ typedef struct Module_
|
||||
Ast **files; // Asts
|
||||
|
||||
Decl** method_extensions;
|
||||
Decl** generic_cache;
|
||||
STable symbols;
|
||||
STable public_symbols;
|
||||
struct Context_ **contexts;
|
||||
@@ -1321,6 +1322,7 @@ typedef struct Context_
|
||||
Decl **functions;
|
||||
Decl **macros;
|
||||
Decl **generics;
|
||||
Decl **generic_methods;
|
||||
Decl **interfaces;
|
||||
Decl **templates;
|
||||
Decl **methods;
|
||||
|
||||
@@ -113,9 +113,16 @@ void context_register_global_decl(Context *context, Decl *decl)
|
||||
vec_add(context->interfaces, decl);
|
||||
decl_set_external_name(decl);
|
||||
break;
|
||||
case DECL_GENFUNC:
|
||||
case DECL_GENERIC:
|
||||
vec_add(context->generics, decl);
|
||||
if (decl->macro_decl.type_parent)
|
||||
{
|
||||
vec_add(context->generic_methods, decl);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
vec_add(context->generics, decl);
|
||||
}
|
||||
decl_set_external_name(decl);
|
||||
break;
|
||||
case DECL_MACRO:
|
||||
|
||||
@@ -561,15 +561,13 @@ Decl *copy_decl(Decl *decl)
|
||||
break;
|
||||
case DECL_ARRAY_VALUE:
|
||||
TODO
|
||||
case DECL_GENFUNC:
|
||||
case DECL_GENERIC:
|
||||
case DECL_MACRO:
|
||||
MACRO_COPY_TYPE(decl->macro_decl.type_parent);
|
||||
MACRO_COPY_DECL_LIST(decl->macro_decl.parameters);
|
||||
MACRO_COPY_AST(decl->macro_decl.body);
|
||||
MACRO_COPY_TYPE(decl->macro_decl.rtype);
|
||||
break;
|
||||
case DECL_GENERIC:
|
||||
TODO
|
||||
case DECL_CT_SWITCH:
|
||||
case DECL_CT_CASE:
|
||||
case DECL_ATTRIBUTE:
|
||||
|
||||
@@ -149,7 +149,6 @@ typedef enum
|
||||
DECL_INTERFACE,
|
||||
DECL_LABEL,
|
||||
DECL_MACRO,
|
||||
DECL_GENFUNC,
|
||||
DECL_STRUCT,
|
||||
DECL_TYPEDEF,
|
||||
DECL_UNION,
|
||||
@@ -157,9 +156,9 @@ typedef enum
|
||||
} DeclKind;
|
||||
|
||||
#define NON_TYPE_DECLS DECL_ARRAY_VALUE: case DECL_IMPORT: case DECL_MACRO: \
|
||||
case DECL_GENERIC: case DECL_CT_IF: case DECL_CT_ELSE: case DECL_CT_ELIF: \
|
||||
case DECL_CT_IF: case DECL_CT_ELSE: case DECL_CT_ELIF: \
|
||||
case DECL_CT_SWITCH: case DECL_CT_CASE: case DECL_ATTRIBUTE: case DECL_LABEL: \
|
||||
case DECL_DEFINE: case DECL_CT_ASSERT: case DECL_GENFUNC
|
||||
case DECL_DEFINE: case DECL_CT_ASSERT: case DECL_GENERIC
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
||||
@@ -1693,9 +1693,10 @@ static inline bool parse_func_macro_header(Context *context, bool rtype_is_optio
|
||||
*/
|
||||
static inline Decl *parse_macro_declaration(Context *context, Visibility visibility)
|
||||
{
|
||||
advance_and_verify(context, TOKEN_MACRO);
|
||||
DeclKind kind = try_consume(context, TOKEN_MACRO) ? DECL_MACRO : DECL_GENERIC;
|
||||
if (kind == DECL_GENERIC) advance_and_verify(context, TOKEN_GENERIC);
|
||||
|
||||
Decl *decl = decl_new(DECL_MACRO, context->tok.id, visibility);
|
||||
Decl *decl = decl_new(kind, context->tok.id, visibility);
|
||||
TypeInfo **rtype_ref = &decl->macro_decl.rtype;
|
||||
TypeInfo **method_type_ref = &decl->macro_decl.type_parent;
|
||||
bool failable;
|
||||
@@ -2236,8 +2237,6 @@ Decl *parse_top_level_statement(Context *context)
|
||||
decl = TRY_DECL_OR(parse_struct_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
case TOKEN_GENERIC:
|
||||
TODO
|
||||
break;
|
||||
case TOKEN_MACRO:
|
||||
decl = TRY_DECL_OR(parse_macro_declaration(context, visibility), poisoned_decl);
|
||||
break;
|
||||
|
||||
@@ -330,15 +330,41 @@ bool enum_to_pointer(Expr* expr, Type *from, Type *type)
|
||||
return int_to_pointer(expr, type);
|
||||
}
|
||||
|
||||
Type *type_by_expr_range(ExprConst *expr)
|
||||
{
|
||||
if (expr->kind == TYPE_FXX)
|
||||
{
|
||||
return type_double;
|
||||
}
|
||||
assert(expr->kind == TYPE_IXX);
|
||||
BigInt *b = &expr->i;
|
||||
// 1. Does it fit in a C int? If so, that's the type.
|
||||
Type *type = type_cint();
|
||||
if (!expr_const_will_overflow(expr, type->type_kind)) return type;
|
||||
|
||||
int width_max = platform_target.int128 ? 128 : 64;
|
||||
int current_width = platform_target.width_c_int * 2;
|
||||
while (current_width <= width_max)
|
||||
{
|
||||
type = type_int_signed_by_bitsize(current_width);
|
||||
if (!expr_const_will_overflow(expr, type->type_kind)) return type;
|
||||
type = type_int_unsigned_by_bitsize(current_width);
|
||||
if (!expr_const_will_overflow(expr, type->type_kind)) return type;
|
||||
current_width *= width_max;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cast_implicitly_to_runtime(Expr *expr)
|
||||
{
|
||||
Type *canonical = expr->type->canonical;
|
||||
Type *type;
|
||||
switch (canonical->type_kind)
|
||||
{
|
||||
case TYPE_IXX:
|
||||
return cast(expr, type_long);
|
||||
case TYPE_FXX:
|
||||
return cast(expr, type_double);
|
||||
type = type_by_expr_range(&expr->const_expr);
|
||||
return type && cast(expr, type);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -610,7 +610,7 @@ static inline const char *name_by_decl(Decl *method_like)
|
||||
return "macro method";
|
||||
case DECL_FUNC:
|
||||
return "method";
|
||||
case DECL_GENFUNC:
|
||||
case DECL_GENERIC:
|
||||
return "generic method";
|
||||
default:
|
||||
UNREACHABLE
|
||||
@@ -1009,6 +1009,7 @@ static bool sema_analyse_macro_method(Context *context, Decl *decl)
|
||||
|
||||
static inline bool sema_analyse_macro(Context *context, Decl *decl)
|
||||
{
|
||||
bool is_generic = decl->decl_kind == DECL_GENERIC;
|
||||
TypeInfo *rtype = decl->macro_decl.rtype;
|
||||
if (decl->macro_decl.rtype && !sema_resolve_type_info(context, rtype)) return decl_poison(decl);
|
||||
VECEACH(decl->macro_decl.parameters, i)
|
||||
@@ -1018,10 +1019,16 @@ static inline bool sema_analyse_macro(Context *context, Decl *decl)
|
||||
assert(param->decl_kind == DECL_VAR);
|
||||
switch (param->var.kind)
|
||||
{
|
||||
case VARDECL_PARAM:
|
||||
case VARDECL_PARAM_EXPR:
|
||||
case VARDECL_PARAM_CT:
|
||||
case VARDECL_PARAM_REF:
|
||||
if (is_generic)
|
||||
{
|
||||
SEMA_ERROR(param, "Only regular parameters and type parameters are allowed for generic functions.");
|
||||
return decl_poison(decl);
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case VARDECL_PARAM:
|
||||
if (param->var.type_info)
|
||||
{
|
||||
if (!sema_resolve_type_info(context, param->var.type_info)) return decl_poison(decl);
|
||||
@@ -1046,6 +1053,11 @@ static inline bool sema_analyse_macro(Context *context, Decl *decl)
|
||||
}
|
||||
param->resolve_status = RESOLVE_DONE;
|
||||
}
|
||||
if (is_generic && vec_size(decl->macro_decl.body_parameters))
|
||||
{
|
||||
SEMA_ERROR(decl->macro_decl.body_parameters[0], "Trailing block syntax is not allowed for generic functions.");
|
||||
return decl_poison(decl);
|
||||
}
|
||||
VECEACH(decl->macro_decl.body_parameters, i)
|
||||
{
|
||||
Decl *param = decl->macro_decl.body_parameters[i];
|
||||
@@ -1195,64 +1207,6 @@ static inline bool sema_analyse_global(Context *context, Decl *decl)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_generic(Context *context, Decl *decl)
|
||||
{
|
||||
// 1. If it has a return type, make sure it resolves.
|
||||
if (decl->generic_decl.rtype && !sema_resolve_type_info(context, decl->generic_decl.rtype)) return false;
|
||||
|
||||
unsigned param_count = vec_size(decl->generic_decl.parameters);
|
||||
if (param_count < 1)
|
||||
{
|
||||
SEMA_ERROR(decl, "A generic function needs at least 1 parameter.");
|
||||
return false;
|
||||
}
|
||||
Ast **cases = decl->generic_decl.cases;
|
||||
|
||||
bool default_has_been_found = false;
|
||||
VECEACH(cases, i)
|
||||
{
|
||||
Ast *generic_case = cases[i];
|
||||
if (generic_case->ast_kind == AST_CASE_STMT)
|
||||
{
|
||||
if (!generic_case->case_stmt.is_type)
|
||||
{
|
||||
SEMA_ERROR(generic_case->case_stmt.expr, "Expected a type as the argument.");
|
||||
return false;
|
||||
}
|
||||
if (!generic_case->case_stmt.is_type_list)
|
||||
{
|
||||
TypeInfo **type_infos = VECNEW(TypeInfo *, 2);
|
||||
vec_add(type_infos, generic_case->case_stmt.type_info);
|
||||
generic_case->case_stmt.type_infos = type_infos;
|
||||
generic_case->case_stmt.is_type_list = true;
|
||||
}
|
||||
TypeInfo **type_infos = generic_case->case_stmt.type_infos;
|
||||
unsigned args = vec_size(type_infos);
|
||||
for (unsigned j = 0; j < args; j++)
|
||||
{
|
||||
if (!sema_resolve_type_info(context, type_infos[j])) return false;
|
||||
}
|
||||
if (args != param_count)
|
||||
{
|
||||
if (param_count == 1)
|
||||
{
|
||||
SEMA_ERROR(type_infos[1], "Expected a single type as the argument.");
|
||||
return false;
|
||||
}
|
||||
SEMA_ERROR(type_infos[args - 1], "Expected %d types in the case statement.", param_count);
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
assert(generic_case->ast_kind == AST_DEFAULT_STMT);
|
||||
if (default_has_been_found)
|
||||
{
|
||||
SEMA_ERROR(generic_case, "More than one default statement found.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1458,9 +1412,8 @@ bool sema_analyse_decl(Context *context, Decl *decl)
|
||||
case DECL_FUNC:
|
||||
if (!sema_analyse_func(context, decl)) return decl_poison(decl);
|
||||
break;
|
||||
case DECL_GENFUNC:
|
||||
TODO
|
||||
case DECL_MACRO:
|
||||
case DECL_GENERIC:
|
||||
if (!sema_analyse_macro(context, decl)) return decl_poison(decl);
|
||||
break;
|
||||
case DECL_VAR:
|
||||
@@ -1482,9 +1435,6 @@ bool sema_analyse_decl(Context *context, Decl *decl)
|
||||
if (!sema_analyse_error(context, decl)) return decl_poison(decl);
|
||||
decl_set_external_name(decl);
|
||||
break;
|
||||
case DECL_GENERIC:
|
||||
if (!sema_analyse_generic(context, decl)) return decl_poison(decl);
|
||||
break;
|
||||
case DECL_DEFINE:
|
||||
if (!sema_analyse_define(context, decl)) return decl_poison(decl);
|
||||
break;
|
||||
|
||||
@@ -192,6 +192,9 @@ static inline bool sema_cast_ident_rvalue(Context *context, Type *to, Expr *expr
|
||||
case DECL_MACRO:
|
||||
SEMA_ERROR(expr, "Expected macro followed by (...) or prefixed by '&'.");
|
||||
return expr_poison(expr);
|
||||
case DECL_GENERIC:
|
||||
SEMA_ERROR(expr, "Expected generic followed by (...) or prefixed by '&'.");
|
||||
return expr_poison(expr);
|
||||
case DECL_ENUM_CONSTANT:
|
||||
expr_replace(expr, decl->enum_constant.expr);
|
||||
return true;
|
||||
@@ -223,8 +226,6 @@ static inline bool sema_cast_ident_rvalue(Context *context, Type *to, Expr *expr
|
||||
case DECL_ARRAY_VALUE:
|
||||
UNREACHABLE
|
||||
case DECL_IMPORT:
|
||||
case DECL_GENERIC:
|
||||
case DECL_GENFUNC:
|
||||
case DECL_CT_IF:
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
@@ -232,9 +233,8 @@ static inline bool sema_cast_ident_rvalue(Context *context, Type *to, Expr *expr
|
||||
case DECL_CT_CASE:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_CT_ASSERT:
|
||||
UNREACHABLE
|
||||
case DECL_DEFINE:
|
||||
TODO
|
||||
UNREACHABLE
|
||||
}
|
||||
switch (decl->var.kind)
|
||||
{
|
||||
@@ -1031,22 +1031,6 @@ static inline bool sema_expr_analyse_var_call(Context *context, Type *to, Expr *
|
||||
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_generic_call(Context *context, Type *to, Decl *decl, Expr *expr)
|
||||
{
|
||||
Expr **arguments = expr->call_expr.arguments;
|
||||
Decl **parameter_list = decl->generic_decl.parameters;
|
||||
if (vec_size(parameter_list) != vec_size(arguments))
|
||||
{
|
||||
SEMA_ERROR(expr, "Expected %d parameter(s) to the generic function.", vec_size(parameter_list));
|
||||
return false;
|
||||
}
|
||||
VECEACH(arguments, i)
|
||||
{
|
||||
if (!sema_analyse_expr(context, NULL, arguments[i])) return false;
|
||||
}
|
||||
|
||||
TODO
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1239,6 +1223,11 @@ static inline bool sema_expr_analyse_macro_call(Context *context, Type *to, Expr
|
||||
case VARDECL_PARAM:
|
||||
// foo
|
||||
if (!sema_analyse_expr_of_required_type(context, param->type, arg, false)) return false;
|
||||
if (!param->type && !cast_implicitly_to_runtime(arg))
|
||||
{
|
||||
SEMA_ERROR(arg, "Constant cannot implicitly be cast to a real type.");
|
||||
return false;
|
||||
}
|
||||
param->alignment = type_abi_alignment(param->type ? param->type : arg->type);
|
||||
break;
|
||||
case VARDECL_PARAM_EXPR:
|
||||
@@ -1422,7 +1411,102 @@ static inline bool sema_expr_analyse_macro_call(Context *context, Type *to, Expr
|
||||
context->macro_scope = old_macro_scope;
|
||||
return ok;
|
||||
}
|
||||
static inline Decl *sema_generate_generic_function(Context *context, Expr *call_expr, Expr *struct_var, Decl *decl, const char *mangled_name)
|
||||
{
|
||||
TODO
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_generic_call(Context *context, Type *to, Expr *call_expr, Expr *struct_var, Decl *decl)
|
||||
{
|
||||
assert(decl->decl_kind == DECL_GENERIC);
|
||||
|
||||
Expr **args = call_expr->call_expr.arguments;
|
||||
Decl **func_params = decl->macro_decl.parameters;
|
||||
|
||||
unsigned explicit_args = vec_size(args);
|
||||
unsigned total_args = explicit_args;
|
||||
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl->external_name);
|
||||
|
||||
// TODO revisit name mangling
|
||||
if (struct_var)
|
||||
{
|
||||
total_args++;
|
||||
scratch_buffer_append_char('@');
|
||||
scratch_buffer_append(struct_var->type->canonical->name);
|
||||
}
|
||||
|
||||
if (total_args != vec_size(func_params))
|
||||
{
|
||||
// TODO HANDLE VARARGS
|
||||
SEMA_ERROR(call_expr, "Mismatch on number of arguments.");
|
||||
return false;
|
||||
}
|
||||
|
||||
int offset = total_args - explicit_args;
|
||||
for (unsigned i = 0; i < explicit_args; i++)
|
||||
{
|
||||
Expr *arg = args[i];
|
||||
Decl *param = func_params[i + offset];
|
||||
if (param->decl_kind == VARDECL_PARAM_CT_TYPE)
|
||||
{
|
||||
if (!sema_analyse_expr_value(context, NULL, arg)) return false;
|
||||
if (arg->expr_kind != EXPR_TYPEINFO)
|
||||
{
|
||||
SEMA_ERROR(arg, "A type, like 'int' or 'double' was expected for the parameter '%s'.", param->name);
|
||||
return false;
|
||||
}
|
||||
scratch_buffer_append_char(',');
|
||||
scratch_buffer_append(arg->type_expr->type->canonical->name);
|
||||
continue;
|
||||
}
|
||||
if (param->var.type_info)
|
||||
{
|
||||
if (!sema_analyse_expr_of_required_type(context, param->var.type_info->type, arg, true)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_expr(context, NULL, arg)) return false;
|
||||
if (!cast_implicitly_to_runtime(arg)) return false;
|
||||
}
|
||||
scratch_buffer_append_char(',');
|
||||
scratch_buffer_append(arg->type->canonical->name);
|
||||
}
|
||||
const char *mangled_name = scratch_buffer_interned();
|
||||
Decl **generic_cache = decl->module->generic_cache;
|
||||
Decl *found = NULL;
|
||||
VECEACH(generic_cache, i)
|
||||
{
|
||||
if (generic_cache[i]->external_name == mangled_name)
|
||||
{
|
||||
found = generic_cache[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
found = sema_generate_generic_function(context, call_expr, struct_var, decl, mangled_name);
|
||||
}
|
||||
// Remove type parameters from call.
|
||||
for (unsigned i = 0; i < explicit_args; i++)
|
||||
{
|
||||
Decl *param = func_params[i + offset];
|
||||
if (param->decl_kind == VARDECL_PARAM_CT_TYPE)
|
||||
{
|
||||
for (unsigned j = i + 1; j < explicit_args; j++)
|
||||
{
|
||||
args[j - 1] = args[j];
|
||||
}
|
||||
explicit_args--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
vec_resize(args, explicit_args);
|
||||
// Perform the normal func call on the found declaration.
|
||||
return sema_expr_analyse_func_call(context, to, call_expr, found, struct_var);
|
||||
}
|
||||
|
||||
static bool sema_analyse_body_expansion(Context *context, Expr *call)
|
||||
{
|
||||
@@ -1537,7 +1621,7 @@ static inline bool sema_expr_analyse_call(Context *context, Type *to, Expr *expr
|
||||
SEMA_ERROR(expr, "Macro declarations cannot be called without using '@' before the macro name.");
|
||||
return false;
|
||||
case DECL_GENERIC:
|
||||
return sema_expr_analyse_generic_call(context, to, decl, expr);
|
||||
return sema_expr_analyse_generic_call(context, to, expr, struct_var, decl);
|
||||
case DECL_POISONED:
|
||||
return false;
|
||||
default:
|
||||
|
||||
@@ -244,7 +244,7 @@ Decl *sema_find_extension_method_in_module(Module *module, Type *type, const cha
|
||||
if (extension->func_decl.type_parent->type == type) return extension;
|
||||
break;
|
||||
case DECL_MACRO:
|
||||
case DECL_GENFUNC:
|
||||
case DECL_GENERIC:
|
||||
if (extension->macro_decl.type_parent->type == type) return extension;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -119,7 +119,6 @@ static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info)
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_IMPORT:
|
||||
case DECL_MACRO:
|
||||
case DECL_GENFUNC:
|
||||
case DECL_GENERIC:
|
||||
case DECL_LABEL:
|
||||
SEMA_TOKID_ERROR(type_info->unresolved.name_loc, "This is not a type.");
|
||||
@@ -137,30 +136,6 @@ static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info)
|
||||
|
||||
}
|
||||
|
||||
Type *type_by_expr_range(ExprConst *expr)
|
||||
{
|
||||
if (expr->kind == TYPE_FXX)
|
||||
{
|
||||
return type_double;
|
||||
}
|
||||
assert(expr->kind == TYPE_IXX);
|
||||
BigInt *b = &expr->i;
|
||||
// 1. Does it fit in a C int? If so, that's the type.
|
||||
Type *type = type_cint();
|
||||
if (!expr_const_will_overflow(expr, type->type_kind)) return type;
|
||||
|
||||
int width_max = platform_target.int128 ? 128 : 64;
|
||||
int current_width = platform_target.width_c_int * 2;
|
||||
while (current_width <= width_max)
|
||||
{
|
||||
type = type_int_signed_by_bitsize(current_width);
|
||||
if (!expr_const_will_overflow(expr, type->type_kind)) return type;
|
||||
type = type_int_unsigned_by_bitsize(current_width);
|
||||
if (!expr_const_will_overflow(expr, type->type_kind)) return type;
|
||||
current_width *= width_max;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool sema_resolve_type_shallow(Context *context, TypeInfo *type_info, bool allow_inferred_type, bool in_shallow)
|
||||
{
|
||||
@@ -192,22 +167,12 @@ bool sema_resolve_type_shallow(Context *context, TypeInfo *type_info, bool allow
|
||||
{
|
||||
return type_info_poison(type_info);
|
||||
}
|
||||
type_info->type = expr->type;
|
||||
switch (type_info->type->type_kind)
|
||||
if (!cast_implicitly_to_runtime(expr))
|
||||
{
|
||||
case TYPE_FXX:
|
||||
case TYPE_IXX:
|
||||
assert(expr->expr_kind == EXPR_CONST);
|
||||
type_info->type = type_by_expr_range(&expr->const_expr);
|
||||
if (!type_info->type)
|
||||
{
|
||||
SEMA_ERROR(expr, "The expression does not fit any runtime type.");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
SEMA_ERROR(expr, "The expression does not fit any runtime type.");
|
||||
return false;
|
||||
}
|
||||
type_info->type = expr->type;
|
||||
type_info->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
12
test/test_suite/macros/macro_convert_literal.c3
Normal file
12
test/test_suite/macros/macro_convert_literal.c3
Normal file
@@ -0,0 +1,12 @@
|
||||
module foo;
|
||||
import std::io;
|
||||
|
||||
macro foo(y)
|
||||
{
|
||||
return y * y;
|
||||
}
|
||||
|
||||
func void main()
|
||||
{
|
||||
io::printf("%d\n", @foo(10));
|
||||
}
|
||||
Reference in New Issue
Block a user