mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
delete_if, retain_if, rindex_of, compact, compact_count added to List.
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
module std::collections::list<Type>;
|
||||
import std::math;
|
||||
|
||||
typedef ElementPredicate = fn bool(Type *type);
|
||||
|
||||
struct List
|
||||
{
|
||||
usz size;
|
||||
@@ -196,6 +198,47 @@ fn void List.swap(List* list, usz i, usz j)
|
||||
@swap(list.entries[i], list.entries[j]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [&inout] list "The list to remove elements from"
|
||||
* @param filter "The function to determine if it should be removed or not"
|
||||
* @return "the number of deleted elements"
|
||||
**/
|
||||
fn usz List.delete_if(List* list, ElementPredicate filter)
|
||||
{
|
||||
usz size = list.size;
|
||||
for (usz i = size; i > 0; i--)
|
||||
{
|
||||
if (filter(&list.entries[i - 1])) continue;
|
||||
for (usz j = i; j < size; j++)
|
||||
{
|
||||
list.entries[j - 1] = list.entries[j];
|
||||
}
|
||||
list.size--;
|
||||
}
|
||||
return size - list.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [&inout] list "The list to remove elements from"
|
||||
* @param selection "The function to determine if it should be kept or not"
|
||||
* @return "the number of deleted elements"
|
||||
**/
|
||||
fn usz List.retain_if(List* list, ElementPredicate selection)
|
||||
{
|
||||
usz size = list.size;
|
||||
for (usz i = size; i > 0; i--)
|
||||
{
|
||||
if (!selection(&list.entries[i - 1])) continue;
|
||||
for (usz j = i; j < size; j++)
|
||||
{
|
||||
list.entries[j - 1] = list.entries[j];
|
||||
}
|
||||
list.size--;
|
||||
}
|
||||
return size - list.size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reserve at least min_capacity
|
||||
**/
|
||||
@@ -219,6 +262,19 @@ fn Type* List.get_ref(List* list, usz index) @operator(&[]) @inline
|
||||
return &list.entries[index];
|
||||
}
|
||||
|
||||
fn void List.ensure_capacity(List* list, usz added = 1) @inline @private
|
||||
{
|
||||
usz new_size = list.size + added;
|
||||
if (list.capacity > new_size) return;
|
||||
|
||||
assert(new_size < usz.max / 2U);
|
||||
usz new_capacity = list.capacity ? 2U * list.capacity : 16U;
|
||||
while (new_size >= new_capacity) new_capacity *= 2U;
|
||||
list.reserve(new_capacity);
|
||||
}
|
||||
|
||||
// Functions for equatable types
|
||||
|
||||
$if (types::is_equatable_type(Type))
|
||||
|
||||
fn usz! List.index_of(List* list, Type type)
|
||||
@@ -230,6 +286,15 @@ fn usz! List.index_of(List* list, Type type)
|
||||
return SearchResult.MISSING?;
|
||||
}
|
||||
|
||||
fn usz! List.rindex_of(List* list, Type type)
|
||||
{
|
||||
foreach_r (i, v : list)
|
||||
{
|
||||
if (v == type) return i;
|
||||
}
|
||||
return SearchResult.MISSING?;
|
||||
}
|
||||
|
||||
fn bool List.equals(List* list, List other_list)
|
||||
{
|
||||
if (list.size != other_list.size) return false;
|
||||
@@ -240,24 +305,70 @@ fn bool List.equals(List* list, List other_list)
|
||||
return true;
|
||||
}
|
||||
|
||||
fn bool List.contains(List* list, Type type)
|
||||
/**
|
||||
* Check for presence of a value in a list.
|
||||
*
|
||||
* @param [&in] list "the list to find elements in"
|
||||
* @param value "The value to search for"
|
||||
* @return "True if the value is found, false otherwise"
|
||||
**/
|
||||
fn bool List.contains(List* list, Type value)
|
||||
{
|
||||
foreach (i, v : list)
|
||||
{
|
||||
if (v == type) return true;
|
||||
if (v == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [&inout] list "The list to remove elements from"
|
||||
* @param value "The value to remove"
|
||||
* @return "the number of deleted elements."
|
||||
**/
|
||||
fn usz List.delete(List* list, Type value)
|
||||
{
|
||||
usz size = list.size;
|
||||
for (usz i = size; i > 0; i--)
|
||||
{
|
||||
if (list.entries[i - 1] != value) continue;
|
||||
for (usz j = i; j < size; j++)
|
||||
{
|
||||
list.entries[j - 1] = list.entries[j];
|
||||
}
|
||||
list.size--;
|
||||
}
|
||||
return size - list.size;
|
||||
}
|
||||
|
||||
$endif
|
||||
|
||||
fn void List.ensure_capacity(List* list, usz added = 1) @inline @private
|
||||
{
|
||||
usz new_size = list.size + added;
|
||||
if (list.capacity > new_size) return;
|
||||
$if (Type.kindof == POINTER)
|
||||
|
||||
assert(new_size < usz.max / 2U);
|
||||
usz new_capacity = list.capacity ? 2U * list.capacity : 16U;
|
||||
while (new_size >= new_capacity) new_capacity *= 2U;
|
||||
list.reserve(new_capacity);
|
||||
/**
|
||||
* @param [&in] list
|
||||
* @return "The number non-null values in the list"
|
||||
**/
|
||||
fn usz List.compact_count(List* list)
|
||||
{
|
||||
usz vals = 0;
|
||||
foreach (v : list) if (v) vals++;
|
||||
return vals;
|
||||
}
|
||||
|
||||
fn usz List.compact(List* list)
|
||||
{
|
||||
usz size = list.size;
|
||||
for (usz i = size; i > 0; i--)
|
||||
{
|
||||
if (list.entries[i - 1]) continue;
|
||||
for (usz j = i; j < size; j++)
|
||||
{
|
||||
list.entries[j - 1] = list.entries[j];
|
||||
}
|
||||
list.size--;
|
||||
}
|
||||
return size - list.size;
|
||||
}
|
||||
|
||||
$endif
|
||||
@@ -3,7 +3,7 @@ module std::core::array;
|
||||
/**
|
||||
* @param [in] array
|
||||
* @param [in] element
|
||||
* @return "the index of the element"
|
||||
* @return "the first index of the element"
|
||||
* @return! SearchResult.MISSING
|
||||
**/
|
||||
macro index_of(array, element)
|
||||
@@ -15,11 +15,27 @@ macro index_of(array, element)
|
||||
return SearchResult.MISSING?;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [in] array
|
||||
* @param [in] element
|
||||
* @return "the last index of the element"
|
||||
* @return! SearchResult.MISSING
|
||||
**/
|
||||
macro rindex_of(array, element)
|
||||
{
|
||||
foreach_r (i, &e : array)
|
||||
{
|
||||
if (*e == element) return i;
|
||||
}
|
||||
return SearchResult.MISSING?;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate two arrays or subarrays, returning a subarray containing the concatenation of them.
|
||||
*
|
||||
* @param [in] arr1
|
||||
* @param [in] arr2
|
||||
* @param [&inout] using "The allocator to use, default is the heap allocator"
|
||||
* @require @typekind(arr1) == SUBARRAY || @typekind(arr1) == ARRAY
|
||||
* @require @typekind(arr2) == SUBARRAY || @typekind(arr2) == ARRAY
|
||||
* @require @typeis(arr1[0], $typeof(arr2[0])) "Arrays must have the same type"
|
||||
@@ -40,4 +56,15 @@ macro concat(arr1, arr2, Allocator* using = mem::heap())
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate two arrays or subarrays, returning a subarray containing the concatenation of them,
|
||||
* allocated using the temp allocator.
|
||||
*
|
||||
* @param [in] arr1
|
||||
* @param [in] arr2
|
||||
* @require @typekind(arr1) == SUBARRAY || @typekind(arr1) == ARRAY
|
||||
* @require @typekind(arr2) == SUBARRAY || @typekind(arr2) == ARRAY
|
||||
* @require @typeis(arr1[0], $typeof(arr2[0])) "Arrays must have the same type"
|
||||
* @ensure result.len == arr1.len + arr2.len
|
||||
**/
|
||||
macro tconcat(arr1, arr2) => concat(arr1, arr2, mem::temp());
|
||||
|
||||
@@ -122,7 +122,7 @@ fn void panicf(String fmt, String file, String function, uint line, args...)
|
||||
/**
|
||||
* Marks the path as unreachable. This will panic in safe mode, and in fast will simply be assumed
|
||||
* never happens.
|
||||
* @param [in] string "The panic message"
|
||||
* @param [in] string "The panic message or format string"
|
||||
**/
|
||||
macro void unreachable(String string = "Unreachable statement reached.", ...) @builtin @noreturn
|
||||
{
|
||||
@@ -130,6 +130,16 @@ macro void unreachable(String string = "Unreachable statement reached.", ...) @b
|
||||
$$unreachable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the path as unsupported, this is similar to unreachable.
|
||||
* @param [in] string "The error message"
|
||||
**/
|
||||
macro void unsupported(String string = "Unsupported function invoked") @builtin @noreturn
|
||||
{
|
||||
panicf(string, $$FILE, $$FUNC, $$LINE, $vasplat());
|
||||
$$unreachable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expr "the expression to cast"
|
||||
* @param $Type "the type to cast to"
|
||||
|
||||
@@ -130,7 +130,7 @@ const MemoryEnvironment MEMORY_ENV = (MemoryEnvironment)$$MEMORY_ENVIRONMENT;
|
||||
|
||||
macro bool os_is_win32()
|
||||
{
|
||||
return OS_TYPE == OsType.WIN32;
|
||||
return OS_TYPE == WIN32;
|
||||
}
|
||||
|
||||
macro bool os_is_darwin()
|
||||
@@ -177,7 +177,7 @@ macro bool os_is_posix()
|
||||
**/
|
||||
fn String! get_var(String name)
|
||||
{
|
||||
$if (COMPILER_LIBC_AVAILABLE && OS_TYPE != OsType.WIN32)
|
||||
$if (COMPILER_LIBC_AVAILABLE && !os_is_win32())
|
||||
@pool()
|
||||
{
|
||||
ZString val = libc::getenv(name.zstr_tcopy());
|
||||
@@ -196,7 +196,7 @@ $endif
|
||||
**/
|
||||
fn void set_var(String name, String value, bool overwrite = true)
|
||||
{
|
||||
$if (COMPILER_LIBC_AVAILABLE && OS_TYPE != OsType.WIN32)
|
||||
$if (COMPILER_LIBC_AVAILABLE && !os_is_win32())
|
||||
@pool()
|
||||
{
|
||||
if (libc::setenv(name.zstr_tcopy(), value.zstr_copy(), (int)overwrite))
|
||||
@@ -213,7 +213,7 @@ $endif
|
||||
**/
|
||||
fn void clear_var(String name)
|
||||
{
|
||||
$if (COMPILER_LIBC_AVAILABLE && OS_TYPE != OsType.WIN32)
|
||||
$if (COMPILER_LIBC_AVAILABLE && !os_is_win32())
|
||||
@pool()
|
||||
{
|
||||
if (libc::unsetenv(name.zstr_tcopy()))
|
||||
|
||||
@@ -55,7 +55,7 @@ macro int @main_to_void_main_args(#m, int argc, char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
$if (env::OS_TYPE == OsType.WIN32)
|
||||
$if (env::os_is_win32())
|
||||
|
||||
extern fn Char16** _win_command_line_to_argv_w(ushort* cmd_line, int* argc_ptr) @extern("CommandLineToArgvW");
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ extern fn int rand();
|
||||
extern fn void srand(uint seed);
|
||||
|
||||
extern fn void longjmp(JmpBuf* buffer, CInt value);
|
||||
$if (env::OS_TYPE == OsType.WIN32)
|
||||
$if (env::os_is_win32())
|
||||
// TODO win32 aarch64
|
||||
extern fn CInt _setjmp(void* frameptr, JmpBuf* buffer);
|
||||
macro CInt setjmp(JmpBuf* buffer) => _setjmp($$frameaddress(), buffer);
|
||||
@@ -152,7 +152,7 @@ typedef Fpos = long;
|
||||
typedef CFile = void*;
|
||||
|
||||
$switch
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.LINUX:
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == LINUX:
|
||||
extern CFile __stdin @extern("stdin");
|
||||
extern CFile __stdout @extern("stdout");
|
||||
extern CFile __stderr @extern("stderr");
|
||||
@@ -162,7 +162,7 @@ $case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.LINUX:
|
||||
macro CFile stdin() { return __stdin; }
|
||||
macro CFile stdout() { return __stdout; }
|
||||
macro CFile stderr() { return __stderr; }
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.MACOS:
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_darwin():
|
||||
extern CFile __stdinp;
|
||||
extern CFile __stdoutp;
|
||||
extern CFile __stderrp;
|
||||
@@ -171,7 +171,7 @@ $case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.MACOS:
|
||||
macro CFile stdin() { return __stdinp; }
|
||||
macro CFile stdout() { return __stdoutp; }
|
||||
macro CFile stderr() { return __stderrp; }
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OsType.WIN32:
|
||||
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
|
||||
extern fn CFile __acrt_iob_func(CInt c);
|
||||
extern fn usz _msize(void* ptr);
|
||||
macro usz malloc_size(void* ptr) { return _msize(ptr); }
|
||||
@@ -185,9 +185,9 @@ $default:
|
||||
$endswitch
|
||||
|
||||
const HAS_MALLOC_SIZE =
|
||||
env::OS_TYPE == OsType.LINUX
|
||||
|| env::OS_TYPE == OsType.WIN32
|
||||
|| env::OS_TYPE == OsType.MACOS;
|
||||
env::OS_TYPE == LINUX
|
||||
|| env::os_is_win32()
|
||||
|| env::os_is_darwin();
|
||||
|
||||
// The following needs to be set per arch+os
|
||||
// For now I have simply pulled the defaults from MacOS
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module std::net::os;
|
||||
import libc;
|
||||
|
||||
$if (env::OS_TYPE == OsType.MACOS)
|
||||
$if (env::os_is_darwin())
|
||||
|
||||
const AI_NUMERICSERV = 0x1000;
|
||||
const AI_ALL = 0x100;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module std::net::os;
|
||||
import libc;
|
||||
|
||||
$if (env::OS_TYPE == OsType.LINUX)
|
||||
$if (env::OS_TYPE == LINUX)
|
||||
|
||||
struct AddrInfo
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module std::net::os;
|
||||
import libc;
|
||||
|
||||
$if (env::OS_TYPE != OsType.WIN32 && $defined(AddrInfo))
|
||||
$if (env::os_is_win32() && $defined(AddrInfo))
|
||||
|
||||
const int F_GETFL = 3;
|
||||
const int F_SETFL = 4;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::net::os;
|
||||
|
||||
$if (env::OS_TYPE == OsType.WIN32)
|
||||
$if (env::os_is_win32())
|
||||
|
||||
const int PLATFORM_AF_INET = 1;
|
||||
const int PLATFORM_AF_IPX = 6;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::os::macos::cf;
|
||||
|
||||
$if (env::OS_TYPE == OsType.MACOS)
|
||||
$if (env::os_is_darwin())
|
||||
|
||||
typedef CFAllocatorRef = distinct void*;
|
||||
typedef CFAllocatorContextRef = distinct void*;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::os::macos::cf;
|
||||
|
||||
$if (env::OS_TYPE == OsType.MACOS)
|
||||
$if (env::os_is_darwin())
|
||||
|
||||
typedef CFArrayRef = distinct void*;
|
||||
typedef CFArrayCallBacksRef = distinct void*;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::os::macos::cf;
|
||||
|
||||
$if (env::OS_TYPE == OsType.MACOS)
|
||||
$if (env::os_is_darwin())
|
||||
|
||||
typedef CFTypeRef = distinct void*;
|
||||
typedef CFIndex = isz;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module std::os::macos::objc;
|
||||
|
||||
$if (env::OS_TYPE == OsType.MACOS)
|
||||
$if (env::os_is_darwin())
|
||||
|
||||
typedef Class = distinct void*;
|
||||
typedef Method = distinct void*;
|
||||
|
||||
@@ -14,7 +14,7 @@ typedef NativeOnceFlag = PthreadOnce;
|
||||
|
||||
typedef Pthread = distinct void*;
|
||||
|
||||
$if (env::OS_TYPE == OsType.LINUX)
|
||||
$if (env::OS_TYPE == LINUX)
|
||||
typedef PthreadMutex = distinct ulong[5];
|
||||
typedef PthreadAttribute = distinct ulong[7];
|
||||
typedef PthreadMutexAttribute = distinct uint;
|
||||
|
||||
@@ -8,7 +8,7 @@ enum ThreadModel
|
||||
}
|
||||
|
||||
const ThreadModel THREAD_MODEL = env::COMPILER_LIBC_AVAILABLE
|
||||
? (env::OS_TYPE == OsType.WIN32 ? ThreadModel.WIN32 : ThreadModel.POSIX)
|
||||
? (env::os_is_win32() ? ThreadModel.WIN32 : ThreadModel.POSIX)
|
||||
: ThreadModel.NONE;
|
||||
|
||||
typedef MutexType = distinct int;
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
|
||||
### Stdlib changes
|
||||
- Stdlib updates to string.
|
||||
- Additions to `List`
|
||||
- Many additions to `List`: `delete`, `array_view`, `add_all`, `compact` etc
|
||||
- Added dstringwriter.
|
||||
- Improved printf formatting.
|
||||
- is_finite/is_nam/is_inf added.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module hello_world;
|
||||
import std;
|
||||
import bar;
|
||||
$if (env::OS_TYPE == OsType.WIN32)
|
||||
$if (env::os_is_win32())
|
||||
fn int test_doubler(int x)
|
||||
{
|
||||
return x * x;
|
||||
|
||||
@@ -133,6 +133,11 @@ static inline bool sema_check_param_uniqueness_and_type(Decl **decls, Decl *curr
|
||||
|
||||
static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent, Decl *decl)
|
||||
{
|
||||
if (decl->resolve_status == RESOLVE_DONE) return decl_ok(decl);
|
||||
if (decl->resolve_status == RESOLVE_RUNNING)
|
||||
{
|
||||
RETURN_SEMA_ERROR(decl, "Circular dependency resolving member.");
|
||||
}
|
||||
assert(!decl->unit || decl->unit->module->is_generic);
|
||||
decl->unit = parent->unit;
|
||||
if (decl->name)
|
||||
|
||||
@@ -157,7 +157,7 @@ static inline Expr *sema_ct_checks_exprlist_compiles(SemaContext *context, Expr
|
||||
static inline bool sema_cast_ct_ident_rvalue(SemaContext *context, Expr *expr);
|
||||
static bool sema_expr_rewrite_to_typeid_property(SemaContext *context, Expr *expr, Expr *typeid, const char *kw);
|
||||
static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr, Type *type, TypeProperty property,
|
||||
AlignSize alignment, AlignSize offset);
|
||||
Type *parent_type);
|
||||
static bool sema_expr_rewrite_typeid_call(Expr *expr, Expr *typeid, TypeIdInfoKind kind, Type *result_type);
|
||||
static inline void sema_expr_rewrite_typeid_kind(Expr *expr, Expr *parent);
|
||||
static inline void sema_expr_replace_with_enum_array(Expr *enum_array_expr, Decl *enum_decl);
|
||||
@@ -177,8 +177,8 @@ static inline int64_t expr_get_index_max(Expr *expr);
|
||||
static inline bool expr_both_any_integer_or_integer_vector(Expr *left, Expr *right);
|
||||
static inline bool expr_both_any_integer_or_integer_bool_vector(Expr *left, Expr *right);
|
||||
static inline bool expr_both_const(Expr *left, Expr *right);
|
||||
static inline bool sema_identifier_find_possible_inferred(Type *to, Expr *expr);
|
||||
static inline bool sema_expr_analyse_enum_constant(Expr *expr, const char *name, Decl *decl);
|
||||
static inline bool sema_identifier_find_possible_inferred(SemaContext *context, Type *to, Expr *expr);
|
||||
static inline bool sema_expr_analyse_enum_constant(SemaContext *context, Expr *expr, const char *name, Decl *decl);
|
||||
|
||||
static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr);
|
||||
static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr);
|
||||
@@ -712,9 +712,11 @@ static inline bool sema_expr_analyse_ternary(SemaContext *context, Expr *expr)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_enum_constant(Expr *expr, const char *name, Decl *decl)
|
||||
static inline bool sema_expr_analyse_enum_constant(SemaContext *context, Expr *expr, const char *name, Decl *decl)
|
||||
{
|
||||
Decl *enum_constant = decl_find_enum_constant(decl, name);
|
||||
|
||||
if (!sema_resolve_type_decl(context, decl->type)) return false;
|
||||
if (!enum_constant) return false;
|
||||
|
||||
assert(enum_constant->resolve_status == RESOLVE_DONE);
|
||||
@@ -726,7 +728,7 @@ static inline bool sema_expr_analyse_enum_constant(Expr *expr, const char *name,
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_identifier_find_possible_inferred(Type *to, Expr *expr)
|
||||
static inline bool sema_identifier_find_possible_inferred(SemaContext *context, Type *to, Expr *expr)
|
||||
{
|
||||
if (to->canonical->type_kind != TYPE_ENUM && to->canonical->type_kind != TYPE_FAULTTYPE) return false;
|
||||
Decl *parent_decl = to->canonical->decl;
|
||||
@@ -734,7 +736,7 @@ static inline bool sema_identifier_find_possible_inferred(Type *to, Expr *expr)
|
||||
{
|
||||
case DECL_ENUM:
|
||||
case DECL_FAULT:
|
||||
return sema_expr_analyse_enum_constant(expr, expr->identifier_expr.ident, parent_decl);
|
||||
return sema_expr_analyse_enum_constant(context, expr, expr->identifier_expr.ident, parent_decl);
|
||||
case DECL_UNION:
|
||||
case DECL_STRUCT:
|
||||
case DECL_BITSTRUCT:
|
||||
@@ -770,7 +772,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
|
||||
// Just start with inference
|
||||
if (!expr->identifier_expr.path && to)
|
||||
{
|
||||
if (sema_identifier_find_possible_inferred(to, expr)) return true;
|
||||
if (sema_identifier_find_possible_inferred(context, to, expr)) return true;
|
||||
}
|
||||
|
||||
Decl *decl = sema_find_path_symbol(context, expr->identifier_expr.ident, expr->identifier_expr.path);
|
||||
@@ -2760,6 +2762,7 @@ static inline void sema_expr_replace_with_enum_array(Expr *enum_array_expr, Decl
|
||||
|
||||
static inline void sema_expr_replace_with_enum_name_array(Expr *enum_array_expr, Decl *enum_decl)
|
||||
{
|
||||
|
||||
Decl **values = enum_decl->enums.values;
|
||||
SourceSpan span = enum_array_expr->span;
|
||||
Expr *initializer = expr_new(EXPR_INITIALIZER_LIST, span);
|
||||
@@ -2789,10 +2792,7 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
|
||||
|
||||
if (!is_const)
|
||||
{
|
||||
AlignSize align;
|
||||
if (!sema_set_abi_alignment(context, parent_type, &align)) return false;
|
||||
if (sema_expr_rewrite_to_type_property(context, expr, canonical, type_property_by_name(name),
|
||||
align, 0)) return true;
|
||||
if (sema_expr_rewrite_to_type_property(context, expr, canonical, type_property_by_name(name), parent_type)) return true;
|
||||
}
|
||||
|
||||
if (!type_may_have_sub_elements(canonical))
|
||||
@@ -2810,7 +2810,7 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
|
||||
case DECL_ENUM:
|
||||
if (is_const)
|
||||
{
|
||||
if (!sema_expr_analyse_enum_constant(expr, name, decl))
|
||||
if (!sema_expr_analyse_enum_constant(context, expr, name, decl))
|
||||
{
|
||||
SEMA_ERROR(expr, "'%s' has no enumeration value '%s'.", decl->name, name);
|
||||
return false;
|
||||
@@ -2822,7 +2822,7 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
|
||||
unit_register_external_symbol(context->compilation_unit, decl);
|
||||
if (is_const)
|
||||
{
|
||||
if (!sema_expr_analyse_enum_constant(expr, name, decl))
|
||||
if (!sema_expr_analyse_enum_constant(context, expr, name, decl))
|
||||
{
|
||||
SEMA_ERROR(expr, "'%s' has no error value '%s'.", decl->name, name);
|
||||
return false;
|
||||
@@ -2924,9 +2924,7 @@ static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *e
|
||||
return true;
|
||||
case TYPE_PROPERTY_KINDOF:
|
||||
case TYPE_PROPERTY_SIZEOF:
|
||||
if (sema_expr_rewrite_to_type_property(context, expr, decl->type, type_property,
|
||||
parent->const_expr.member.align,
|
||||
parent->const_expr.member.offset)) return true;
|
||||
if (sema_expr_rewrite_to_type_property(context, expr, decl->type, type_property, decl->type)) return true;
|
||||
return true;
|
||||
case TYPE_PROPERTY_ELEMENTS:
|
||||
case TYPE_PROPERTY_EXTNAMEOF:
|
||||
@@ -3008,6 +3006,7 @@ static inline bool sema_create_const_kind(Expr *expr, Type *type)
|
||||
static inline bool sema_create_const_len(SemaContext *context, Expr *expr, Type *type)
|
||||
{
|
||||
assert(type == type_flatten(type) && "Should be flattened already.");
|
||||
|
||||
size_t len;
|
||||
switch (type->type_kind)
|
||||
{
|
||||
@@ -3031,6 +3030,7 @@ static inline bool sema_create_const_len(SemaContext *context, Expr *expr, Type
|
||||
|
||||
static inline bool sema_create_const_inner(SemaContext *context, Expr *expr, Type *type)
|
||||
{
|
||||
if (!sema_resolve_type_decl(context, type)) return false;
|
||||
Type *inner = NULL;
|
||||
switch (type->type_kind)
|
||||
{
|
||||
@@ -3283,9 +3283,7 @@ static bool sema_expr_rewrite_to_typeid_property(SemaContext *context, Expr *exp
|
||||
if (typeid->expr_kind == EXPR_CONST)
|
||||
{
|
||||
Type *type = typeid->const_expr.typeid;
|
||||
AlignSize align;
|
||||
if (!sema_set_abi_alignment(context, type, &align)) return false;
|
||||
return sema_expr_rewrite_to_type_property(context, expr, type, property, align, 0);
|
||||
return sema_expr_rewrite_to_type_property(context, expr, type, property, type);
|
||||
}
|
||||
switch (property)
|
||||
{
|
||||
@@ -3379,7 +3377,7 @@ EVAL:
|
||||
}
|
||||
|
||||
static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr, Type *type, TypeProperty property,
|
||||
AlignSize alignment, AlignSize offset)
|
||||
Type *parent_type)
|
||||
{
|
||||
assert(type == type->canonical);
|
||||
if (property == TYPE_PROPERTY_NONE) return false;
|
||||
@@ -3407,16 +3405,19 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
return sema_create_const_max(context, expr, type, flat);
|
||||
case TYPE_PROPERTY_NAMES:
|
||||
if (!type_kind_is_enumlike(flat->type_kind)) return false;
|
||||
if (!sema_resolve_type_decl(context, type)) return false;
|
||||
sema_expr_replace_with_enum_name_array(expr, flat->decl);
|
||||
return sema_analyse_expr(context, expr);
|
||||
case TYPE_PROPERTY_ASSOCIATED:
|
||||
return sema_create_const_associated(context, expr, flat);
|
||||
case TYPE_PROPERTY_ELEMENTS:
|
||||
if (!type_kind_is_enumlike(flat->type_kind)) return false;
|
||||
if (!sema_resolve_type_decl(context, type)) return false;
|
||||
expr_rewrite_const_int(expr, type_isz, vec_size(flat->decl->enums.values));
|
||||
return true;
|
||||
case TYPE_PROPERTY_VALUES:
|
||||
if (!type_kind_is_enumlike(flat->type_kind)) return false;
|
||||
if (!sema_resolve_type_decl(context, type)) return false;
|
||||
sema_expr_replace_with_enum_array(expr, flat->decl);
|
||||
return sema_analyse_expr(context, expr);
|
||||
case TYPE_PROPERTY_NAN:
|
||||
@@ -3428,8 +3429,12 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
case TYPE_PROPERTY_MEMBERSOF:
|
||||
sema_create_const_membersof(context, expr, flat, alignment, offset);
|
||||
{
|
||||
AlignSize align;
|
||||
if (!sema_set_abi_alignment(context, parent_type, &align)) return false;
|
||||
sema_create_const_membersof(context, expr, flat, align, 0);
|
||||
return true;
|
||||
}
|
||||
case TYPE_PROPERTY_PARAMS:
|
||||
if (flat->type_kind == TYPE_POINTER && flat->pointer->type_kind == TYPE_FUNC) flat = flat->pointer;
|
||||
return sema_create_const_params(context, expr, flat);
|
||||
@@ -3439,12 +3444,15 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
expr_rewrite_const_typeid(expr, type_infoptr(flat->function.signature->rtype)->type);
|
||||
return true;
|
||||
case TYPE_PROPERTY_SIZEOF:
|
||||
if (!sema_resolve_type_decl(context, type)) return false;
|
||||
expr_rewrite_const_int(expr, type_usz, type_size(type));
|
||||
return true;
|
||||
case TYPE_PROPERTY_NAMEOF:
|
||||
if (!sema_resolve_type_decl(context, type)) return false;
|
||||
sema_expr_rewrite_to_type_nameof(expr, type, TOKEN_CT_NAMEOF);
|
||||
return true;
|
||||
case TYPE_PROPERTY_QNAMEOF:
|
||||
if (!sema_resolve_type_decl(context, type)) return false;
|
||||
sema_expr_rewrite_to_type_nameof(expr, type, TOKEN_CT_QNAMEOF);
|
||||
return true;
|
||||
case TYPE_PROPERTY_ALIGNOF:
|
||||
@@ -3456,6 +3464,7 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
}
|
||||
case TYPE_PROPERTY_EXTNAMEOF:
|
||||
if (type_is_builtin(type->type_kind)) return false;
|
||||
if (!sema_resolve_type_decl(context, type)) return false;
|
||||
sema_expr_rewrite_to_type_nameof(expr, type, TOKEN_CT_EXTNAMEOF);
|
||||
return true;
|
||||
case TYPE_PROPERTY_NONE:
|
||||
|
||||
@@ -622,6 +622,7 @@ Decl *sema_resolve_method(CompilationUnit *unit, Decl *type, const char *method_
|
||||
return sema_resolve_type_method(unit, type->type, method_name, ambiguous_ref, private_ref);
|
||||
}
|
||||
|
||||
|
||||
bool sema_resolve_type_decl(SemaContext *context, Type *type)
|
||||
{
|
||||
switch (type->type_kind)
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.500"
|
||||
#define COMPILER_VERSION "0.4.501"
|
||||
@@ -1,9 +1,9 @@
|
||||
module linkedlist_test;
|
||||
module linkedlist_test @test;
|
||||
import std::collections::linkedlist;
|
||||
|
||||
typedef IntList = LinkedList<int>;
|
||||
|
||||
fn void! test_push() @test
|
||||
fn void! test_push()
|
||||
{
|
||||
IntList list;
|
||||
list.push(23);
|
||||
@@ -16,7 +16,7 @@ fn void! test_push() @test
|
||||
assert(list.first()! == 55);
|
||||
}
|
||||
|
||||
fn void! test_push_last() @test
|
||||
fn void! test_push_last()
|
||||
{
|
||||
IntList list;
|
||||
list.push_last(23);
|
||||
@@ -29,7 +29,7 @@ fn void! test_push_last() @test
|
||||
assert(list.first()! == 23);
|
||||
}
|
||||
|
||||
fn void! test_get() @test
|
||||
fn void! test_get()
|
||||
{
|
||||
IntList list;
|
||||
list.push(23);
|
||||
@@ -40,7 +40,7 @@ fn void! test_get() @test
|
||||
assert(list.get(2) == 23);
|
||||
}
|
||||
|
||||
fn void! test_insert() @test
|
||||
fn void! test_insert()
|
||||
{
|
||||
IntList list;
|
||||
list.push(23);
|
||||
@@ -59,7 +59,7 @@ fn void! test_insert() @test
|
||||
assert(list.get(6) == 1111);
|
||||
}
|
||||
|
||||
fn void! test_set() @test
|
||||
fn void! test_set()
|
||||
{
|
||||
IntList list;
|
||||
list.push(23);
|
||||
@@ -71,7 +71,7 @@ fn void! test_set() @test
|
||||
assert(list.get(2) == 24);
|
||||
}
|
||||
|
||||
fn void! test_remove() @test
|
||||
fn void! test_remove()
|
||||
{
|
||||
IntList list;
|
||||
for (int i = 0; i < 10; i++) list.push(i);
|
||||
@@ -84,7 +84,7 @@ fn void! test_remove() @test
|
||||
assert(list.get(5) == 1);
|
||||
assert(list.get(4) == 3);
|
||||
}
|
||||
fn void! test_remove_value() @test
|
||||
fn void! test_remove_value()
|
||||
{
|
||||
IntList list;
|
||||
list.push(23);
|
||||
@@ -112,7 +112,7 @@ fn void! test_remove_value() @test
|
||||
assert(!list.len());
|
||||
}
|
||||
|
||||
fn void! test_remove_last_value() @test
|
||||
fn void! test_remove_last_value()
|
||||
{
|
||||
IntList list;
|
||||
list.push(23);
|
||||
@@ -140,7 +140,7 @@ fn void! test_remove_last_value() @test
|
||||
assert(!list.len());
|
||||
}
|
||||
|
||||
fn void! test_pop() @test
|
||||
fn void! test_pop()
|
||||
{
|
||||
IntList list;
|
||||
list.push(23);
|
||||
@@ -164,7 +164,7 @@ fn void! test_pop() @test
|
||||
assert(list.len() == 1);
|
||||
}
|
||||
|
||||
fn void! test_remove_first() @test
|
||||
fn void! test_remove_first()
|
||||
{
|
||||
IntList list;
|
||||
list.push(23);
|
||||
@@ -188,7 +188,7 @@ fn void! test_remove_first() @test
|
||||
assert(list.len() == 1);
|
||||
}
|
||||
|
||||
fn void! test_remove_last() @test
|
||||
fn void! test_remove_last()
|
||||
{
|
||||
IntList list;
|
||||
list.push(23);
|
||||
|
||||
45
test/unit/stdlib/collections/list.c3
Normal file
45
test/unit/stdlib/collections/list.c3
Normal file
@@ -0,0 +1,45 @@
|
||||
module listtests @test;
|
||||
import std::collections::list;
|
||||
|
||||
typedef IntList = List<int>;
|
||||
typedef PtrList = List<void*>;
|
||||
|
||||
fn void! test_delete_contains_index()
|
||||
{
|
||||
IntList test;
|
||||
test.add_array({ 1, 2 });
|
||||
assert(test.contains(1));
|
||||
assert(test.contains(2));
|
||||
assert(!test.contains(0));
|
||||
assert(!test.contains(3));
|
||||
assert(test.array_view() == int[]{ 1, 2 });
|
||||
test.push(3);
|
||||
assert(test.array_view() == int[]{ 1, 2, 3 });
|
||||
assert(test.contains(3));
|
||||
test.delete(1);
|
||||
assert(test.array_view() == int[]{ 2, 3 });
|
||||
assert(!test.contains(1));
|
||||
assert(test.contains(2));
|
||||
assert(test.len() == 2);
|
||||
test.push(0);
|
||||
test.insert_at(0, 0);
|
||||
assert(test.array_view() == int[]{ 0, 2, 3, 0 });
|
||||
assert(test.index_of(0)! == 0);
|
||||
assert(test.rindex_of(0)! == 3);
|
||||
test.delete(0);
|
||||
assert(test.len() == 2);
|
||||
assert(test.array_view() == int[]{ 2, 3 });
|
||||
}
|
||||
|
||||
fn void! test_compact()
|
||||
{
|
||||
PtrList test;
|
||||
test.add_array({ null, &test });
|
||||
assert(test.compact_count() == 1);
|
||||
test.push(null);
|
||||
assert(test.compact_count() == 1);
|
||||
assert(test.len() == 3);
|
||||
assert(test.compact() == 2);
|
||||
assert(test.len() == 1);
|
||||
assert(test.compact() == 0);
|
||||
}
|
||||
Reference in New Issue
Block a user