Compare commits

...

1 Commits
v0.6.1 ... v0.5

42 changed files with 1000 additions and 1098 deletions

View File

@@ -0,0 +1,7 @@
c3yacc: grammar.y c3.l
bison -d grammar.y; cc -c grammar.tab.c
flex c3.l; gcc -c lex.yy.c
cc -o c3yacc lex.yy.o grammar.tab.o
clean:
rm -f c3yacc grammar.output *.o grammar.tab.* lex.yy.c

View File

@@ -8,10 +8,11 @@ UA [A-Z_0-9]
DC [a-z]
UC [A-Z]
E [Ee][+-]?{D}+
P [Pp][+-]?{D}+
%{
#include <stdio.h>
#include "y.tab.h"
#include "grammar.tab.h"
void count(void);
void comment(void);
@@ -35,9 +36,11 @@ void comment(void);
"for" { count(); return(FOR); }
"foreach" { count(); return(FOREACH); }
"foreach_r" { count(); return(FOREACH_R); }
"fn" { count(); return(FUNC); }
"fn" { count(); return(FN); }
"if" { count(); return(IF); }
"int" { count(); return(INT); }
"inline" { count(); return(INLINE); }
"ichar" { count(); return(ICHAR); }
"uint" { count(); return(UINT); }
"long" { count(); return(LONG); }
"nextcase" { count(); return(NEXTCASE); }
@@ -45,7 +48,7 @@ void comment(void);
"return" { count(); return(RETURN); }
"short" { count(); return(SHORT); }
"ushort" { count(); return(USHORT); }
"fault" { count(); return(ERROR); }
"fault" { count(); return(FAULT); }
"module" { count(); return(MODULE); }
"struct" { count(); return(STRUCT); }
"switch" { count(); return(SWITCH); }
@@ -54,17 +57,17 @@ void comment(void);
"void" { count(); return(VOID); }
"while" { count(); return(WHILE); }
"null" { count(); return(NUL); }
"$for" { count(); return(CTFOR); }
"$foreach" { count(); return(CTFOREACH); }
"$case" { count(); return(CTCASE); }
"$switch" { count(); return(CTSWITCH); }
"$default" { count(); return(CTDEFAULT); }
"$if" { count(); return(CTIF); }
"$else" { count(); return(CTELSE); }
"$endif" { count(); return(CTENDIF); }
"$endswitch" { count(); return(CTENDIF); }
"$endforeach" { count(); return(CTENDFOREACH); }
"$endfor" { count(); return(CTENDFOR); }
"$for" { count(); return(CT_FOR); }
"$foreach" { count(); return(CT_FOREACH); }
"$case" { count(); return(CT_CASE); }
"$switch" { count(); return(CT_SWITCH); }
"$default" { count(); return(CT_DEFAULT); }
"$if" { count(); return(CT_IF); }
"$else" { count(); return(CT_ELSE); }
"$endif" { count(); return(CT_ENDIF); }
"$endswitch" { count(); return(CT_ENDSWITCH); }
"$endforeach" { count(); return(CT_ENDFOREACH); }
"$endfor" { count(); return(CT_ENDFOR); }
@[_]*[A-Z]{UA}* { count(); return(AT_CONST_IDENT); }
#[_]*[A-Z]{UA}* { count(); return(HASH_CONST_IDENT); }
@@ -78,21 +81,22 @@ $[_]*[A-Z]{UA}*[a-z]{AN}* { count(); return(CT_TYPE_IDENT); }
#[_]*[a-z]{AN}* { count(); return(HASH_IDENT); }
$[_]*[a-z]{AN}* { count(); return(CT_IDENT); }
[_]*[a-z]{AN}* { count(); return(IDENT); }
0[xX]{H}+ { count(); return(CONSTANT); }
0{D}+? { count(); return(CONSTANT); }
{D}+ { count(); return(CONSTANT); }
L?'(\\.|[^\\'])+' { count(); return(CONSTANT); }
0[xX]{H}+ { count(); return(INTEGER); }
0[oO]{D}+? { count(); return(INTEGER); }
{D}+ { count(); return(INTEGER); }
{D}+{E} { count(); return(CONSTANT); }
{D}*"."{D}+({E})? { count(); return(CONSTANT); }
{D}+"."{D}*({E})? { count(); return(CONSTANT); }
{D}+{E} { count(); return(REAL); }
0[xX]{H}+{P} { count(); return(REAL); }
{D}+"."{D}*({E})? { count(); return(REAL); }
0[xX]{H}+"."{H}*({P})? { count(); return(REAL); }
L?\"(\\.|[^\\"])*\" { count(); return(STRING_LITERAL); }
\"(\\.|[^\\"])*\" { count(); return(STRING_LITERAL); }
\'(\\.|[^\\'])*\' { count(); return(CHAR_LITERAL); }
"..." { count(); return(ELLIPSIS); }
".." { count(); return(DOTDOT); }
">>=" { count(); return(RIGHT_ASSIGN); }
"<<=" { count(); return(LEFT_ASSIGN); }
">>=" { count(); return(SHR_ASSIGN); }
"<<=" { count(); return(SHL_ASSIGN); }
"+=" { count(); return(ADD_ASSIGN); }
"-=" { count(); return(SUB_ASSIGN); }
"*=" { count(); return(MUL_ASSIGN); }
@@ -101,8 +105,8 @@ L?\"(\\.|[^\\"])*\" { count(); return(STRING_LITERAL); }
"&=" { count(); return(AND_ASSIGN); }
"^=" { count(); return(XOR_ASSIGN); }
"|=" { count(); return(OR_ASSIGN); }
">>" { count(); return(RIGHT_OP); }
"<<" { count(); return(LEFT_OP); }
">>" { count(); return(SHR_OP); }
"<<" { count(); return(SHL_OP); }
"++" { count(); return(INC_OP); }
"--" { count(); return(DEC_OP); }
"&&" { count(); return(AND_OP); }
@@ -120,7 +124,6 @@ L?\"(\\.|[^\\"])*\" { count(); return(STRING_LITERAL); }
":" { count(); return(':'); }
"=" { count(); return('='); }
"(" { count(); return('('); }
"@" { count(); return(AT); }
")" { count(); return(')'); }
("[") { count(); return('['); }
("]") { count(); return(']'); }

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,11 @@
INLINE bool is_aarch64_illegal_vector(Type *type)
{
if (type->type_kind != TYPE_VECTOR) return type->type_kind == TYPE_SCALED_VECTOR;
if (type->type_kind != TYPE_VECTOR)
{
// Return true if scaled vector
return false;
}
ArraySize len = type->array.len;
if (!is_power_of_two(len)) return true;
switch (type_size(type))
@@ -22,7 +26,7 @@ INLINE bool is_aarch64_illegal_vector(Type *type)
ABIArgInfo *aarch64_coerce_illegal_vector(Type *type)
{
if (type->type_kind == TYPE_SCALED_VECTOR)
if (false /*type->type_kind == TYPE_SCALED_VECTOR*/)
{
/*
Type *base_type = type->array.base;

View File

@@ -389,7 +389,6 @@ static void x64_classify(Type *type, ByteSize offset_base, X64Class *lo_class, X
case TYPE_FAULTTYPE:
case TYPE_BITSTRUCT:
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
case CT_TYPES:
UNREACHABLE
case TYPE_VOID:
@@ -436,9 +435,6 @@ static void x64_classify(Type *type, ByteSize offset_base, X64Class *lo_class, X
case TYPE_VECTOR:
x64_classify_vector(type, offset_base, current, lo_class, hi_class, named);
break;
case TYPE_SCALED_VECTOR:
*current = CLASS_MEMORY;
break;
}
}
@@ -584,7 +580,6 @@ 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_OPTIONAL_ANY:
case CT_TYPES:
UNREACHABLE
case TYPE_I128:
@@ -596,8 +591,6 @@ AbiType x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_typ
case TYPE_UNION:
case TYPE_VECTOR:
break;
case TYPE_SCALED_VECTOR:
return (AbiType) { .type = type };
}
ByteSize size = type_size(source_type);
assert(size != source_offset);

View File

@@ -119,11 +119,8 @@ static bool x86_should_return_type_in_reg(Type *type)
case TYPE_BITSTRUCT:
case CT_TYPES:
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
case TYPE_FLEXIBLE_ARRAY:
UNREACHABLE
case TYPE_SCALED_VECTOR:
return false;
case ALL_INTS:
case ALL_FLOATS:
case TYPE_BOOL:
@@ -468,7 +465,6 @@ static ABIArgInfo *x86_classify_argument(CallABI call, Regs *regs, Type *type)
case TYPE_TYPEID:
case TYPE_BITSTRUCT:
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
case CT_TYPES:
case TYPE_FLEXIBLE_ARRAY:
UNREACHABLE
@@ -485,8 +481,6 @@ static ABIArgInfo *x86_classify_argument(CallABI call, Regs *regs, Type *type)
case TYPE_ANY:
case TYPE_ARRAY:
return x86_classify_aggregate(call, regs, type);
case TYPE_SCALED_VECTOR:
// No scaled vectors in x86
UNREACHABLE
}
UNREACHABLE

View File

@@ -184,7 +184,6 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
case TYPE_FUNC:
case TYPE_SUBARRAY:
case CT_TYPES:
case TYPE_OPTIONAL_ANY:
return false;
case TYPE_ANY:
*base = type_iptr->canonical;
@@ -238,7 +237,7 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
}
goto TYPECHECK;
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
// Same with scaled vectors
return false;
case TYPE_ARRAY:
// Empty arrays? Not homogenous.

View File

@@ -41,6 +41,8 @@ static inline Type *type_lowering(Type *type)
case TYPE_BITSTRUCT:
type = type->decl->bitstruct.base_type->type;
continue;
case TYPE_WILDCARD:
type = type_void;
default:
return type;
}

View File

@@ -1848,10 +1848,11 @@ extern Type *type_u128, *type_i128;
extern Type *type_typeid, *type_anyerr, *type_typeinfo, *type_member;
extern Type *type_any;
extern Type *type_untypedlist;
extern Type *type_anyfail;
extern Type *type_wildcard;
extern Type *type_cint;
extern Type *type_cuint;
extern Type *type_chars;
extern Type *type_wildcard_optional;
extern Type *type_string;
@@ -2343,7 +2344,7 @@ Type *type_get_subarray(Type *arr_type);
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 *optional_type);
Type *type_get_vector(Type *vector_type, unsigned len);
Type *type_get_vector_bool(Type *original_type);
@@ -2387,8 +2388,7 @@ INLINE const char *type_invalid_storage_type_name(Type *type);
INLINE bool type_is_float(Type *type);
INLINE bool type_is_floatlike(Type *type);
INLINE bool type_is_optional(Type *type);
INLINE bool type_is_optional_type(Type *type);
INLINE bool type_is_optional_any(Type *type);
INLINE bool type_is_wildcard(Type *type);
INLINE bool type_is_void(Type *type);
INLINE bool type_is_integer(Type *type);
INLINE bool type_is_integer_unsigned(Type *type);
@@ -2445,7 +2445,6 @@ INLINE Type *type_no_optional(Type *type)
{
if (!type) return NULL;
if (type->type_kind == TYPE_OPTIONAL) return type->optional;
if (type->type_kind == TYPE_OPTIONAL_ANY) return type_void;
return type;
}
@@ -2466,7 +2465,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_OPTIONAL_ANY) return type;
if (!make_optional || type->type_kind == TYPE_OPTIONAL) return type;
return type_get_optional(type);
}
@@ -2510,7 +2509,6 @@ INLINE bool type_len_is_inferred(Type *type)
case TYPE_SUBARRAY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_VECTOR:
case TYPE_SCALED_VECTOR:
type = type->array.base;
continue;
case TYPE_INFERRED_ARRAY:
@@ -2526,22 +2524,17 @@ INLINE bool type_len_is_inferred(Type *type)
}
}
INLINE bool type_is_optional(Type *type)
INLINE bool type_is_wildcard(Type *type)
{
DECL_TYPE_KIND_REAL(kind, type);
return kind == TYPE_OPTIONAL || kind == TYPE_OPTIONAL_ANY;
return type == type_wildcard || type == type_wildcard_optional;
}
INLINE bool type_is_optional_type(Type *type)
INLINE bool type_is_optional(Type *type)
{
DECL_TYPE_KIND_REAL(kind, type);
return kind == TYPE_OPTIONAL;
}
INLINE bool type_is_optional_any(Type *type)
{
return type->canonical == type_anyfail;
}
INLINE bool type_is_void(Type *type)
{
return type->canonical == type_void;
@@ -2581,15 +2574,13 @@ INLINE bool type_info_poison(TypeInfo *type)
INLINE bool type_is_arraylike(Type *type)
{
DECL_TYPE_KIND_REAL(kind, type);
return kind == TYPE_ARRAY || kind == TYPE_VECTOR || kind == TYPE_FLEXIBLE_ARRAY || kind == TYPE_SCALED_VECTOR;
return kind == TYPE_ARRAY || kind == TYPE_VECTOR || kind == TYPE_FLEXIBLE_ARRAY;
}
INLINE bool type_is_any_arraylike(Type *type)
{
DECL_TYPE_KIND_REAL(kind, type);
return kind == TYPE_ARRAY || kind == TYPE_VECTOR
|| kind == TYPE_FLEXIBLE_ARRAY || kind == TYPE_SCALED_VECTOR
|| kind == TYPE_INFERRED_VECTOR || kind == TYPE_INFERRED_ARRAY;
return kind >= TYPE_FIRST_ARRAYLIKE && kind <= TYPE_LAST_ARRAYLIKE;
}
INLINE CanonicalType *type_pointer_type(Type *type)
@@ -2674,13 +2665,16 @@ INLINE const char *type_invalid_storage_type_name(Type *type)
INLINE bool type_is_invalid_storage_type(Type *type)
{
if (!type) return false;
if (type == type_wildcard_optional) return true;
switch (type->type_kind)
{
case TYPE_MEMBER:
case TYPE_UNTYPED_LIST:
case TYPE_TYPEINFO:
case TYPE_WILDCARD:
return true;
default:
return false;
}
}
@@ -2764,8 +2758,6 @@ static inline Type *type_base(Type *type)
case TYPE_OPTIONAL:
type = type->optional;
break;
case TYPE_OPTIONAL_ANY:
return type_void;
case TYPE_TYPEDEF:
UNREACHABLE
default:
@@ -2787,8 +2779,6 @@ static inline Type *type_flatten(Type *type)
case TYPE_OPTIONAL:
type = type->optional;
break;
case TYPE_OPTIONAL_ANY:
return type_void;
case TYPE_TYPEDEF:
UNREACHABLE
default:
@@ -2879,7 +2869,7 @@ INLINE bool type_flat_is_vector_bitstruct(Type *type)
INLINE bool type_kind_is_any_vector(TypeKind kind)
{
return kind == TYPE_VECTOR || kind == TYPE_INFERRED_VECTOR || kind == TYPE_SCALED_VECTOR;
return kind == TYPE_VECTOR || kind == TYPE_INFERRED_VECTOR;
}
INLINE bool type_flat_is_bool_vector(Type *type)

View File

@@ -653,7 +653,7 @@ RETRY:
MACRO_COPY_ASTID(ast->if_stmt.else_body);
MACRO_COPY_ASTID(ast->if_stmt.then_body);
break;
case AST_NEXT_STMT:
case AST_NEXTCASE_STMT:
MACRO_COPY_EXPR(ast->nextcase_stmt.expr);
break;
case AST_NOP_STMT:
@@ -802,7 +802,6 @@ TypeInfo *copy_type_info(CopyStruct *c, TypeInfo *source)
case TYPE_INFO_INFERRED_ARRAY:
case TYPE_INFO_SUBARRAY:
case TYPE_INFO_INFERRED_VECTOR:
case TYPE_INFO_SCALED_VECTOR:
assert(source->resolve_status == RESOLVE_NOT_DONE);
copy->array.base = copy_type_info(c, source->array.base);
return copy;

View File

@@ -72,7 +72,7 @@ typedef enum
AST_RETURN_STMT,
AST_BLOCK_EXIT_STMT,
AST_SWITCH_STMT,
AST_NEXT_STMT,
AST_NEXTCASE_STMT,
AST_CONTRACT,
} AstKind;
@@ -346,7 +346,7 @@ typedef enum
PREC_SHIFT, // << >>
PREC_MULTIPLICATIVE, // * / %
PREC_UNARY, // ! - + ~ * & prefix ++/-- try? catch? (type)
PREC_CALL, // . () [] postfix ++/--
PREC_CALL, // . () [] postfix ++ -- !! ? !
PREC_MACRO,
PREC_FIRST = PREC_MACRO
} Precedence;
@@ -379,7 +379,6 @@ typedef enum
TYPE_INFO_VECTOR,
TYPE_INFO_INFERRED_ARRAY,
TYPE_INFO_INFERRED_VECTOR,
TYPE_INFO_SCALED_VECTOR,
TYPE_INFO_SUBARRAY,
TYPE_INFO_POINTER,
} TypeInfoKind;
@@ -541,7 +540,6 @@ typedef enum
TOKEN_MODULE,
TOKEN_NEXTCASE,
TOKEN_NULL,
TOKEN_PRIVATE,
TOKEN_RETURN,
TOKEN_STATIC,
TOKEN_STRUCT,
@@ -561,7 +559,6 @@ typedef enum
TOKEN_CT_DEFAULT, // $default
TOKEN_CT_DEFINED, // $defined
TOKEN_CT_ECHO, // $echo
TOKEN_CT_ELIF, // $elif
TOKEN_CT_ELSE, // $else
TOKEN_CT_ENDFOR, // $endfor
TOKEN_CT_ENDFOREACH, // $endforeach
@@ -657,22 +654,23 @@ typedef enum
TYPE_TYPEDEF,
TYPE_DISTINCT,
TYPE_ARRAY,
TYPE_FIRST_ARRAYLIKE = TYPE_ARRAY,
TYPE_SUBARRAY,
TYPE_INFERRED_ARRAY,
TYPE_FLEXIBLE_ARRAY,
TYPE_INFERRED_ARRAY,
TYPE_VECTOR,
TYPE_INFERRED_VECTOR,
TYPE_LAST_ARRAYLIKE = TYPE_INFERRED_VECTOR,
TYPE_UNTYPED_LIST,
TYPE_OPTIONAL,
TYPE_OPTIONAL_ANY,
TYPE_WILDCARD,
TYPE_TYPEINFO,
TYPE_MEMBER,
TYPE_INFERRED_VECTOR,
TYPE_SCALED_VECTOR,
TYPE_VECTOR,
TYPE_LAST = TYPE_ANY
} TypeKind;
#define CT_TYPES TYPE_TYPEINFO: case TYPE_INFERRED_ARRAY: case TYPE_INFERRED_VECTOR: case TYPE_UNTYPED_LIST: \
case TYPE_POISONED: case TYPE_MEMBER
case TYPE_POISONED: case TYPE_MEMBER: case TYPE_WILDCARD
#define ALL_INTS TYPE_I8: case TYPE_I16: case TYPE_I32: case TYPE_I64: case TYPE_I128: \
case TYPE_U8: case TYPE_U16: case TYPE_U32: case TYPE_U64: case TYPE_U128
#define ALL_SIGNED_INTS TYPE_I8: case TYPE_I16: case TYPE_I32: case TYPE_I64: case TYPE_I128

View File

@@ -554,6 +554,7 @@ void expr_rewrite_to_const_zero(Expr *expr, Type *type)
case TYPE_POISONED:
case TYPE_VOID:
case TYPE_INFERRED_VECTOR:
case TYPE_WILDCARD:
UNREACHABLE
case ALL_INTS:
expr_rewrite_const_int(expr, type, 0);
@@ -577,7 +578,6 @@ void expr_rewrite_to_const_zero(Expr *expr, Type *type)
break;
case TYPE_FUNC:
case TYPE_TYPEDEF:
case TYPE_OPTIONAL_ANY:
case TYPE_OPTIONAL:
case TYPE_TYPEINFO:
case TYPE_MEMBER:
@@ -590,7 +590,6 @@ void expr_rewrite_to_const_zero(Expr *expr, Type *type)
case TYPE_INFERRED_ARRAY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_UNTYPED_LIST:
case TYPE_SCALED_VECTOR:
case TYPE_VECTOR:
{
ConstInitializer *init = CALLOCS(ConstInitializer);

View File

@@ -47,7 +47,6 @@ static void header_print_type(FILE *file, Type *type)
{
case CT_TYPES:
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
UNREACHABLE
case TYPE_VOID:
OUTPUT("void");
@@ -104,8 +103,6 @@ static void header_print_type(FILE *file, Type *type)
header_print_type(file, type->pointer);
OUTPUT("*");
return;
case TYPE_SCALED_VECTOR:
error_exit("Scaled vectors are not supported yet.");
case TYPE_FUNC:
OUTPUT("%s", decl_get_extname(type->decl));
return;
@@ -367,8 +364,8 @@ RETRY:
case TYPE_TYPEINFO:
case TYPE_MEMBER:
case TYPE_INFERRED_VECTOR:
case TYPE_WILDCARD:
UNREACHABLE
case TYPE_OPTIONAL_ANY:
case TYPE_VOID:
case TYPE_BOOL:
case ALL_FLOATS:
@@ -447,8 +444,6 @@ RETRY:
type = type->optional;
goto RETRY;
break;
case TYPE_SCALED_VECTOR:
error_exit("Scaled vectors are not supported yet.");
case TYPE_VECTOR:
if (htable_get(table, type)) return;
OUTPUT("typedef ");

View File

@@ -534,7 +534,6 @@ static inline LLVMMetadataRef llvm_get_debug_type_internal(GenContext *c, Type *
case CT_TYPES:
UNREACHABLE
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
// If this is reachable then we're not doing the proper lowering.
UNREACHABLE
case TYPE_BOOL:
@@ -587,8 +586,6 @@ static inline LLVMMetadataRef llvm_get_debug_type_internal(GenContext *c, Type *
return type->backend_debug_type = llvm_debug_errunion_type(c, type);
case TYPE_ANY:
return type->backend_debug_type = llvm_debug_any_type(c, type);
case TYPE_SCALED_VECTOR:
UNSUPPORTED;
}
UNREACHABLE
}

View File

@@ -153,6 +153,7 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue
{
llvm_emit_expr(c, &value, expr);
}
if (value.type != type_void) llvm_store(c, ref, &value);
}
@@ -3433,7 +3434,6 @@ void llvm_emit_comp(GenContext *c, BEValue *result, BEValue *lhs, BEValue *rhs,
assert(binary_op >= BINARYOP_GT && binary_op <= BINARYOP_EQ);
switch (lhs->type->type_kind)
{
case TYPE_POISONED:
case TYPE_VOID:
UNREACHABLE;
case TYPE_BOOL:
@@ -3458,20 +3458,14 @@ void llvm_emit_comp(GenContext *c, BEValue *result, BEValue *lhs, BEValue *rhs,
case TYPE_FAULTTYPE:
case TYPE_TYPEDEF:
case TYPE_DISTINCT:
case TYPE_INFERRED_ARRAY:
case TYPE_UNTYPED_LIST:
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
case TYPE_TYPEINFO:
case TYPE_MEMBER:
case TYPE_INFERRED_VECTOR:
case CT_TYPES:
UNREACHABLE
case TYPE_FUNC:
break;
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_BITSTRUCT:
case TYPE_SCALED_VECTOR:
case TYPE_FLEXIBLE_ARRAY:
UNREACHABLE
case TYPE_SUBARRAY:
@@ -4613,9 +4607,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_OPTIONAL_ANY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
UNREACHABLE
break;
case TYPE_BOOL:
@@ -5660,8 +5652,8 @@ static inline void llvm_emit_optional(GenContext *c, BEValue *be_value, Expr *ex
// Finally we need to replace the result with something undefined here.
// It will be optimized away.
Type *type = type_no_optional(expr->type);
if (type->canonical == type_void)
Type *type = type_lowering(expr->type);
if (type == type_void)
{
llvm_value_set(be_value, NULL, type_void);
return;

View File

@@ -749,7 +749,7 @@ static void llvm_emit_switch_jump_table(GenContext *c,
static void llvm_emit_switch_body(GenContext *c, BEValue *switch_value, Ast *switch_ast)
{
bool is_if_chain = switch_ast->switch_stmt.flow.if_chain;
Type *switch_type = switch_ast->ast_kind == AST_IF_CATCH_SWITCH_STMT ? type_lowering(type_anyerr) : exprptr(switch_ast->switch_stmt.cond)->type;
Type *switch_type = switch_ast->ast_kind == AST_IF_CATCH_SWITCH_STMT ? type_lowering(type_anyerr) : switch_value->type;
Ast **cases = switch_ast->switch_stmt.cases;
ArraySize case_count = vec_size(cases);
@@ -865,11 +865,21 @@ static void llvm_emit_switch_body(GenContext *c, BEValue *switch_value, Ast *swi
llvm_emit_block(c, exit_block);
}
void gencontext_emit_switch(GenContext *context, Ast *ast)
void llvm_emit_switch(GenContext *c, Ast *ast)
{
BEValue switch_value;
llvm_emit_decl_expr_list(context, &switch_value, exprptrzero(ast->switch_stmt.cond), false);
llvm_emit_switch_body(context, &switch_value, ast);
Expr *expr = exprptrzero(ast->switch_stmt.cond);
if (expr)
{
// Regular switch
llvm_emit_decl_expr_list(c, &switch_value, expr, false);
}
else
{
// Match switch, so set the value to true
llvm_value_set(&switch_value, llvm_const_int(c, type_bool, 1), type_bool);
}
llvm_emit_switch_body(c, &switch_value, ast);
}
@@ -1472,7 +1482,7 @@ void llvm_emit_stmt(GenContext *c, Ast *ast)
case AST_FOR_STMT:
llvm_emit_for_stmt(c, ast);
break;
case AST_NEXT_STMT:
case AST_NEXTCASE_STMT:
gencontext_emit_next_stmt(c, ast);
break;
case AST_DEFER_STMT:
@@ -1495,7 +1505,7 @@ void llvm_emit_stmt(GenContext *c, Ast *ast)
case AST_CT_FOREACH_STMT:
UNREACHABLE
case AST_SWITCH_STMT:
gencontext_emit_switch(c, ast);
llvm_emit_switch(c, ast);
break;
}
}

View File

@@ -317,7 +317,6 @@ LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type)
case CT_TYPES:
UNREACHABLE
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
case TYPE_TYPEDEF:
case TYPE_DISTINCT:
case TYPE_ENUM:
@@ -368,8 +367,6 @@ LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type)
LLVMStructSetBody(virtual_type, types, 2, false);
return any_type->backend_type = virtual_type;
}
case TYPE_SCALED_VECTOR:
return any_type->backend_type = LLVMScalableVectorType(llvm_get_type(c, any_type->array.base), any_type->array.len);
case TYPE_VECTOR:
return any_type->backend_type = LLVMVectorType(llvm_get_type(c, any_type->array.base), any_type->array.len);
}
@@ -660,12 +657,7 @@ LLVMValueRef llvm_get_typeid(GenContext *c, Type *type)
}
case TYPE_TYPEDEF:
return llvm_get_typeid(c, type->canonical);
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_UNTYPED_LIST:
case TYPE_OPTIONAL_ANY:
case TYPE_TYPEINFO:
case TYPE_MEMBER:
case CT_TYPES:
UNREACHABLE
case TYPE_VOID:
return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_VOID, 0);
@@ -690,10 +682,6 @@ LLVMValueRef llvm_get_typeid(GenContext *c, Type *type)
return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_VARIANT, 0);
case TYPE_TYPEID:
return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_TYPEID, 0);
case TYPE_POISONED:
UNREACHABLE
case TYPE_SCALED_VECTOR:
UNSUPPORTED;
}
UNREACHABLE
}

View File

@@ -63,6 +63,20 @@ bool parse_range(ParseContext *c, Range *range)
return true;
}
/**
* rethrow_expr ::= call_expr '?'
*/
static Expr *parse_rethrow_expr(ParseContext *c, Expr *left_side)
{
assert(expr_ok(left_side));
advance_and_verify(c, TOKEN_QUESTION);
Expr *expr_ternary = expr_new_expr(EXPR_RETHROW, left_side);
expr_ternary->rethrow_expr.inner = left_side;
RANGE_EXTEND_PREV(expr_ternary);
return expr_ternary;
}
/**
* Parse lhs [op] [rhs]
* This will return lhs if no candidate is found.
@@ -72,6 +86,15 @@ inline Expr *parse_precedence_with_left_side(ParseContext *c, Expr *left_side, P
while (1)
{
TokenType tok = c->tok;
// Special '?' parsing
if (tok == TOKEN_QUESTION && !rules[peek((c))].prefix)
{
// Greater than rethrow precedence? Then break
if (precedence > PREC_CALL) break;
if (!expr_ok(left_side)) return left_side;
left_side = parse_rethrow_expr(c, left_side);
continue;
}
Precedence token_precedence = rules[tok].precedence;
// See if the operator precedence is greater than the last, if so exit.
// Note that if the token is not an operator then token_precedence = 0
@@ -92,7 +115,6 @@ inline Expr *parse_precedence_with_left_side(ParseContext *c, Expr *left_side, P
return left_side;
}
/**
* Parse an expression in any position.
*/
@@ -130,7 +152,7 @@ static inline Expr *parse_for_try_expr(ParseContext *c)
}
/**
* catch_unwrap ::= CATCH IDENT | (type? IDENT '=' (expr | '(' expr (',' expr) ')'))
* catch_unwrap ::= CATCH (IDENT | type? IDENT '=' (expr | '(' expr (',' expr) ')')))
*/
static inline Expr *parse_catch_unwrap(ParseContext *c)
{
@@ -234,6 +256,9 @@ static inline Expr *parse_try_unwrap_chain(ParseContext *c)
return try_unwrap_chain;
}
/**
* assert_expr ::= try_unwrap_chain | expr
*/
Expr *parse_assert_expr(ParseContext *c)
{
if (tok_is(c, TOKEN_TRY))
@@ -305,7 +330,7 @@ Expr* parse_constant_expr(ParseContext *c)
}
/**
* param_path : ('[' expression ']' | '.' IDENT)*
* param_path ::= ('[' expr ']' | '.' IDENT)*
*
* @param c
* @param path reference to the path to return
@@ -408,7 +433,7 @@ Expr *parse_vasplat(ParseContext *c)
return expr;
}
/**
* param_list ::= ('...' parameter | parameter (',' parameter)*)?
* param_list ::= ('...' arg | arg (',' arg)*)?
*
* parameter ::= (param_path '=')? expr
*/
@@ -465,11 +490,7 @@ bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *
/**
* expression_list
* : expression
* | expression_list ',' expression
* ;
* @return Ast *
* expression_list ::= decl_or_expr+
*/
Expr *parse_expression_list(ParseContext *c, bool allow_decl)
{
@@ -606,8 +627,6 @@ static Expr *parse_post_unary(ParseContext *c, Expr *left)
}
static Expr *parse_ternary_expr(ParseContext *c, Expr *left_side)
{
assert(expr_ok(left_side));
@@ -624,14 +643,7 @@ static Expr *parse_ternary_expr(ParseContext *c, Expr *left_side)
else
{
advance_and_verify(c, TOKEN_QUESTION);
if (!rules[c->tok].prefix)
{
expr_ternary->expr_kind = EXPR_RETHROW;
expr_ternary->rethrow_expr.inner = left_side;
RANGE_EXTEND_PREV(expr_ternary);
return expr_ternary;
}
ASSIGN_EXPR_OR_RET(Expr * true_expr, parse_expr(c), poisoned_expr);
ASSIGN_EXPR_OR_RET(Expr *true_expr, parse_expr(c), poisoned_expr);
expr_ternary->ternary_expr.then_expr = exprid(true_expr);
CONSUME_OR_RET(TOKEN_COLON, poisoned_expr);
}
@@ -1758,8 +1770,9 @@ ParseRule rules[TOKEN_EOF + 1] = {
[TOKEN_ANYERR] = { parse_type_identifier, NULL, PREC_NONE },
[TOKEN_VARIANT] = { parse_type_identifier, NULL, PREC_NONE },
// This is handles in a special manner for rethrow.
[TOKEN_QUESTION] = { NULL, parse_ternary_expr, PREC_TERNARY },
[TOKEN_QUESTQUEST] = { NULL, parse_binary, PREC_TERNARY},
[TOKEN_QUESTQUEST] = { NULL, parse_binary, PREC_OR},
[TOKEN_ELVIS] = { NULL, parse_ternary_expr, PREC_TERNARY },
[TOKEN_PLUSPLUS] = { parse_unary_expr, parse_post_unary, PREC_CALL },
[TOKEN_MINUSMINUS] = { parse_unary_expr, parse_post_unary, PREC_CALL },

View File

@@ -42,7 +42,6 @@ void recover_top_level(ParseContext *c)
{
switch (c->tok)
{
case TOKEN_PRIVATE:
case TOKEN_IMPORT:
case TOKEN_EXTERN:
case TOKEN_ENUM:
@@ -90,8 +89,6 @@ INLINE bool parse_decl_initializer(ParseContext *c, Decl *decl)
*/
static inline bool parse_top_level_block(ParseContext *c, Decl ***decls, TokenType end1, TokenType end2, TokenType end3)
{
consume_deprecated_symbol(c, TOKEN_COLON); // TODO remove
// Check whether we reached a terminating token or EOF
while (!tok_is(c, end1) && !tok_is(c, end2) && !tok_is(c, end3) && !tok_is(c, TOKEN_EOF))
{
@@ -117,23 +114,9 @@ static inline Decl *parse_ct_if_top_level(ParseContext *c)
advance_and_verify(c, TOKEN_CT_IF);
ASSIGN_EXPR_OR_RET(ct->ct_if_decl.expr, parse_const_paren_expr(c), poisoned_decl);
if (!parse_top_level_block(c, &ct->ct_if_decl.then, TOKEN_CT_ENDIF, TOKEN_CT_ELIF, TOKEN_CT_ELSE)) return poisoned_decl;
if (!parse_top_level_block(c, &ct->ct_if_decl.then, TOKEN_CT_ENDIF, TOKEN_CT_ENDIF, TOKEN_CT_ELSE)) return poisoned_decl;
CtIfDecl *ct_if_decl = &ct->ct_if_decl;
// Chain elif TODO remove
while (tok_is(c, TOKEN_CT_ELIF))
{
sema_warning_at(c->span, "$elif is deprecated, use $switch instead.");
Decl *ct_elif = decl_new_ct(DECL_CT_IF, c->span);
advance_and_verify(c, TOKEN_CT_ELIF);
ASSIGN_EXPR_OR_RET(ct_elif->ct_elif_decl.expr, parse_const_paren_expr(c), poisoned_decl);
if (!parse_top_level_block(c, &ct_elif->ct_elif_decl.then, TOKEN_CT_ENDIF, TOKEN_CT_ELIF, TOKEN_CT_ELSE)) return poisoned_decl;
ct_if_decl->elif = ct_elif;
ct_if_decl = &ct_elif->ct_elif_decl;
}
// <- end
// final else
if (tok_is(c, TOKEN_CT_ELSE))
{
@@ -143,7 +126,6 @@ static inline Decl *parse_ct_if_top_level(ParseContext *c)
if (!parse_top_level_block(c, &ct_else->ct_else_decl, TOKEN_CT_ENDIF, TOKEN_CT_ENDIF, TOKEN_CT_ENDIF)) return poisoned_decl;
}
CONSUME_OR_RET(TOKEN_CT_ENDIF, poisoned_decl);
consume_deprecated_symbol(c, TOKEN_EOS); // TODO remove
return ct;
}
@@ -192,14 +174,12 @@ static inline Decl *parse_ct_switch_top_level(ParseContext *c)
if (!tok_is(c, TOKEN_CT_CASE) && !tok_is(c, TOKEN_CT_DEFAULT) && !tok_is(c, TOKEN_CT_ENDSWITCH))
{
ASSIGN_EXPR_OR_RET(ct->ct_switch_decl.expr, parse_const_paren_expr(c), poisoned_decl);
consume_deprecated_symbol(c, TOKEN_COLON); // TODO remove
}
while (!try_consume(c, TOKEN_CT_ENDSWITCH))
{
ASSIGN_DECL_OR_RET(Decl *result, parse_ct_case(c), poisoned_decl);
vec_add(ct->ct_switch_decl.cases, result);
}
consume_deprecated_symbol(c, TOKEN_EOS); // TODO remove
return ct;
}
@@ -672,11 +652,7 @@ static inline TypeInfo *parse_vector_type_index(ParseContext *c, TypeInfo *type)
advance_and_verify(c, TOKEN_LVEC);
TypeInfo *vector = type_info_new(TYPE_INFO_VECTOR, type->span);
vector->array.base = type;
if (try_consume(c, TOKEN_RVEC))
{
vector->kind = TYPE_INFO_SCALED_VECTOR;
}
else if (try_consume(c, TOKEN_STAR))
if (try_consume(c, TOKEN_STAR))
{
CONSUME_OR_RET(TOKEN_RVEC, poisoned_type_info);
vector->kind = TYPE_INFO_INFERRED_VECTOR;
@@ -1497,20 +1473,16 @@ static inline bool parse_fn_parameter_list(ParseContext *c, Signature *signature
/**
* Expect pointer to after '{'
*
* struct_body
* : '{' struct_declaration_list '}'
* ;
* struct_body ::= '{' struct_declaration_list '}'
*
* struct_declaration_list
* : struct_member_declaration
* | struct_declaration_list struct_member_declaration
* ;
* struct_declaration_list ::= struct_member_decl+
*
* struct_member_declaration
* : type_expression identifier_list opt_attributes ';'
* struct_member_decl ::=
* (type_expression identifier_list opt_attributes ';')
* | struct_or_union IDENT opt_attributes struct_body
* | struct_or_union opt_attributes struct_body
* ;
* | BITSTRUCT IDENT ':' type opt_attributes struct_body
* | BITSTRUCT ':' type opt_attributes struct_body
*
* @param parent the parent of the struct
*/
@@ -1554,8 +1526,7 @@ bool parse_struct_body(ParseContext *c, Decl *parent)
index++;
if (index > MAX_MEMBERS)
{
SEMA_ERROR(member, "Can't add another member: the count would exceed maximum of %d elements.", MAX_MEMBERS);
return false;
RETURN_SEMA_ERROR(member, "Can't add another member: the count would exceed maximum of %d elements.", MAX_MEMBERS);
}
continue;
}
@@ -1564,13 +1535,11 @@ bool parse_struct_body(ParseContext *c, Decl *parent)
{
if (parent->decl_kind != DECL_STRUCT)
{
SEMA_ERROR_HERE("Only structs may have 'inline' elements, did you make a mistake?");
return false;
RETURN_SEMA_ERROR_HERE("Only structs may have 'inline' elements, did you make a mistake?");
}
if (index > 0)
{
SEMA_ERROR_LAST("Only the first element may be 'inline', did you order your fields wrong?");
return false;
RETURN_SEMA_ERROR_LAST("Only the first element may be 'inline', did you order your fields wrong?");
}
parent->is_substruct = true;
was_inline = true;
@@ -1580,26 +1549,21 @@ bool parse_struct_body(ParseContext *c, Decl *parent)
while (1)
{
if (!tok_is(c, TOKEN_IDENT))
{
SEMA_ERROR_HERE("A valid member name was expected here.");
return false;
}
if (!tok_is(c, TOKEN_IDENT)) RETURN_SEMA_ERROR_HERE("A valid member name was expected here.");
Decl *member = decl_new_var_current(c, type, VARDECL_MEMBER);
vec_add(parent->strukt.members, member);
index++;
if (index > MAX_MEMBERS)
{
SEMA_ERROR(member, "Can't add another member: the count would exceed maximum of %d elements.", MAX_MEMBERS);
return false;
RETURN_SEMA_ERROR(member, "Can't add another member: the count would exceed maximum of %d elements.", MAX_MEMBERS);
}
advance(c);
if (!parse_attributes(c, &member->attributes, NULL)) return false;
if (!try_consume(c, TOKEN_COMMA)) break;
if (was_inline)
{
SEMA_ERROR(member, "'Inline' can only be applied to a single member, so please define it on its own line.");
return false;
RETURN_SEMA_ERROR(member, "'inline' can only be applied to a single member, so please define it on its own line.");
}
}
CONSUME_EOS_OR_RET(false);
@@ -1611,11 +1575,7 @@ bool parse_struct_body(ParseContext *c, Decl *parent)
/**
* struct_declaration
* : struct_or_union TYPE_IDENT opt_attributes struct_body
* ;
*
* @param visibility
* struct_declaration ::= struct_or_union TYPE_IDENT opt_attributes struct_body
*/
static inline Decl *parse_struct_declaration(ParseContext *c)
{
@@ -1627,22 +1587,18 @@ static inline Decl *parse_struct_declaration(ParseContext *c)
Decl *decl = decl_new_with_type(symstr(c), c->span, decl_from_token(type));
if (!consume_type_name(c, type_name)) return poisoned_decl;
if (!parse_attributes_for_global(c, decl)) return poisoned_decl;
if (!parse_struct_body(c, decl)) return poisoned_decl;
if (!parse_struct_body(c, decl))
{
return poisoned_decl;
}
DEBUG_LOG("Parsed %s %s completely.", type_name, decl->name);
return decl;
}
/**
* body ::= '{' (TYPE IDENT ':' expr '..' expr EOS)* '}'
* @param c
* @param decl
* @return
* bitstruct_body ::= '{' bitstruct_def* | bitstruct_simple_def* '}'
*
* bitstruct_def ::= base_type IDENT ':' constant_expr (DOTDOT constant_expr)? ';'
* bitstruct_simple_def ::= base_type IDENT ';'
*/
static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl)
{
@@ -1651,7 +1607,7 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl)
bool is_consecutive = false;
while (!try_consume(c, TOKEN_RBRACE))
{
ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_type(c), false);
ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_base_type(c), false);
Decl *member_decl = decl_new_var_current(c, type, VARDECL_BITMEMBER);
if (!try_consume(c, TOKEN_IDENT))
@@ -1664,13 +1620,13 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl)
SEMA_ERROR_HERE("Expected a field name at this position.");
return false;
}
if (is_consecutive || tok_is(c, TOKEN_EOS))
if (tok_is(c, TOKEN_EOS))
{
if (!is_consecutive)
{
if (decl->bitstruct.members)
{
SEMA_ERROR_HERE("Expected a ':'.");
SEMA_ERROR(member_decl, "Bitstructs either have bit ranges for all members, or no members have ranges mixing is not permitted. Either add a range to this member or remove ranges from the other member(s).");
return false;
}
is_consecutive = true;
@@ -1693,13 +1649,18 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl)
member_decl->var.end = NULL;
}
CONSUME_EOS_OR_RET(false);
if (is_consecutive)
{
SEMA_ERROR(member_decl->var.start, "Bitstructs either have bit ranges for all members, or no members have ranges mixing is not permitted. Either remove this range, or add ranges to all other members.");
return false;
}
vec_add(decl->bitstruct.members, member_decl);
}
decl->bitstruct.consecutive = is_consecutive;
return true;
}
/**
* bitstruct_declaration = 'bitstruct' IDENT ':' type bitstruct_body
* bitstruct_declaration ::= 'bitstruct' TYPE_IDENT ':' type bitstruct_body
*/
static inline Decl *parse_bitstruct_declaration(ParseContext *c)
{
@@ -1730,11 +1691,11 @@ static inline Decl *parse_top_level_const_declaration(ParseContext *c)
/**
* macro_arguments ::= '(' parameters (EOS trailing_block_parameter )? ')'
* macro_params ::= parameters? (EOS trailing_block_param)?
*
* trailing_block_parameter ::= '@' IDENT ( '(' parameters ')' )?
* trailing_block_param ::= AT_IDENT ( '(' parameters? ')' )?
*/
static bool parse_macro_arguments(ParseContext *c, Decl *macro)
static bool parse_macro_params(ParseContext *c, Decl *macro)
{
CONSUME_OR_RET(TOKEN_LPAREN, false);
@@ -1797,16 +1758,17 @@ static inline void decl_add_type(Decl *decl, TypeKind kind)
decl->type = type;
}
/**
* define_type_body ::= TYPE_IDENT '=' 'distinct'? (func_typedef | type generic_params?) ';'
* typedef_declaration ::= TYPEDEF TYPE_IDENT '=' 'distinct'? typedef_type ';'
*
* typedef_type ::= func_typedef | type generic_params?
* func_typedef ::= 'fn' optional_type parameter_type_list
*/
static inline Decl *parse_define_type(ParseContext *c)
static inline Decl *parse_typedef_declaration(ParseContext *c)
{
advance(c);
advance_and_verify(c, TOKEN_TYPEDEF);
Decl *decl = decl_new(DECL_POISONED, symstr(c), c->span);
DEBUG_LOG("Parse define %s", decl->name);
DEBUG_LOG("Parse typedef %s", decl->name);
if (!try_consume(c, TOKEN_TYPE_IDENT))
{
if (token_is_any_type(c->tok))
@@ -1908,9 +1870,9 @@ static inline Decl *parse_define_type(ParseContext *c)
}
/**
* define_ident ::= 'define' (IDENT | CONST_IDENT) '=' identifier_alias generic_params?
* define_ident ::= 'define' (IDENT | CONST_IDENT | AT_IDENT) '=' identifier_alias generic_params?
*
* identifier_alias ::= path? (IDENT | CONST_IDENT)
* identifier_alias ::= path? (IDENT | CONST_IDENT | AT_IDENT)
*/
static inline Decl *parse_define_ident(ParseContext *c)
{
@@ -1996,25 +1958,13 @@ static inline Decl *parse_define_ident(ParseContext *c)
if (!params) return poisoned_decl;
decl->define_decl.generic_params = params;
}
else if (!tok_is(c, TOKEN_EOS) && decl->define_decl.ident == kw_distinct)
{
if (token_is_any_type(c->tok))
{
SEMA_ERROR(decl, "A type name alias must start with an uppercase letter.");
}
else
{
sema_error_at(decl->define_decl.span, "'distinct' can only be used with types.");
}
return poisoned_decl;
}
RANGE_EXTEND_PREV(decl);
CONSUME_EOS_OR_RET(poisoned_decl);
return decl;
}
/**
* define_attribute ::= 'define' AT_TYPE_IDENT '(' parameter_list ')' ('=' attribute_list)?
* define_attribute ::= 'define' AT_TYPE_IDENT '(' parameter_list ')' opt_attributes '=' '{' attributes? '}' ';'
*/
static inline Decl *parse_define_attribute(ParseContext *c)
{
@@ -2054,9 +2004,6 @@ static inline Decl *parse_define(ParseContext *c)
case TOKEN_AT_TYPE_IDENT:
// define @Foo = @inline, @noreturn
return parse_define_attribute(c);
case TOKEN_TYPE_IDENT:
sema_warning_at(c->span, "Defining types with 'define' is deprecated. Use 'typedef'.");
return parse_define_type(c);
default:
return parse_define_ident(c);
}
@@ -2138,7 +2085,8 @@ static inline bool parse_func_macro_header(ParseContext *c, Decl *decl)
/**
* macro ::= macro_header '(' macro_params ')' compound_statement
* macro ::= MACRO macro_header '(' macro_params ')' opt_attributes macro_body
* macro_body ::= IMPLIES expression ';' | compound_statement
*/
static inline Decl *parse_macro_declaration(ParseContext *c, AstId docs)
{
@@ -2149,7 +2097,7 @@ static inline Decl *parse_macro_declaration(ParseContext *c, AstId docs)
decl->func_decl.docs = docs;
if (!parse_func_macro_header(c, decl)) return poisoned_decl;
const char *block_parameter = NULL;
if (!parse_macro_arguments(c, decl)) return poisoned_decl;
if (!parse_macro_params(c, decl)) return poisoned_decl;
if (!parse_attributes_for_global(c, decl)) return poisoned_decl;
if (tok_is(c, TOKEN_IMPLIES))
@@ -2158,27 +2106,21 @@ static inline Decl *parse_macro_declaration(ParseContext *c, AstId docs)
parse_short_body(c, decl->func_decl.signature.rtype, true), poisoned_decl);
return decl;
}
ASSIGN_ASTID_OR_RET(decl->func_decl.body, parse_stmt(c), poisoned_decl);
ASSIGN_ASTID_OR_RET(decl->func_decl.body, parse_compound_stmt(c), poisoned_decl);
return decl;
}
/**
* error_declaration
* : FAULT TYPE_IDENT ';'
* | FAULT TYPE_IDENT '{' error_data '}'
* ;
* fault_declaration ::= FAULT opt_attributes '{' faults ','? '}'
*/
static inline Decl *parse_fault_declaration(ParseContext *c)
{
advance(c);
// advance_and_verify(context, TOKEN_ERRTYPE);
advance_and_verify(c, TOKEN_FAULT);
Decl *decl = decl_new_with_type(symstr(c), c->span, DECL_FAULT);
if (!consume_type_name(c, "fault")) return poisoned_decl;
TypeInfo *type = NULL;
CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl);
decl->enums.type_info = type_info_new_base(type_iptr->canonical, decl->span);
@@ -2201,8 +2143,7 @@ static inline Decl *parse_fault_declaration(ParseContext *c)
{
SEMA_ERROR(fault_const, "This fault value was declared twice.");
SEMA_NOTE(other_constant, "The previous declaration was here.");
decl_poison(fault_const);
break;
return poisoned_decl;
}
}
vec_add(decl->enums.values, fault_const);
@@ -2212,6 +2153,11 @@ static inline Decl *parse_fault_declaration(ParseContext *c)
EXPECT_OR_RET(TOKEN_RBRACE, poisoned_decl);
}
}
if (ordinal == 0)
{
sema_error_at(c->prev_span, "Declaration of '%s' contains no values, at least one value is required.", decl->name);
return poisoned_decl;
}
return decl;
}
@@ -2426,7 +2372,7 @@ static inline bool check_no_visibility_before(ParseContext *c, bool is_private)
/**
*
* import ::= IMPORT import_path (',' import_path)* EOS
* import ::= IMPORT import_path (',' import_path)* opt_attributes EOS
*
* @return true if import succeeded
*/
@@ -2800,11 +2746,6 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref)
AstId contracts = 0;
if (!parse_contracts(c, &contracts)) return poisoned_decl;
Decl *decl;
bool is_private = try_consume(c, TOKEN_PRIVATE); // TODO remove
if (is_private)
{
sema_warning_at(c->prev_span, "The use of 'private' is deprecated. Use '@private' instead.");
}
TokenType tok = c->tok;
if (tok != TOKEN_MODULE && !c->unit->module)
@@ -2863,7 +2804,7 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref)
return poisoned_decl;
case TOKEN_TYPEDEF:
if (contracts) goto CONTRACT_NOT_ALLOWED;
decl = parse_define_type(c);
decl = parse_typedef_declaration(c);
break;
case TOKEN_DEFINE:
if (contracts) goto CONTRACT_NOT_ALLOWED;
@@ -2967,7 +2908,6 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref)
return poisoned_decl;
}
if (!decl_ok(decl)) return decl;
if (is_private) decl->visibility = VISIBLE_PRIVATE; // TODO remove
assert(decl);
return decl;
CONTRACT_NOT_ALLOWED:
@@ -2975,11 +2915,3 @@ CONTRACT_NOT_ALLOWED:
return poisoned_decl;
}
void consume_deprecated_symbol(ParseContext *c, TokenType type)
{
if (try_consume(c, type))
{
sema_warning_at(c->prev_span, "'%s' is deprecated here.", token_type_to_string(type));
}
}

View File

@@ -5,12 +5,11 @@
#include "compiler_internal.h"
#include "parser_internal.h"
// --- Internal functions
static inline Expr *parse_asm_expr(ParseContext *c);
static Ast *parse_declaration_statment_after_type(ParseContext *c, TypeInfo *type)
static Ast *parse_decl_stmt_after_type(ParseContext *c, TypeInfo *type)
{
Ast *ast = ast_calloc();
ast->span = type->span;
@@ -95,7 +94,7 @@ static inline Ast *parse_declaration_stmt(ParseContext *c)
bool is_static = !is_threadlocal && try_consume(c, TOKEN_STATIC);
is_static = is_threadlocal || is_static;
ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), poisoned_ast);
ASSIGN_AST_OR_RET(Ast *result, parse_declaration_statment_after_type(c, type), poisoned_ast);
ASSIGN_AST_OR_RET(Ast *result, parse_decl_stmt_after_type(c, type), poisoned_ast);
CONSUME_EOS_OR_RET(poisoned_ast);
if (result->ast_kind == AST_DECLARE_STMT)
{
@@ -411,8 +410,11 @@ static inline Ast* parse_asm_block_stmt(ParseContext *c)
/**
* do_stmt
* : DO statement WHILE '(' expression ')' ';'
* do_stmt ::= DO optional_label compound_stmt (WHILE '(' expression ')')? ';'
*
* Note that we transform do to a for loop (with a special flag)
* and in parsing we allow a regular statement, but disambiguate that
* during semantic analysis.
*/
static inline Ast* parse_do_stmt(ParseContext *c)
{
@@ -460,8 +462,7 @@ static inline Ast *parse_case_stmts(ParseContext *c, TokenType case_type, TokenT
/**
* defer_stmt
* : DEFER statement
* defer_stmt ::= DEFER (TRY | CATCH)? statement
*/
static inline Ast* parse_defer_stmt(ParseContext *c)
{
@@ -480,8 +481,9 @@ static inline Ast* parse_defer_stmt(ParseContext *c)
}
/**
* while_stmt
* : WHILE '(' control_expression ')' statement
* while_stmt ::= WHILE optional_label '(' cond ')' statement
*
* Note that during parsing we rewrite this as a for loop.
*/
static inline Ast* parse_while_stmt(ParseContext *c)
{
@@ -489,7 +491,6 @@ static inline Ast* parse_while_stmt(ParseContext *c)
advance_and_verify(c, TOKEN_WHILE);
ASSIGN_DECL_OR_RET(while_ast->for_stmt.flow.label, parse_optional_label(c, while_ast), poisoned_ast);
CONSUME_OR_RET(TOKEN_LPAREN, poisoned_ast);
ASSIGN_EXPRID_OR_RET(while_ast->for_stmt.cond, parse_cond(c), poisoned_ast);
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_ast);
@@ -507,21 +508,9 @@ static inline Ast* parse_while_stmt(ParseContext *c)
/**
* if_expr
* : optional_type IDENT '=' initializer
* | optional_type IDENT NOFAIL_ASSIGN expression
* | expression
* ;
*
* if_cond_expr
* : if_expr
* | if_cond_expr ',' if_expr
* ;
*
* if_stmt
* : IF '(' control_expression ')' statement
* | IF '(' control_expression ')' compound_statement ELSE compound_statement
* ;
* if_stmt ::= IF optional_label '(' cond ')' switch_body (ELSE compound_stmt)?
* | IF optional_label '(' cond ')' compound_stmt (ELSE compound_stmt)?
* | IF optional_label '(' cond ')' statement
*/
static inline Ast* parse_if_stmt(ParseContext *c)
{
@@ -532,6 +521,7 @@ static inline Ast* parse_if_stmt(ParseContext *c)
ASSIGN_EXPRID_OR_RET(if_ast->if_stmt.cond, parse_cond(c), poisoned_ast);
unsigned row = c->span.row;
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_ast);
// Special case, we might have if ( ) { case ... }
if (tok_is(c, TOKEN_LBRACE) && (peek(c) == TOKEN_CASE || peek(c) == TOKEN_DEFAULT))
{
@@ -551,11 +541,10 @@ static inline Ast* parse_if_stmt(ParseContext *c)
ast_poison(astptr(if_ast->if_stmt.then_body));
}
}
if (!try_consume(c, TOKEN_ELSE))
if (try_consume(c, TOKEN_ELSE))
{
return if_ast;
ASSIGN_ASTID_OR_RET(if_ast->if_stmt.else_body, parse_stmt(c), poisoned_ast);
}
ASSIGN_ASTID_OR_RET(if_ast->if_stmt.else_body, parse_stmt(c), poisoned_ast);
return if_ast;
}
@@ -563,9 +552,9 @@ static inline Ast* parse_if_stmt(ParseContext *c)
/**
*
* case_stmt
* : CASE constant_expression ':' case_stmts
* | CASE constant_expression ELLIPSIS constant_expression ':' cast_stmts
* | CAST type ':' cast_stmts
* : CASE expression ':' case_stmts
* | CASE expression DOTDOT expression ':' case_stmts
* | CAST type ':' case_stmts
* ;
*/
static inline Ast *parse_case_stmt(ParseContext *c, TokenType case_type, TokenType default_type)
@@ -642,8 +631,7 @@ bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, Token
/**
* switch
* : SWITCH '(' decl_expr_list ')' '{' switch_body '}'
* switch ::= SWITCH optional_label ('(' cond ')')? switch_body
*/
static inline Ast* parse_switch_stmt(ParseContext *c)
{
@@ -652,9 +640,7 @@ static inline Ast* parse_switch_stmt(ParseContext *c)
ASSIGN_DECL_OR_RET(switch_ast->switch_stmt.flow.label, parse_optional_label(c, switch_ast), poisoned_ast);
if (!try_consume(c, TOKEN_LPAREN))
{
Expr *cond = expr_new(EXPR_COND, switch_ast->span);
vec_add(cond->cond_expr, expr_new_const_bool(switch_ast->span, type_bool, true));
switch_ast->switch_stmt.cond = exprid(cond);
switch_ast->switch_stmt.cond = 0;
}
else
{
@@ -668,52 +654,58 @@ static inline Ast* parse_switch_stmt(ParseContext *c)
/**
* for_statement
* : FOR '(' decl_expr_list ';' expression ';' ')' statement
* | FOR '(' decl_expr_list ';' ';' expression_list ')' statement
* | FOR '(' decl_expr_list ';' expression ';' expression_list ')' statement
* | FOR '(' ';' expression ';' ')' statement
* | FOR '(' ';' ';' expression_list ')' statement
* | FOR '(' ';' expression ';' expression_list ')' statement
* ;
* for_stmt ::= IF optional_label '(' expression_list? ';' cond? ';' expression_list? ')' statement
*/
static inline Ast* parse_for_stmt(ParseContext *c)
{
Ast *ast = new_ast(AST_FOR_STMT, c->span);
advance_and_verify(c, TOKEN_FOR);
ASSIGN_DECL_OR_RET(ast->for_stmt.flow.label, parse_optional_label(c, ast), poisoned_ast);
CONSUME_OR_RET(TOKEN_LPAREN, poisoned_ast);
if (!tok_is(c, TOKEN_EOS))
{
ASSIGN_EXPRID_OR_RET(ast->for_stmt.init, parse_expression_list(c, true), poisoned_ast);
}
else
// Label
ASSIGN_DECL_OR_RET(ast->for_stmt.flow.label, parse_optional_label(c, ast), poisoned_ast);
CONSUME_OR_RET(TOKEN_LPAREN, poisoned_ast);
if (try_consume(c, TOKEN_EOS))
{
ast->for_stmt.init = 0;
}
CONSUME_EOS_OR_RET(poisoned_ast);
else
{
ASSIGN_EXPRID_OR_RET(ast->for_stmt.init, parse_expression_list(c, true), poisoned_ast);
CONSUME_EOS_OR_RET(poisoned_ast);
}
if (!tok_is(c, TOKEN_EOS))
if (try_consume(c, TOKEN_EOS))
{
ast->for_stmt.cond = 0;
}
else
{
ASSIGN_EXPRID_OR_RET(ast->for_stmt.cond, parse_cond(c), poisoned_ast);
CONSUME_EOS_OR_RET(poisoned_ast);
}
CONSUME_EOS_OR_RET(poisoned_ast);
if (!tok_is(c, TOKEN_RPAREN))
if (try_consume(c, TOKEN_RPAREN))
{
ast->for_stmt.incr = 0;
}
else
{
ASSIGN_EXPRID_OR_RET(ast->for_stmt.incr, parse_expression_list(c, false), poisoned_ast);
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_ast);
}
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_ast);
// Ast range does not include the body
RANGE_EXTEND_PREV(ast);
ASSIGN_AST_OR_RET(Ast *body, parse_stmt(c), poisoned_ast);
ast->for_stmt.body = astid(body);
return ast;
}
/**
* foreach_var ::= optional_type? '&'? IDENT
*/
static inline bool parse_foreach_var(ParseContext *c, Ast *foreach)
{
TypeInfo *type = NULL;
@@ -733,21 +725,15 @@ static inline bool parse_foreach_var(ParseContext *c, Ast *foreach)
Decl *var = decl_new_var(symstr(c), c->span, type, VARDECL_LOCAL);
if (!try_consume(c, TOKEN_IDENT))
{
if (type)
{
SEMA_ERROR_HERE("Expected an identifier after the type.");
return false;
}
SEMA_ERROR_HERE("Expected an identifier or type.");
return false;
if (type) RETURN_SEMA_ERROR_HERE("Expected an identifier after the type.");
RETURN_SEMA_ERROR_HERE("Expected an identifier or type.");
}
foreach->foreach_stmt.variable = declid(var);
return true;
}
/**
* foreach_statement
* : FOREACH (CONST_IDENT ':')? '(' type? '*'? IDENT (',' type? '*'? IDENT) ':' expression ')' statement
* ;
* foreach_stmt ::= (FOREACH | FOREACH_R) optional_label '(' foreach_vars ':' expression ')' statement
* foreach_vars ::= foreach_var (',' foreach_var)?
*/
static inline Ast* parse_foreach_stmt(ParseContext *c)
{
@@ -788,48 +774,52 @@ static inline Ast* parse_foreach_stmt(ParseContext *c)
}
/**
* continue_stmt
* : CONTINUE
* continue_stmt ::= CONTINUE optional_label_target ';'
*/
static inline Ast* parse_continue(ParseContext *c)
static inline Ast* parse_continue_stmt(ParseContext *c)
{
Ast *ast = new_ast(AST_CONTINUE_STMT, c->span);
advance_and_verify(c, TOKEN_CONTINUE);
parse_optional_label_target(c, &ast->contbreak_stmt.label);
if (ast->contbreak_stmt.label.name) ast->contbreak_stmt.is_label = true;
RANGE_EXTEND_PREV(ast);
CONSUME_EOS_OR_RET(poisoned_ast);
return ast;
}
/**
* next ::= NEXTCASE ((CONST ':')? expression)?
* next ::= NEXTCASE ((CONST_IDENT ':')? expression)? ';'
*/
static inline Ast* parse_next(ParseContext *c)
static inline Ast* parse_nextcase_stmt(ParseContext *c)
{
Ast *ast = new_ast(AST_NEXT_STMT, c->span);
Ast *ast = new_ast(AST_NEXTCASE_STMT, c->span);
advance_and_verify(c, TOKEN_NEXTCASE);
if (!tok_is(c, TOKEN_EOS))
if (try_consume(c, TOKEN_EOS))
{
if (tok_is(c, TOKEN_CONST_IDENT) && peek(c) == TOKEN_COLON)
{
parse_optional_label_target(c, &ast->nextcase_stmt.label);
advance_and_verify(c, TOKEN_COLON);
}
ASSIGN_EXPR_OR_RET(ast->nextcase_stmt.expr, parse_expr(c), poisoned_ast);
return ast;
}
if (tok_is(c, TOKEN_CONST_IDENT) && peek(c) == TOKEN_COLON)
{
parse_optional_label_target(c, &ast->nextcase_stmt.label);
advance_and_verify(c, TOKEN_COLON);
}
ASSIGN_EXPR_OR_RET(ast->nextcase_stmt.expr, parse_expr(c), poisoned_ast);
CONSUME_EOS_OR_RET(poisoned_ast);
return ast;
}
/**
* break
* : BREAK
* break_stmt ::= BREAK optional_label_target ';'
*/
static inline Ast* parse_break(ParseContext *c)
static inline Ast* parse_break_stmt(ParseContext *c)
{
Ast *ast = new_ast(AST_BREAK_STMT, c->span);
advance_and_verify(c, TOKEN_BREAK);
parse_optional_label_target(c, &ast->contbreak_stmt.label);
if (ast->contbreak_stmt.label.name) ast->contbreak_stmt.is_label = true;
RANGE_EXTEND_PREV(ast);
CONSUME_EOS_OR_RET(poisoned_ast);
return ast;
}
@@ -851,7 +841,7 @@ static inline Ast *parse_expr_stmt(ParseContext *c)
static inline Ast *parse_decl_or_expr_stmt(ParseContext *c)
{
ASSIGN_EXPR_OR_RET(Expr * expr, parse_expr(c), poisoned_ast);
ASSIGN_EXPR_OR_RET(Expr *expr, parse_expr(c), poisoned_ast);
// We might be parsing "int!"
// If so we need to unwrap this.
if (expr->expr_kind == EXPR_OPTIONAL && expr->inner_expr->expr_kind == EXPR_TYPEINFO)
@@ -860,7 +850,7 @@ static inline Ast *parse_decl_or_expr_stmt(ParseContext *c)
}
if (expr->expr_kind == EXPR_TYPEINFO)
{
ASSIGN_AST_OR_RET(Ast *ast, parse_declaration_statment_after_type(c, expr->type_expr), poisoned_ast);
ASSIGN_AST_OR_RET(Ast *ast, parse_decl_stmt_after_type(c, expr->type_expr), poisoned_ast);
CONSUME_EOS_OR_RET(poisoned_ast);
return ast;
}
@@ -898,55 +888,36 @@ static inline bool parse_ct_compound_stmt(ParseContext *c, AstId *start)
while (1)
{
TokenType tok = c->tok;
if (tok == TOKEN_CT_ELSE || tok == TOKEN_CT_ELIF || tok == TOKEN_CT_ENDIF) break;
if (tok == TOKEN_CT_ELSE || tok == TOKEN_CT_ENDIF) break;
ASSIGN_AST_OR_RET(Ast *stmt, parse_stmt(c), false);
ast_append(&next, stmt);
}
return true;
}
/**
* ct_else_stmt
* : CT_ELSE ':' ct_compound_stmt
*/
static inline Ast* parse_ct_else_stmt(ParseContext *c)
{
Ast *ast = new_ast(AST_CT_ELSE_STMT, c->span);
advance_and_verify(c, TOKEN_CT_ELSE);
consume_deprecated_symbol(c, TOKEN_COLON);
if (!parse_ct_compound_stmt(c, &ast->ct_else_stmt)) return poisoned_ast;
return ast;
}
/**
* ct_if_stmt
* : CT_IF '(' expression ')' ':' ct_compound_stmt (ct_elif_stmt | ct_else_stmt) CT_ENDIF EOS
* : CT_IF '(' expression ')' ct_compound_stmt (ct_elif_stmt | ct_else_stmt) CT_ENDIF EOS
* ;
*/
static inline Ast* parse_ct_if_stmt(ParseContext *c, bool is_elif)
static inline Ast *parse_ct_if_stmt(ParseContext *c)
{
Ast *ast = ast_new_curr(c, AST_CT_IF_STMT);
if (is_elif) sema_warning_at(c->span, "$elif is deprecated, use $switch instead.");
advance_and_verify(c, is_elif ? TOKEN_CT_ELIF : TOKEN_CT_IF);
advance_and_verify(c, TOKEN_CT_IF);
ASSIGN_EXPR_OR_RET(ast->ct_if_stmt.expr, parse_const_paren_expr(c), poisoned_ast);
consume_deprecated_symbol(c, TOKEN_COLON);
if (!parse_ct_compound_stmt(c, &ast->ct_if_stmt.then)) return poisoned_ast;
if (tok_is(c, TOKEN_CT_ELIF))
if (tok_is(c, TOKEN_CT_ELSE))
{
ASSIGN_ASTID_OR_RET(ast->ct_if_stmt.elif, parse_ct_if_stmt(c, true), poisoned_ast);
Ast *else_ast = new_ast(AST_CT_ELSE_STMT, c->span);
advance_and_verify(c, TOKEN_CT_ELSE);
if (!parse_ct_compound_stmt(c, &else_ast->ct_else_stmt)) return poisoned_ast;
ast->ct_if_stmt.elif = astid(else_ast);
}
else if (tok_is(c, TOKEN_CT_ELSE))
{
ASSIGN_ASTID_OR_RET(ast->ct_if_stmt.elif, parse_ct_else_stmt(c), poisoned_ast);
}
if (is_elif) return ast;
advance_and_verify(c, TOKEN_CT_ENDIF);
RANGE_EXTEND_PREV(ast);
consume_deprecated_symbol(c, TOKEN_EOS);
return ast;
}
@@ -958,7 +929,7 @@ static inline Ast* parse_ct_if_stmt(ParseContext *c, bool is_elif)
* | RETURN
* ;
*/
static inline Ast *parse_return(ParseContext *c)
static inline Ast *parse_return_stmt(ParseContext *c)
{
advance_and_verify(c, TOKEN_RETURN);
Ast *ast = ast_new_curr(c, AST_RETURN_STMT);
@@ -966,6 +937,7 @@ static inline Ast *parse_return(ParseContext *c)
{
ASSIGN_EXPR_OR_RET(ast->return_stmt.expr, parse_expr(c), poisoned_ast);
}
CONSUME_EOS_OR_RET(poisoned_ast);
return ast;
}
@@ -976,11 +948,7 @@ static inline Ast *parse_return(ParseContext *c)
/**
* ct_foreach_stmt
* | CT_FOREACH '(' CT_IDENT (',' CT_IDENT)? ':' expr ')' ':' statement* CT_ENDFOREACH EOS
* ;
*
* @return
* ct_foreach_stmt ::= CT_FOREACH '(' CT_IDENT (',' CT_IDENT)? ':' expr ')' statement* CT_ENDFOREACH
*/
static inline Ast* parse_ct_foreach_stmt(ParseContext *c)
{
@@ -1000,7 +968,6 @@ static inline Ast* parse_ct_foreach_stmt(ParseContext *c)
TRY_CONSUME_OR_RET(TOKEN_COLON, "Expected ':'.", poisoned_ast);
ASSIGN_EXPRID_OR_RET(ast->ct_foreach_stmt.expr, parse_expr(c), poisoned_ast);
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_ast);
consume_deprecated_symbol(c, TOKEN_COLON);
Ast *body = new_ast(AST_COMPOUND_STMT, ast->span);
ast->ct_foreach_stmt.body = astid(body);
AstId *current = &body->compound_stmt.first_stmt;
@@ -1010,7 +977,6 @@ static inline Ast* parse_ct_foreach_stmt(ParseContext *c)
*current = astid(stmt);
current = &stmt->next;
}
consume_deprecated_symbol(c, TOKEN_EOS);
return ast;
}
@@ -1042,8 +1008,6 @@ static inline Ast* parse_ct_for_stmt(ParseContext *c)
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_ast);
consume_deprecated_symbol(c, TOKEN_COLON);
Ast *body = new_ast(AST_COMPOUND_STMT, ast->span);
ast->for_stmt.body = astid(body);
AstId *current = &body->compound_stmt.first_stmt;
@@ -1053,33 +1017,23 @@ static inline Ast* parse_ct_for_stmt(ParseContext *c)
*current = astid(stmt);
current = &stmt->next;
}
consume_deprecated_symbol(c, TOKEN_EOS);
return ast;
}
/**
* CTSWITCH '(' expression ')' ':' '{' ct_switch_body '}'
* ct_switch_stmt ::= CT_SWITCH const_paren_expr? ct_case_statement* CT_ENDSWITCH
*
* ct_switch_body
* : ct_case_statement
* | ct_switch_body ct_case_statement
* ;
*
* ct_case_statement
* : CTCASE type_list ':' statement
* | CTDEFAULT ':' statement
* ;
*
* @return
* ct_case_statement ::= (CT_CASE constant_expr | CT_DEFAULT) ':' opt_stmt_list
*/
static inline Ast* parse_ct_switch_stmt(ParseContext *c)
{
Ast *ast = ast_new_curr(c, AST_CT_SWITCH_STMT);
advance_and_verify(c, TOKEN_CT_SWITCH);
if (!tok_is(c, TOKEN_CT_CASE) && !tok_is(c, TOKEN_CT_DEFAULT) && !tok_is(c, TOKEN_CT_ENDSWITCH))
// Is it a paren expr?
if (tok_is(c, TOKEN_LPAREN))
{
ASSIGN_EXPRID_OR_RET(ast->ct_switch_stmt.cond, parse_const_paren_expr(c), poisoned_ast);
consume_deprecated_symbol(c, TOKEN_COLON);
}
Ast **cases = NULL;
@@ -1102,11 +1056,13 @@ static inline Ast* parse_ct_switch_stmt(ParseContext *c)
}
vec_add(cases, result);
}
consume_deprecated_symbol(c, TOKEN_EOS);
ast->ct_switch_stmt.body = cases;
return ast;
}
/**
* assert_stmt ::= ASSERT '(' assert_expr (',' expr)? ')' ';'
*/
static inline Ast *parse_assert_stmt(ParseContext *c)
{
Ast *ast = ast_new_curr(c, AST_ASSERT_STMT);
@@ -1204,16 +1160,8 @@ Ast *parse_stmt(ParseContext *c)
case TOKEN_STATIC: // Static means declaration!
case TOKEN_CONST: // Const means declaration!
return parse_declaration_stmt(c);
case TOKEN_AT_TYPE_IDENT:
case TOKEN_AT_CONST_IDENT:
case TOKEN_AT:
case TOKEN_AT_IDENT:
return parse_expr_stmt(c);
case TOKEN_RETURN:
{
ASSIGN_AST_OR_RET(Ast *ast, parse_return(c), poisoned_ast);
RETURN_AFTER_EOS(ast);
}
return parse_return_stmt(c);
case TOKEN_IF:
return parse_if_stmt(c);
case TOKEN_WHILE:
@@ -1230,24 +1178,15 @@ Ast *parse_stmt(ParseContext *c)
case TOKEN_FOREACH_R:
return parse_foreach_stmt(c);
case TOKEN_CONTINUE:
{
ASSIGN_AST_OR_RET(Ast *ast, parse_continue(c), poisoned_ast);
RETURN_AFTER_EOS(ast);
}
return parse_continue_stmt(c);
case TOKEN_CASE:
SEMA_ERROR_HERE("'case' was found outside of 'switch', did you mismatch a '{ }' pair?");
advance(c);
return poisoned_ast;
case TOKEN_BREAK:
{
ASSIGN_AST_OR_RET(Ast *ast, parse_break(c), poisoned_ast);
RETURN_AFTER_EOS(ast);
}
return parse_break_stmt(c);
case TOKEN_NEXTCASE:
{
ASSIGN_AST_OR_RET(Ast *ast, parse_next(c), poisoned_ast);
RETURN_AFTER_EOS(ast);
}
return parse_nextcase_stmt(c);
case TOKEN_ASM:
return parse_asm_block_stmt(c);
case TOKEN_DEFAULT:
@@ -1259,7 +1198,7 @@ Ast *parse_stmt(ParseContext *c)
case TOKEN_CT_ASSERT:
return parse_ct_assert_stmt(c);
case TOKEN_CT_IF:
return parse_ct_if_stmt(c, false);
return parse_ct_if_stmt(c);
case TOKEN_CT_SWITCH:
return parse_ct_switch_stmt(c);
case TOKEN_CT_FOREACH:
@@ -1307,6 +1246,10 @@ Ast *parse_stmt(ParseContext *c)
case TOKEN_CT_VAEXPR:
case TOKEN_CT_VACONST:
case TOKEN_CT_VAREF:
case TOKEN_AT_TYPE_IDENT:
case TOKEN_AT_CONST_IDENT:
case TOKEN_AT:
case TOKEN_AT_IDENT:
return parse_expr_stmt(c);
case TOKEN_ASSERT:
return parse_assert_stmt(c);
@@ -1366,7 +1309,6 @@ Ast *parse_stmt(ParseContext *c)
case TOKEN_DOCS_END:
case TOKEN_DOC_COMMENT:
case TOKEN_CT_CASE:
case TOKEN_CT_ELIF:
case TOKEN_CT_ELSE:
case TOKEN_CT_DEFAULT:
case TOKEN_CT_ENDIF:
@@ -1374,7 +1316,6 @@ Ast *parse_stmt(ParseContext *c)
case TOKEN_RBRAPIPE:
case TOKEN_BANGBANG:
case TOKEN_UNDERSCORE:
case TOKEN_PRIVATE:
case TOKEN_BITSTRUCT:
case TOKEN_LVEC:
case TOKEN_RVEC:
@@ -1411,23 +1352,6 @@ Ast *parse_stmt(ParseContext *c)
UNREACHABLE
}
Ast *parse_jump_stmt_no_eos(ParseContext *c)
{
switch (c->tok)
{
case TOKEN_NEXTCASE:
return parse_next(c);
case TOKEN_RETURN:
return parse_return(c);
case TOKEN_BREAK:
return parse_break(c);
case TOKEN_CONTINUE:
return parse_continue(c);
default:
UNREACHABLE
}
}
/**
* compound_stmt

View File

@@ -45,7 +45,6 @@ Expr *parse_cond(ParseContext *c);
Expr *parse_assert_expr(ParseContext *c);
Ast* parse_compound_stmt(ParseContext *c);
Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool require_eos);
Ast *parse_jump_stmt_no_eos(ParseContext *c);
bool parse_attribute(ParseContext *c, Attr **attribute_ref);
bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref);
@@ -79,7 +78,6 @@ bool try_consume(ParseContext *c, TokenType type);
bool consume(ParseContext *c, TokenType type, const char *message, ...);
bool consume_const_name(ParseContext *c, const char* type);
Expr *parse_precedence_with_left_side(ParseContext *c, Expr *left_side, Precedence precedence);
void consume_deprecated_symbol(ParseContext *c, TokenType type);
INLINE const char *symstr(ParseContext *c)
{

View File

@@ -667,6 +667,7 @@ CastKind cast_to_bool_kind(Type *type)
{
switch (type_flatten(type)->type_kind)
{
case TYPE_WILDCARD:
case TYPE_BOOL:
return CAST_BOOLBOOL;
case TYPE_ANYERR:
@@ -684,7 +685,6 @@ CastKind cast_to_bool_kind(Type *type)
case TYPE_TYPEDEF:
case TYPE_DISTINCT:
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
case TYPE_ENUM:
// These are not possible due to flattening.
UNREACHABLE
@@ -705,7 +705,6 @@ CastKind cast_to_bool_kind(Type *type)
case TYPE_UNTYPED_LIST:
case TYPE_ANY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
case TYPE_MEMBER:
// Everything else is an error
return CAST_ERROR;
@@ -1005,7 +1004,6 @@ static bool cast_from_pointer(SemaContext *context, Expr *expr, Type *from, Type
return cast_with_optional(expr, to_type, add_optional);
}
return sema_error_cannot_convert(expr, to_type, true, silent);
case TYPE_OPTIONAL_ANY:
case TYPE_OPTIONAL:
UNREACHABLE
default:
@@ -1519,8 +1517,10 @@ static bool cast_expr_inner(SemaContext *context, Expr *expr, Type *to_type, boo
// 3. void! -> SomeFault (explicit)
if (type_is_optional(from_type))
{
Type *opt = from_type->optional;
// *! -> int => ok, gives int!
if (from_type == type_anyfail)
if (opt == type_wildcard)
{
if (may_not_be_optional)
{
@@ -1533,11 +1533,8 @@ static bool cast_expr_inner(SemaContext *context, Expr *expr, Type *to_type, boo
return true;
}
// Here we have something like int!
assert(from_type->type_kind == TYPE_OPTIONAL);
// If it is void!, then there are special rules:
if (from_type->optional == type_void)
if (opt == type_void)
{
// void! x; anyerr y = x;
if (!type_is_optional(to_type) && to == type_anyerr)
@@ -1585,7 +1582,7 @@ static bool cast_expr_inner(SemaContext *context, Expr *expr, Type *to_type, boo
}
// We may already be done.
if (from == to)
if (from == to || from == type_wildcard)
{
expr->type = type_add_optional(to_type, add_optional);
return true;
@@ -1629,7 +1626,6 @@ static bool cast_expr_inner(SemaContext *context, Expr *expr, Type *to_type, boo
if (type_is_integer(to) || type_is_float(to)) goto CAST_IF_EXPLICIT;
goto CAST_FAILED;
case TYPE_VECTOR:
case TYPE_SCALED_VECTOR:
return cast_from_vector(context, expr, from, to, to_type, add_optional, is_explicit, silent);
case TYPE_ARRAY:
return cast_from_array(context, expr, from, to, to_type, add_optional, is_explicit, silent);
@@ -1641,6 +1637,8 @@ static bool cast_expr_inner(SemaContext *context, Expr *expr, Type *to_type, boo
return cast_from_float(context, expr, from, to, to_type, add_optional, is_explicit, silent);
case TYPE_POISONED:
return false;
case TYPE_WILDCARD:
UNREACHABLE
case TYPE_VOID:
case TYPE_INFERRED_ARRAY:
case TYPE_TYPEINFO:
@@ -1653,7 +1651,6 @@ static bool cast_expr_inner(SemaContext *context, Expr *expr, Type *to_type, boo
if (!type_is_pointer_sized_or_more(to_type)) goto CAST_FAILED;
goto CAST_IF_EXPLICIT;
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
case TYPE_TYPEDEF:
UNREACHABLE;
case TYPE_ANY:
@@ -1817,7 +1814,6 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type)
{
switch (from_type->type_kind)
{
case TYPE_OPTIONAL_ANY:
case TYPE_OPTIONAL:
case TYPE_VOID:
UNREACHABLE
@@ -1889,7 +1885,6 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type)
if (type_is_integer(to)) return insert_cast(expr, CAST_ERINT, to_type);
break;
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
return false;
case TYPE_ARRAY:
if (to->type_kind == TYPE_VECTOR) return array_to_vector(expr, to_type);
@@ -1935,17 +1930,18 @@ bool cast(Expr *expr, Type *to_type)
if (type_is_optional(from_type)) return voidfail_to_error(expr, to_type);
}
if (type_is_optional_any(from_type))
{
expr->type = type_get_optional(to_type);
return true;
}
if (type_is_optional_type(from_type))
if (type_is_optional(from_type))
{
from_type = from_type->optional;
from_is_optional = true;
}
if (from_type == type_wildcard)
{
expr->type = type_add_optional(to_type, from_is_optional);
return true;
}
from_type = type_flatten(from_type);
if (type_len_is_inferred(to_type))
{

View File

@@ -204,11 +204,6 @@ static bool sema_analyse_union_members(SemaContext *context, Decl *decl, Decl **
SEMA_ERROR(member, "Flexible array members not allowed in unions.");
return false;
}
if (member->type->type_kind == TYPE_SCALED_VECTOR)
{
SEMA_ERROR(member, "Scaled vector members not allowed in unions / structs.");
return false;
}
AlignSize member_alignment;
if (!sema_set_abi_alignment(context, member->type, &member_alignment)) return false;
ByteSize member_size = type_size(member->type);
@@ -313,11 +308,6 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl *
}
decl->has_variable_array = true;
}
if (member_type->type_kind == TYPE_SCALED_VECTOR)
{
SEMA_ERROR(member, "Scaled vectors may not be used in structs and unions.");
return false;
}
if (member_type->type_kind == TYPE_INFERRED_ARRAY)
{
if (i != member_count - 1)
@@ -928,7 +918,6 @@ static inline bool sema_analyse_distinct(SemaContext *context, Decl *decl)
case TYPE_FLEXIBLE_ARRAY:
UNREACHABLE
return false;
case TYPE_OPTIONAL_ANY:
case TYPE_OPTIONAL:
UNREACHABLE
case TYPE_FAULTTYPE:
@@ -952,7 +941,6 @@ static inline bool sema_analyse_distinct(SemaContext *context, Decl *decl)
case TYPE_ARRAY:
case TYPE_SUBARRAY:
case TYPE_VECTOR:
case TYPE_SCALED_VECTOR:
break;
}
// Do we need anything else?
@@ -2205,7 +2193,6 @@ static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl)
Type *rtype = rtype_info->type;
bool is_int_return = true;
bool is_err_return = false;
if (rtype->type_kind == TYPE_OPTIONAL_ANY) is_err_return = true;
if (!is_err_return && type_is_optional(rtype))
{
if (rtype->optional->type_kind != TYPE_VOID)
@@ -2547,7 +2534,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->optional == type_void)
if (type == type_wildcard_optional || 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));
@@ -2687,6 +2674,11 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
decl->type = init_expr->type;
if (type_is_invalid_storage_type(init_expr->type))
{
if (init_expr->type == type_wildcard_optional || init_expr->type == type_wildcard)
{
SEMA_ERROR(init_expr, "No type can be inferred from the optional result.");
return false;
}
if (init_expr->type == type_untypedlist)
{
SEMA_ERROR(init_expr, "The type of an untyped list cannot be inferred, you can try adding an explicit type to solve this.");

View File

@@ -698,18 +698,7 @@ static inline bool sema_expr_analyse_ternary(SemaContext *context, Expr *expr)
if (left_canonical != right_canonical)
{
Type *max;
if (left_canonical->type_kind == TYPE_OPTIONAL_ANY)
{
max = right_canonical;
}
else if (right_canonical->type_kind == TYPE_OPTIONAL_ANY)
{
max = left_canonical;
}
else
{
max = type_find_max_type(type_no_optional(left_canonical), type_no_optional(right_canonical));
}
max = type_find_max_type(type_no_optional(left_canonical), type_no_optional(right_canonical));
if (!max)
{
SEMA_ERROR(expr, "Cannot find a common parent type of '%s' and '%s'",
@@ -1465,8 +1454,8 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call
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));
return false;
assert(!type_is_wildcard(arg->type));
RETURN_SEMA_ERROR(arg, "A value of type %s can only be passed as a compile time parameter.", type_quoted_error_string(arg->type));
}
if (!param->alignment)
{
@@ -1581,29 +1570,28 @@ static inline Type *context_unify_returns(SemaContext *context)
bool all_returns_need_casts = false;
Type *common_type = NULL;
bool optional = false;
bool no_return = true;
// 1. Loop through the returns.
VECEACH(context->returns, i)
bool optional = false;
unsigned returns = vec_size(context->returns);
if (!returns) return type_void;
for (unsigned i = 0; i < returns; i++)
{
Ast *return_stmt = context->returns[i];
Type *rtype;
if (!return_stmt)
{
optional = true;
continue;
rtype = type_wildcard;
}
no_return = false;
Expr *ret_expr = return_stmt->return_stmt.expr;
Type *rtype = ret_expr ? ret_expr->type : type_void;
if (type_is_optional_any(rtype))
else
{
optional = true;
continue;
}
if (type_is_optional(rtype))
{
optional = true;
rtype = type_no_optional(rtype);
Expr *ret_expr = return_stmt->return_stmt.expr;
rtype = ret_expr ? ret_expr->type : type_void;
if (type_is_optional(rtype))
{
optional = true;
rtype = type_no_optional(rtype);
}
}
// 2. If we have no common type, set to the return type.
if (!common_type)
@@ -1634,24 +1622,12 @@ static inline Type *context_unify_returns(SemaContext *context)
all_returns_need_casts = true;
}
// If we have no return (or only anyfail)
if (!common_type)
{
assert(!all_returns_need_casts && "We should never need casts here.");
// 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 optional => void.
return type_void;
}
assert(common_type);
// 7. Insert casts.
if (all_returns_need_casts)
{
assert(!type_is_optional_type(common_type));
assert(common_type != type_wildcard);
VECEACH(context->returns, i)
{
Ast *return_stmt = context->returns[i];
@@ -3035,7 +3011,6 @@ static inline bool sema_create_const_len(SemaContext *context, Expr *expr, Type
case TYPE_FAULTTYPE:
len = vec_size(type->decl->enums.values);
break;
case TYPE_SCALED_VECTOR:
case TYPE_INFERRED_ARRAY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SUBARRAY:
@@ -3071,7 +3046,6 @@ static inline bool sema_create_const_inner(SemaContext *context, Expr *expr, Typ
case TYPE_SUBARRAY:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_SCALED_VECTOR:
case TYPE_VECTOR:
inner = type->array.base;
break;
@@ -5636,9 +5610,6 @@ static inline bool sema_expr_analyse_not(SemaContext *context, Expr *expr)
case TYPE_VECTOR:
expr->type = type_get_vector(type_bool, canonical->array.len);
return true;
case TYPE_SCALED_VECTOR:
expr->type = type_get_scaled_vector(type_bool);
return true;
case TYPE_INFERRED_VECTOR:
UNREACHABLE;
default:
@@ -5840,23 +5811,7 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr)
// Here we might need to insert casts.
Type *else_type = rhs->type;
if (type_is_optional_any(type))
{
// One possibility is that both sides have the "optional any" type
// if so then we're done.
if (else_type == type)
{
expr->type = type;
return true;
}
// Otherwise assign the type of "else":
type = else_type;
}
else if (type_is_optional_any(else_type))
{
expr->type = type;
return true;
}
// Remove any possible optional of the else type.
bool add_optional = type_is_optional(else_type);
type = type_no_optional(type);
@@ -6020,11 +5975,7 @@ static inline bool sema_expr_analyse_rethrow(SemaContext *context, Expr *expr)
return false;
}
expr->rethrow_expr.cleanup = context_get_defers(context, context->active_scope.defer_last, 0, false);
if (inner->type == type_anyfail)
{
SEMA_ERROR(expr, "This expression will always throw, which isn't allowed.");
return false;
}
expr->type = type_no_optional(inner->type);
if (!IS_OPTIONAL(inner))
@@ -6033,7 +5984,6 @@ static inline bool sema_expr_analyse_rethrow(SemaContext *context, Expr *expr)
return false;
}
if (context->active_scope.flags & (SCOPE_EXPR_BLOCK | SCOPE_MACRO))
{
vec_add(context->returns, NULL);
@@ -6042,7 +5992,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 an optional result, but the function does not allow optional 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 '!!' instead?");
return false;
}
}
@@ -6055,11 +6005,6 @@ static inline bool sema_expr_analyse_force_unwrap(SemaContext *context, Expr *ex
{
Expr *inner = expr->inner_expr;
if (!sema_analyse_expr(context, inner)) return false;
if (inner->type == type_anyfail)
{
SEMA_ERROR(expr, "This expression will always throw, which isn't allowed.");
return false;
}
expr->type = type_no_optional(inner->type);
if (!IS_OPTIONAL(inner))
{
@@ -6123,7 +6068,8 @@ static inline bool sema_expr_analyse_expr_block(SemaContext *context, Type *infe
success = false;
goto EXIT;
}
if (type_no_optional(sum_returns) != type_void && !context->active_scope.jump_end)
Type *return_no_optional = type_no_optional(sum_returns);
if (return_no_optional != type_wildcard && return_no_optional != type_void && !context->active_scope.jump_end)
{
Ast *ast = ast_last(astptr(expr->expr_block.first_stmt));
SEMA_ERROR(ast, "Expected a return statement following this statement.");
@@ -6170,7 +6116,7 @@ static inline bool sema_expr_analyse_optional(SemaContext *context, Expr *expr)
SEMA_ERROR(inner, "You cannot use the '!' operator on expressions of type %s", type_quoted_error_string(type));
return false;
}
expr->type = type_anyfail;
expr->type = type_wildcard_optional;
return true;
}
@@ -6677,13 +6623,6 @@ RETRY:
if (!type_ok(type)) return type;
return type_get_inferred_vector(type);
}
case TYPE_INFO_SCALED_VECTOR:
{
Type *type = sema_expr_check_type_exists(context, type_info->array.base);
if (!type) return NULL;
if (!type_ok(type)) return type;
return type_get_scaled_vector(type);
}
case TYPE_INFO_POINTER:
{
// If it's an array, make sure we can resolve the length
@@ -7362,7 +7301,7 @@ bool sema_analyse_cond_expr(SemaContext *context, Expr *expr)
bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allow_optional)
{
if (to && type_is_optional_type(to))
if (to && type_is_optional(to))
{
to = to->optional;
assert(allow_optional);

View File

@@ -558,9 +558,6 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
if (!sema_analyse_expr(context, expr)) return false;
return cast(expr, to);
}
case TYPE_SCALED_VECTOR:
SEMA_ERROR(expr, "Scaled vectors cannot be initialized using an initializer list, since the length is not known at compile time.");
return false;
case TYPE_POINTER:
if (is_zero_init)
{
@@ -573,7 +570,6 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex
case TYPE_POISONED:
case TYPE_FUNC:
case TYPE_TYPEDEF:
case TYPE_OPTIONAL_ANY:
case TYPE_OPTIONAL:
case TYPE_TYPEINFO:
case TYPE_MEMBER:

View File

@@ -37,7 +37,7 @@ static void sema_trace_stmt_chain_liveness(AstId astid)
case AST_RETURN_STMT:
case AST_BREAK_STMT:
case AST_CONTINUE_STMT:
case AST_NEXT_STMT:
case AST_NEXTCASE_STMT:
return;
default:
break;
@@ -163,7 +163,7 @@ static void sema_trace_stmt_liveness(Ast *ast)
case AST_DEFAULT_STMT:
sema_trace_stmt_liveness(ast->case_stmt.body);
return;
case AST_NEXT_STMT:
case AST_NEXTCASE_STMT:
sema_trace_stmt_chain_liveness(ast->nextcase_stmt.defer_id);
sema_trace_expr_liveness(ast->nextcase_stmt.switch_expr);
return;

View File

@@ -626,10 +626,9 @@ bool sema_resolve_type_decl(SemaContext *context, Type *type)
{
switch (type->type_kind)
{
case TYPE_OPTIONAL_ANY:
return true;
case TYPE_POISONED:
return false;
case TYPE_WILDCARD:
case TYPE_VOID:
case TYPE_BOOL:
case ALL_INTS:
@@ -641,7 +640,6 @@ bool sema_resolve_type_decl(SemaContext *context, Type *type)
case TYPE_UNTYPED_LIST:
case TYPE_MEMBER:
case TYPE_INFERRED_VECTOR:
case TYPE_SCALED_VECTOR:
case TYPE_VECTOR:
case TYPE_SUBARRAY:
return true;

View File

@@ -1205,6 +1205,12 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement)
return success;
}
/**
* foreach_stmt ::= foreach
* @param context
* @param statement
* @return
*/
static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statement)
{
// Pull out the relevant data.
@@ -1678,7 +1684,7 @@ static bool sema_analyse_asm_string_stmt(SemaContext *context, Ast *stmt)
*/
static inline Decl *sema_analyse_label(SemaContext *context, Ast *stmt)
{
Label *label = stmt->ast_kind == AST_NEXT_STMT ? &stmt->nextcase_stmt.label : &stmt->contbreak_stmt.label;
Label *label = stmt->ast_kind == AST_NEXTCASE_STMT ? &stmt->nextcase_stmt.label : &stmt->contbreak_stmt.label;
const char *name = label->name;
Decl *target = sema_find_label_symbol(context, name);
if (!target)
@@ -1696,7 +1702,7 @@ static inline Decl *sema_analyse_label(SemaContext *context, Ast *stmt)
case AST_CONTINUE_STMT:
SEMA_ERROR(stmt, "You cannot use continue out of an expression block.");
return poisoned_decl;
case AST_NEXT_STMT:
case AST_NEXTCASE_STMT:
SEMA_ERROR(stmt, "You cannot use nextcase to exit an expression block.");
return poisoned_decl;
default:
@@ -1713,7 +1719,7 @@ static inline Decl *sema_analyse_label(SemaContext *context, Ast *stmt)
case AST_CONTINUE_STMT:
SEMA_ERROR(stmt, "You cannot use continue out of a defer.");
return poisoned_decl;
case AST_NEXT_STMT:
case AST_NEXTCASE_STMT:
SEMA_ERROR(stmt, "You cannot use nextcase out of a defer.");
return poisoned_decl;
default:
@@ -1743,7 +1749,7 @@ static inline Decl *sema_analyse_label(SemaContext *context, Ast *stmt)
case AST_CONTINUE_STMT:
SEMA_ERROR(stmt, "You cannot use continue out of a defer.");
return poisoned_decl;
case AST_NEXT_STMT:
case AST_NEXTCASE_STMT:
SEMA_ERROR(stmt, "You cannot use nextcase out of a defer.");
return poisoned_decl;
default:
@@ -2441,21 +2447,19 @@ static inline bool sema_analyse_switch_stmt(SemaContext *context, Ast *statement
SCOPE_START_WITH_LABEL(statement->switch_stmt.flow.label);
Expr *cond = exprptr(statement->switch_stmt.cond);
Expr *cond = exprptrzero(statement->switch_stmt.cond);
Type *switch_type;
ExprVariantSwitch var_switch;
Decl *variant_decl = NULL;
if (statement->ast_kind == AST_SWITCH_STMT)
{
if (!sema_analyse_cond(context, cond, COND_TYPE_EVALTYPE_VALUE)) return false;
Expr *last = VECLAST(cond->cond_expr);
switch_type = last->type->canonical;
if (last->expr_kind == EXPR_VARIANTSWITCH)
if (cond && !sema_analyse_cond(context, cond, COND_TYPE_EVALTYPE_VALUE)) return false;
Expr *last = cond ? VECLAST(cond->cond_expr) : NULL;
switch_type = last ? last->type->canonical : type_bool;
if (last && last->expr_kind == EXPR_VARIANTSWITCH)
{
var_switch = last->variant_switch;
Expr *inner;
if (var_switch.is_assign)
{
@@ -2741,7 +2745,7 @@ static inline bool sema_analyse_statement_inner(SemaContext *context, Ast *state
return sema_analyse_return_stmt(context, statement);
case AST_SWITCH_STMT:
return sema_analyse_switch_stmt(context, statement);
case AST_NEXT_STMT:
case AST_NEXTCASE_STMT:
return sema_analyse_nextcase_stmt(context, statement);
case AST_CT_SWITCH_STMT:
return sema_analyse_ct_switch_stmt(context, statement);

View File

@@ -140,9 +140,6 @@ static inline bool sema_resolve_array_type(SemaContext *context, TypeInfo *type,
case TYPE_INFO_INFERRED_VECTOR:
type->type = type_get_inferred_vector(type->array.base->type);
break;
case TYPE_INFO_SCALED_VECTOR:
type->type = type_get_scaled_vector(type->array.base->type);
break;
case TYPE_INFO_VECTOR:
{
ArraySize width;
@@ -273,14 +270,18 @@ INLINE bool sema_resolve_evaltype(SemaContext *context, TypeInfo *type_info, boo
INLINE bool sema_resolve_typeof(SemaContext *context, TypeInfo *type_info)
{
Expr *expr = type_info->unresolved_type_expr;
if (!sema_analyse_expr(context, expr))
{
return false;
}
if (!sema_analyse_expr(context, expr)) return false;
if (type_is_invalid_storage_type(expr->type))
{
SEMA_ERROR(expr, "Expected a regular runtime expression here.");
return false;
if (expr->type == type_wildcard)
{
RETURN_SEMA_ERROR(expr, "This expression has no concrete type.");
}
if (expr->type == type_wildcard_optional)
{
RETURN_SEMA_ERROR(expr, "This optional expression is untyped.");
}
RETURN_SEMA_ERROR(expr, "Expected a regular runtime expression here.");
}
type_info->type = expr->type;
return true;
@@ -292,8 +293,7 @@ INLINE bool sema_resolve_typefrom(SemaContext *context, TypeInfo *type_info)
if (!sema_analyse_expr(context, expr)) return false;
if (!expr_is_const(expr) || expr->const_expr.const_kind != CONST_TYPEID)
{
SEMA_ERROR(expr, "Expected a constant typeid value.");
return false;
RETURN_SEMA_ERROR(expr, "Expected a constant typeid value.");
}
type_info->type = expr->const_expr.typeid;
return true;
@@ -304,16 +304,12 @@ INLINE bool sema_resolve_vatype(SemaContext *context, TypeInfo *type_info)
{
if (!context->current_macro)
{
SEMA_ERROR(type_info, "'%s' can only be used inside of a macro.", token_type_to_string(TOKEN_CT_VATYPE));
return false;
RETURN_SEMA_ERROR(type_info, "'%s' can only be used inside of a macro.", token_type_to_string(TOKEN_CT_VATYPE));
}
ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, type_info->unresolved_type_expr),
false);
if (arg_expr->expr_kind != EXPR_TYPEINFO)
{
SEMA_ERROR(arg_expr, "The argument was not a type.");
return false;
}
if (arg_expr->expr_kind != EXPR_TYPEINFO) RETURN_SEMA_ERROR(arg_expr, "The argument was not a type.");
assert(arg_expr->resolve_status == RESOLVE_DONE);
type_info->type = arg_expr->type_expr->type;
return true;
@@ -372,7 +368,6 @@ static inline bool sema_resolve_type(SemaContext *context, TypeInfo *type_info,
return type_info_poison(type_info);
}
FALLTHROUGH;
case TYPE_INFO_SCALED_VECTOR:
case TYPE_INFO_SUBARRAY:
case TYPE_INFO_ARRAY:
case TYPE_INFO_VECTOR:

View File

@@ -245,8 +245,6 @@ const char *token_type_to_string(TokenType type)
return "nextcase";
case TOKEN_NULL:
return "null";
case TOKEN_PRIVATE:
return "private";
case TOKEN_RETURN:
return "return";
case TOKEN_STATIC:
@@ -346,8 +344,6 @@ const char *token_type_to_string(TokenType type)
return "$foreach";
case TOKEN_CT_ELSE:
return "$else";
case TOKEN_CT_ELIF:
return "$elif";
case TOKEN_CT_ENDIF:
return "$endif";
case TOKEN_CT_ENDSWITCH:

View File

@@ -14,7 +14,7 @@ static struct
Type usz, isz, uptr, iptr;
Type string;
Type voidstar, typeid, anyerr, member, typeinfo, untyped_list;
Type any, anyfail;
Type any, wildcard;
} t;
Type *type_bool = &t.u1;
@@ -43,9 +43,10 @@ Type *type_uptr = &t.uptr;
Type *type_usz = &t.usz;
Type *type_anyerr = &t.anyerr;
Type *type_untypedlist = &t.untyped_list;
Type *type_anyfail = &t.anyfail;
Type *type_wildcard = &t.wildcard;
Type *type_member = &t.member;
Type *type_chars = NULL;
Type *type_wildcard_optional = NULL;
Type *type_string = &t.string;
static unsigned size_subarray;
@@ -56,10 +57,9 @@ static AlignSize max_alignment_vector;
#define INFERRED_ARRAY_OFFSET 1
#define FLEXIBLE_ARRAY_OFFSET 2
#define SUB_ARRAY_OFFSET 3
#define SCALED_VECTOR_OFFSET 4
#define INFERRED_VECTOR_OFFSET 5
#define OPTIONAL_OFFSET 6
#define ARRAY_OFFSET 7
#define INFERRED_VECTOR_OFFSET 4
#define OPTIONAL_OFFSET 5
#define ARRAY_OFFSET 6
Type *type_cint;
Type *type_cuint;
@@ -126,9 +126,6 @@ static void type_append_name_to_scratch(Type *type)
type_append_name_to_scratch(type->pointer);
scratch_buffer_append_char('*');
break;
case TYPE_OPTIONAL_ANY:
scratch_buffer_append("void!");
break;
case TYPE_OPTIONAL:
if (type->optional)
{
@@ -148,10 +145,6 @@ static void type_append_name_to_scratch(Type *type)
type_append_name_to_scratch(type->array.base);
scratch_buffer_append("[*]");
break;
case TYPE_SCALED_VECTOR:
type_append_name_to_scratch(type->array.base);
scratch_buffer_append("[<>]");
break;
case TYPE_VOID:
case TYPE_BOOL:
case ALL_INTS:
@@ -167,6 +160,7 @@ static void type_append_name_to_scratch(Type *type)
case TYPE_INFERRED_VECTOR:
case TYPE_TYPEINFO:
case TYPE_MEMBER:
case TYPE_WILDCARD:
UNREACHABLE
break;
case TYPE_FUNC:
@@ -226,6 +220,7 @@ const char *type_to_error_string(Type *type)
case TYPE_UNTYPED_LIST:
case TYPE_ANY:
case TYPE_MEMBER:
case TYPE_WILDCARD:
return type->name;
case TYPE_FUNC:
scratch_buffer_clear();
@@ -233,16 +228,12 @@ const char *type_to_error_string(Type *type)
return str_printf("fn %s", scratch_buffer_to_string());
case TYPE_INFERRED_VECTOR:
return str_printf("%s[<*>]", type_to_error_string(type->array.base));
case TYPE_SCALED_VECTOR:
return str_printf("%s[<>]", type_to_error_string(type->array.base));
case TYPE_VECTOR:
return str_printf("%s[<%llu>]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
case TYPE_TYPEINFO:
return "typeinfo";
case TYPE_TYPEID:
return "typeid";
case TYPE_OPTIONAL_ANY:
return "void!";
case TYPE_POINTER:
if (type->pointer->type_kind == TYPE_FUNC)
{
@@ -289,7 +280,6 @@ RETRY:
}
case CT_TYPES:
UNREACHABLE;
case TYPE_SCALED_VECTOR:
case TYPE_FLEXIBLE_ARRAY:
return 0;
case TYPE_OPTIONAL:
@@ -310,7 +300,6 @@ RETRY:
assert(type->decl->resolve_status == RESOLVE_DONE);
return type->decl->strukt.size;
case TYPE_VOID:
case TYPE_OPTIONAL_ANY:
return 1;
case TYPE_BOOL:
case TYPE_TYPEID:
@@ -385,8 +374,6 @@ bool type_is_abi_aggregate(Type *type)
RETRY:
switch (type->type_kind)
{
case TYPE_POISONED:
return false;
case TYPE_OPTIONAL:
type = type->optional;
goto RETRY;
@@ -399,7 +386,6 @@ bool type_is_abi_aggregate(Type *type)
case TYPE_BITSTRUCT:
case ALL_FLOATS:
case TYPE_VOID:
case TYPE_OPTIONAL_ANY:
case ALL_INTS:
case TYPE_BOOL:
case TYPE_TYPEID:
@@ -416,13 +402,8 @@ bool type_is_abi_aggregate(Type *type)
case TYPE_ARRAY:
case TYPE_ANY:
return true;
case TYPE_TYPEINFO:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_UNTYPED_LIST:
case CT_TYPES:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
case TYPE_MEMBER:
UNREACHABLE
}
UNREACHABLE
@@ -485,7 +466,6 @@ bool type_is_comparable(Type *type)
case TYPE_BITSTRUCT:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
case TYPE_MEMBER:
return false;
case TYPE_TYPEDEF:
@@ -511,8 +491,8 @@ bool type_is_comparable(Type *type)
case TYPE_FAULTTYPE:
case TYPE_UNTYPED_LIST:
case TYPE_TYPEINFO:
case TYPE_SCALED_VECTOR:
case TYPE_VECTOR:
case TYPE_WILDCARD:
return true;
}
UNREACHABLE
@@ -522,13 +502,7 @@ void type_mangle_introspect_name_to_buffer(Type *type)
{
switch (type->type_kind)
{
case TYPE_POISONED:
case TYPE_TYPEINFO:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_UNTYPED_LIST:
case TYPE_OPTIONAL_ANY:
case TYPE_MEMBER:
case CT_TYPES:
UNREACHABLE
case TYPE_VOID:
case TYPE_BOOL:
@@ -561,10 +535,6 @@ void type_mangle_introspect_name_to_buffer(Type *type)
scratch_buffer_append_char('$');
type_mangle_introspect_name_to_buffer(type->array.base);
return;
case TYPE_SCALED_VECTOR:
scratch_buffer_append("vn$");
type_mangle_introspect_name_to_buffer(type->array.base);
return;
case TYPE_ARRAY:
scratch_buffer_append_char('a');
scratch_buffer_append_unsigned_int(type->array.len);
@@ -646,6 +616,7 @@ AlignSize type_abi_alignment(Type *type)
case TYPE_TYPEINFO:
case TYPE_UNTYPED_LIST:
case TYPE_MEMBER:
case TYPE_WILDCARD:
UNREACHABLE;
case TYPE_BITSTRUCT:
type = type->decl->bitstruct.base_type->type;
@@ -665,7 +636,6 @@ AlignSize type_abi_alignment(Type *type)
return alignment;
}
case TYPE_VOID:
case TYPE_OPTIONAL_ANY:
return 1;
case TYPE_OPTIONAL:
type = type->optional;
@@ -702,8 +672,6 @@ AlignSize type_abi_alignment(Type *type)
goto RETRY;
case TYPE_SUBARRAY:
return alignment_subarray;
case TYPE_SCALED_VECTOR:
UNSUPPORTED;
}
UNREACHABLE
}
@@ -872,37 +840,10 @@ static Type *type_generate_flexible_array(Type *arr_type, bool canonical)
return arr;
}
static Type *type_generate_scaled_vector(Type *arr_type, bool canonical)
{
if (canonical) arr_type = arr_type->canonical;
if (!arr_type->type_cache)
{
create_type_cache(arr_type);
}
Type *arr = arr_type->type_cache[SCALED_VECTOR_OFFSET];
if (arr == NULL)
{
arr = type_new(TYPE_SCALED_VECTOR, str_printf("%s[<>]", arr_type->name));
arr->array.base = arr_type;
arr->array.len = 0;
arr_type->type_cache[SCALED_VECTOR_OFFSET] = arr;
if (arr_type == arr_type->canonical)
{
arr->canonical = arr;
}
else
{
arr->canonical = type_generate_scaled_vector(arr_type->canonical, true);
}
}
return arr;
}
Type *type_get_ptr_recurse(Type *ptr_type)
{
assert(ptr_type->type_kind != TYPE_OPTIONAL_ANY);
if (ptr_type->type_kind == TYPE_OPTIONAL)
{
ptr_type = ptr_type->optional;
@@ -943,11 +884,6 @@ Type *type_get_flexible_array(Type *arr_type)
return type_generate_flexible_array(arr_type, false);
}
Type *type_get_scaled_vector(Type *arr_type)
{
return type_generate_scaled_vector(arr_type, false);
}
static inline bool array_structurally_equivalent_to_struct(Type *array, Type *type)
{
assert(array->type_kind == TYPE_ARRAY);
@@ -1067,7 +1003,6 @@ Type *type_get_indexed_type(Type *type)
case TYPE_SUBARRAY:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_SCALED_VECTOR:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_VECTOR:
return type->array.base;
@@ -1490,7 +1425,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_OPTIONAL_ANY, 1, 1, 1);
type_create("void", &t.wildcard, TYPE_WILDCARD, 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);
@@ -1507,6 +1442,7 @@ void type_setup(PlatformTarget *target)
size_subarray = (unsigned)(alignment_subarray * 2);
type_init("anyerr", &t.anyerr, TYPE_ANYERR, target->width_pointer, target->align_pointer);
type_chars = type_get_subarray(type_char);
type_wildcard_optional = type_get_optional(type_wildcard);
Decl *string_decl = decl_new_with_type(symtab_preset("String", TOKEN_TYPE_IDENT), INVALID_SPAN, DECL_DISTINCT);
string_decl->extname = string_decl->name;
string_decl->is_substruct = true;
@@ -1558,10 +1494,8 @@ bool type_is_scalar(Type *type)
case TYPE_ARRAY:
case TYPE_SUBARRAY:
case TYPE_VECTOR:
case TYPE_OPTIONAL_ANY:
case TYPE_ANY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
return false;
case TYPE_BOOL:
case ALL_INTS:
@@ -1799,7 +1733,6 @@ bool type_may_have_method(Type *type)
case TYPE_FLEXIBLE_ARRAY:
case TYPE_VECTOR:
case TYPE_BOOL:
case TYPE_SCALED_VECTOR:
return true;
case TYPE_TYPEDEF:
UNREACHABLE
@@ -1809,9 +1742,9 @@ bool type_may_have_method(Type *type)
case TYPE_FUNC:
case TYPE_UNTYPED_LIST:
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
case TYPE_TYPEINFO:
case TYPE_MEMBER:
case TYPE_WILDCARD:
return false;
}
UNREACHABLE
@@ -1962,6 +1895,9 @@ Type *type_find_max_type(Type *type, Type *other)
if (type == other) return type;
if (type == type_wildcard) return other;
if (other == type_wildcard) return type;
// Lower inlined distinct types.
while (type->type_kind == TYPE_DISTINCT && type->decl->is_substruct) type = type->decl->distinct_decl.base_type;
while (other->type_kind == TYPE_DISTINCT && other->decl->is_substruct) other = other->decl->distinct_decl.base_type;
@@ -1983,7 +1919,7 @@ Type *type_find_max_type(Type *type, Type *other)
case TYPE_INFERRED_VECTOR:
case TYPE_POISONED:
case TYPE_OPTIONAL:
case TYPE_OPTIONAL_ANY:
case TYPE_WILDCARD:
UNREACHABLE
case TYPE_VOID:
case TYPE_BOOL:
@@ -1991,7 +1927,6 @@ Type *type_find_max_type(Type *type, Type *other)
case TYPE_ANY:
case TYPE_BITSTRUCT:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
return NULL;
case ALL_INTS:
if (other->type_kind == TYPE_DISTINCT && type_underlying_is_numeric(other)) return other;
@@ -2183,14 +2118,13 @@ unsigned type_get_introspection_kind(TypeKind kind)
case TYPE_SUBARRAY:
return INTROSPECT_TYPE_SUBARRAY;
case TYPE_VECTOR:
case TYPE_SCALED_VECTOR:
case TYPE_INFERRED_VECTOR:
return INTROSPECT_TYPE_VECTOR;
case TYPE_UNTYPED_LIST:
case TYPE_OPTIONAL_ANY:
case TYPE_TYPEINFO:
case TYPE_OPTIONAL:
case TYPE_MEMBER:
case TYPE_WILDCARD:
UNREACHABLE
return 0;
}
@@ -2210,6 +2144,7 @@ Module *type_base_module(Type *type)
case TYPE_ANY:
case TYPE_ANYERR:
case TYPE_TYPEID:
case TYPE_WILDCARD:
return NULL;
case TYPE_POINTER:
type = type->pointer;
@@ -2231,7 +2166,6 @@ Module *type_base_module(Type *type)
case TYPE_INFERRED_ARRAY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_VECTOR:
case TYPE_SCALED_VECTOR:
case TYPE_INFERRED_VECTOR:
type = type->array.base;
goto RETRY;
@@ -2239,7 +2173,6 @@ Module *type_base_module(Type *type)
type = type->optional;
goto RETRY;
case TYPE_UNTYPED_LIST:
case TYPE_OPTIONAL_ANY:
case TYPE_TYPEINFO:
case TYPE_MEMBER:
UNREACHABLE

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.116"
#define COMPILER_VERSION "0.4.117"

View File

@@ -1,11 +1,11 @@
bitstruct Foo : char
{
bool a : 1;
bool b; // #error: Expected a ':'
bool b; // #error: remove ranges from the other member
}
bitstruct Foo2 : char
{
bool a;
bool b : 1; // #error: Expected ';'
bool b : 1; // #error: ranges to all other members
}

View File

@@ -6,7 +6,9 @@ fault MyErr
fn void test()
{
int! x;
int! d = ($typeof(MyErr.FOO!))(x); // #error: Casting to an optional type is not allowed
double! y;
int! d = ($typeof(MyErr.FOO!))(x); // #error: This optional expression is untyped
int! df = ($typeof(y))(x); // #error: Casting to an optional type is not allowed
}

View File

@@ -26,7 +26,7 @@ fn void foo2()
fn void foo3()
{
int a;
$switch ({ 1, 3 }): // #error: Only types, strings, enums, integers, floats and booleans
$switch ({ 1, 3 }) // #error: Only types, strings, enums, integers, floats and booleans
$case 1:
io::printn("Hello");
$default:

View File

@@ -1,5 +1,7 @@
fault Error
{}
{
ABC
}
typedef Foo1 = distinct Error; // #error: You cannot create a distinct type

View File

@@ -1,4 +0,0 @@
import std::io;
define foo = distinct x; // #error: can only be used with types
define bar = distinct int; // #error: type name alias must start with an uppercase

View File

@@ -0,0 +1,4 @@
module test;
fault Foo
{
} // #error: no values

View File

@@ -9,5 +9,5 @@ macro test()
fn void main()
{
test() ?? 2; // #error: Cannot find a common type for 'void' and 'int'
test() ?? 2; // No longer an error!
}

View File

@@ -0,0 +1,38 @@
fn int! abc()
{
return 1;
}
macro test()
{
abc()?;
}
fn void a()
{
String s = $typeof(test()).qnameof; // #error: This optional expression is untyped.
}
fn void b()
{
$sizeof(test()); // #error: This optional expression is untyped.
}
fn void c()
{
$sizeof(test() ?? 1);
}
fn void! d()
{
$typeof(test()?) g; // #error: This expression has no concrete type
}
macro e()
{
var g = test()?; // #error: No type can be inferred from the optional result
}
fn void! h()
{
e();
}

View File

@@ -3,7 +3,7 @@ fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop,
struct TreeNode { int abc; NodeNotifyHandler notifyHandler; }
struct TreeView { int abc; }
private fn void TreeView.addNodeInternal(TreeView* this, int nop, TreeNode* node, TreeNode* pnode = null, int pos = -1)
fn void TreeView.addNodeInternal(TreeView* this, int nop, TreeNode* node, TreeNode* pnode = null, int pos = -1) @private
{
node.notifyHandler = &TreeView.nodeNotifyHandler; // This is the line
}

View File

@@ -1,9 +1,9 @@
typedef NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data);
private fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) {}
fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) @private {}
struct TreeNode { int abc; NodeNotifyHandler notifyHandler; }
struct TreeView { int abc; }
private fn void TreeView.addNodeInternal(TreeView* this, int nop, TreeNode* node, TreeNode* pnode = null, int pos = -1)
fn void TreeView.addNodeInternal(TreeView* this, int nop, TreeNode* node, TreeNode* pnode = null, int pos = -1) @private
{
node.notifyHandler = &(this.nodeNotifyHandler); // #error: Taking the address of a method
}