delete_if, retain_if, rindex_of, compact, compact_count added to List.

This commit is contained in:
Christoffer Lerno
2023-04-21 12:15:35 +02:00
parent 809321e20c
commit 8059dc1539
24 changed files with 278 additions and 70 deletions

View File

@@ -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

View File

@@ -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());

View File

@@ -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"

View File

@@ -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()))

View File

@@ -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");

View File

@@ -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

View File

@@ -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;

View File

@@ -1,7 +1,7 @@
module std::net::os;
import libc;
$if (env::OS_TYPE == OsType.LINUX)
$if (env::OS_TYPE == LINUX)
struct AddrInfo
{

View File

@@ -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;

View File

@@ -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;

View File

@@ -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*;

View File

@@ -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*;

View File

@@ -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;

View File

@@ -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*;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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.

View File

@@ -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;

View File

@@ -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)

View File

@@ -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:

View File

@@ -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)

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.500"
#define COMPILER_VERSION "0.4.501"

View File

@@ -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);

View 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);
}