mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Compare commits
1 Commits
0.4godbolt
...
v0.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bcc56e6fe |
7
resources/grammar/Makefile
Normal file
7
resources/grammar/Makefile
Normal 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
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 ");
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 },
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.116"
|
||||
#define COMPILER_VERSION "0.4.117"
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
fault Error
|
||||
{}
|
||||
{
|
||||
ABC
|
||||
}
|
||||
|
||||
typedef Foo1 = distinct Error; // #error: You cannot create a distinct type
|
||||
|
||||
|
||||
@@ -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
|
||||
4
test/test_suite/errors/empty_fault.c3
Normal file
4
test/test_suite/errors/empty_fault.c3
Normal file
@@ -0,0 +1,4 @@
|
||||
module test;
|
||||
fault Foo
|
||||
{
|
||||
} // #error: no values
|
||||
@@ -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!
|
||||
}
|
||||
38
test/test_suite/errors/optional_sizeof.c3
Normal file
38
test/test_suite/errors/optional_sizeof.c3
Normal 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();
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user