mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Cleanup of naming change to optional. Fix of builtin optional handling.
This commit is contained in:
@@ -216,7 +216,7 @@ enum TypeKind : char
|
||||
UNION,
|
||||
BITSTRUCT,
|
||||
FUNC,
|
||||
FAILABLE,
|
||||
OPTIONAL,
|
||||
ARRAY,
|
||||
SUBARRAY,
|
||||
VECTOR,
|
||||
|
||||
@@ -159,7 +159,7 @@ private fn void! Formatter.out_str(Formatter* this, variant arg)
|
||||
case FUNC:
|
||||
if (this.print_with_function(arg)?) return;
|
||||
return this.out_substr("<function>");
|
||||
case FAILABLE:
|
||||
case OPTIONAL:
|
||||
unreachable();
|
||||
case DISTINCT:
|
||||
if (this.print_with_function(arg)?) return;
|
||||
|
||||
@@ -238,8 +238,8 @@ macro_argument_list
|
||||
;
|
||||
|
||||
declaration
|
||||
: failable_type IDENT '=' initializer
|
||||
| failable_type IDENT
|
||||
: optional_type IDENT '=' initializer
|
||||
| optional_type IDENT
|
||||
;
|
||||
|
||||
param_declaration
|
||||
@@ -291,7 +291,7 @@ type
|
||||
| type '[' '+' ']'
|
||||
;
|
||||
|
||||
failable_type
|
||||
optional_type
|
||||
: type
|
||||
| type '!'
|
||||
;
|
||||
@@ -419,8 +419,8 @@ expression_statement
|
||||
|
||||
|
||||
if_expr
|
||||
: failable_type IDENT '=' initializer
|
||||
| failable_type IDENT NOFAIL_ASSIGN expression
|
||||
: optional_type IDENT '=' initializer
|
||||
| optional_type IDENT NOFAIL_ASSIGN expression
|
||||
| expression
|
||||
;
|
||||
|
||||
@@ -513,7 +513,7 @@ func_name
|
||||
;
|
||||
|
||||
func_declaration
|
||||
: FUNC failable_type func_name opt_parameter_type_list opt_attributes
|
||||
: FUNC optional_type func_name opt_parameter_type_list opt_attributes
|
||||
;
|
||||
|
||||
func_definition
|
||||
@@ -594,7 +594,7 @@ const_declaration
|
||||
;
|
||||
|
||||
func_typedef
|
||||
: FUNC failable_type opt_parameter_type_list
|
||||
: FUNC optional_type opt_parameter_type_list
|
||||
;
|
||||
|
||||
typedef_declaration
|
||||
|
||||
@@ -170,7 +170,7 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
type = type->optional;
|
||||
goto RETRY;
|
||||
case TYPE_DISTINCT:
|
||||
type = type->decl->distinct_decl.base_type;
|
||||
@@ -183,7 +183,7 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
|
||||
case TYPE_FUNC:
|
||||
case TYPE_SUBARRAY:
|
||||
case CT_TYPES:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
return false;
|
||||
case TYPE_ANY:
|
||||
*base = type_iptr->canonical;
|
||||
|
||||
@@ -332,8 +332,8 @@ struct Type_
|
||||
TypeFunction function;
|
||||
// Type*
|
||||
Type *pointer;
|
||||
// Failable
|
||||
Type *failable;
|
||||
// Optional
|
||||
Type *optional;
|
||||
// Bitstruct
|
||||
Type *bitstruct;
|
||||
};
|
||||
@@ -354,7 +354,7 @@ struct TypeInfo_
|
||||
{
|
||||
ResolveStatus resolve_status : 3;
|
||||
TypeInfoKind kind : 6;
|
||||
bool failable : 1;
|
||||
bool optional : 1;
|
||||
TypeInfoCompressedKind subtype : 4;
|
||||
Type *type;
|
||||
SourceSpan span;
|
||||
@@ -447,8 +447,8 @@ typedef struct VarDecl_
|
||||
union
|
||||
{
|
||||
// Variable
|
||||
void *failable_ref;
|
||||
int tb_failable_reg;
|
||||
void *optional_ref;
|
||||
int tb_optional_reg;
|
||||
};
|
||||
};
|
||||
struct
|
||||
@@ -976,7 +976,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
void *block_return_exit;
|
||||
void *block_failable_exit;
|
||||
void *block_optional_exit;
|
||||
void *block_error_var;
|
||||
void *block_return_out;
|
||||
} BlockExit;
|
||||
@@ -1047,7 +1047,7 @@ typedef struct
|
||||
struct
|
||||
{
|
||||
bool assign_existing : 1;
|
||||
Expr *failable;
|
||||
Expr *optional;
|
||||
union
|
||||
{
|
||||
Decl *decl;
|
||||
@@ -1749,7 +1749,7 @@ typedef struct FunctionPrototype_
|
||||
CallABI call_abi : 4;
|
||||
Variadic variadic : 3;
|
||||
bool use_win64 : 1;
|
||||
bool is_failable : 1;
|
||||
bool is_optional : 1;
|
||||
bool ret_by_ref : 1;
|
||||
unsigned short vararg_index;
|
||||
Type *rtype;
|
||||
@@ -2028,7 +2028,7 @@ AsmRegister *asm_reg_by_index(unsigned index);
|
||||
|
||||
bool cast_implicit_silent(SemaContext *context, Expr *expr, Type *to_type);
|
||||
bool cast_implicit(SemaContext *context, Expr *expr, Type *to_type);
|
||||
bool cast_implicit_maybe_failable(SemaContext *context, Expr *expr, Type *to_type, bool may_be_failable);
|
||||
bool cast_implicit_maybe_optional(SemaContext *context, Expr *expr, Type *to_type, bool may_be_optional);
|
||||
bool cast_explicit(SemaContext *context, Expr *expr, Type *to_type);
|
||||
|
||||
bool cast(Expr *expr, Type *to_type);
|
||||
@@ -2188,7 +2188,7 @@ void sema_erase_var(SemaContext *context, Decl *decl);
|
||||
void sema_erase_unwrapped(SemaContext *context, Decl *decl);
|
||||
bool sema_analyse_cond_expr(SemaContext *context, Expr *expr);
|
||||
|
||||
bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allow_failable);
|
||||
bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allow_optional);
|
||||
MemberIndex sema_get_initializer_const_array_size(SemaContext *context, Expr *initializer, bool *may_be_array, bool *is_const_size);
|
||||
bool sema_analyse_expr(SemaContext *context, Expr *expr);
|
||||
bool sema_analyse_inferred_expr(SemaContext *context, Type *to, Expr *expr);
|
||||
@@ -2201,7 +2201,7 @@ bool sema_analyse_statement(SemaContext *context, Ast *statement);
|
||||
bool sema_expr_analyse_assign_right_side(SemaContext *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped_var);
|
||||
bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *expr);
|
||||
Expr **sema_expand_vasplat_exprs(SemaContext *c, Expr **exprs);
|
||||
bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool failable);
|
||||
bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool optional);
|
||||
Decl *sema_resolve_symbol_in_current_dynamic_scope(SemaContext *context, const char *symbol);
|
||||
Decl *sema_decl_stack_resolve_symbol(const char *symbol);
|
||||
Decl *sema_find_decl_in_modules(Module **module_list, Path *path, const char *interned_name);
|
||||
@@ -2294,7 +2294,7 @@ Type *type_get_inferred_array(Type *arr_type);
|
||||
Type *type_get_inferred_vector(Type *arr_type);
|
||||
Type *type_get_flexible_array(Type *arr_type);
|
||||
Type *type_get_scaled_vector(Type *arr_type);
|
||||
Type *type_get_optional(Type *failable_type);
|
||||
Type *type_get_optional(Type *optional_type);
|
||||
Type *type_get_vector(Type *vector_type, unsigned len);
|
||||
Type *type_get_vector_bool(Type *original_type);
|
||||
Type *type_int_signed_by_bitsize(BitSize bitsize);
|
||||
@@ -2392,8 +2392,8 @@ TokenType binaryop_to_token(BinaryOp type);
|
||||
INLINE Type *type_no_optional(Type *type)
|
||||
{
|
||||
if (!type) return NULL;
|
||||
if (type->type_kind == TYPE_OPTIONAL) return type->failable;
|
||||
if (type->type_kind == TYPE_FAILABLE_ANY) return type_void;
|
||||
if (type->type_kind == TYPE_OPTIONAL) return type->optional;
|
||||
if (type->type_kind == TYPE_OPTIONAL_ANY) return type_void;
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -2414,7 +2414,7 @@ INLINE bool type_is_pointer_sized(Type *type)
|
||||
|
||||
INLINE Type *type_add_optional(Type *type, bool make_optional)
|
||||
{
|
||||
if (!make_optional || type->type_kind == TYPE_OPTIONAL || type->type_kind == TYPE_FAILABLE_ANY) return type;
|
||||
if (!make_optional || type->type_kind == TYPE_OPTIONAL || type->type_kind == TYPE_OPTIONAL_ANY) return type;
|
||||
return type_get_optional(type);
|
||||
}
|
||||
|
||||
@@ -2466,7 +2466,7 @@ INLINE bool type_len_is_inferred(Type *type)
|
||||
INLINE bool type_is_optional(Type *type)
|
||||
{
|
||||
DECL_TYPE_KIND_REAL(kind, type);
|
||||
return kind == TYPE_OPTIONAL || kind == TYPE_FAILABLE_ANY;
|
||||
return kind == TYPE_OPTIONAL || kind == TYPE_OPTIONAL_ANY;
|
||||
}
|
||||
|
||||
INLINE bool type_is_optional_type(Type *type)
|
||||
@@ -2571,7 +2571,7 @@ INLINE bool type_may_negate(Type *type)
|
||||
type = type->canonical;
|
||||
goto RETRY;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
type = type->optional;
|
||||
goto RETRY;
|
||||
default:
|
||||
return false;
|
||||
@@ -2695,7 +2695,7 @@ static inline Type *type_flatten_distinct_optional(Type *type)
|
||||
type = type->canonical;
|
||||
continue;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
type = type->optional;
|
||||
continue;
|
||||
case TYPE_DISTINCT:
|
||||
type = type->decl->distinct_decl.base_type;
|
||||
@@ -2729,9 +2729,9 @@ static inline Type *type_flatten(Type *type)
|
||||
type = type->decl->enums.type_info->type;
|
||||
break;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
type = type->optional;
|
||||
break;
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
return type_void;
|
||||
case TYPE_TYPEDEF:
|
||||
UNREACHABLE
|
||||
|
||||
@@ -384,7 +384,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
|
||||
case EXPR_FORCE_UNWRAP:
|
||||
case EXPR_TRY:
|
||||
case EXPR_CATCH:
|
||||
case EXPR_FAILABLE:
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_GROUP:
|
||||
case EXPR_STRINGIFY:
|
||||
case EXPR_CT_EVAL:
|
||||
|
||||
@@ -205,7 +205,7 @@ typedef enum
|
||||
INTROSPECT_TYPE_UNION = 11,
|
||||
INTROSPECT_TYPE_BITSTRUCT = 12,
|
||||
INTROSPECT_TYPE_FUNC = 13,
|
||||
INTROSPECT_TYPE_FAILABLE = 14,
|
||||
INTROSPECT_TYPE_OPTIONAL = 14,
|
||||
INTROSPECT_TYPE_ARRAY = 15,
|
||||
INTROSPECT_TYPE_SUBARRAY = 16,
|
||||
INTROSPECT_TYPE_VECTOR = 17,
|
||||
@@ -243,7 +243,7 @@ typedef enum
|
||||
EXPR_DESIGNATOR,
|
||||
EXPR_EXPRESSION_LIST,
|
||||
EXPR_EXPR_BLOCK,
|
||||
EXPR_FAILABLE,
|
||||
EXPR_OPTIONAL,
|
||||
EXPR_FLATPATH,
|
||||
EXPR_FORCE_UNWRAP,
|
||||
EXPR_GROUP,
|
||||
@@ -672,7 +672,7 @@ typedef enum
|
||||
TYPE_FLEXIBLE_ARRAY,
|
||||
TYPE_UNTYPED_LIST,
|
||||
TYPE_OPTIONAL,
|
||||
TYPE_FAILABLE_ANY,
|
||||
TYPE_OPTIONAL_ANY,
|
||||
TYPE_TYPEINFO,
|
||||
TYPE_MEMBER,
|
||||
TYPE_INFERRED_VECTOR,
|
||||
|
||||
@@ -106,7 +106,7 @@ bool expr_may_addr(Expr *expr)
|
||||
case EXPR_DESIGNATOR:
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
case EXPR_EXPR_BLOCK:
|
||||
case EXPR_FAILABLE:
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_FLATPATH:
|
||||
case EXPR_FORCE_UNWRAP:
|
||||
case EXPR_HASH_IDENT:
|
||||
@@ -240,7 +240,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
|
||||
case EXPR_TYPEID_INFO:
|
||||
expr = exprptr(expr->typeid_info_expr.parent);
|
||||
goto RETRY;
|
||||
case EXPR_FAILABLE:
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_GROUP:
|
||||
expr = expr->inner_expr;
|
||||
goto RETRY;
|
||||
@@ -462,8 +462,8 @@ void expr_insert_addr(Expr *original)
|
||||
Expr *inner = expr_copy(original);
|
||||
original->expr_kind = EXPR_UNARY;
|
||||
Type *inner_type = inner->type;
|
||||
bool failable = type_is_optional(inner->type);
|
||||
original->type = type_add_optional(type_get_ptr(type_no_optional(inner_type)), failable);
|
||||
bool optional = type_is_optional(inner->type);
|
||||
original->type = type_add_optional(type_get_ptr(type_no_optional(inner_type)), optional);
|
||||
original->unary_expr.operator = UNARYOP_ADDR;
|
||||
original->unary_expr.expr = inner;
|
||||
}
|
||||
@@ -577,7 +577,7 @@ void expr_rewrite_to_const_zero(Expr *expr, Type *type)
|
||||
break;
|
||||
case TYPE_FUNC:
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_MEMBER:
|
||||
@@ -701,7 +701,7 @@ bool expr_is_pure(Expr *expr)
|
||||
case EXPR_DESIGNATOR:
|
||||
case EXPR_DECL:
|
||||
case EXPR_EXPR_BLOCK:
|
||||
case EXPR_FAILABLE:
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_RETHROW:
|
||||
case EXPR_HASH_IDENT:
|
||||
case EXPR_MACRO_BLOCK:
|
||||
|
||||
@@ -35,7 +35,7 @@ static void header_print_type(FILE *file, Type *type)
|
||||
case TYPE_BITSTRUCT:
|
||||
TODO
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
// If this is reachable then we are not doing the proper lowering.
|
||||
UNREACHABLE
|
||||
case TYPE_VOID:
|
||||
|
||||
@@ -341,11 +341,11 @@ void llvm_set_global_tls(Decl *decl)
|
||||
}
|
||||
LLVMSetThreadLocal(decl->backend_ref, true);
|
||||
LLVMSetThreadLocalMode(decl->backend_ref, thread_local_mode);
|
||||
void *failable_ref = decl->var.failable_ref;
|
||||
if (failable_ref)
|
||||
void *optional_ref = decl->var.optional_ref;
|
||||
if (optional_ref)
|
||||
{
|
||||
LLVMSetThreadLocal(failable_ref, true);
|
||||
LLVMSetThreadLocalMode(failable_ref, thread_local_mode);
|
||||
LLVMSetThreadLocal(optional_ref, true);
|
||||
LLVMSetThreadLocalMode(optional_ref, thread_local_mode);
|
||||
}
|
||||
}
|
||||
void llvm_set_internal_linkage(LLVMValueRef alloc)
|
||||
@@ -425,22 +425,22 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl)
|
||||
}
|
||||
llvm_set_global_tls(decl);
|
||||
|
||||
LLVMValueRef failable_ref = decl->var.failable_ref;
|
||||
if (failable_ref)
|
||||
LLVMValueRef optional_ref = decl->var.optional_ref;
|
||||
if (optional_ref)
|
||||
{
|
||||
llvm_set_alignment(failable_ref, type_alloca_alignment(type_anyerr));
|
||||
LLVMSetUnnamedAddress(failable_ref, LLVMGlobalUnnamedAddr);
|
||||
llvm_set_alignment(optional_ref, type_alloca_alignment(type_anyerr));
|
||||
LLVMSetUnnamedAddress(optional_ref, LLVMGlobalUnnamedAddr);
|
||||
}
|
||||
if (init_expr && IS_OPTIONAL(init_expr) && init_expr->expr_kind == EXPR_FAILABLE)
|
||||
if (init_expr && IS_OPTIONAL(init_expr) && init_expr->expr_kind == EXPR_OPTIONAL)
|
||||
{
|
||||
UNREACHABLE
|
||||
}
|
||||
if (decl->visibility != VISIBLE_EXTERN)
|
||||
{
|
||||
LLVMSetInitializer(decl->backend_ref, init_value);
|
||||
if (failable_ref)
|
||||
if (optional_ref)
|
||||
{
|
||||
LLVMSetInitializer(failable_ref, llvm_get_zero(c, type_anyerr));
|
||||
LLVMSetInitializer(optional_ref, llvm_get_zero(c, type_anyerr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,20 +452,20 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl)
|
||||
{
|
||||
case VISIBLE_MODULE:
|
||||
LLVMSetVisibility(global_ref, LLVMProtectedVisibility);
|
||||
if (failable_ref) LLVMSetVisibility(failable_ref, LLVMProtectedVisibility);
|
||||
if (optional_ref) LLVMSetVisibility(optional_ref, LLVMProtectedVisibility);
|
||||
break;
|
||||
case VISIBLE_PUBLIC:
|
||||
LLVMSetVisibility(global_ref, LLVMDefaultVisibility);
|
||||
if (failable_ref) LLVMSetVisibility(failable_ref, LLVMDefaultVisibility);
|
||||
if (optional_ref) LLVMSetVisibility(optional_ref, LLVMDefaultVisibility);
|
||||
break;
|
||||
case VISIBLE_EXTERN:
|
||||
LLVMSetLinkage(global_ref, LLVMExternalLinkage);
|
||||
if (failable_ref) LLVMSetLinkage(failable_ref, LLVMExternalLinkage);
|
||||
if (optional_ref) LLVMSetLinkage(optional_ref, LLVMExternalLinkage);
|
||||
//LLVMSetVisibility(decl->backend_ref, LLVMDefaultVisibility);
|
||||
break;
|
||||
case VISIBLE_LOCAL:
|
||||
LLVMSetLinkage(global_ref, LLVMInternalLinkage);
|
||||
if (failable_ref) LLVMSetLinkage(failable_ref, LLVMInternalLinkage);
|
||||
if (optional_ref) LLVMSetLinkage(optional_ref, LLVMInternalLinkage);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -928,7 +928,7 @@ void llvm_add_global_decl(GenContext *c, Decl *decl)
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl_get_extname(decl));
|
||||
scratch_buffer_append(".f");
|
||||
decl->var.failable_ref = llvm_add_global(c, scratch_buffer_to_string(), type_anyerr, 0);
|
||||
decl->var.optional_ref = llvm_add_global(c, scratch_buffer_to_string(), type_anyerr, 0);
|
||||
}
|
||||
llvm_set_global_tls(decl);
|
||||
}
|
||||
@@ -938,7 +938,7 @@ LLVMValueRef llvm_get_opt_ref(GenContext *c, Decl *decl)
|
||||
llvm_get_ref(c, decl);
|
||||
decl = decl_flatten(decl);
|
||||
if (decl->decl_kind != DECL_VAR) return NULL;
|
||||
return decl->var.failable_ref;
|
||||
return decl->var.optional_ref;
|
||||
}
|
||||
|
||||
LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl)
|
||||
|
||||
@@ -290,7 +290,7 @@ void c_abi_func_create_riscv(FunctionPrototype *prototype)
|
||||
unsigned arg_gprs_left = is_ret_indirect ? gpr - 1 : gpr;
|
||||
unsigned arg_fprs_left = platform_target.riscv.flen ? fpr : 0;
|
||||
|
||||
// If we have a failable, then the return type is a parameter.
|
||||
// If we have an optional, then the return type is a parameter.
|
||||
if (prototype->ret_by_ref)
|
||||
{
|
||||
prototype->ret_by_ref_abi_info = riscv_classify_argument_type(type_get_ptr(type_lowering(prototype->ret_by_ref_type)),
|
||||
|
||||
@@ -389,7 +389,7 @@ static void x64_classify(Type *type, ByteSize offset_base, X64Class *lo_class, X
|
||||
case TYPE_FAULTTYPE:
|
||||
case TYPE_BITSTRUCT:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case CT_TYPES:
|
||||
UNREACHABLE
|
||||
case TYPE_VOID:
|
||||
@@ -584,7 +584,7 @@ AbiType x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_typ
|
||||
case TYPE_FAULTTYPE:
|
||||
case TYPE_BITSTRUCT:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case CT_TYPES:
|
||||
UNREACHABLE
|
||||
case TYPE_I128:
|
||||
|
||||
@@ -122,7 +122,7 @@ static bool x86_should_return_type_in_reg(Type *type)
|
||||
case TYPE_BITSTRUCT:
|
||||
case CT_TYPES:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
UNREACHABLE
|
||||
case TYPE_SCALED_VECTOR:
|
||||
@@ -589,7 +589,7 @@ static ABIArgInfo *x86_classify_argument(CallABI call, Regs *regs, Type *type)
|
||||
case TYPE_TYPEID:
|
||||
case TYPE_BITSTRUCT:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case CT_TYPES:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
UNREACHABLE
|
||||
@@ -663,7 +663,7 @@ void c_abi_func_create_x86(FunctionPrototype *prototype)
|
||||
regs.int_regs = 3;
|
||||
}
|
||||
|
||||
// 4. Classify the return type. In the case of failable, we need to classify the failable itself as the
|
||||
// 4. Classify the return type. In the case of optional, we need to classify the optional itself as the
|
||||
// return type.
|
||||
prototype->ret_abi_info = x86_classify_return(prototype->call_abi, ®s, prototype->abi_ret_type);
|
||||
if (prototype->ret_by_ref)
|
||||
|
||||
@@ -535,7 +535,7 @@ static inline LLVMMetadataRef llvm_get_debug_type_internal(GenContext *c, Type *
|
||||
case CT_TYPES:
|
||||
UNREACHABLE
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
// If this is reachable then we're not doing the proper lowering.
|
||||
UNREACHABLE
|
||||
case TYPE_BOOL:
|
||||
|
||||
@@ -20,7 +20,7 @@ static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Ex
|
||||
static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr);
|
||||
static inline void llvm_emit_elvis_expr(GenContext *c, BEValue *value, Expr *expr);
|
||||
static inline void llvm_emit_expr_block(GenContext *context, BEValue *be_value, Expr *expr);
|
||||
static inline void llvm_emit_failable(GenContext *c, BEValue *be_value, Expr *expr);
|
||||
static inline void llvm_emit_optional(GenContext *c, BEValue *be_value, Expr *expr);
|
||||
static inline void llvm_emit_inc_dec_change(GenContext *c, BEValue *addr, BEValue *after, BEValue *before, Expr *expr,
|
||||
int diff);
|
||||
static inline void llvm_emit_initialize_reference(GenContext *c, BEValue *ref, Expr *expr);
|
||||
@@ -72,13 +72,13 @@ static inline LLVMValueRef llvm_emit_exprid_to_rvalue(GenContext *c, ExprId expr
|
||||
return value.value;
|
||||
}
|
||||
|
||||
BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef failable)
|
||||
BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef optional)
|
||||
{
|
||||
assert(ref->kind == BE_ADDRESS || ref->kind == BE_ADDRESS_FAILABLE);
|
||||
assert(ref->kind == BE_ADDRESS || ref->kind == BE_ADDRESS_OPTIONAL);
|
||||
|
||||
assert(failable || !IS_OPTIONAL(expr));
|
||||
// Special optimization of handling of failable
|
||||
if (expr->expr_kind == EXPR_FAILABLE)
|
||||
assert(optional || !IS_OPTIONAL(expr));
|
||||
// Special optimization of handling of optional
|
||||
if (expr->expr_kind == EXPR_OPTIONAL)
|
||||
{
|
||||
PUSH_OPT();
|
||||
|
||||
@@ -88,8 +88,8 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue
|
||||
// Emit the fault type.
|
||||
llvm_emit_expr(c, &result, expr->inner_expr);
|
||||
LLVMValueRef err_val = result.value;
|
||||
// Store it in the failable
|
||||
llvm_store_to_ptr(c, failable, &result);
|
||||
// Store it in the optional
|
||||
llvm_store_to_ptr(c, optional, &result);
|
||||
// Set the result to an undef value
|
||||
llvm_value_set(&result, llvm_get_undef(c, ref->type), ref->type);
|
||||
|
||||
@@ -111,7 +111,7 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue
|
||||
if (IS_OPTIONAL(expr))
|
||||
{
|
||||
assign_block = llvm_basic_block_new(c, "after_assign");
|
||||
assert(failable);
|
||||
assert(optional);
|
||||
if (c->opt_var)
|
||||
{
|
||||
c->catch_block = rejump_block = llvm_basic_block_new(c, "optional_assign_jump");
|
||||
@@ -120,7 +120,7 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue
|
||||
{
|
||||
c->catch_block = assign_block;
|
||||
}
|
||||
c->opt_var = failable;
|
||||
c->opt_var = optional;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -157,9 +157,9 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue
|
||||
if (value.type != type_void) llvm_store(c, ref, &value);
|
||||
}
|
||||
|
||||
if (failable)
|
||||
if (optional)
|
||||
{
|
||||
llvm_store_to_ptr_raw(c, failable, llvm_get_zero(c, type_anyerr), type_anyerr);
|
||||
llvm_store_to_ptr_raw(c, optional, llvm_get_zero(c, type_anyerr), type_anyerr);
|
||||
}
|
||||
POP_OPT();
|
||||
|
||||
@@ -169,7 +169,7 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue
|
||||
if (rejump_block)
|
||||
{
|
||||
llvm_emit_block(c, rejump_block);
|
||||
LLVMValueRef error = llvm_load_natural_alignment(c, type_anyerr, failable, "reload_err");
|
||||
LLVMValueRef error = llvm_load_natural_alignment(c, type_anyerr, optional, "reload_err");
|
||||
llvm_store_to_ptr_raw(c, c->opt_var, error, type_anyerr);
|
||||
llvm_emit_br(c, c->catch_block);
|
||||
}
|
||||
@@ -2568,7 +2568,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
|
||||
LLVMValueRef parent_addr = parent_addr_x.value;
|
||||
LLVMValueRef parent_load_value = NULL;
|
||||
LLVMValueRef parent_base;
|
||||
bool is_failable = type_is_optional(parent_type);
|
||||
bool is_optional = type_is_optional(parent_type);
|
||||
parent_type = type_no_optional(parent_type);
|
||||
switch (parent_type->type_kind)
|
||||
{
|
||||
@@ -3803,7 +3803,7 @@ static inline void llvm_emit_catch_expr(GenContext *c, BEValue *value, Expr *exp
|
||||
return;
|
||||
}
|
||||
|
||||
if (inner->expr_kind == EXPR_FAILABLE)
|
||||
if (inner->expr_kind == EXPR_OPTIONAL)
|
||||
{
|
||||
llvm_emit_expr(c, value, inner->inner_expr);
|
||||
return;
|
||||
@@ -3895,7 +3895,7 @@ static inline void llvm_emit_rethrow_expr(GenContext *c, BEValue *be_value, Expr
|
||||
c->catch_block = guard_block;
|
||||
|
||||
llvm_emit_expr(c, be_value, expr->rethrow_expr.inner);
|
||||
// Fold the failable.
|
||||
// Fold the optional.
|
||||
llvm_value_fold_optional(c, be_value);
|
||||
|
||||
// Restore.
|
||||
@@ -4032,13 +4032,13 @@ static void llvm_emit_binary_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
Expr *left = exprptr(expr->binary_expr.left);
|
||||
llvm_emit_expr(c, be_value, left);
|
||||
assert(llvm_value_is_addr(be_value));
|
||||
LLVMValueRef failable_ref = NULL;
|
||||
LLVMValueRef optional_ref = NULL;
|
||||
if (left->expr_kind == EXPR_IDENTIFIER)
|
||||
{
|
||||
failable_ref = decl_optional_ref(left->identifier_expr.decl);
|
||||
optional_ref = decl_optional_ref(left->identifier_expr.decl);
|
||||
be_value->kind = BE_ADDRESS;
|
||||
}
|
||||
*be_value = llvm_emit_assign_expr(c, be_value, exprptr(expr->binary_expr.right), failable_ref);
|
||||
*be_value = llvm_emit_assign_expr(c, be_value, exprptr(expr->binary_expr.right), optional_ref);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4453,7 +4453,7 @@ static void llvm_expand_type_to_args(GenContext *context, Type *param_type, LLVM
|
||||
case TYPE_BITSTRUCT:
|
||||
case TYPE_OPTIONAL:
|
||||
case CT_TYPES:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_SCALED_VECTOR:
|
||||
UNREACHABLE
|
||||
@@ -4909,8 +4909,8 @@ void llvm_emit_raw_call(GenContext *c, BEValue *result_value, FunctionPrototype
|
||||
UNREACHABLE
|
||||
case ABI_ARG_IGNORE:
|
||||
// 12. Basically void returns or empty structs.
|
||||
// Here we know we don't have a failable or any return value that can be used.
|
||||
assert(!prototype->is_failable && "Failable should have produced a return value.");
|
||||
// Here we know we don't have an optional or any return value that can be used.
|
||||
assert(!prototype->is_optional && "Optional should have produced a return value.");
|
||||
*result_value = (BEValue) { .type = type_void, .kind = BE_VALUE };
|
||||
return;
|
||||
case ABI_ARG_INDIRECT:
|
||||
@@ -5028,13 +5028,13 @@ void llvm_emit_raw_call(GenContext *c, BEValue *result_value, FunctionPrototype
|
||||
}
|
||||
}
|
||||
|
||||
// 17. Handle failables.
|
||||
// 17. Handle optionals.
|
||||
if (sret_return)
|
||||
{
|
||||
*result_value = (BEValue) { .type = type_void, .kind = BE_VALUE };
|
||||
return;
|
||||
}
|
||||
if (prototype->is_failable)
|
||||
if (prototype->is_optional)
|
||||
{
|
||||
BEValue no_err;
|
||||
|
||||
@@ -5191,7 +5191,7 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
ABIArgInfo *ret_info = prototype->ret_abi_info;
|
||||
Type *call_return_type = prototype->abi_ret_type;
|
||||
|
||||
// 5. In the case of a failable, the error is replacing the regular return abi.
|
||||
// 5. In the case of an optional, the error is replacing the regular return abi.
|
||||
LLVMValueRef error_var = NULL;
|
||||
|
||||
*result_value = (BEValue){ .kind = BE_VALUE, .value = NULL };
|
||||
@@ -5201,7 +5201,7 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
{
|
||||
case ABI_ARG_INDIRECT:
|
||||
// 6a. We can use the stored error var if there is no redirect.
|
||||
if (prototype->is_failable && c->opt_var && !ret_info->attributes.realign)
|
||||
if (prototype->is_optional && c->opt_var && !ret_info->attributes.realign)
|
||||
{
|
||||
error_var = c->opt_var;
|
||||
arg_values[arg_count++] = error_var;
|
||||
@@ -5239,7 +5239,7 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
}
|
||||
|
||||
|
||||
// 7. We might have a failable indirect return and a normal return.
|
||||
// 7. We might have an optional indirect return and a normal return.
|
||||
// In this case we need to add it by hand.
|
||||
BEValue synthetic_return_param = { 0 };
|
||||
if (prototype->ret_by_ref)
|
||||
@@ -5365,7 +5365,7 @@ static inline void llvm_emit_return_block(GenContext *c, BEValue *be_value, Type
|
||||
|
||||
BlockExit exit = {
|
||||
.block_return_exit = expr_block,
|
||||
.block_failable_exit = error_block,
|
||||
.block_optional_exit = error_block,
|
||||
.block_error_var = error_out,
|
||||
.block_return_out = NULL,
|
||||
};
|
||||
@@ -5410,7 +5410,7 @@ static inline void llvm_emit_return_block(GenContext *c, BEValue *be_value, Type
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
// Failable? Then we use the normal path
|
||||
// Optional? Then we use the normal path
|
||||
if (IS_OPTIONAL(ret_expr)) break;
|
||||
|
||||
// Optimization, emit directly to value
|
||||
@@ -5510,7 +5510,7 @@ LLVMValueRef llvm_emit_call_intrinsic(GenContext *context, unsigned intrinsic, L
|
||||
return LLVMBuildCall2(context->builder, type, decl, values, arg_count, "");
|
||||
}
|
||||
|
||||
static inline void llvm_emit_failable(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
static inline void llvm_emit_optional(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
{
|
||||
Expr *fail = expr->inner_expr;
|
||||
// If there is an error value, assign to it.
|
||||
@@ -5637,7 +5637,7 @@ static void llvm_emit_macro_body_expansion(GenContext *c, BEValue *value, Expr *
|
||||
|
||||
static inline void llvm_emit_try_unwrap(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
if (!expr->try_unwrap_expr.failable)
|
||||
if (!expr->try_unwrap_expr.optional)
|
||||
{
|
||||
LLVMValueRef fail_ref = decl_optional_ref(expr->try_unwrap_expr.decl);
|
||||
LLVMValueRef errv = llvm_load(c, llvm_get_type(c, type_anyerr), fail_ref, type_abi_alignment(type_anyerr), "load.err");
|
||||
@@ -5656,7 +5656,7 @@ static inline void llvm_emit_try_unwrap(GenContext *c, BEValue *value, Expr *exp
|
||||
llvm_value_set_decl_address(c, &addr, expr->try_unwrap_expr.decl);
|
||||
}
|
||||
assert(llvm_value_is_addr(&addr));
|
||||
llvm_emit_try_assign_try_catch(c, true, value, &addr, NULL, expr->try_unwrap_expr.failable);
|
||||
llvm_emit_try_assign_try_catch(c, true, value, &addr, NULL, expr->try_unwrap_expr.optional);
|
||||
}
|
||||
|
||||
void llvm_emit_catch_unwrap(GenContext *c, BEValue *value, Expr *expr)
|
||||
@@ -5729,9 +5729,9 @@ static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *ex
|
||||
BEValue check;
|
||||
LLVMBasicBlockRef exit = llvm_basic_block_new(c, "check_type_ok");
|
||||
IntrospectType checks[8] = { INTROSPECT_TYPE_ARRAY, INTROSPECT_TYPE_POINTER,
|
||||
INTROSPECT_TYPE_VECTOR, INTROSPECT_TYPE_ENUM,
|
||||
INTROSPECT_TYPE_SUBARRAY, INTROSPECT_TYPE_DISTINCT,
|
||||
INTROSPECT_TYPE_FAILABLE, INTROSPECT_TYPE_SUBARRAY };
|
||||
INTROSPECT_TYPE_VECTOR, INTROSPECT_TYPE_ENUM,
|
||||
INTROSPECT_TYPE_SUBARRAY, INTROSPECT_TYPE_DISTINCT,
|
||||
INTROSPECT_TYPE_OPTIONAL, INTROSPECT_TYPE_SUBARRAY };
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
llvm_emit_int_comp_raw(c,
|
||||
@@ -6155,8 +6155,8 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
case EXPR_POINTER_OFFSET:
|
||||
llvm_emit_pointer_offset(c, value, expr);
|
||||
return;
|
||||
case EXPR_FAILABLE:
|
||||
llvm_emit_failable(c, value, expr);
|
||||
case EXPR_OPTIONAL:
|
||||
llvm_emit_optional(c, value, expr);
|
||||
return;
|
||||
case EXPR_TRY:
|
||||
llvm_emit_try_expr(c, value, expr);
|
||||
|
||||
@@ -273,7 +273,7 @@ static inline void llvm_emit_return_value(GenContext *context, LLVMValueRef valu
|
||||
}
|
||||
|
||||
|
||||
void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *failable)
|
||||
void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *optional)
|
||||
{
|
||||
FunctionPrototype *prototype = c->cur_func.prototype;
|
||||
|
||||
@@ -286,27 +286,27 @@ void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *failabl
|
||||
|
||||
ABIArgInfo *info = prototype->ret_abi_info;
|
||||
|
||||
// If we have a failable it's always the return argument, so we need to copy
|
||||
// If we have an optional it's always the return argument, so we need to copy
|
||||
// the return value into the return value holder.
|
||||
LLVMValueRef return_out = c->return_out;
|
||||
Type *call_return_type = prototype->abi_ret_type;
|
||||
|
||||
BEValue no_fail;
|
||||
|
||||
// In this case we use the failable as the actual return.
|
||||
if (prototype->is_failable)
|
||||
// In this case we use the optional as the actual return.
|
||||
if (prototype->is_optional)
|
||||
{
|
||||
if (return_value && return_value->value)
|
||||
{
|
||||
llvm_store_to_ptr_aligned(c, c->return_out, return_value, type_alloca_alignment(return_value->type));
|
||||
}
|
||||
return_out = c->failable_out;
|
||||
if (!failable)
|
||||
return_out = c->optional_out;
|
||||
if (!optional)
|
||||
{
|
||||
llvm_value_set(&no_fail, llvm_get_zero(c, type_anyerr), type_anyerr);
|
||||
failable = &no_fail;
|
||||
optional = &no_fail;
|
||||
}
|
||||
return_value = failable;
|
||||
return_value = optional;
|
||||
}
|
||||
assert(return_value || info->kind == ABI_ARG_IGNORE);
|
||||
|
||||
@@ -514,13 +514,13 @@ void llvm_emit_body(GenContext *c, LLVMValueRef function, const char *module_nam
|
||||
}
|
||||
}
|
||||
|
||||
c->failable_out = NULL;
|
||||
c->optional_out = NULL;
|
||||
c->return_out = NULL;
|
||||
if (prototype && prototype->ret_abi_info->kind == ABI_ARG_INDIRECT)
|
||||
{
|
||||
if (prototype->is_failable)
|
||||
if (prototype->is_optional)
|
||||
{
|
||||
c->failable_out = LLVMGetParam(c->function, arg++);
|
||||
c->optional_out = LLVMGetParam(c->function, arg++);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ typedef enum
|
||||
{
|
||||
BE_VALUE,
|
||||
BE_ADDRESS,
|
||||
BE_ADDRESS_FAILABLE,
|
||||
BE_ADDRESS_OPTIONAL,
|
||||
BE_BOOLEAN,
|
||||
BE_BOOLVECTOR,
|
||||
} BackendValueKind;
|
||||
@@ -31,7 +31,7 @@ typedef struct
|
||||
AlignSize alignment;
|
||||
Type *type; // Should never be a distinct or canonical type.
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef failable;
|
||||
LLVMValueRef optional;
|
||||
} BEValue;
|
||||
|
||||
typedef struct
|
||||
@@ -105,7 +105,7 @@ typedef struct GenContext_
|
||||
DebugContext debug;
|
||||
Module *code_module;
|
||||
LLVMValueRef return_out;
|
||||
LLVMValueRef failable_out;
|
||||
LLVMValueRef optional_out;
|
||||
BEValue retval;
|
||||
int in_block;
|
||||
bool current_block_is_target : 1;
|
||||
@@ -245,7 +245,7 @@ static inline LLVMValueRef decl_optional_ref(Decl *decl)
|
||||
assert(decl->decl_kind == DECL_VAR);
|
||||
if (decl->var.kind == VARDECL_UNWRAPPED) return decl_optional_ref(decl->var.alias);
|
||||
if (decl->type->type_kind != TYPE_OPTIONAL) return NULL;
|
||||
return decl->var.failable_ref;
|
||||
return decl->var.optional_ref;
|
||||
}
|
||||
|
||||
INLINE bool llvm_is_global_eval(GenContext *c);
|
||||
@@ -254,7 +254,7 @@ INLINE bool llvm_is_local_eval(GenContext *c);
|
||||
|
||||
// -- BE value --
|
||||
void llvm_value_addr(GenContext *c, BEValue *value);
|
||||
static inline bool llvm_value_is_addr(BEValue *value) { return value->kind == BE_ADDRESS || value->kind == BE_ADDRESS_FAILABLE; }
|
||||
static inline bool llvm_value_is_addr(BEValue *value) { return value->kind == BE_ADDRESS || value->kind == BE_ADDRESS_OPTIONAL; }
|
||||
static inline bool llvm_value_is_bool(BEValue *value) { return value->kind == BE_BOOLEAN; }
|
||||
bool llvm_value_is_const(BEValue *value);
|
||||
void llvm_value_rvalue(GenContext *context, BEValue *value);
|
||||
@@ -351,7 +351,7 @@ void llvm_emit_cond_br(GenContext *context, BEValue *value, LLVMBasicBlockRef th
|
||||
void llvm_emit_cond_br_raw(GenContext *context, LLVMValueRef b, LLVMBasicBlockRef then_block, LLVMBasicBlockRef else_block);
|
||||
void llvm_emit_br(GenContext *c, LLVMBasicBlockRef next_block);
|
||||
void llvm_emit_jump_to_optional_exit(GenContext *c, LLVMValueRef opt_value);
|
||||
void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *failable);
|
||||
void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *optional);
|
||||
void llvm_emit_return_implicit(GenContext *c);
|
||||
|
||||
// -- Blocks --
|
||||
@@ -443,7 +443,7 @@ void llvm_emit_subarray_pointer(GenContext *context, BEValue *subarray, BEValue
|
||||
void llvm_emit_compound_stmt(GenContext *c, Ast *ast);
|
||||
LLVMValueRef llvm_emit_const_bitstruct(GenContext *c, ConstInitializer *initializer);
|
||||
void llvm_emit_function_body(GenContext *context, Decl *decl);
|
||||
BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef failable);
|
||||
BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef optional);
|
||||
INLINE void llvm_emit_exprid(GenContext *c, BEValue *value, ExprId expr);
|
||||
INLINE void llvm_emit_statement_chain(GenContext *c, AstId current);
|
||||
void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, Expr *expr);
|
||||
|
||||
@@ -51,7 +51,7 @@ void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value)
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl->extname);
|
||||
scratch_buffer_append("$f");
|
||||
decl->var.failable_ref = llvm_add_global(c, scratch_buffer_to_string(), type_anyerr, 0);
|
||||
decl->var.optional_ref = llvm_add_global(c, scratch_buffer_to_string(), type_anyerr, 0);
|
||||
}
|
||||
llvm_emit_global_variable_init(c, decl);
|
||||
c->builder = builder;
|
||||
@@ -61,36 +61,36 @@ void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value)
|
||||
assert(!decl->backend_ref);
|
||||
llvm_emit_local_var_alloca(c, decl);
|
||||
Expr *init = decl->var.init_expr;
|
||||
bool is_failable = IS_OPTIONAL(decl);
|
||||
if (is_failable)
|
||||
bool is_optional = IS_OPTIONAL(decl);
|
||||
if (is_optional)
|
||||
{
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(decl->name);
|
||||
scratch_buffer_append(".f");
|
||||
decl->var.failable_ref = llvm_emit_alloca_aligned(c, type_anyerr, scratch_buffer_to_string());
|
||||
// Only clear out the result if the assignment isn't a failable.
|
||||
decl->var.optional_ref = llvm_emit_alloca_aligned(c, type_anyerr, scratch_buffer_to_string());
|
||||
// Only clear out the result if the assignment isn't an optional.
|
||||
}
|
||||
|
||||
if (init)
|
||||
{
|
||||
llvm_value_set_decl_address(c, value, decl);
|
||||
value->kind = BE_ADDRESS;
|
||||
BEValue res = llvm_emit_assign_expr(c, value, decl->var.init_expr, decl->var.failable_ref);
|
||||
if (!is_failable) *value = res;
|
||||
BEValue res = llvm_emit_assign_expr(c, value, decl->var.init_expr, decl->var.optional_ref);
|
||||
if (!is_optional) *value = res;
|
||||
}
|
||||
else if (decl->var.no_init)
|
||||
{
|
||||
llvm_value_set(value, LLVMGetUndef(alloc_type), decl->type);
|
||||
if (decl->var.failable_ref)
|
||||
if (decl->var.optional_ref)
|
||||
{
|
||||
llvm_store_to_ptr_raw(c, decl->var.failable_ref, llvm_get_undef(c, type_anyerr), type_anyerr);
|
||||
llvm_store_to_ptr_raw(c, decl->var.optional_ref, llvm_get_undef(c, type_anyerr), type_anyerr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (decl->var.failable_ref)
|
||||
if (decl->var.optional_ref)
|
||||
{
|
||||
llvm_store_to_ptr_zero(c, decl->var.failable_ref, type_anyerr);
|
||||
llvm_store_to_ptr_zero(c, decl->var.optional_ref, type_anyerr);
|
||||
}
|
||||
|
||||
Type *type = type_lowering(decl->type);
|
||||
@@ -170,7 +170,7 @@ static inline void llvm_emit_return(GenContext *c, Ast *ast)
|
||||
PUSH_OPT();
|
||||
|
||||
Expr *expr = ast->return_stmt.expr;
|
||||
if (expr && expr->expr_kind == EXPR_FAILABLE)
|
||||
if (expr && expr->expr_kind == EXPR_OPTIONAL)
|
||||
{
|
||||
BEValue be_value;
|
||||
llvm_emit_expr(c, &be_value, expr->inner_expr);
|
||||
@@ -234,7 +234,7 @@ static inline void llvm_emit_block_exit_return(GenContext *c, Ast *ast)
|
||||
LLVMValueRef error_out = NULL;
|
||||
BlockExit *exit = *ast->return_stmt.block_exit_ref;
|
||||
c->opt_var = exit->block_error_var;
|
||||
c->catch_block = exit->block_failable_exit;
|
||||
c->catch_block = exit->block_optional_exit;
|
||||
|
||||
LLVMBasicBlockRef err_cleanup_block = NULL;
|
||||
Expr *ret_expr = ast->return_stmt.expr;
|
||||
@@ -267,7 +267,7 @@ static inline void llvm_emit_block_exit_return(GenContext *c, Ast *ast)
|
||||
llvm_emit_br(c, exit->block_return_exit);
|
||||
llvm_emit_block(c, err_cleanup_block);
|
||||
llvm_emit_statement_chain(c, err_cleanup);
|
||||
llvm_emit_jmp(c, exit->block_failable_exit);
|
||||
llvm_emit_jmp(c, exit->block_optional_exit);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ LLVMValueRef llvm_store_to_ptr_aligned(GenContext *c, LLVMValueRef destination,
|
||||
FALLTHROUGH;
|
||||
case BE_VALUE:
|
||||
return llvm_store_to_ptr_raw_aligned(c, destination, value->value, alignment);
|
||||
case BE_ADDRESS_FAILABLE:
|
||||
case BE_ADDRESS_OPTIONAL:
|
||||
UNREACHABLE
|
||||
case BE_ADDRESS:
|
||||
{
|
||||
@@ -93,7 +93,7 @@ LLVMValueRef llvm_load_value(GenContext *c, BEValue *value)
|
||||
case BE_BOOLEAN:
|
||||
case BE_VALUE:
|
||||
return value->value;
|
||||
case BE_ADDRESS_FAILABLE:
|
||||
case BE_ADDRESS_OPTIONAL:
|
||||
UNREACHABLE
|
||||
case BE_ADDRESS:
|
||||
return llvm_load(c, llvm_get_type(c, value->type), value->value, value->alignment, "");
|
||||
|
||||
@@ -279,7 +279,7 @@ LLVMTypeRef llvm_update_prototype_abi(GenContext *context, FunctionPrototype *pr
|
||||
break;
|
||||
}
|
||||
|
||||
// If it's failable and it's not void (meaning ret_abi_info will be NULL)
|
||||
// If it's optional and it's not void (meaning ret_abi_info will be NULL)
|
||||
if (prototype->ret_by_ref)
|
||||
{
|
||||
add_func_type_param(context, type_get_ptr(type_lowering(prototype->ret_by_ref_type)), prototype->ret_by_ref_abi_info, params);
|
||||
@@ -345,7 +345,7 @@ LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type)
|
||||
case CT_TYPES:
|
||||
UNREACHABLE
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_DISTINCT:
|
||||
case TYPE_ENUM:
|
||||
@@ -686,7 +686,7 @@ LLVMValueRef llvm_get_typeid(GenContext *c, Type *type)
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_OPTIONAL:
|
||||
return llvm_generate_introspection_global(c, NULL, type, INTROSPECT_TYPE_FAILABLE, type->failable, 0, NULL, false);
|
||||
return llvm_generate_introspection_global(c, NULL, type, INTROSPECT_TYPE_OPTIONAL, type->optional, 0, NULL, false);
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return llvm_generate_introspection_global(c, NULL, type, INTROSPECT_TYPE_ARRAY, type->array.base, 0, NULL, false);
|
||||
case TYPE_VECTOR:
|
||||
@@ -723,7 +723,7 @@ LLVMValueRef llvm_get_typeid(GenContext *c, Type *type)
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_MEMBER:
|
||||
UNREACHABLE
|
||||
|
||||
@@ -142,9 +142,9 @@ void llvm_emit_jump_to_optional_exit(GenContext *c, LLVMValueRef opt_value)
|
||||
|
||||
void llvm_value_fold_optional(GenContext *c, BEValue *value)
|
||||
{
|
||||
if (value->kind == BE_ADDRESS_FAILABLE)
|
||||
if (value->kind == BE_ADDRESS_OPTIONAL)
|
||||
{
|
||||
llvm_emit_jump_to_optional_exit(c, llvm_load_natural_alignment(c, type_anyerr, value->failable, "optval"));
|
||||
llvm_emit_jump_to_optional_exit(c, llvm_load_natural_alignment(c, type_anyerr, value->optional, "optval"));
|
||||
value->kind = BE_ADDRESS;
|
||||
}
|
||||
}
|
||||
@@ -154,8 +154,8 @@ void llvm_value_set_decl_address(GenContext *c, BEValue *value, Decl *decl)
|
||||
LLVMValueRef backend_ref = llvm_get_ref(c, decl);
|
||||
llvm_value_set_address(value, backend_ref, decl->type, decl->alignment);
|
||||
|
||||
if ((value->failable = llvm_get_opt_ref(c, decl)))
|
||||
if ((value->optional = llvm_get_opt_ref(c, decl)))
|
||||
{
|
||||
value->kind = BE_ADDRESS_FAILABLE;
|
||||
value->kind = BE_ADDRESS_OPTIONAL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,13 +671,13 @@ Expr *parse_initializer_list(ParseContext *c, Expr *left)
|
||||
return initializer_list;
|
||||
}
|
||||
|
||||
static Expr *parse_failable(ParseContext *c, Expr *left_side)
|
||||
static Expr *parse_optional(ParseContext *c, Expr *left_side)
|
||||
{
|
||||
Expr *failable = expr_new(EXPR_FAILABLE, left_side->span);
|
||||
Expr *optional = expr_new(EXPR_OPTIONAL, left_side->span);
|
||||
advance_and_verify(c, TOKEN_BANG);
|
||||
failable->inner_expr = left_side;
|
||||
RANGE_EXTEND_PREV(failable);
|
||||
return failable;
|
||||
optional->inner_expr = left_side;
|
||||
RANGE_EXTEND_PREV(optional);
|
||||
return optional;
|
||||
}
|
||||
|
||||
|
||||
@@ -881,7 +881,7 @@ static Expr *parse_ct_sizeof(ParseContext *c, Expr *left)
|
||||
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr);
|
||||
Expr *typeof_expr = expr_new(EXPR_TYPEINFO, inner->span);
|
||||
TypeInfo *type_info = type_info_new(TYPE_INFO_TYPEOF, inner->span);
|
||||
type_info->failable = try_consume(c, TOKEN_BANG);
|
||||
type_info->optional = try_consume(c, TOKEN_BANG);
|
||||
type_info->unresolved_type_expr = inner;
|
||||
typeof_expr->type_expr = type_info;
|
||||
access->access_expr.parent = typeof_expr;
|
||||
@@ -1626,7 +1626,7 @@ Expr *parse_type_expression_with_path(ParseContext *c, Path *path)
|
||||
advance_and_verify(c, TOKEN_TYPE_IDENT);
|
||||
RANGE_EXTEND_PREV(type);
|
||||
ASSIGN_TYPE_OR_RET(type, parse_type_with_base(c, type), poisoned_expr);
|
||||
type->failable = try_consume(c, TOKEN_BANG);
|
||||
type->optional = try_consume(c, TOKEN_BANG);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1716,7 +1716,7 @@ ParseRule rules[TOKEN_EOF + 1] = {
|
||||
[TOKEN_MOD] = { NULL, parse_binary, PREC_MULTIPLICATIVE },
|
||||
[TOKEN_STAR] = { parse_unary_expr, parse_binary, PREC_MULTIPLICATIVE },
|
||||
[TOKEN_DOT] = { NULL, parse_access_expr, PREC_CALL },
|
||||
[TOKEN_BANG] = { parse_unary_expr, parse_failable, PREC_CALL },
|
||||
[TOKEN_BANG] = { parse_unary_expr, parse_optional, PREC_CALL },
|
||||
[TOKEN_BYTES] = { parse_bytes_expr, NULL, PREC_NONE },
|
||||
[TOKEN_BIT_NOT] = { parse_unary_expr, NULL, PREC_UNARY },
|
||||
[TOKEN_BIT_XOR] = { NULL, parse_binary, PREC_BIT },
|
||||
|
||||
@@ -757,8 +757,8 @@ TypeInfo *parse_optional_type(ParseContext *c)
|
||||
ASSIGN_TYPE_OR_RET(info, parse_type_with_base(c, info), poisoned_type_info);
|
||||
if (try_consume(c, TOKEN_BANG))
|
||||
{
|
||||
assert(!info->failable);
|
||||
info->failable = true;
|
||||
assert(!info->optional);
|
||||
info->optional = true;
|
||||
if (info->resolve_status == RESOLVE_DONE)
|
||||
{
|
||||
info->type = type_get_optional(info->type);
|
||||
@@ -822,9 +822,9 @@ Decl *parse_decl(ParseContext *c)
|
||||
ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), poisoned_decl);
|
||||
|
||||
ASSIGN_DECL_OR_RET(Decl * decl, parse_decl_after_type(c, type), poisoned_decl);
|
||||
if (type->failable && decl->var.unwrap)
|
||||
if (type->optional && decl->var.unwrap)
|
||||
{
|
||||
SEMA_ERROR(decl, "You cannot use unwrap with a failable variable.");
|
||||
SEMA_ERROR(decl, "You cannot use unwrap with an optional variable.");
|
||||
return poisoned_decl;
|
||||
}
|
||||
decl->var.is_static = is_static || is_threadlocal;
|
||||
@@ -1035,9 +1035,9 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref)
|
||||
|
||||
/**
|
||||
* global_declaration
|
||||
* : global? failable_type IDENT ';'
|
||||
* | global? failable_type IDENT '=' expression ';'
|
||||
* | global? failable_type func_definition
|
||||
* : global? optional_type IDENT ';'
|
||||
* | global? optional_type IDENT '=' expression ';'
|
||||
* | global? optional_type func_definition
|
||||
* ;
|
||||
*
|
||||
* @param visibility
|
||||
@@ -1088,7 +1088,7 @@ static inline Decl *parse_global_declaration(ParseContext *c, Visibility visibil
|
||||
static inline bool parse_param_decl(ParseContext *c, Visibility parent_visibility, Decl*** parameters, bool require_name)
|
||||
{
|
||||
ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), false);
|
||||
if (type->failable)
|
||||
if (type->optional)
|
||||
{
|
||||
SEMA_ERROR(type, "Parameters may not be optional.");
|
||||
return false;
|
||||
@@ -1336,7 +1336,7 @@ bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref
|
||||
SEMA_ERROR_HERE("Expected a parameter.");
|
||||
return false;
|
||||
}
|
||||
if (type && type->failable)
|
||||
if (type && type->optional)
|
||||
{
|
||||
SEMA_ERROR(type, "Parameters may not be optional.");
|
||||
return false;
|
||||
@@ -1673,7 +1673,7 @@ static inline Expr **parse_generic_parameters(ParseContext *c)
|
||||
/**
|
||||
* define_type_body ::= TYPE_IDENT '=' 'distinct'? (func_typedef | type generic_params?) ';'
|
||||
*
|
||||
* func_typedef ::= 'fn' failable_type parameter_type_list
|
||||
* func_typedef ::= 'fn' optional_type parameter_type_list
|
||||
*/
|
||||
static inline Decl *parse_define_type(ParseContext *c, Visibility visibility)
|
||||
{
|
||||
@@ -1924,8 +1924,8 @@ static inline bool parse_func_macro_header(ParseContext *c, Decl *decl)
|
||||
// 5a. What if we don't have a method type?
|
||||
if (!method_type)
|
||||
{
|
||||
// 5b. If the rtype is not optional or the return type was a failable, then this is an error.
|
||||
if (!is_macro || rtype->failable)
|
||||
// 5b. If the rtype is not optional or the return type was an optional, then this is an error.
|
||||
if (!is_macro || rtype->optional)
|
||||
{
|
||||
SEMA_ERROR_LAST("This looks like you are declaring a method without a return type?");
|
||||
return false;
|
||||
@@ -2167,7 +2167,7 @@ static inline Decl *parse_enum_declaration(ParseContext *c, Visibility visibilit
|
||||
* ;
|
||||
*
|
||||
* func_declaration
|
||||
* : FN failable_type func_name '(' opt_parameter_type_list ')' opt_attributes
|
||||
* : FN optional_type func_name '(' opt_parameter_type_list ')' opt_attributes
|
||||
* ;
|
||||
*
|
||||
* @param visibility
|
||||
|
||||
@@ -410,8 +410,8 @@ static inline Ast* parse_while_stmt(ParseContext *c)
|
||||
|
||||
/**
|
||||
* if_expr
|
||||
* : failable_type IDENT '=' initializer
|
||||
* | failable_type IDENT NOFAIL_ASSIGN expression
|
||||
* : optional_type IDENT '=' initializer
|
||||
* | optional_type IDENT NOFAIL_ASSIGN expression
|
||||
* | expression
|
||||
* ;
|
||||
*
|
||||
@@ -625,7 +625,7 @@ static inline bool parse_foreach_var(ParseContext *c, Ast *foreach)
|
||||
{
|
||||
ASSIGN_TYPE_OR_RET(type, parse_optional_type(c), false);
|
||||
|
||||
// Add the failable to the type for nicer error reporting.
|
||||
// Add the optional to the type for nicer error reporting.
|
||||
RANGE_EXTEND_PREV(type);
|
||||
}
|
||||
if (try_consume(c, TOKEN_AMP))
|
||||
@@ -769,7 +769,7 @@ static inline Ast *parse_decl_or_expr_stmt(ParseContext *c)
|
||||
ast->span = expr->span;
|
||||
// We might be parsing "int!"
|
||||
// If so we need to unwrap this.
|
||||
if (expr->expr_kind == EXPR_FAILABLE && expr->inner_expr->expr_kind == EXPR_TYPEINFO)
|
||||
if (expr->expr_kind == EXPR_OPTIONAL && expr->inner_expr->expr_kind == EXPR_TYPEINFO)
|
||||
{
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ static inline unsigned builtin_expected_args(BuiltinFunction func);
|
||||
|
||||
static bool sema_check_builtin_args_match(Expr **args, size_t arg_len)
|
||||
{
|
||||
Type *first = args[0]->type->canonical;
|
||||
Type *first = type_no_optional(args[0]->type->canonical);
|
||||
for (size_t i = 1; i < arg_len; i++)
|
||||
{
|
||||
if (first != args[i]->type->canonical)
|
||||
if (first != type_no_optional(args[i]->type->canonical))
|
||||
{
|
||||
SEMA_ERROR(args[i], "Expected an expression of type %s.", type_quoted_error_string(args[0]->type));
|
||||
return false;
|
||||
@@ -167,7 +167,7 @@ static inline bool sema_expr_analyse_shufflevector(SemaContext *context, Expr *e
|
||||
SEMA_ERROR(expr, "Expected 2 or 3 arguments.");
|
||||
return false;
|
||||
}
|
||||
bool failable = false;
|
||||
bool optional = false;
|
||||
Expr *mask = args[arg_count - 1];
|
||||
unsigned len = 0;
|
||||
if (expr_is_const_initializer(mask))
|
||||
@@ -186,7 +186,7 @@ static inline bool sema_expr_analyse_shufflevector(SemaContext *context, Expr *e
|
||||
for (unsigned i = 0; i < arg_count; i++)
|
||||
{
|
||||
if (!sema_analyse_expr(context, args[i])) return false;
|
||||
failable = failable || type_is_optional(args[i]->type);
|
||||
optional = optional || type_is_optional(args[i]->type);
|
||||
}
|
||||
|
||||
if (!sema_check_builtin_args(args,
|
||||
@@ -231,7 +231,7 @@ static inline bool sema_expr_analyse_shufflevector(SemaContext *context, Expr *e
|
||||
return false;
|
||||
}
|
||||
FOREACH_END();
|
||||
expr->type = type_add_optional(args[0]->type, failable);
|
||||
expr->type = type_add_optional(args[0]->type, optional);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -269,14 +269,14 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
SEMA_ERROR(expr, "Expected at least %d arguments to builtin.\n", expected_args);
|
||||
return false;
|
||||
}
|
||||
bool failable = false;
|
||||
bool optional = false;
|
||||
|
||||
// 2. We can now check all the arguments, since they in general work on the
|
||||
// exact type size, we don't do any forced promotion.
|
||||
for (unsigned i = 0; i < arg_count; i++)
|
||||
{
|
||||
if (!sema_analyse_expr(context, args[i])) return false;
|
||||
failable = failable || type_is_optional(args[i]->type);
|
||||
optional = optional || type_is_optional(args[i]->type);
|
||||
}
|
||||
|
||||
Type *rtype = NULL;
|
||||
@@ -346,7 +346,7 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
(BuiltinArg[]) { BA_INTEGER, BA_INTEGER, BA_POINTER },
|
||||
arg_count)) return false;
|
||||
if (!sema_check_builtin_args_match(args, 2)) return false;
|
||||
if (args[0]->type->canonical != args[2]->type->canonical->pointer)
|
||||
if (type_no_optional(args[0]->type->canonical) != type_no_optional(args[2]->type->canonical->pointer))
|
||||
{
|
||||
SEMA_ERROR(args[2], "Expected %s, not %s.", type_to_error_string(type_get_ptr(args[0]->type)),
|
||||
type_to_error_string(args[2]->type));
|
||||
@@ -364,11 +364,11 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
(BuiltinArg[]) { BA_INTEGER, BA_INTEGER },
|
||||
arg_count)) return false;
|
||||
if (!sema_check_builtin_args_match(args, arg_count)) return false;
|
||||
rtype = type_no_optional(args[0]->type->canonical);
|
||||
rtype = args[0]->type->canonical;
|
||||
break;
|
||||
case BUILTIN_EXACT_NEG:
|
||||
if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_INTLIKE }, arg_count)) return false;
|
||||
rtype = type_no_optional(args[0]->type->canonical);
|
||||
rtype = args[0]->type->canonical;
|
||||
break;
|
||||
case BUILTIN_MEMCOPY:
|
||||
case BUILTIN_MEMCOPY_INLINE:
|
||||
@@ -565,7 +565,7 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
case BUILTIN_NONE:
|
||||
UNREACHABLE
|
||||
}
|
||||
expr->type = type_add_optional(rtype, failable);
|
||||
expr->type = type_add_optional(rtype, optional);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -442,7 +442,7 @@ CastKind cast_to_bool_kind(Type *type)
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_ANY:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_SCALED_VECTOR:
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
@@ -469,7 +469,7 @@ static bool cast_may_explicit(Type *from_type, Type *to_type, bool is_const)
|
||||
TypeKind to_kind = to_type->type_kind;
|
||||
switch (from_type->type_kind)
|
||||
{
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
return true;
|
||||
case TYPE_DISTINCT:
|
||||
case TYPE_TYPEDEF:
|
||||
@@ -553,7 +553,7 @@ bool type_may_convert_to_anyerr(Type *type)
|
||||
{
|
||||
if (type_is_optional_any(type)) return true;
|
||||
if (!type_is_optional_type(type)) return false;
|
||||
return type->failable->canonical == type_void;
|
||||
return type->optional->canonical == type_void;
|
||||
}
|
||||
|
||||
static inline bool cast_may_array(Type *from, Type *to, bool is_explicit)
|
||||
@@ -828,7 +828,7 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type)
|
||||
return expr;
|
||||
}
|
||||
return NULL;
|
||||
case EXPR_FAILABLE:
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_HASH_IDENT:
|
||||
case EXPR_FLATPATH:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
@@ -996,7 +996,7 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type)
|
||||
return expr;
|
||||
}
|
||||
return NULL;
|
||||
case EXPR_FAILABLE:
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_HASH_IDENT:
|
||||
case EXPR_FLATPATH:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
@@ -1118,9 +1118,9 @@ bool cast_implicit(SemaContext *context, Expr *expr, Type *to_type)
|
||||
return cast_expr_inner(context, expr, to_type, (CastOptions) { .no_report = false });
|
||||
}
|
||||
|
||||
bool cast_implicit_maybe_failable(SemaContext *context, Expr *expr, Type *to_type, bool may_be_failable)
|
||||
bool cast_implicit_maybe_optional(SemaContext *context, Expr *expr, Type *to_type, bool may_be_optional)
|
||||
{
|
||||
return cast_expr_inner(context, expr, to_type, (CastOptions) { .may_not_be_optional = !may_be_failable });
|
||||
return cast_expr_inner(context, expr, to_type, (CastOptions) { .may_not_be_optional = !may_be_optional });
|
||||
}
|
||||
|
||||
bool cast_implicit_silent(SemaContext *context, Expr *expr, Type *to_type)
|
||||
@@ -1527,7 +1527,7 @@ static inline bool cast_pointer(SemaContext *context, Expr *expr, Type *from, Ty
|
||||
return cast_with_optional(expr, to_type, add_optional);
|
||||
}
|
||||
return sema_error_cannot_convert(expr, to_type, true, options.no_report);
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_OPTIONAL:
|
||||
UNREACHABLE
|
||||
default:
|
||||
@@ -1573,7 +1573,7 @@ static bool cast_expr_inner(SemaContext *context, Expr *expr, Type *to_type, Cas
|
||||
assert(from_type->type_kind == TYPE_OPTIONAL);
|
||||
|
||||
// If it is void!, then there are special rules:
|
||||
if (from_type->failable == type_void)
|
||||
if (from_type->optional == type_void)
|
||||
{
|
||||
// void! x; anyerr y = x;
|
||||
if (!type_is_optional(to_type) && to == type_anyerr)
|
||||
@@ -1887,7 +1887,7 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type)
|
||||
{
|
||||
switch (from_type->type_kind)
|
||||
{
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_VOID:
|
||||
UNREACHABLE
|
||||
@@ -2011,7 +2011,7 @@ bool cast(Expr *expr, Type *to_type)
|
||||
{
|
||||
assert(!type_is_optional(to_type));
|
||||
Type *from_type = expr->type;
|
||||
bool from_is_failable = false;
|
||||
bool from_is_optional = false;
|
||||
Type *to = type_flatten_distinct(to_type);
|
||||
|
||||
// Special case *! => error
|
||||
@@ -2028,8 +2028,8 @@ bool cast(Expr *expr, Type *to_type)
|
||||
|
||||
if (type_is_optional_type(from_type))
|
||||
{
|
||||
from_type = from_type->failable;
|
||||
from_is_failable = true;
|
||||
from_type = from_type->optional;
|
||||
from_is_optional = true;
|
||||
}
|
||||
from_type = type_flatten_distinct(from_type);
|
||||
if (type_len_is_inferred(to_type))
|
||||
@@ -2039,7 +2039,7 @@ bool cast(Expr *expr, Type *to_type)
|
||||
}
|
||||
if (from_type == to)
|
||||
{
|
||||
expr->type = type_add_optional(to_type, from_is_failable);
|
||||
expr->type = type_add_optional(to_type, from_is_optional);
|
||||
if (expr->expr_kind == EXPR_CONST)
|
||||
{
|
||||
expr->const_expr.narrowable = false;
|
||||
@@ -2051,7 +2051,7 @@ bool cast(Expr *expr, Type *to_type)
|
||||
if (!cast_inner(expr, from_type, to, to_type)) return false;
|
||||
|
||||
Type *result_type = expr->type;
|
||||
if (from_is_failable && !type_is_optional(result_type))
|
||||
if (from_is_optional && !type_is_optional(result_type))
|
||||
{
|
||||
expr->type = type_get_optional(result_type);
|
||||
}
|
||||
|
||||
@@ -897,12 +897,12 @@ static inline bool sema_analyse_distinct(SemaContext *context, Decl *decl)
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
UNREACHABLE
|
||||
return false;
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_OPTIONAL:
|
||||
SEMA_ERROR(decl, "You cannot create a distinct type from a failable.");
|
||||
SEMA_ERROR(decl, "You cannot create a distinct type from am optional.");
|
||||
return false;
|
||||
case TYPE_FAULTTYPE:
|
||||
SEMA_ERROR(decl, "You cannot create a distinct type from an error type.");
|
||||
SEMA_ERROR(decl, "You cannot create a distinct type from a fault type.");
|
||||
return false;
|
||||
case TYPE_ANYERR:
|
||||
SEMA_ERROR(decl, "You cannot create a distinct type from an error union.");
|
||||
@@ -970,7 +970,7 @@ static inline bool sema_analyse_enum_param(SemaContext *context, Decl *param, bo
|
||||
if (!sema_analyse_expr_rhs(context, param->type, expr, true)) return false;
|
||||
if (IS_OPTIONAL(expr))
|
||||
{
|
||||
SEMA_ERROR(expr, "Default arguments may not be failable.");
|
||||
SEMA_ERROR(expr, "Default arguments may not be optionals.");
|
||||
return false;
|
||||
}
|
||||
if (!expr_is_constant_eval(expr, CONSTANT_EVAL_GLOBAL_INIT))
|
||||
@@ -1886,12 +1886,12 @@ static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl)
|
||||
Type *rtype = type_flatten_distinct(rtype_info->type);
|
||||
bool is_int_return = true;
|
||||
bool is_err_return = false;
|
||||
if (rtype->type_kind == TYPE_FAILABLE_ANY) is_err_return = true;
|
||||
if (rtype->type_kind == TYPE_OPTIONAL_ANY) is_err_return = true;
|
||||
if (!is_err_return && type_is_optional(rtype))
|
||||
{
|
||||
if (rtype->failable->type_kind != TYPE_VOID)
|
||||
if (rtype->optional->type_kind != TYPE_VOID)
|
||||
{
|
||||
SEMA_ERROR(rtype_info, "The return type of 'main' cannot be a failable, unless it is 'void!'.");
|
||||
SEMA_ERROR(rtype_info, "The return type of 'main' cannot be an optional, unless it is 'void!'.");
|
||||
return false;
|
||||
}
|
||||
is_int_return = false;
|
||||
@@ -2295,7 +2295,7 @@ bool sema_analyse_decl_type(SemaContext *context, Type *type, SourceSpan span)
|
||||
break;
|
||||
}
|
||||
if (!type_is_optional(type)) return true;
|
||||
if (type_is_optional_any(type) || type_flatten_distinct(type->failable) == type_void)
|
||||
if (type_is_optional_any(type) || type_flatten_distinct(type->optional) == type_void)
|
||||
{
|
||||
sema_error_at(span, "The use of 'void!' as a variable type is not permitted, use %s instead.",
|
||||
type_quoted_error_string(type_anyerr));
|
||||
@@ -2530,7 +2530,7 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
|
||||
{
|
||||
if (decl->var.unwrap && IS_OPTIONAL(init))
|
||||
{
|
||||
SEMA_ERROR(decl->var.init_expr, "A failable expression was expected here.");
|
||||
SEMA_ERROR(decl->var.init_expr, "An optional expression was expected here.");
|
||||
return decl_poison(decl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ static inline bool sema_expr_analyse_force_unwrap(SemaContext *context, Expr *ex
|
||||
static inline bool sema_expr_analyse_typeid(SemaContext *context, Expr *expr);
|
||||
static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr);
|
||||
static inline bool sema_expr_analyse_expr_block(SemaContext *context, Type *infer_type, Expr *expr);
|
||||
static inline bool sema_expr_analyse_failable(SemaContext *context, Expr *expr);
|
||||
static inline bool sema_expr_analyse_optional(SemaContext *context, Expr *expr);
|
||||
static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr *expr, bool report_missing);
|
||||
static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Expr *expr);
|
||||
static inline bool sema_expr_analyse_ct_stringify(SemaContext *context, Expr *expr);
|
||||
@@ -125,15 +125,15 @@ static bool sema_binary_is_expr_lvalue(Expr *top_expr, Expr *expr);
|
||||
static void sema_binary_unify_voidptr(Expr *left, Expr *right, Type **left_type_ref, Type **right_type_ref);
|
||||
|
||||
// -- function helper functions
|
||||
static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr, Type *func_ptr_type, bool failable);
|
||||
static inline bool sema_expr_analyse_func_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool failable);
|
||||
static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call, CalledDecl callee, bool *failable);
|
||||
static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr, Type *func_ptr_type, bool optional);
|
||||
static inline bool sema_expr_analyse_func_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool optional);
|
||||
static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call, CalledDecl callee, bool *optional);
|
||||
static inline bool sema_call_analyse_func_invocation(SemaContext *context, Type *type, Expr *expr, Expr *struct_var,
|
||||
bool failable, const char *name);
|
||||
bool optional, const char *name);
|
||||
static inline bool sema_call_check_invalid_body_arguments(SemaContext *context, Expr *call, CalledDecl *callee);
|
||||
INLINE bool sema_call_expand_arguments(SemaContext *context, CalledDecl *callee, Expr *call, Expr **args,
|
||||
unsigned func_param_count, Variadic variadic, unsigned vararg_index,
|
||||
bool *failable,
|
||||
bool *optional,
|
||||
Expr ***varargs_ref,
|
||||
Expr **vararg_splat_ref);
|
||||
static inline int sema_call_find_index_of_named_parameter(Decl **func_params, Expr *expr);
|
||||
@@ -463,7 +463,7 @@ static bool sema_binary_is_expr_lvalue(Expr *top_expr, Expr *expr)
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
case EXPR_DESIGNATOR:
|
||||
case EXPR_EXPR_BLOCK:
|
||||
case EXPR_FAILABLE:
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_FLATPATH:
|
||||
case EXPR_FORCE_UNWRAP:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
@@ -670,17 +670,17 @@ static inline bool sema_expr_analyse_ternary(SemaContext *context, Expr *expr)
|
||||
Expr *right = exprptr(expr->ternary_expr.else_expr);
|
||||
if (!sema_analyse_expr(context, right)) return expr_poison(expr);
|
||||
|
||||
bool is_failable = false;
|
||||
bool is_optional = false;
|
||||
Type *left_canonical = left->type->canonical;
|
||||
Type *right_canonical = right->type->canonical;
|
||||
if (left_canonical != right_canonical)
|
||||
{
|
||||
Type *max;
|
||||
if (left_canonical->type_kind == TYPE_FAILABLE_ANY)
|
||||
if (left_canonical->type_kind == TYPE_OPTIONAL_ANY)
|
||||
{
|
||||
max = right_canonical;
|
||||
}
|
||||
else if (right_canonical->type_kind == TYPE_FAILABLE_ANY)
|
||||
else if (right_canonical->type_kind == TYPE_OPTIONAL_ANY)
|
||||
{
|
||||
max = left_canonical;
|
||||
}
|
||||
@@ -833,7 +833,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
|
||||
}
|
||||
if (IS_OPTIONAL(decl))
|
||||
{
|
||||
SEMA_ERROR(expr, "Constants may never be 'failable', please remove the '!'.");
|
||||
SEMA_ERROR(expr, "Constants may never be 'optional', please remove the '!'.");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -1030,7 +1030,7 @@ static inline bool sema_call_check_invalid_body_arguments(SemaContext *context,
|
||||
|
||||
INLINE bool sema_call_expand_arguments(SemaContext *context, CalledDecl *callee, Expr *call, Expr **args,
|
||||
unsigned func_param_count, Variadic variadic, unsigned vararg_index,
|
||||
bool *failable,
|
||||
bool *optional,
|
||||
Expr ***varargs_ref,
|
||||
Expr **vararg_splat_ref)
|
||||
{
|
||||
@@ -1222,7 +1222,7 @@ static inline bool sema_call_check_inout_param_match(SemaContext *context, Decl
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call, CalledDecl callee, bool *failable)
|
||||
static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call, CalledDecl callee, bool *optional)
|
||||
{
|
||||
// 1. Check body arguments (for macro calls, or possibly broken )
|
||||
if (!sema_call_check_invalid_body_arguments(context, call, &callee)) return false;
|
||||
@@ -1293,7 +1293,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
param_count,
|
||||
variadic,
|
||||
vararg_index,
|
||||
failable, &varargs, &vararg_splat)) return false;
|
||||
optional, &varargs, &vararg_splat)) return false;
|
||||
|
||||
args = call->call_expr.arguments;
|
||||
num_args = vec_size(args);
|
||||
@@ -1318,7 +1318,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
}
|
||||
|
||||
// Set the argument at the location.
|
||||
*failable |= IS_OPTIONAL(val);
|
||||
*optional |= IS_OPTIONAL(val);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1327,7 +1327,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
{
|
||||
// 11e. A simple variadic value:
|
||||
if (!sema_analyse_expr_rhs(context, variadic_type, val, true)) return false;
|
||||
*failable |= IS_OPTIONAL(val);
|
||||
*optional |= IS_OPTIONAL(val);
|
||||
}
|
||||
}
|
||||
call->call_expr.varargs = varargs;
|
||||
@@ -1346,7 +1346,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
type_quoted_error_string(variadic_type));
|
||||
return false;
|
||||
}
|
||||
*failable |= IS_OPTIONAL(vararg_splat);
|
||||
*optional |= IS_OPTIONAL(vararg_splat);
|
||||
call->call_expr.splat = vararg_splat;
|
||||
}
|
||||
// 7. Loop through the parameters.
|
||||
@@ -1373,7 +1373,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
// &foo
|
||||
if (!sema_analyse_expr_lvalue(context, arg)) return false;
|
||||
if (!sema_expr_check_assign(context, arg)) return false;
|
||||
*failable |= IS_OPTIONAL(arg);
|
||||
*optional |= IS_OPTIONAL(arg);
|
||||
if (!sema_call_check_inout_param_match(context, param, arg)) return false;
|
||||
if (type_is_invalid_storage_type(type))
|
||||
{
|
||||
@@ -1400,7 +1400,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
case VARDECL_PARAM:
|
||||
// foo
|
||||
if (!sema_analyse_expr_rhs(context, type, arg, true)) return false;
|
||||
if (IS_OPTIONAL(arg)) *failable = true;
|
||||
if (IS_OPTIONAL(arg)) *optional = true;
|
||||
if (type_is_invalid_storage_type(arg->type))
|
||||
{
|
||||
SEMA_ERROR(arg, "A value of type %s can only be passed as a compile time parameter.", type_quoted_error_string(arg->type));
|
||||
@@ -1457,7 +1457,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
|
||||
return true;
|
||||
}
|
||||
static inline bool sema_call_analyse_func_invocation(SemaContext *context, Type *type, Expr *expr, Expr *struct_var,
|
||||
bool failable, const char *name)
|
||||
bool optional, const char *name)
|
||||
{
|
||||
Signature *sig = type->function.signature;
|
||||
CalledDecl callee = {
|
||||
@@ -1475,7 +1475,7 @@ static inline bool sema_call_analyse_func_invocation(SemaContext *context, Type
|
||||
}
|
||||
|
||||
bool is_unused = expr->call_expr.result_unused;
|
||||
if (!sema_call_analyse_invocation(context, expr, callee, &failable)) return false;
|
||||
if (!sema_call_analyse_invocation(context, expr, callee, &optional)) return false;
|
||||
|
||||
Type *rtype = type->function.prototype->rtype;
|
||||
|
||||
@@ -1493,12 +1493,12 @@ static inline bool sema_call_analyse_func_invocation(SemaContext *context, Type
|
||||
}
|
||||
}
|
||||
|
||||
expr->type = type_add_optional(rtype, failable);
|
||||
expr->type = type_add_optional(rtype, optional);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr, Type *func_ptr_type, bool failable)
|
||||
static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr, Type *func_ptr_type, bool optional)
|
||||
{
|
||||
Decl *decl = NULL;
|
||||
if (func_ptr_type->type_kind != TYPE_POINTER || func_ptr_type->pointer->type_kind != TYPE_FUNC)
|
||||
@@ -1508,7 +1508,7 @@ static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr,
|
||||
}
|
||||
Type *pointee = func_ptr_type->pointer;
|
||||
expr->call_expr.is_pointer_call = true;
|
||||
return sema_call_analyse_func_invocation(context, pointee, expr, NULL, failable, func_ptr_type->pointer->name);
|
||||
return sema_call_analyse_func_invocation(context, pointee, expr, NULL, optional, func_ptr_type->pointer->name);
|
||||
}
|
||||
|
||||
// Unify returns in a macro or expression block.
|
||||
@@ -1517,7 +1517,7 @@ static inline Type *context_unify_returns(SemaContext *context)
|
||||
bool all_returns_need_casts = false;
|
||||
Type *common_type = NULL;
|
||||
|
||||
bool failable = false;
|
||||
bool optional = false;
|
||||
bool no_return = true;
|
||||
// 1. Loop through the returns.
|
||||
VECEACH(context->returns, i)
|
||||
@@ -1525,7 +1525,7 @@ static inline Type *context_unify_returns(SemaContext *context)
|
||||
Ast *return_stmt = context->returns[i];
|
||||
if (!return_stmt)
|
||||
{
|
||||
failable = true;
|
||||
optional = true;
|
||||
continue;
|
||||
}
|
||||
no_return = false;
|
||||
@@ -1533,12 +1533,12 @@ static inline Type *context_unify_returns(SemaContext *context)
|
||||
Type *rtype = ret_expr ? ret_expr->type : type_void;
|
||||
if (type_is_optional_any(rtype))
|
||||
{
|
||||
failable = true;
|
||||
optional = true;
|
||||
continue;
|
||||
}
|
||||
if (type_is_optional(rtype))
|
||||
{
|
||||
failable = true;
|
||||
optional = true;
|
||||
rtype = type_no_optional(rtype);
|
||||
}
|
||||
// 2. If we have no common type, set to the return type.
|
||||
@@ -1574,13 +1574,13 @@ static inline Type *context_unify_returns(SemaContext *context)
|
||||
if (!common_type)
|
||||
{
|
||||
assert(!all_returns_need_casts && "We should never need casts here.");
|
||||
// A failable?
|
||||
if (failable)
|
||||
// An optional?
|
||||
if (optional)
|
||||
{
|
||||
// If there are only implicit returns, then we assume void!, otherwise it's an "anyfail"
|
||||
return no_return ? type_get_optional(type_void) : type_anyfail;
|
||||
}
|
||||
// No failable => void.
|
||||
// No optional => void.
|
||||
return type_void;
|
||||
}
|
||||
|
||||
@@ -1601,10 +1601,10 @@ static inline Type *context_unify_returns(SemaContext *context)
|
||||
}
|
||||
}
|
||||
|
||||
return type_add_optional(common_type, failable);
|
||||
return type_add_optional(common_type, optional);
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_func_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool failable)
|
||||
static inline bool sema_expr_analyse_func_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool optional)
|
||||
{
|
||||
expr->call_expr.is_pointer_call = false;
|
||||
if (decl->func_decl.attr_test)
|
||||
@@ -1616,14 +1616,14 @@ static inline bool sema_expr_analyse_func_call(SemaContext *context, Expr *expr,
|
||||
decl->type,
|
||||
expr,
|
||||
struct_var,
|
||||
failable,
|
||||
optional,
|
||||
decl->name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool failable)
|
||||
bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool optional)
|
||||
{
|
||||
assert(decl->decl_kind == DECL_MACRO);
|
||||
|
||||
@@ -1642,7 +1642,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
.struct_var = struct_var
|
||||
};
|
||||
|
||||
if (!sema_call_analyse_invocation(context, call_expr, callee, &failable)) return false;
|
||||
if (!sema_call_analyse_invocation(context, call_expr, callee, &optional)) return false;
|
||||
|
||||
unsigned vararg_index = decl->func_decl.signature.vararg_index;
|
||||
Expr **args = call_expr->call_expr.arguments;
|
||||
@@ -1725,17 +1725,17 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
macro_context.call_env = context->call_env;
|
||||
rtype = decl->func_decl.signature.rtype ? type_infoptr(decl->func_decl.signature.rtype)->type : NULL;
|
||||
macro_context.expected_block_type = rtype;
|
||||
bool may_failable = true;
|
||||
bool may_be_optional = true;
|
||||
if (rtype)
|
||||
{
|
||||
if (type_is_optional(rtype))
|
||||
{
|
||||
failable = true;
|
||||
optional = true;
|
||||
rtype = type_no_optional(rtype);
|
||||
}
|
||||
else
|
||||
{
|
||||
may_failable = false;
|
||||
may_be_optional = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1797,7 +1797,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
Ast *return_stmt = macro_context.returns[i];
|
||||
if (!return_stmt)
|
||||
{
|
||||
assert(may_failable);
|
||||
assert(may_be_optional);
|
||||
continue;
|
||||
}
|
||||
Expr *ret_expr = return_stmt->return_stmt.expr;
|
||||
@@ -1823,21 +1823,21 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
}
|
||||
}
|
||||
bool success = cast_implicit_silent(context, ret_expr, rtype);
|
||||
if (inferred_len || (!may_failable && IS_OPTIONAL(ret_expr)) || !success)
|
||||
if (inferred_len || (!may_be_optional && IS_OPTIONAL(ret_expr)) || !success)
|
||||
{
|
||||
SEMA_ERROR(ret_expr, "Expected %s, not %s.", type_quoted_error_string(rtype),
|
||||
type_quoted_error_string(type));
|
||||
return SCOPE_POP_ERROR();
|
||||
}
|
||||
if (may_failable) ret_expr->type = type_add_optional(ret_expr->type, may_failable);
|
||||
if (may_be_optional) ret_expr->type = type_add_optional(ret_expr->type, may_be_optional);
|
||||
}
|
||||
call_expr->type = type_add_optional(rtype, failable);
|
||||
call_expr->type = type_add_optional(rtype, optional);
|
||||
}
|
||||
else
|
||||
{
|
||||
Type *sum_returns = context_unify_returns(¯o_context);
|
||||
if (!sum_returns) return SCOPE_POP_ERROR();
|
||||
call_expr->type = type_add_optional(sum_returns, failable);
|
||||
call_expr->type = type_add_optional(sum_returns, optional);
|
||||
}
|
||||
|
||||
assert(call_expr->type);
|
||||
@@ -1974,27 +1974,27 @@ static bool sema_call_analyse_body_expansion(SemaContext *macro_context, Expr *c
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool failable)
|
||||
bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl, Expr *struct_var, bool optional)
|
||||
{
|
||||
expr->call_expr.is_type_method = struct_var != NULL;
|
||||
if (decl == NULL)
|
||||
{
|
||||
return sema_expr_analyse_var_call(context, expr,
|
||||
type_flatten_distinct_optional(exprptr(expr->call_expr.function)->type), failable);
|
||||
type_flatten_distinct_optional(exprptr(expr->call_expr.function)->type), optional);
|
||||
}
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_MACRO:
|
||||
expr->call_expr.func_ref = declid(decl);
|
||||
expr->call_expr.is_func_ref = true;
|
||||
return sema_expr_analyse_macro_call(context, expr, struct_var, decl, failable);
|
||||
return sema_expr_analyse_macro_call(context, expr, struct_var, decl, optional);
|
||||
case DECL_VAR:
|
||||
assert(struct_var == NULL);
|
||||
return sema_expr_analyse_var_call(context, expr, decl->type->canonical, failable || IS_OPTIONAL(decl));
|
||||
return sema_expr_analyse_var_call(context, expr, decl->type->canonical, optional || IS_OPTIONAL(decl));
|
||||
case DECL_FUNC:
|
||||
expr->call_expr.func_ref = declid(decl);
|
||||
expr->call_expr.is_func_ref = true;
|
||||
return sema_expr_analyse_func_call(context, expr, decl, struct_var, failable);
|
||||
return sema_expr_analyse_func_call(context, expr, decl, struct_var, optional);
|
||||
case DECL_GENERIC:
|
||||
expr->call_expr.func_ref = declid(decl);
|
||||
expr->call_expr.is_func_ref = true;
|
||||
@@ -2020,7 +2020,7 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr)
|
||||
{
|
||||
return sema_call_analyse_body_expansion(context, expr);
|
||||
}
|
||||
bool failable = func_expr->type && IS_OPTIONAL(func_expr);
|
||||
bool optional = func_expr->type && IS_OPTIONAL(func_expr);
|
||||
Decl *decl;
|
||||
Expr *struct_var = NULL;
|
||||
switch (func_expr->expr_kind)
|
||||
@@ -2070,7 +2070,7 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr)
|
||||
}
|
||||
}
|
||||
decl = decl ? decl_flatten(decl) : NULL;
|
||||
return sema_expr_analyse_general_call(context, expr, decl, struct_var, failable);
|
||||
return sema_expr_analyse_general_call(context, expr, decl, struct_var, optional);
|
||||
}
|
||||
|
||||
static void sema_subscript_deref_array_pointers(Expr *expr)
|
||||
@@ -2312,7 +2312,7 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
|
||||
if (!sema_analyse_expr(context, index)) return false;
|
||||
|
||||
// 3. Check failability due to value.
|
||||
bool failable = IS_OPTIONAL(subscripted);
|
||||
bool optional = IS_OPTIONAL(subscripted);
|
||||
|
||||
Type *underlying_type = type_flatten(subscripted->type);
|
||||
|
||||
@@ -2475,7 +2475,7 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
|
||||
}
|
||||
}
|
||||
expr->subscript_expr.expr = exprid(current_expr);
|
||||
expr->type = type_add_optional(index_type, failable);
|
||||
expr->type = type_add_optional(index_type, optional);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2515,7 +2515,7 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr)
|
||||
assert(expr->expr_kind == EXPR_SLICE);
|
||||
Expr *subscripted = exprptr(expr->subscript_expr.expr);
|
||||
if (!sema_analyse_expr(context, subscripted)) return false;
|
||||
bool failable = IS_OPTIONAL(subscripted);
|
||||
bool optional = IS_OPTIONAL(subscripted);
|
||||
Type *type = type_flatten(subscripted->type);
|
||||
Type *original_type = type_no_optional(subscripted->type);
|
||||
Expr *start = exprptr(expr->subscript_expr.range.start);
|
||||
@@ -2633,7 +2633,7 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr)
|
||||
{
|
||||
result_type = original_type;
|
||||
}
|
||||
expr->type = type_add_optional(result_type, failable);
|
||||
expr->type = type_add_optional(result_type, optional);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2964,7 +2964,7 @@ static inline bool sema_create_const_inner(SemaContext *context, Expr *expr, Typ
|
||||
inner = type->pointer;
|
||||
break;
|
||||
case TYPE_OPTIONAL:
|
||||
inner = type->failable;
|
||||
inner = type->optional;
|
||||
break;
|
||||
case TYPE_DISTINCT:
|
||||
inner = type->decl->distinct_decl.base_type->canonical;
|
||||
@@ -3427,7 +3427,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr)
|
||||
}
|
||||
|
||||
// 6. Copy failability
|
||||
bool failable = IS_OPTIONAL(parent);
|
||||
bool optional = IS_OPTIONAL(parent);
|
||||
|
||||
assert(expr->expr_kind == EXPR_ACCESS);
|
||||
assert(parent->resolve_status == RESOLVE_DONE);
|
||||
@@ -3554,7 +3554,7 @@ CHECK_DEEPER:
|
||||
return false;
|
||||
}
|
||||
expr->access_expr.parent = current_parent;
|
||||
expr->type = method->type ? type_add_optional(method->type, failable) : NULL;
|
||||
expr->type = method->type ? type_add_optional(method->type, optional) : NULL;
|
||||
expr->access_expr.ref = method;
|
||||
if (method->decl_kind == DECL_FUNC) unit_register_external_symbol(context->compilation_unit, method);
|
||||
return true;
|
||||
@@ -3627,7 +3627,7 @@ CHECK_DEEPER:
|
||||
}
|
||||
// 13. Copy properties.
|
||||
expr->access_expr.parent = current_parent;
|
||||
expr->type = type_add_optional(member->type, failable);
|
||||
expr->type = type_add_optional(member->type, optional);
|
||||
expr->access_expr.ref = member;
|
||||
return true;
|
||||
}
|
||||
@@ -4127,7 +4127,7 @@ static bool sema_expr_analyse_op_assign(SemaContext *context, Expr *expr, Expr *
|
||||
|
||||
// 5. Cast the right hand side to the one on the left
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
if (!cast_implicit_maybe_failable(context, right, no_fail, IS_OPTIONAL(left))) return false;
|
||||
if (!cast_implicit_maybe_optional(context, right, no_fail, IS_OPTIONAL(left))) return false;
|
||||
// 6. Check for zero in case of div or mod.
|
||||
if (right->expr_kind == EXPR_CONST)
|
||||
{
|
||||
@@ -4206,11 +4206,11 @@ static bool sema_expr_analyse_add_sub_assign(SemaContext *context, Expr *expr, E
|
||||
// 3. Copy type & set properties.
|
||||
if (IS_OPTIONAL(right) && !IS_OPTIONAL(left))
|
||||
{
|
||||
SEMA_ERROR(right, "Cannot assign a failable value to a non-failable.");
|
||||
SEMA_ERROR(right, "Cannot assign an optional value to a non-optional.");
|
||||
return false;
|
||||
}
|
||||
expr->type = left->type;
|
||||
bool failable = IS_OPTIONAL(left) || IS_OPTIONAL(right);
|
||||
bool optional = IS_OPTIONAL(left) || IS_OPTIONAL(right);
|
||||
|
||||
|
||||
// 5. In the pointer case we have to treat this differently.
|
||||
@@ -4245,7 +4245,7 @@ static bool sema_expr_analyse_add_sub_assign(SemaContext *context, Expr *expr, E
|
||||
{
|
||||
expr->expr_kind = EXPR_BITASSIGN;
|
||||
}
|
||||
expr->type = type_add_optional(expr->type, failable);
|
||||
expr->type = type_add_optional(expr->type, optional);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4827,7 +4827,7 @@ static bool sema_expr_analyse_shift_assign(SemaContext *context, Expr *expr, Exp
|
||||
// 1. Analyze the two sub lhs & rhs *without coercion*
|
||||
if (!sema_binary_analyse_subexpr(context, expr, left, right)) return false;
|
||||
|
||||
bool failable = IS_OPTIONAL(left) || IS_OPTIONAL(right);
|
||||
bool optional = IS_OPTIONAL(left) || IS_OPTIONAL(right);
|
||||
|
||||
// 2. Ensure the lhs side is assignable
|
||||
if (!sema_expr_check_assign(context, left)) return false;
|
||||
@@ -4860,7 +4860,7 @@ static bool sema_expr_analyse_shift_assign(SemaContext *context, Expr *expr, Exp
|
||||
{
|
||||
expr->expr_kind = EXPR_BITASSIGN;
|
||||
}
|
||||
expr->type = type_add_optional(left->type, failable);
|
||||
expr->type = type_add_optional(left->type, optional);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4952,7 +4952,7 @@ static bool sema_expr_analyse_comp(SemaContext *context, Expr *expr, Expr *left,
|
||||
|
||||
bool is_equality_type_op = expr->binary_expr.operator == BINARYOP_NE || expr->binary_expr.operator == BINARYOP_EQ;
|
||||
|
||||
// Flatten enum/distinct/failable
|
||||
// Flatten enum/distinct/optional
|
||||
Type *left_type = type_flatten(left->type);
|
||||
Type *right_type = type_flatten(right->type);
|
||||
|
||||
@@ -5447,7 +5447,7 @@ static inline bool sema_expr_analyse_incdec(SemaContext *context, Expr *expr)
|
||||
return sema_expr_analyse_ct_incdec(context, expr, inner);
|
||||
}
|
||||
|
||||
// 4. Flatten typedef, enum, distinct, failable
|
||||
// 4. Flatten typedef, enum, distinct, optional
|
||||
Type *type = type_flatten(inner->type);
|
||||
|
||||
// 5. We can only inc/dec numbers or pointers.
|
||||
@@ -5534,7 +5534,7 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr)
|
||||
Type *type = lhs->type;
|
||||
if (!type_is_optional(type))
|
||||
{
|
||||
SEMA_ERROR(lhs, "No failable to use '\?\?' with, please remove the '\?\?'.");
|
||||
SEMA_ERROR(lhs, "No optional to use '\?\?' with, please remove the '\?\?'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5542,7 +5542,7 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr)
|
||||
if (!sema_analyse_expr(context, rhs)) return false;
|
||||
if (expr->binary_expr.widen && !cast_widen_top_down(context, rhs, expr->type)) return false;
|
||||
|
||||
if (lhs->expr_kind == EXPR_FAILABLE)
|
||||
if (lhs->expr_kind == EXPR_OPTIONAL)
|
||||
{
|
||||
expr_replace(expr, rhs);
|
||||
return true;
|
||||
@@ -5693,7 +5693,7 @@ static inline bool sema_expr_analyse_try(SemaContext *context, Expr *expr)
|
||||
if (!sema_analyse_expr(context, inner)) return false;
|
||||
if (!IS_OPTIONAL(inner))
|
||||
{
|
||||
SEMA_ERROR(inner, "Expected a failable expression to 'try'.");
|
||||
SEMA_ERROR(inner, "Expected an optional expression to 'try'.");
|
||||
return false;
|
||||
}
|
||||
expr->type = type_bool;
|
||||
@@ -5706,7 +5706,7 @@ static inline bool sema_expr_analyse_catch(SemaContext *context, Expr *expr)
|
||||
if (!sema_analyse_expr(context, inner)) return false;
|
||||
if (!IS_OPTIONAL(inner))
|
||||
{
|
||||
SEMA_ERROR(inner, "Expected a failable expression to 'catch'.");
|
||||
SEMA_ERROR(inner, "Expected an optional expression to 'catch'.");
|
||||
return false;
|
||||
}
|
||||
expr->type = type_anyerr;
|
||||
@@ -5738,7 +5738,7 @@ static inline bool sema_expr_analyse_rethrow(SemaContext *context, Expr *expr)
|
||||
|
||||
if (!IS_OPTIONAL(inner))
|
||||
{
|
||||
SEMA_ERROR(expr, "No failable to rethrow before '?' in the expression, please remove '?'.");
|
||||
SEMA_ERROR(expr, "No optional to rethrow before '?' in the expression, please remove '?'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5751,7 +5751,7 @@ static inline bool sema_expr_analyse_rethrow(SemaContext *context, Expr *expr)
|
||||
{
|
||||
if (context->rtype && context->rtype->type_kind != TYPE_OPTIONAL)
|
||||
{
|
||||
SEMA_ERROR(expr, "This expression implicitly returns with a failable result, but the function does not allow failable results. Did you mean to use 'else' instead?");
|
||||
SEMA_ERROR(expr, "This expression implicitly returns with an optional result, but the function does not allow optional results. Did you mean to use 'else' instead?");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -5772,7 +5772,7 @@ static inline bool sema_expr_analyse_force_unwrap(SemaContext *context, Expr *ex
|
||||
expr->type = type_no_optional(inner->type);
|
||||
if (!IS_OPTIONAL(inner))
|
||||
{
|
||||
SEMA_ERROR(expr, "No failable to rethrow before '!!' in the expression, please remove '!!'.");
|
||||
SEMA_ERROR(expr, "No optional to rethrow before '!!' in the expression, please remove '!!'.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -5856,18 +5856,18 @@ static inline bool sema_expr_analyse_expr_block(SemaContext *context, Type *infe
|
||||
|
||||
|
||||
|
||||
static inline bool sema_expr_analyse_failable(SemaContext *context, Expr *expr)
|
||||
static inline bool sema_expr_analyse_optional(SemaContext *context, Expr *expr)
|
||||
{
|
||||
Expr *inner = expr->inner_expr;
|
||||
if (!sema_analyse_expr(context, inner)) return false;
|
||||
|
||||
if (IS_OPTIONAL(inner))
|
||||
{
|
||||
SEMA_ERROR(inner, "The inner expression is already a failable.");
|
||||
SEMA_ERROR(inner, "The inner expression is already an optional.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inner->expr_kind == EXPR_FAILABLE)
|
||||
if (inner->expr_kind == EXPR_OPTIONAL)
|
||||
{
|
||||
SEMA_ERROR(inner, "It looks like you added one too many '!' after the error.");
|
||||
return false;
|
||||
@@ -6740,7 +6740,7 @@ static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr
|
||||
if (type_is_optional(type))
|
||||
{
|
||||
SEMA_ERROR(expr->expr_compound_literal.type_info,
|
||||
"The type here should always be written as a plain type and not a failable, please remove the '!'.");
|
||||
"The type here should always be written as a plain type and not an optional, please remove the '!'.");
|
||||
return false;
|
||||
}
|
||||
if (!sema_expr_analyse_initializer_list(context, type, expr->expr_compound_literal.initializer)) return false;
|
||||
@@ -6796,8 +6796,8 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr)
|
||||
return sema_expr_analyse_hash_identifier(context, expr);
|
||||
case EXPR_CT_IDENT:
|
||||
return sema_expr_analyse_ct_identifier(context, expr);
|
||||
case EXPR_FAILABLE:
|
||||
return sema_expr_analyse_failable(context, expr);
|
||||
case EXPR_OPTIONAL:
|
||||
return sema_expr_analyse_optional(context, expr);
|
||||
case EXPR_COMPILER_CONST:
|
||||
return sema_expr_analyse_compiler_const(context, expr, true);
|
||||
case EXPR_POINTER_OFFSET:
|
||||
@@ -6879,7 +6879,7 @@ bool sema_analyse_cond_expr(SemaContext *context, Expr *expr)
|
||||
if (!sema_analyse_expr(context, expr)) return false;
|
||||
if (IS_OPTIONAL(expr))
|
||||
{
|
||||
SEMA_ERROR(expr, "A failable %s cannot be implicitly converted to a regular boolean value, use 'try(<expr>)' "
|
||||
SEMA_ERROR(expr, "An optional %s cannot be implicitly converted to a regular boolean value, use 'try(<expr>)' "
|
||||
"and 'catch(<expr>)' to conditionally execute on success or failure.",
|
||||
type_quoted_error_string(expr->type));
|
||||
return false;
|
||||
@@ -6888,15 +6888,15 @@ bool sema_analyse_cond_expr(SemaContext *context, Expr *expr)
|
||||
}
|
||||
|
||||
|
||||
bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allow_failable)
|
||||
bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allow_optional)
|
||||
{
|
||||
if (to && type_is_optional_type(to))
|
||||
{
|
||||
to = to->failable;
|
||||
assert(allow_failable);
|
||||
to = to->optional;
|
||||
assert(allow_optional);
|
||||
}
|
||||
if (!sema_analyse_inferred_expr(context, to, expr)) return false;
|
||||
if (to && allow_failable && to->canonical != expr->type->canonical && expr->type->canonical->type_kind == TYPE_FAULTTYPE)
|
||||
if (to && allow_optional && to->canonical != expr->type->canonical && expr->type->canonical->type_kind == TYPE_FAULTTYPE)
|
||||
{
|
||||
Type *canonical = type_flatten_distinct(to);
|
||||
if (canonical != type_anyerr && canonical->type_kind != TYPE_FAULTTYPE && expr->expr_kind == EXPR_CONST)
|
||||
@@ -6905,10 +6905,10 @@ bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allo
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (to && !cast_implicit_maybe_failable(context, expr, to, allow_failable)) return false;
|
||||
if (!allow_failable && IS_OPTIONAL(expr))
|
||||
if (to && !cast_implicit_maybe_optional(context, expr, to, allow_optional)) return false;
|
||||
if (!allow_optional && IS_OPTIONAL(expr))
|
||||
{
|
||||
SEMA_ERROR(expr, "You cannot have a failable here.");
|
||||
SEMA_ERROR(expr, "You cannot have an optional here.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -7071,7 +7071,7 @@ RETRY:
|
||||
case TYPE_VECTOR:
|
||||
return type->array.len;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
type = type->optional;
|
||||
goto RETRY;
|
||||
default:
|
||||
return -1;
|
||||
|
||||
@@ -84,7 +84,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
|
||||
return false;
|
||||
}
|
||||
|
||||
bool failable = false;
|
||||
bool optional = false;
|
||||
|
||||
bool is_bitstruct = assigned->decl_kind == DECL_BITSTRUCT;
|
||||
if (is_bitstruct && assigned->bitstruct.overlap)
|
||||
@@ -162,10 +162,10 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
|
||||
{
|
||||
if (!sema_bit_assignment_check(element, members[i])) return false;
|
||||
}
|
||||
failable = failable || IS_OPTIONAL(element);
|
||||
optional = optional || IS_OPTIONAL(element);
|
||||
}
|
||||
assert(initializer->type);
|
||||
if (failable) initializer->type = type_get_optional(initializer->type);
|
||||
if (optional) initializer->type = type_get_optional(initializer->type);
|
||||
|
||||
// 6. There's the case of too few values as well. Mark the last field as wrong.
|
||||
assert(elements_needed <= size);
|
||||
@@ -250,7 +250,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
return false;
|
||||
}
|
||||
|
||||
bool failable = false;
|
||||
bool optional = false;
|
||||
unsigned count = vec_size(elements);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
@@ -262,7 +262,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
}
|
||||
if (!sema_analyse_expr_rhs(context, inner_type, element, true)) return false;
|
||||
Type *element_type = type_no_optional(element->type);
|
||||
failable = failable || IS_OPTIONAL(element);
|
||||
optional = optional || IS_OPTIONAL(element);
|
||||
}
|
||||
if (inferred_len)
|
||||
{
|
||||
@@ -274,7 +274,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
}
|
||||
|
||||
assert(initializer->type);
|
||||
if (failable) initializer->type = type_get_optional(initializer->type);
|
||||
if (optional) initializer->type = type_get_optional(initializer->type);
|
||||
|
||||
if (expected_members > size)
|
||||
{
|
||||
@@ -334,7 +334,7 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type
|
||||
bool is_bitstruct = original->type_kind == TYPE_BITSTRUCT;
|
||||
bool is_structlike = type_is_union_or_strukt(original) || is_bitstruct;
|
||||
MemberIndex max_index = -1;
|
||||
bool failable = false;
|
||||
bool optional = false;
|
||||
Type *inner_type = NULL;
|
||||
bool is_inferred = type_is_len_inferred(flattened);
|
||||
VECEACH(init_expressions, i)
|
||||
@@ -349,7 +349,7 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type
|
||||
{
|
||||
if (!sema_bit_assignment_check(value, member)) return false;
|
||||
}
|
||||
failable = failable || IS_OPTIONAL(value);
|
||||
optional = optional || IS_OPTIONAL(value);
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
if (!inner_type)
|
||||
{
|
||||
|
||||
@@ -84,7 +84,7 @@ bool sema_analyse_ct_expr(SemaContext *context, Expr *expr);
|
||||
Decl *sema_find_operator(SemaContext *context, Expr *expr, OperatorOverload operator_overload);
|
||||
bool sema_insert_method_call(SemaContext *context, Expr *method_call, Decl *method_decl, Expr *parent, Expr **arguments);
|
||||
bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr);
|
||||
bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool failable);
|
||||
bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool optional);
|
||||
Expr *sema_expr_analyse_ct_arg_index(SemaContext *context, Expr *index_expr);
|
||||
Expr *sema_ct_eval_expr(SemaContext *c, bool is_type, Expr *inner, bool report_missing);
|
||||
bool sema_analyse_asm(SemaContext *context, AsmInlineBlock *block, Ast *asm_stmt);
|
||||
|
||||
@@ -874,7 +874,7 @@ void sema_unwrap_var(SemaContext *context, Decl *decl)
|
||||
Decl *alias = decl_copy(decl);
|
||||
alias->var.kind = VARDECL_UNWRAPPED;
|
||||
alias->var.alias = decl;
|
||||
alias->type = alias->type->failable;
|
||||
alias->type = alias->type->optional;
|
||||
alias->resolve_status = RESOLVE_DONE;
|
||||
sema_append_local(context, alias);
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ static void sema_unwrappable_from_catch_in_else(SemaContext *c, Expr *cond)
|
||||
if (expr->expr_kind != EXPR_IDENTIFIER) continue;
|
||||
Decl *decl = expr->identifier_expr.decl;
|
||||
if (decl->decl_kind != DECL_VAR) continue;
|
||||
assert(decl->type->type_kind == TYPE_OPTIONAL && "The variable should always be failable at this point.");
|
||||
assert(decl->type->type_kind == TYPE_OPTIONAL && "The variable should always be optional at this point.");
|
||||
|
||||
// 5. Locals and globals may be unwrapped
|
||||
switch (decl->var.kind)
|
||||
@@ -442,10 +442,10 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr)
|
||||
{
|
||||
assert(expr->expr_kind == EXPR_TRY_UNWRAP);
|
||||
Expr *ident = expr->try_unwrap_expr.variable;
|
||||
Expr *failable = expr->try_unwrap_expr.init;
|
||||
Expr *optional = expr->try_unwrap_expr.init;
|
||||
|
||||
// Case A. Unwrapping a single variable.
|
||||
if (!failable)
|
||||
if (!optional)
|
||||
{
|
||||
if (!sema_analyse_expr(context, ident)) return false;
|
||||
if (ident->expr_kind != EXPR_IDENTIFIER)
|
||||
@@ -456,7 +456,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr)
|
||||
Decl *decl = ident->identifier_expr.decl;
|
||||
if (decl->decl_kind != DECL_VAR)
|
||||
{
|
||||
SEMA_ERROR(ident, "Expected this to be the name of a failable variable, but it isn't. Did you mistype?");
|
||||
SEMA_ERROR(ident, "Expected this to be the name of an optional variable, but it isn't. Did you mistype?");
|
||||
return false;
|
||||
}
|
||||
if (!IS_OPTIONAL(decl))
|
||||
@@ -466,7 +466,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr)
|
||||
SEMA_ERROR(ident, "This variable is already unwrapped, so you cannot use 'try' on it again, please remove the 'try'.");
|
||||
return false;
|
||||
}
|
||||
SEMA_ERROR(ident, "Expected this variable to be a failable, otherwise it can't be used for unwrap, maybe you didn't intend to use 'try'?");
|
||||
SEMA_ERROR(ident, "Expected this variable to be an optional, otherwise it can't be used for unwrap, maybe you didn't intend to use 'try'?");
|
||||
return false;
|
||||
}
|
||||
expr->try_unwrap_expr.decl = decl;
|
||||
@@ -492,7 +492,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr)
|
||||
if (!sema_resolve_type_info(context, var_type)) return false;
|
||||
if (IS_OPTIONAL(var_type))
|
||||
{
|
||||
SEMA_ERROR(var_type, "Only non-failable types may be used as types for 'try', please remove the '!'.");
|
||||
SEMA_ERROR(var_type, "Only non-optional types may be used as types for 'try', please remove the '!'.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -506,30 +506,30 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr)
|
||||
// 3b. Make sure it's assignable
|
||||
if (!sema_expr_check_assign(context, ident)) return false;
|
||||
|
||||
// 3c. It can't be failable either.
|
||||
// 3c. It can't be optional either.
|
||||
if (IS_OPTIONAL(ident))
|
||||
{
|
||||
if (ident->expr_kind == EXPR_IDENTIFIER)
|
||||
{
|
||||
SEMA_ERROR(ident, "This is a failable variable, you should only have non-failable variables on the left side unless you use 'try' without '='.");
|
||||
SEMA_ERROR(ident, "This is an optional variable, you should only have non-optional variables on the left side unless you use 'try' without '='.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SEMA_ERROR(ident, "This is a failable expression, it can't go on the left hand side of a 'try'.");
|
||||
SEMA_ERROR(ident, "This is an optional expression, it can't go on the left hand side of a 'try'.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3d. We can now analyse the expression using the variable type.
|
||||
if (!sema_analyse_expr(context, failable)) return false;
|
||||
if (!sema_analyse_expr(context, optional)) return false;
|
||||
|
||||
if (!IS_OPTIONAL(failable))
|
||||
if (!IS_OPTIONAL(optional))
|
||||
{
|
||||
SEMA_ERROR(failable, "Expected a failable expression to 'try' here. If it isn't a failable, remove 'try'.");
|
||||
SEMA_ERROR(optional, "Expected an optional expression to 'try' here. If it isn't an optional, remove 'try'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cast_implicit(context, failable, ident->type)) return false;
|
||||
if (!cast_implicit(context, optional, ident->type)) return false;
|
||||
|
||||
expr->try_unwrap_expr.assign_existing = true;
|
||||
expr->try_unwrap_expr.lhs = ident;
|
||||
@@ -559,23 +559,23 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr)
|
||||
}
|
||||
|
||||
// 4b. Evaluate the expression
|
||||
if (!sema_analyse_expr(context, failable)) return false;
|
||||
if (!sema_analyse_expr(context, optional)) return false;
|
||||
|
||||
if (!IS_OPTIONAL(failable))
|
||||
if (!IS_OPTIONAL(optional))
|
||||
{
|
||||
SEMA_ERROR(failable, "Expected a failable expression to 'try' here. If it isn't a failable, remove 'try'.");
|
||||
SEMA_ERROR(optional, "Expected an optional expression to 'try' here. If it isn't an optional, remove 'try'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (var_type)
|
||||
{
|
||||
if (!cast_implicit(context, failable, var_type->type)) return false;
|
||||
if (!cast_implicit(context, optional, var_type->type)) return false;
|
||||
}
|
||||
|
||||
// 4c. Create a type_info if needed.
|
||||
if (!var_type)
|
||||
{
|
||||
var_type = type_info_new_base(failable->type->failable, failable->span);
|
||||
var_type = type_info_new_base(optional->type->optional, optional->span);
|
||||
}
|
||||
|
||||
// 4d. A new declaration is created.
|
||||
@@ -587,7 +587,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr)
|
||||
expr->try_unwrap_expr.decl = decl;
|
||||
}
|
||||
|
||||
expr->try_unwrap_expr.failable = failable;
|
||||
expr->try_unwrap_expr.optional = optional;
|
||||
expr->type = type_bool;
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
@@ -698,7 +698,7 @@ RESOLVE_EXPRS:;
|
||||
if (!sema_analyse_expr(context, fail)) return false;
|
||||
if (!type_is_optional(fail->type))
|
||||
{
|
||||
SEMA_ERROR(fail, "This expression is not failable, did you add it by mistake?");
|
||||
SEMA_ERROR(fail, "This expression is not optional, did you add it by mistake?");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -718,7 +718,7 @@ static void sema_remove_unwraps_from_try(SemaContext *c, Expr *cond)
|
||||
Expr *expr = chain[i];
|
||||
if (expr->expr_kind != EXPR_TRY_UNWRAP) continue;
|
||||
if (expr->try_unwrap_expr.assign_existing) continue;
|
||||
if (expr->try_unwrap_expr.failable)
|
||||
if (expr->try_unwrap_expr.optional)
|
||||
{
|
||||
sema_erase_var(c, expr->try_unwrap_expr.decl);
|
||||
}
|
||||
@@ -884,7 +884,7 @@ static inline bool sema_analyse_cond(SemaContext *context, Expr *expr, CondType
|
||||
SEMA_ERROR(last, "Expected a declaration with initializer.");
|
||||
return false;
|
||||
}
|
||||
// 3e. Expect that it isn't a failable
|
||||
// 3e. Expect that it isn't an optional
|
||||
if (IS_OPTIONAL(init) && !decl->var.unwrap)
|
||||
{
|
||||
return sema_error_failed_cast(last, last->type, cast_to_bool ? type_bool : init->type);
|
||||
@@ -1185,7 +1185,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
|
||||
|
||||
if (IS_OPTIONAL(enumerator))
|
||||
{
|
||||
SEMA_ERROR(enumerator, "The expression may not be failable.");
|
||||
SEMA_ERROR(enumerator, "The expression may not be optional.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1259,7 +1259,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
|
||||
|
||||
if (type_is_optional(var->var.type_info->type))
|
||||
{
|
||||
SEMA_ERROR(var->var.type_info, "The variable may not be a failable.");
|
||||
SEMA_ERROR(var->var.type_info, "The variable may not be an optional.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1272,7 +1272,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
|
||||
index_var_type = index->var.type_info->type;
|
||||
if (type_is_optional(index_var_type))
|
||||
{
|
||||
SEMA_ERROR(index->var.type_info, "The index may not be a failable.");
|
||||
SEMA_ERROR(index->var.type_info, "The index may not be an optional.");
|
||||
return false;
|
||||
}
|
||||
if (!type_is_integer(type_flatten(index_var_type)))
|
||||
|
||||
@@ -412,7 +412,7 @@ APPEND_QUALIFIERS:
|
||||
type_info->type = type_get_subarray(type_get_subarray(type_info->type));
|
||||
break;
|
||||
}
|
||||
if (type_info->failable)
|
||||
if (type_info->optional)
|
||||
{
|
||||
Type *type = type_info->type;
|
||||
if (!type_is_optional(type)) type_info->type = type_get_optional(type);
|
||||
|
||||
@@ -18,7 +18,7 @@ void tinybackend_codegen_setup()
|
||||
}
|
||||
|
||||
static inline bool tinybackend_value_is_addr(TBEValue *value)
|
||||
{ return value->kind == TBE_ADDRESS || value->kind == TBE_ADDRESS_FAILABLE; }
|
||||
{ return value->kind == TBE_ADDRESS || value->kind == TBE_ADDRESS_OPTIONAL; }
|
||||
|
||||
|
||||
static TB_CallingConv tilde_call_convention(CallABI abi)
|
||||
@@ -299,7 +299,7 @@ static TB_FunctionPrototype *tilde_get_function_type(TB_Module *module, Function
|
||||
break;
|
||||
}
|
||||
|
||||
// If it's failable and it's not void (meaning ret_abi_info will be NULL)
|
||||
// If it's optional and it's not void (meaning ret_abi_info will be NULL)
|
||||
if (prototype->ret_by_ref)
|
||||
{
|
||||
add_func_type_param(type_get_ptr(type_lowering(prototype->ret_by_ref_type)),
|
||||
@@ -505,7 +505,7 @@ static inline void tilde_emit_block(TbContext *c, TB_Label label)
|
||||
TB_Register tilde_value_rvalue_get(TbContext *c, TBEValue *value)
|
||||
{
|
||||
if (value->kind == TBE_VALUE) return value->reg;
|
||||
//llvm_value_fold_failable(c, value);
|
||||
//llvm_value_fold_optional(c, value);
|
||||
return tilde_load_aligned(c,
|
||||
tbtype(value->type),
|
||||
value->reg,
|
||||
@@ -694,7 +694,7 @@ static void tinybackend_emit_binary_expr(TbContext *c, TBEValue *TBE_VALUE, Expr
|
||||
tinybackend_emit_exprid(c, TBE_VALUE, expr->binary_expr.left);
|
||||
assert(tinybackend_value_is_addr(TBE_VALUE));
|
||||
|
||||
*TBE_VALUE = tilde_emit_assign_expr(c, TBE_VALUE, exprptr(expr->binary_expr.right), TB_NULL_REG /* failable_ref */);
|
||||
*TBE_VALUE = tilde_emit_assign_expr(c, TBE_VALUE, exprptr(expr->binary_expr.right), TB_NULL_REG /* optional_ref */);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -767,7 +767,7 @@ static TB_Register tilde_emit_local_decl(TbContext *c, Decl *decl)
|
||||
scratch_buffer_append(decl->name);
|
||||
scratch_buffer_append(".f");
|
||||
decl->var.tb_failable_reg = tb_inst_local(c->f, type_size(type_anyerr), type_alloca_alignment(type_anyerr));
|
||||
// Only clear out the result if the assignment isn't a failable.
|
||||
// Only clear out the result if the assignment isn't an optional.
|
||||
}
|
||||
|
||||
TBEValue value;
|
||||
|
||||
@@ -271,7 +271,7 @@ void tilde_emit_call_expr(TbContext *c, TBEValue *result_value, Expr *expr)
|
||||
ABIArgInfo *ret_info = prototype->ret_abi_info;
|
||||
Type *call_return_type = prototype->abi_ret_type;
|
||||
|
||||
// 5. In the case of a failable, the error is replacing the regular return abi.
|
||||
// 5. In the case of an optional, the error is replacing the regular return abi.
|
||||
TB_Reg error_var = 0;
|
||||
|
||||
*result_value = (TBEValue){ .kind = TBE_VALUE, .reg = 0 };
|
||||
|
||||
@@ -58,7 +58,7 @@ static AlignSize max_alignment_vector;
|
||||
#define SUB_ARRAY_OFFSET 3
|
||||
#define SCALED_VECTOR_OFFSET 4
|
||||
#define INFERRED_VECTOR_OFFSET 5
|
||||
#define FAILABLE_OFFSET 6
|
||||
#define OPTIONAL_OFFSET 6
|
||||
#define ARRAY_OFFSET 7
|
||||
|
||||
Type *type_cint;
|
||||
@@ -126,13 +126,13 @@ static void type_append_name_to_scratch(Type *type)
|
||||
type_append_name_to_scratch(type->pointer);
|
||||
scratch_buffer_append_char('*');
|
||||
break;
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
scratch_buffer_append("void!");
|
||||
break;
|
||||
case TYPE_OPTIONAL:
|
||||
if (type->failable)
|
||||
if (type->optional)
|
||||
{
|
||||
type_append_name_to_scratch(type->failable);
|
||||
type_append_name_to_scratch(type->optional);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -241,7 +241,7 @@ const char *type_to_error_string(Type *type)
|
||||
return "typeinfo";
|
||||
case TYPE_TYPEID:
|
||||
return "typeid";
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
return "void!";
|
||||
case TYPE_POINTER:
|
||||
if (type->pointer->type_kind == TYPE_FUNC)
|
||||
@@ -250,8 +250,8 @@ const char *type_to_error_string(Type *type)
|
||||
}
|
||||
return str_printf("%s*", type_to_error_string(type->pointer));
|
||||
case TYPE_OPTIONAL:
|
||||
if (!type->failable) return "void!";
|
||||
return str_printf("%s!", type_to_error_string(type->failable));
|
||||
if (!type->optional) return "void!";
|
||||
return str_printf("%s!", type_to_error_string(type->optional));
|
||||
case TYPE_ARRAY:
|
||||
return str_printf("%s[%llu]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
@@ -291,7 +291,7 @@ RETRY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
return 0;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
type = type->optional;
|
||||
goto RETRY;
|
||||
case TYPE_TYPEDEF:
|
||||
type = type->canonical;
|
||||
@@ -306,7 +306,7 @@ RETRY:
|
||||
assert(type->decl->resolve_status == RESOLVE_DONE);
|
||||
return type->decl->strukt.size;
|
||||
case TYPE_VOID:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
return 1;
|
||||
case TYPE_BOOL:
|
||||
case TYPE_TYPEID:
|
||||
@@ -377,7 +377,7 @@ bool type_is_abi_aggregate(Type *type)
|
||||
case TYPE_POISONED:
|
||||
return false;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
type = type->optional;
|
||||
goto RETRY;
|
||||
case TYPE_DISTINCT:
|
||||
type = type->decl->distinct_decl.base_type;
|
||||
@@ -388,7 +388,7 @@ bool type_is_abi_aggregate(Type *type)
|
||||
case TYPE_BITSTRUCT:
|
||||
case ALL_FLOATS:
|
||||
case TYPE_VOID:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case ALL_INTS:
|
||||
case TYPE_BOOL:
|
||||
case TYPE_TYPEID:
|
||||
@@ -497,7 +497,7 @@ void type_mangle_introspect_name_to_buffer(Type *type)
|
||||
case TYPE_INFERRED_ARRAY:
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_MEMBER:
|
||||
UNREACHABLE
|
||||
case TYPE_VOID:
|
||||
@@ -523,7 +523,7 @@ void type_mangle_introspect_name_to_buffer(Type *type)
|
||||
return;
|
||||
case TYPE_OPTIONAL:
|
||||
scratch_buffer_append("f$");
|
||||
type_mangle_introspect_name_to_buffer(type->failable);
|
||||
type_mangle_introspect_name_to_buffer(type->optional);
|
||||
return;
|
||||
case TYPE_VECTOR:
|
||||
scratch_buffer_append_char('v');
|
||||
@@ -634,10 +634,10 @@ AlignSize type_abi_alignment(Type *type)
|
||||
return alignment;
|
||||
}
|
||||
case TYPE_VOID:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
return 1;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
type = type->optional;
|
||||
goto RETRY;
|
||||
case TYPE_DISTINCT:
|
||||
type = type->decl->distinct_decl.base_type;
|
||||
@@ -710,29 +710,29 @@ static Type *type_generate_ptr(Type *ptr_type, bool canonical)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static Type *type_generate_failable(Type *failable_type, bool canonical)
|
||||
static Type *type_generate_optional(Type *optional_type, bool canonical)
|
||||
{
|
||||
if (canonical) failable_type = failable_type->canonical;
|
||||
if (!failable_type->type_cache)
|
||||
if (canonical) optional_type = optional_type->canonical;
|
||||
if (!optional_type->type_cache)
|
||||
{
|
||||
create_type_cache(failable_type);
|
||||
create_type_cache(optional_type);
|
||||
}
|
||||
Type *failable = failable_type->type_cache[FAILABLE_OFFSET];
|
||||
if (failable == NULL)
|
||||
Type *optional = optional_type->type_cache[OPTIONAL_OFFSET];
|
||||
if (optional == NULL)
|
||||
{
|
||||
failable = type_new(TYPE_OPTIONAL, str_printf("%s!", failable_type->name));
|
||||
failable->pointer = failable_type;
|
||||
failable_type->type_cache[FAILABLE_OFFSET] = failable;
|
||||
if (failable_type == failable_type->canonical)
|
||||
optional = type_new(TYPE_OPTIONAL, str_printf("%s!", optional_type->name));
|
||||
optional->pointer = optional_type;
|
||||
optional_type->type_cache[OPTIONAL_OFFSET] = optional;
|
||||
if (optional_type == optional_type->canonical)
|
||||
{
|
||||
failable->canonical = failable;
|
||||
optional->canonical = optional;
|
||||
}
|
||||
else
|
||||
{
|
||||
failable->canonical = type_generate_failable(failable_type->canonical, true);
|
||||
optional->canonical = type_generate_optional(optional_type->canonical, true);
|
||||
}
|
||||
}
|
||||
return failable;
|
||||
return optional;
|
||||
}
|
||||
|
||||
static Type *type_generate_subarray(Type *arr_type, bool canonical)
|
||||
@@ -870,10 +870,10 @@ static Type *type_generate_scaled_vector(Type *arr_type, bool canonical)
|
||||
|
||||
Type *type_get_ptr_recurse(Type *ptr_type)
|
||||
{
|
||||
assert(ptr_type->type_kind != TYPE_FAILABLE_ANY);
|
||||
assert(ptr_type->type_kind != TYPE_OPTIONAL_ANY);
|
||||
if (ptr_type->type_kind == TYPE_OPTIONAL)
|
||||
{
|
||||
ptr_type = ptr_type->failable;
|
||||
ptr_type = ptr_type->optional;
|
||||
return type_get_optional(type_get_ptr(ptr_type));
|
||||
}
|
||||
return type_get_ptr(ptr_type);
|
||||
@@ -885,10 +885,10 @@ Type *type_get_ptr(Type *ptr_type)
|
||||
return type_generate_ptr(ptr_type, false);
|
||||
}
|
||||
|
||||
Type *type_get_optional(Type *failable_type)
|
||||
Type *type_get_optional(Type *optional_type)
|
||||
{
|
||||
assert(!type_is_optional(failable_type));
|
||||
return type_generate_failable(failable_type, false);
|
||||
assert(!type_is_optional(optional_type));
|
||||
return type_generate_optional(optional_type, false);
|
||||
}
|
||||
|
||||
Type *type_get_subarray(Type *arr_type)
|
||||
@@ -1236,7 +1236,7 @@ static bool compare_func_param(Type *one, Type *other)
|
||||
case TYPE_FUNC:
|
||||
return one->function.prototype->raw_type == other->function.prototype->raw_type;
|
||||
case TYPE_OPTIONAL:
|
||||
return compare_func_param(one->failable, other->failable);
|
||||
return compare_func_param(one->optional, other->optional);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1270,7 +1270,7 @@ static Type *flatten_raw_function_type(Type *type)
|
||||
case TYPE_FUNC:
|
||||
return type->function.prototype->raw_type;
|
||||
case TYPE_OPTIONAL:
|
||||
current = type->failable;
|
||||
current = type->optional;
|
||||
other = flatten_raw_function_type(current);
|
||||
return other == current ? type : type_get_optional(other);
|
||||
case TYPE_POINTER:
|
||||
@@ -1307,9 +1307,9 @@ static inline Type *func_create_new_func_proto(Signature *sig, CallABI abi, uint
|
||||
proto->rtype = rtype;
|
||||
if (type_is_optional(rtype))
|
||||
{
|
||||
proto->is_failable = true;
|
||||
Type *real_return_type = rtype->failable;
|
||||
proto->ret_by_ref_type = rtype->failable;
|
||||
proto->is_optional = true;
|
||||
Type *real_return_type = rtype->optional;
|
||||
proto->ret_by_ref_type = rtype->optional;
|
||||
proto->ret_by_ref = real_return_type->type_kind != TYPE_VOID;
|
||||
proto->abi_ret_type = type_anyerr;
|
||||
}
|
||||
@@ -1455,7 +1455,7 @@ void type_setup(PlatformTarget *target)
|
||||
type_create("typeinfo", &t.typeinfo, TYPE_TYPEINFO, 1, 1, 1);
|
||||
type_create("member_ref", &t.member, TYPE_MEMBER, 1, 1, 1);
|
||||
type_create("untyped_list", &t.untyped_list, TYPE_UNTYPED_LIST, 1, 1, 1);
|
||||
type_create("void!", &t.anyfail, TYPE_FAILABLE_ANY, 1, 1, 1);
|
||||
type_create("void!", &t.anyfail, TYPE_OPTIONAL_ANY, 1, 1, 1);
|
||||
type_init("typeid", &t.typeid, TYPE_TYPEID, target->width_pointer, target->align_pointer);
|
||||
type_init("void*", &t.voidstar, TYPE_POINTER, target->width_pointer, target->align_pointer);
|
||||
create_type_cache(type_void);
|
||||
@@ -1517,7 +1517,7 @@ bool type_is_scalar(Type *type)
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_ANY:
|
||||
case TYPE_FLEXIBLE_ARRAY:
|
||||
case TYPE_SCALED_VECTOR:
|
||||
@@ -1538,7 +1538,7 @@ bool type_is_scalar(Type *type)
|
||||
type = type->decl->distinct_decl.base_type;
|
||||
goto RETRY;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
type = type->optional;
|
||||
if (!type) return false;
|
||||
goto RETRY;
|
||||
case TYPE_TYPEDEF:
|
||||
@@ -1731,7 +1731,7 @@ bool type_may_have_method(Type *type)
|
||||
case TYPE_FUNC:
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_MEMBER:
|
||||
return false;
|
||||
@@ -1891,7 +1891,7 @@ Type *type_find_max_type(Type *type, Type *other)
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
case TYPE_POISONED:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
UNREACHABLE
|
||||
case TYPE_VOID:
|
||||
case TYPE_BOOL:
|
||||
@@ -2087,7 +2087,7 @@ unsigned type_get_introspection_kind(TypeKind kind)
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
return INTROSPECT_TYPE_VECTOR;
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_OPTIONAL:
|
||||
case TYPE_MEMBER:
|
||||
@@ -2136,10 +2136,10 @@ Module *type_base_module(Type *type)
|
||||
type = type->array.base;
|
||||
goto RETRY;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->failable;
|
||||
type = type->optional;
|
||||
goto RETRY;
|
||||
case TYPE_UNTYPED_LIST:
|
||||
case TYPE_FAILABLE_ANY:
|
||||
case TYPE_OPTIONAL_ANY:
|
||||
case TYPE_TYPEINFO:
|
||||
case TYPE_MEMBER:
|
||||
UNREACHABLE
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.3.124"
|
||||
#define COMPILER_VERSION "0.3.125"
|
||||
8
test/test_suite/builtins/builtin_with_optional.c3
Normal file
8
test/test_suite/builtins/builtin_with_optional.c3
Normal file
@@ -0,0 +1,8 @@
|
||||
fn void main()
|
||||
{
|
||||
float x;
|
||||
x = $$fma(x, x, x);
|
||||
float! y;
|
||||
y = $$fma(x, x, y);
|
||||
x = $$fma(x, x, y); // #error: 'float!'
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
fault Error
|
||||
{}
|
||||
|
||||
define Foo1 = distinct Error; // #error: You cannot create a distinct type from an error
|
||||
define Foo1 = distinct Error; // #error: You cannot create a distinct
|
||||
|
||||
define Foo3 = distinct void; // #error: create a distinct type from 'void'
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ fn void syntaxErrors()
|
||||
if (i + 1) {} // #error: optional, but was 'int!'
|
||||
for (int x = i;;) {} // #error: 'int!' to 'int'
|
||||
for (int x = 0; x < i + 1;) {} // #error: optional, but was 'bool!'.
|
||||
for (int x = 0; x < 10; x += i + 1) {} // #error: Cannot assign a failable value to a non-failable
|
||||
for (int x = 0; x < 10; x += i + 1) {} // #error: Cannot assign an optional value to a non-optional
|
||||
switch (i + 1) // #error: optional, but was 'int!'
|
||||
{
|
||||
default:
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
|
||||
fn void test()
|
||||
{
|
||||
test()?; // #error: No failable to rethrow before '?' in the expression, please remove '?'
|
||||
test()?; // #error: No optional to rethrow before '?' in the expression, please remove '?'
|
||||
int i = 0;
|
||||
if (i?) return; // #error: No failable to rethrow before '?' in the expression, please remove '?'
|
||||
if (i?) return; // #error: No optional to rethrow before '?' in the expression, please remove '?'
|
||||
int! j = 0;
|
||||
if (j?) return; // #error: This expression implicitly returns with a failable result, but the function
|
||||
if ((j?)?) return; // #error: This expression implicitly returns with a failable result, but the function
|
||||
if (j?) return; // #error: This expression implicitly returns with an optional result, but the function
|
||||
if ((j?)?) return; // #error: This expression implicitly returns with an optional result, but the function
|
||||
}
|
||||
|
||||
fn void! test2()
|
||||
{
|
||||
int! j = 0;
|
||||
if (j?) return;
|
||||
if ((j?)?) return; // #error: No failable to rethrow before '?' in the expression, please remove '?'
|
||||
if ((j?)?) return; // #error: No optional to rethrow before '?' in the expression, please remove '?'
|
||||
}
|
||||
@@ -28,7 +28,7 @@ fn void test4()
|
||||
|
||||
int! a;
|
||||
int b;
|
||||
if (try b = 1) {} // #error: Expected a failable expression to 'try' here. If it isn't a failable, remove 'try'
|
||||
if (try b = 1) {} // #error: remove 'try'
|
||||
}
|
||||
|
||||
fn void test5()
|
||||
@@ -36,7 +36,7 @@ fn void test5()
|
||||
|
||||
int! a;
|
||||
int b;
|
||||
if (try a = a) {} // #error: This is a failable variable, you should only have non-failable variables on the left side unless you use 'try' without '='
|
||||
if (try a = a) {} // #error: you use 'try' without '='
|
||||
}
|
||||
|
||||
fn void test6()
|
||||
|
||||
@@ -33,12 +33,12 @@ fn void test4()
|
||||
|
||||
fn void test5()
|
||||
{
|
||||
foreach (int! y : z) foo(); // #error: The variable may not be a failable.
|
||||
foreach (int! y : z) foo(); // #error: The variable may not be an optional.
|
||||
}
|
||||
|
||||
fn void test6()
|
||||
{
|
||||
foreach (int! i, y : z) foo(); // #error: The index may not be a failable.
|
||||
foreach (int! i, y : z) foo(); // #error: The index may not be an optional.
|
||||
}
|
||||
|
||||
fn void test7()
|
||||
|
||||
@@ -33,12 +33,12 @@ fn void test4()
|
||||
|
||||
fn void test5()
|
||||
{
|
||||
foreach_r (int! y : z) foo(); // #error: The variable may not be a failable.
|
||||
foreach_r (int! y : z) foo(); // #error: The variable may not be an optional.
|
||||
}
|
||||
|
||||
fn void test6()
|
||||
{
|
||||
foreach_r (int! i, y : z) foo(); // #error: The index may not be a failable.
|
||||
foreach_r (int! i, y : z) foo(); // #error: The index may not be an optional.
|
||||
}
|
||||
|
||||
fn void test7()
|
||||
|
||||
@@ -4,7 +4,7 @@ fn void test()
|
||||
{
|
||||
int[3]! x;
|
||||
int g;
|
||||
foreach_r (z : x) // #error: The expression may not be failable.
|
||||
foreach_r (z : x) // #error: The expression may not be optional.
|
||||
{
|
||||
g += z;
|
||||
x[0] = 1;
|
||||
|
||||
@@ -4,7 +4,7 @@ fn void test()
|
||||
{
|
||||
int[3]! x;
|
||||
int g;
|
||||
foreach (z : x) // #error: The expression may not be failable.
|
||||
foreach (z : x) // #error: The expression may not be optional.
|
||||
{
|
||||
g += z;
|
||||
x[0] = 1;
|
||||
|
||||
@@ -30,5 +30,5 @@ fn void test3()
|
||||
{
|
||||
x = !x;
|
||||
}
|
||||
while (x); // #error: A failable 'bool!' cannot be implicitly converted to a regular boolean value
|
||||
while (x); // #error: 'bool!' cannot be implicitly converted to a regular boolean value
|
||||
}
|
||||
8
test/test_suite2/builtins/builtin_with_optional.c3
Normal file
8
test/test_suite2/builtins/builtin_with_optional.c3
Normal file
@@ -0,0 +1,8 @@
|
||||
fn void main()
|
||||
{
|
||||
float x;
|
||||
x = $$fma(x, x, x);
|
||||
float! y;
|
||||
y = $$fma(x, x, y);
|
||||
x = $$fma(x, x, y); // #error: 'float!'
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
fault Error
|
||||
{}
|
||||
|
||||
define Foo1 = distinct Error; // #error: You cannot create a distinct type from an error
|
||||
define Foo1 = distinct Error; // #error: You cannot create a distinct type
|
||||
|
||||
define Foo3 = distinct void; // #error: create a distinct type from 'void'
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ fn void syntaxErrors()
|
||||
if (i + 1) {} // #error: optional, but was 'int!'
|
||||
for (int x = i;;) {} // #error: 'int!' to 'int'
|
||||
for (int x = 0; x < i + 1;) {} // #error: optional, but was 'bool!'.
|
||||
for (int x = 0; x < 10; x += i + 1) {} // #error: Cannot assign a failable value to a non-failable
|
||||
for (int x = 0; x < 10; x += i + 1) {} // #error: Cannot assign an optional value to a non-optional
|
||||
switch (i + 1) // #error: optional, but was 'int!'
|
||||
{
|
||||
default:
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
|
||||
fn void test()
|
||||
{
|
||||
test()?; // #error: No failable to rethrow before '?' in the expression, please remove '?'
|
||||
test()?; // #error: No optional to rethrow before '?' in the expression, please remove '?'
|
||||
int i = 0;
|
||||
if (i?) return; // #error: No failable to rethrow before '?' in the expression, please remove '?'
|
||||
if (i?) return; // #error: No optional to rethrow before '?' in the expression, please remove '?'
|
||||
int! j = 0;
|
||||
if (j?) return; // #error: This expression implicitly returns with a failable result, but the function
|
||||
if ((j?)?) return; // #error: This expression implicitly returns with a failable result, but the function
|
||||
if (j?) return; // #error: This expression implicitly returns with an optional result, but the function
|
||||
if ((j?)?) return; // #error: This expression implicitly returns with an optional result, but the function
|
||||
}
|
||||
|
||||
fn void! test2()
|
||||
{
|
||||
int! j = 0;
|
||||
if (j?) return;
|
||||
if ((j?)?) return; // #error: No failable to rethrow before '?' in the expression, please remove '?'
|
||||
if ((j?)?) return; // #error: No optional to rethrow before '?' in the expression, please remove '?'
|
||||
}
|
||||
@@ -28,7 +28,7 @@ fn void test4()
|
||||
|
||||
int! a;
|
||||
int b;
|
||||
if (try b = 1) {} // #error: Expected a failable expression to 'try' here. If it isn't a failable, remove 'try'
|
||||
if (try b = 1) {} // #error: remove 'try'
|
||||
}
|
||||
|
||||
fn void test5()
|
||||
@@ -36,7 +36,7 @@ fn void test5()
|
||||
|
||||
int! a;
|
||||
int b;
|
||||
if (try a = a) {} // #error: This is a failable variable, you should only have non-failable variables on the left side unless you use 'try' without '='
|
||||
if (try a = a) {} // #error: you use 'try' without '='
|
||||
}
|
||||
|
||||
fn void test6()
|
||||
|
||||
@@ -26,7 +26,7 @@ fn void! testMayError()
|
||||
|
||||
fn void main()
|
||||
{
|
||||
// ratio has a failable type.
|
||||
// ratio has an optional type.
|
||||
double! ratio = divide(foo(), bar());
|
||||
|
||||
// Handle the error
|
||||
|
||||
@@ -33,12 +33,12 @@ fn void test4()
|
||||
|
||||
fn void test5()
|
||||
{
|
||||
foreach (int! y : z) foo(); // #error: The variable may not be a failable.
|
||||
foreach (int! y : z) foo(); // #error: The variable may not be an optional.
|
||||
}
|
||||
|
||||
fn void test6()
|
||||
{
|
||||
foreach (int! i, y : z) foo(); // #error: The index may not be a failable.
|
||||
foreach (int! i, y : z) foo(); // #error: The index may not be an optional.
|
||||
}
|
||||
|
||||
fn void test7()
|
||||
|
||||
@@ -33,12 +33,12 @@ fn void test4()
|
||||
|
||||
fn void test5()
|
||||
{
|
||||
foreach_r (int! y : z) foo(); // #error: The variable may not be a failable.
|
||||
foreach_r (int! y : z) foo(); // #error: The variable may not be an optional.
|
||||
}
|
||||
|
||||
fn void test6()
|
||||
{
|
||||
foreach_r (int! i, y : z) foo(); // #error: The index may not be a failable.
|
||||
foreach_r (int! i, y : z) foo(); // #error: The index may not be an optional.
|
||||
}
|
||||
|
||||
fn void test7()
|
||||
|
||||
@@ -4,7 +4,7 @@ fn void test()
|
||||
{
|
||||
int[3]! x;
|
||||
int g;
|
||||
foreach_r (z : x) // #error: The expression may not be failable.
|
||||
foreach_r (z : x) // #error: The expression may not be optional.
|
||||
{
|
||||
g += z;
|
||||
x[0] = 1;
|
||||
|
||||
@@ -4,7 +4,7 @@ fn void test()
|
||||
{
|
||||
int[3]! x;
|
||||
int g;
|
||||
foreach (z : x) // #error: The expression may not be failable.
|
||||
foreach (z : x) // #error: The expression may not be optional.
|
||||
{
|
||||
g += z;
|
||||
x[0] = 1;
|
||||
|
||||
@@ -30,5 +30,5 @@ fn void test3()
|
||||
{
|
||||
x = !x;
|
||||
}
|
||||
while (x); // #error: A failable 'bool!' cannot be implicitly converted to a regular boolean value
|
||||
while (x); // #error: 'bool!' cannot be implicitly converted to a regular boolean value
|
||||
}
|
||||
Reference in New Issue
Block a user