$elif deprecated.

This commit is contained in:
Christoffer Lerno
2023-03-20 16:54:45 +01:00
parent 02d073675a
commit 9c145996b0
19 changed files with 197 additions and 142 deletions

View File

@@ -8,25 +8,26 @@
module std::collections::enumset<Enum>;
$if (Enum.elements > 128)
$switch
$case (Enum.elements > 128):
typedef EnumSetType @private = char[(Enum.elements + 7) / 8];
const IS_CHAR_ARRAY = true;
$elif (Enum.elements > 64)
$case (Enum.elements > 64):
typedef EnumSetType @private = uint128;
const IS_CHAR_ARRAY = false;
$elif (Enum.elements > 32 || $$C_INT_SIZE > 32)
$case (Enum.elements > 32 || $$C_INT_SIZE > 32):
typedef EnumSetType @private = ulong;
const IS_CHAR_ARRAY = false;
$elif (Enum.elements > 16 || $$C_INT_SIZE > 16)
$case (Enum.elements > 16 || $$C_INT_SIZE > 16):
typedef EnumSetType @private = uint;
const IS_CHAR_ARRAY = false;
$elif (Enum.elements > 8 || $$C_INT_SIZE > 8)
$case (Enum.elements > 8 || $$C_INT_SIZE > 8):
typedef EnumSetType @private = ushort;
const IS_CHAR_ARRAY = false;
$else
$default:
typedef EnumSetType @private = char;
const IS_CHAR_ARRAY = false;
$endif
$endswitch
typedef EnumSet = distinct EnumSetType;

View File

@@ -212,24 +212,27 @@ fn void Object.set_object(Object* o, String key, Object* new_object) @private
macro Object* object_from_value(value) @private
{
var $Type = $typeof(value);
$if (types::is_int($Type))
$switch
$case types::is_int($Type):
return new_int(value);
$elif (types::is_float($Type))
$case types::is_float($Type):
return new_float(value);
$elif ($Type.typeid == String.typeid)
$case $Type.typeid == String.typeid:
return new_string(value);
$elif ($Type.typeid == bool.typeid)
$case $Type.typeid == bool.typeid:
return new_bool(value);
$elif ($Type.typeid == Object*.typeid)
$case $Type.typeid == Object*.typeid:
return value;
$elif ($Type.typeid == void*.typeid)
$case $Type.typeid == void*.typeid:
assert(value == null);
return &NULL_OBJECT;
$elif ($checks(String s = value))
$case $checks(String s = value):
return new_string(value);
$else
$default:
$assert(false, "Unsupported object type.");
$endif
$endswitch
}
macro Object* Object.set(Object* o, String key, value)

View File

@@ -8,13 +8,14 @@ module std::core::builtin;
**/
macro less(a, b) @builtin
{
$if ($defined(a.less))
$switch
$case $defined(a.less):
return a.less(b);
$elif ($defined(a.compare_to))
$case $defined(a.compare_to):
return a.compare_to(b) < 0;
$else
$default:
return a < b;
$endif
$endswitch
}
/**
@@ -22,13 +23,14 @@ macro less(a, b) @builtin
**/
macro less_eq(a, b) @builtin
{
$if ($defined(a.less))
$switch
$case $defined(a.less):
return !b.less(a);
$elif ($defined(a.compare_to))
$case $defined(a.compare_to):
return a.compare_to(b) <= 0;
$else
$default:
return a <= b;
$endif
$endswitch
}
/**
@@ -36,13 +38,14 @@ macro less_eq(a, b) @builtin
**/
macro greater(a, b) @builtin
{
$if ($defined(a.less))
$switch
$case $defined(a.less):
return b.less(a);
$elif ($defined(a.compare_to))
$case $defined(a.compare_to):
return a.compare_to(b) > 0;
$else
$default:
return a > b;
$endif
$endswitch
}
/**
@@ -50,13 +53,14 @@ macro greater(a, b) @builtin
**/
macro greater_eq(a, b) @builtin
{
$if ($defined(a.less))
$switch
$case $defined(a.less):
return !a.less(b);
$elif ($defined(a.compare_to))
$case $defined(a.compare_to):
return a.compare_to(b) >= 0;
$else
$default:
return a >= b;
$endif
$endswitch
}
/**
@@ -64,15 +68,16 @@ macro greater_eq(a, b) @builtin
**/
macro bool equals(a, b) @builtin
{
$if ($defined(a.equals))
$switch
$case $defined(a.equals):
return a.equals(b);
$elif ($defined(a.compare_to))
$case $defined(a.compare_to):
return a.compare_to(b) == 0;
$elif ($defined(a.less))
$case $defined(a.less):
return !a.less(b) && !b.less(a);
$else
$default:
return a == b;
$endif
$endswitch
}
macro min(x, ...) @builtin

View File

@@ -302,13 +302,14 @@ macro void DString.append(DString* str, value)
$case Char32:
str.append_char32(value);
$default:
$if (@convertible(value, Char32))
str.append_char32(value);
$elif (@convertible(value, String))
str.append_chars(value);
$else
$assert(false, "Unsupported type for append use printf instead.");
$endif
$switch
$case @convertible(value, Char32):
str.append_char32(value);
$case @convertible(value, String):
str.append_chars(value);
$default:
$assert(false, "Unsupported type for append use printf instead.");
$endswitch
$endswitch
}

View File

@@ -278,13 +278,14 @@ macro void VarString.append(VarString* str, value)
$case Char32:
str.append_char32(value);
$default:
$if (@convertible(value, Char32))
str.append_char32(value);
$elif (@convertible(value, String))
str.append_chars(value);
$else
$assert(false, "Unsupported type for append use printf instead.");
$endif
$switch
$case @convertible(value, Char32):
str.append_char32(value);
$case @convertible(value, String):
str.append_chars(value);
$default:
$assert(false, "Unsupported type for append use printf instead.");
$endswitch
$endswitch
}

View File

@@ -2,14 +2,15 @@ module std::io::os;
import libc;
$if (!env::COMPILER_LIBC_AVAILABLE)
$switch
$case !env::COMPILER_LIBC_AVAILABLE:
fn void! native_chdir(Path path)
{
unreachable("'getcwd' not available");
}
$elif (env::OS_TYPE == OsType.WIN32)
$case env::os_is_win32():
macro void! native_chdir(Path path)
{
@@ -20,7 +21,7 @@ macro void! native_chdir(Path path)
return IoError.GENERAL_ERROR!;
}
$else
$default:
extern fn int _chdir(ZString) @extern("chdir");
macro void! native_chdir(Path p)
@@ -39,4 +40,4 @@ macro void! native_chdir(Path p)
}
}
$endif
$endswitch

View File

@@ -1,14 +1,15 @@
module std::io::os;
import libc;
$if (!env::COMPILER_LIBC_AVAILABLE)
$switch
$case !env::COMPILER_LIBC_AVAILABLE:
fn String! getcwd(Allocator* using = mem::heap())
{
unreachable("'getcwd' not available");
}
$elif (env::OS_TYPE == OsType.WIN32)
$case env::os_is_win32():
extern fn Char16* _wgetcwd(Char16* buffer, int maxlen);
extern fn usz wcslen(Char16* str);
@@ -30,7 +31,7 @@ macro String! getcwd(Allocator* using = mem::heap())
return str::utf16to8(str16, using);
}
$else
$default:
extern fn ZString _getcwd(char* pwd, usz len) @extern("getcwd");
macro String! getcwd(Allocator* using = mem::heap())
@@ -50,4 +51,4 @@ macro String! getcwd(Allocator* using = mem::heap())
return res.copy(using);
}
$endif
$endswitch

View File

@@ -151,7 +151,8 @@ $endif
typedef Fpos = long;
typedef CFile = void*;
$if (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.LINUX)
$switch
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.LINUX:
extern CFile __stdin @extern("stdin");
extern CFile __stdout @extern("stdout");
extern CFile __stderr @extern("stderr");
@@ -161,7 +162,7 @@ $if (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.LINUX)
macro CFile stdin() { return __stdin; }
macro CFile stdout() { return __stdout; }
macro CFile stderr() { return __stderr; }
$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.MACOSX)
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.MACOSX:
extern CFile __stdinp;
extern CFile __stdoutp;
extern CFile __stderrp;
@@ -170,18 +171,18 @@ $elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.MACOSX)
macro CFile stdin() { return __stdinp; }
macro CFile stdout() { return __stdoutp; }
macro CFile stderr() { return __stderrp; }
$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.WIN32)
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.WIN32:
extern fn CFile __acrt_iob_func(CInt c);
extern fn usz _msize(void* ptr);
macro usz malloc_size(void* ptr) { return _msize(ptr); }
macro CFile stdin() { return __acrt_iob_func(0); }
macro CFile stdout() { return __acrt_iob_func(1); }
macro CFile stderr() { return __acrt_iob_func(2); }
$else
$default:
macro CFile stdin() { return (CFile*)(uptr)0; }
macro CFile stdout() { return (CFile*)(uptr)1; }
macro CFile stderr() { return (CFile*)(uptr)2; }
$endif
$endswitch
const HAS_MALLOC_SIZE =
env::OS_TYPE == OsType.LINUX
@@ -385,7 +386,7 @@ const Errno ENOEXEC = 8; // Exec format error
const Errno EBADF = 9; // Bad file number
const Errno ECHILD = 10; // No child processes
$if (env::OS_TYPE == OsType.MACOSX)
$if (env::OS_TYPE == MACOSX)
const Errno EAGAIN = 35; // Try again Macos
$else
const Errno EAGAIN = 11; // Try again
@@ -415,7 +416,9 @@ const Errno EPIPE = 32; // Broken pipe
const Errno EDOM = 33; // Math argument out of domain of func
const Errno ERANGE = 34; // Math result not representable
$if (env::OS_TYPE == OsType.MACOSX)
$switch (env::OS_TYPE)
$case MACOSX:
const Errno EDEADLK = 11; // Resource deadlock would occur MacOS
const Errno ENAMETOOLONG = 63; // File name too long MacOS
const Errno ELOOP = 62; // Too many symbolic links encountered
@@ -426,7 +429,7 @@ const Errno ENETUNREACH = 51; // Network is unreachable MacOS
const Errno ENETRESET = 52; // Network dropped connection because of reset MacOS
const Errno EOPNOTSUPP = 45; // Operation not supported on transport endpoint
$elif (env::OS_TYPE == OsType.WIN32)
$case WIN32:
const Errno EDEADLK = 36; // Resource deadlock would occur Win32
const Errno ENAMETOOLONG = 38; // File name too long Win32
const Errno ELOOP = 114; // Too many symbolic links encountered
@@ -437,7 +440,7 @@ const Errno ENETUNREACH = 118; // Network is unreachable
const Errno ENETRESET = 117; // Network dropped connection because of reset
const Errno EOPNOTSUPP = 130; // Operation not supported on transport endpoint
$else
$default:
const Errno EDEADLK = 35; // Resource deadlock would occur Linux (others?)
const Errno ENAMETOOLONG = 36; // File name too long Linux (others?)
const Errno ELOOP = 40; // Too many symbolic links encountered
@@ -448,7 +451,7 @@ const Errno ENETUNREACH = 101; // Network is unreachable
const Errno ENETRESET = 102; // Network dropped connection because of reset
const Errno EOPNOTSUPP = 95; // Operation not supported on transport endpoint
$endif
$endswitch
@@ -523,27 +526,30 @@ const Errno ECONNREFUSED = 111; /* Connection refused */
const Errno EHOSTDOWN = 112; /* Host is down */
const Errno EHOSTUNREACH = 113; /* No route to host */
*/
$if (env::OS_TYPE == OsType.MACOSX)
$switch (env::OS_TYPE)
$case MACOSX:
const Errno ETIMEDOUT = 60; // Connection timed out
const Errno EINPROGRESS = 36; // Operation now in progress MacOS
const Errno EALREADY = 37; // Operation already in progress MacOS
const Errno EDQUOT = 69; // Quota exceeded, MacOS
const Errno EWOULDBLOCK = 35; // Operation would block
$elif (env::OS_TYPE == OsType.WIN32)
$case WIN32:
const Errno ETIMEDOUT = 138; // Connection timed out
const Errno EALREADY = 103; // Operation already in progress
const Errno EINPROGRESS = 112; // Operation now in progress Win32
const Errno EDQUOT = -122; // Quota exceeded, not in Win32
const Errno EWOULDBLOCK = 140; // Operation would block
$else
$default:
const Errno ETIMEDOUT = 110; // Connection timed out
const Errno EALREADY = 114; // Operation already in progress
const Errno EINPROGRESS = 115; // Operation now in progress
const Errno EDQUOT = 122; // Quota exceeded
const Errno EWOULDBLOCK = 41; // Operation would block
$endif
$endswitch
/*
const Errno ESTALE = 116; /* Stale NFS file handle */

View File

@@ -1,18 +1,21 @@
module libc::os;
$if (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.LINUX)
$switch
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == LINUX:
extern fn int* __errno_location();
macro int errno() => *__errno_location();
macro void errno_set(int err) => *(__errno_location()) = err;
$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.MACOSX)
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == MACOSX:
extern fn int* __error();
macro int errno() => *__error();
macro void errno_set(int err) => *(__error()) = err;
$elif (env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.WIN32)
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == WIN32:
macro int errno()
{
@@ -26,10 +29,10 @@ macro void errno_set(int err) => _set_errno(err);
extern fn void _get_errno(int* result);
extern fn void _set_errno(int err);
$else
$default:
tlocal int _errno_c3 = 0;
fn void errno_set(int err) => _errno_c3 = err;
fn int errno() => _errno_c3;
$endif
$endswitch

View File

@@ -407,13 +407,14 @@ macro sqrt(x) => $$sqrt(values::promote_int(x));
macro tan(x)
{
var $Type = $typeof(x);
$if (types::is_vector($Type))
$switch
$case types::is_vector($Type):
return $$sin(x) / $$cos(x);
$elif ($Type.typeid == float.typeid)
$case $Type.typeid == float.typeid:
return _tanf(x);
$else
$default:
return _tan(x);
$endif
$endswitch
}
/**

View File

@@ -109,18 +109,21 @@ generic boor2(i)
return 10001;
}
$if ($e > 0)
$switch
$case $e > 0:
{
fn void foo() {}
}
$elif ($e < 0)
$case $e < 0:
{
fn void foo() { printf("HELO"); }
}
$else
$default:
{
fn void foo() { printf("OLEH"); }
}
$endswitch
$if ($e > 0)
{

View File

@@ -5,17 +5,16 @@
#include "compiler_internal.h"
#include "parser_internal.h"
static bool context_next_is_path_prefix_start(ParseContext *c);
static Decl *parse_const_declaration(ParseContext *c, bool is_global);
static inline Decl *parse_func_definition(ParseContext *c, AstId docs, bool is_interface);
static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl);
INLINE bool parse_decl_initializer(ParseContext *c, Decl *decl);
static inline Decl *parse_static_top_level(ParseContext *c);
static Decl *parse_include(ParseContext *c);
static bool parse_attributes_for_global(ParseContext *c, Decl *decl);
INLINE bool parse_decl_initializer(ParseContext *c, Decl *decl);
INLINE Decl *decl_new_var_current(ParseContext *c, TypeInfo *type, VarDeclKind kind);
static bool context_next_is_path_prefix_start(ParseContext *c);
INLINE Decl *decl_new_var_current(ParseContext *c, TypeInfo *type, VarDeclKind kind)
{
@@ -125,8 +124,10 @@ static inline Decl *parse_ct_if_top_level(ParseContext *c)
if (!parse_top_level_block(c, &ct->ct_if_decl.then, TOKEN_CT_ENDIF, TOKEN_CT_ELIF, TOKEN_CT_ELSE)) return poisoned_decl;
CtIfDecl *ct_if_decl = &ct->ct_if_decl;
// Chain elif
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_ELIF, 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);
@@ -135,6 +136,7 @@ static inline Decl *parse_ct_if_top_level(ParseContext *c)
ct_if_decl->elif = ct_elif;
ct_if_decl = &ct_elif->ct_elif_decl;
}
// final else
if (tok_is(c, TOKEN_CT_ELSE))
{
Decl *ct_else = decl_new_ct(DECL_CT_ELSE, c->span);
@@ -179,7 +181,7 @@ static inline Decl *parse_ct_case(ParseContext *c)
}
/**
* ct_switch_top_level ::= CT_SWITCH const_paren_expr '{' ct_case* '}'
* ct_switch_top_level ::= CT_SWITCH const_paren_expr? ct_case* CT_ENDSWITCH
* @param c
* @return the declaration if successfully parsed, NULL otherwise.
*/
@@ -187,8 +189,11 @@ static inline Decl *parse_ct_switch_top_level(ParseContext *c)
{
Decl *ct = decl_new_ct(DECL_CT_SWITCH, c->span);
advance_and_verify(c, TOKEN_CT_SWITCH);
ASSIGN_EXPR_OR_RET(ct->ct_switch_decl.expr, parse_const_paren_expr(c), poisoned_decl);
consume_deprecated_symbol(c, TOKEN_COLON);
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);
}
while (!try_consume(c, TOKEN_CT_ENDSWITCH))
{
ASSIGN_DECL_OR_RET(Decl *result, parse_ct_case(c), poisoned_decl);

View File

@@ -930,7 +930,9 @@ static inline Ast* parse_ct_else_stmt(ParseContext *c)
static inline Ast* parse_ct_if_stmt(ParseContext *c, bool is_elif)
{
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);
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;
@@ -1076,8 +1078,11 @@ 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);
ASSIGN_EXPRID_OR_RET(ast->ct_switch_stmt.cond, parse_const_paren_expr(c), poisoned_ast);
consume_deprecated_symbol(c, TOKEN_COLON);
if (!tok_is(c, TOKEN_CT_CASE) && !tok_is(c, TOKEN_CT_DEFAULT) && !tok_is(c, TOKEN_CT_ENDSWITCH))
{
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;
while (!try_consume(c, TOKEN_CT_ENDSWITCH))

View File

@@ -178,10 +178,10 @@ static inline bool sema_analyse_top_level_if(SemaContext *context, Decl *ct_if)
static inline bool sema_analyse_top_level_switch(SemaContext *context, Decl *ct_switch)
{
Expr *cond = ct_switch->ct_switch_decl.expr;
if (!sema_analyse_ct_expr(context, cond)) return false;
Type *type = cond->type;
if (cond && !sema_analyse_ct_expr(context, cond)) return false;
Type *type = cond ? cond->type : type_bool;
bool is_type = type == type_typeid;
ExprConst *switch_expr_const = &cond->const_expr;
ExprConst *switch_expr_const = cond ? &cond->const_expr : NULL;
Decl **cases = ct_switch->ct_switch_decl.cases;
unsigned case_count = vec_size(cases);
@@ -213,6 +213,12 @@ static inline bool sema_analyse_top_level_switch(SemaContext *context, Decl *ct_
SEMA_ERROR(expr, "The $case must have a constant expression.");
return false;
}
if (!cond)
{
if (!expr->const_expr.b) continue;
if (matched_case == case_count) matched_case = (int)i;
continue;
}
if (to_expr && to_expr->expr_kind != EXPR_CONST)
{
SEMA_ERROR(to_expr, "The $case must have a constant expression.");

View File

@@ -2193,12 +2193,12 @@ static inline bool sema_analyse_ct_switch_stmt(SemaContext *context, Ast *statem
{
unsigned ct_context = sema_context_push_ct_stack(context);
// Evaluate the switch statement
Expr *cond = exprptr(statement->ct_switch_stmt.cond);
if (!sema_analyse_ct_expr(context, cond)) goto FAILED;
Expr *cond = exprptrzero(statement->ct_switch_stmt.cond);
if (cond && !sema_analyse_ct_expr(context, cond)) goto FAILED;
// If we have a type, then we do different evaluation
// compared to when it is a value.
Type *type = cond->type;
Type *type = cond ? cond->type : type_bool;
bool is_type = false;
switch (type_flatten(type)->type_kind)
{
@@ -2214,11 +2214,12 @@ static inline bool sema_analyse_ct_switch_stmt(SemaContext *context, Ast *statem
if (expr_is_const_string(cond)) break;
FALLTHROUGH;
default:
assert(cond);
SEMA_ERROR(cond, "Only types, strings, enums, integers, floats and booleans may be used with '$switch'.");
goto FAILED;
}
ExprConst *switch_expr_const = &cond->const_expr;
ExprConst *switch_expr_const = cond ? &cond->const_expr : NULL;
Ast **cases = statement->ct_switch_stmt.body;
unsigned case_count = vec_size(cases);
@@ -2234,7 +2235,6 @@ static inline bool sema_analyse_ct_switch_stmt(SemaContext *context, Ast *statem
{
case AST_CASE_STMT:
{
Expr *expr = stmt->case_stmt.expr;
Expr *to_expr = stmt->case_stmt.to_expr;
if (to_expr)
@@ -2264,6 +2264,12 @@ static inline bool sema_analyse_ct_switch_stmt(SemaContext *context, Ast *statem
SEMA_ERROR(expr, "The $case must have a constant expression.");
goto FAILED;
}
if (!cond)
{
if (!expr->const_expr.b) continue;
if (matched_case == case_count) matched_case = (int)i;
continue;
}
if (to_expr && !expr_is_const(to_expr))
{
SEMA_ERROR(to_expr, "The $case must have a constant expression.");
@@ -2292,7 +2298,7 @@ static inline bool sema_analyse_ct_switch_stmt(SemaContext *context, Ast *statem
}
if (expr_const_in_range(switch_expr_const, const_expr, const_to_expr))
{
matched_case = (int) i;
matched_case = (int)i;
}
break;
}

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.114"
#define COMPILER_VERSION "0.4.115"

View File

@@ -1,60 +1,63 @@
$if (0)
$else
$if (0)
$elif (0)
$elif (0)
$else
$switch
$case false:
$case false:
$case false:
$default:
int x = 1;
$endif
$endswitch
$endif
$if (0)
$switch
$case false:
$assert(false);
$elif (0)
$case false:
$assert(false);
$else
$default:
$assert(true);
$endif
$endswitch
$if (1)
$assert(true);
int d = 5;
$elif (0)
$assert(false);
$else
$assert(false);
$endif
$if (0)
$switch
$case false:
$assert(true);
$elif (1)
$case true:
$assert(true);
int c = 5;
$else
$default:
$assert(false);
$endif
$endswitch
$if (0)
$switch
$case false:
$assert(true);
$elif (1)
$case true:
$assert(true);
int b = 4;
$elif (0)
$case false:
$assert(false);
$else
$default:
$assert(false);
$endif
$endswitch
$if (0)
$switch
$case false:
$assert(true);
$elif (0)
$case false:
$assert(false);
$elif (1)
$case true:
$assert(true);
int a = 3;
$else
$default:
$assert(false);
$endif
$endswitch
// #expect: ct_if.ll

View File

@@ -16,13 +16,16 @@ $else // #error: Expected the start of a global declaration here
$endif
$if (1)
$elif (2)
$else
$endif
$switch
$case true:
$case true:
$default:
$endswitch
$switch
$case true:
$case true:
$case true:
$default:
$endswitch
$if (1)
$elif (2)
$elif (3)
$else
$endif

View File

@@ -6,35 +6,36 @@ macro testbitcast(expr, $Type)
$Type x @noinit;
var $size = (usz)($sizeof(expr));
$if ($alignof(expr) >= 8 && $Type.alignof >= 8)
$switch
$case $alignof(expr) >= 8 && $Type.alignof >= 8:
ulong *b = (ulong*)(&expr);
ulong *to = (ulong*)(&x);
for (usz i = 0; i < $size; i += 8)
{
to[i] = b[i];
}
$elif ($alignof(expr) >= 4 && $Type.alignof >= 4)
$case $alignof(expr) >= 4 && $Type.alignof >= 4:
uint* b = (uint*)(&expr);
uint* to = (uint*)(&x);
for (usz i = 0; i < $size; i += 4)
{
to[i] = b[i];
}
$elif ($alignof(expr) >= 2 && $Type.alignof >= 2)
$case $alignof(expr) >= 2 && $Type.alignof >= 2:
ushort* b = (ushort*)(&expr);
ushort* to = (ushort*)(&x);
for (usz i = 0; i < $size; i += 2)
{
to[i] = b[i];
}
$else
$default:
char* b = (char*)(&expr);
char* to = (char*)(&x);
for (usz i = 0; i < $size; i++)
{
to[i] = b[i];
}
$endif
$endswitch
return x;
}