mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
$elif deprecated.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.114"
|
||||
#define COMPILER_VERSION "0.4.115"
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user