diff --git a/lib/std/bits.c3 b/lib/std/bits.c3 index 862e8435f..64ada6e1a 100644 --- a/lib/std/bits.c3 +++ b/lib/std/bits.c3 @@ -4,169 +4,169 @@ module std::bits; /** * @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector` **/ -macro reverse(i) = $$bitreverse(i); +macro reverse(i) => $$bitreverse(i); /** * @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector` **/ -macro bswap(i) @builtin = $$bswap(i); +macro bswap(i) @builtin => $$bswap(i); -macro uint[<*>].popcount(uint[<*>] i) = $$popcount(i); -macro uint[<*>].ctz(uint[<*>] i) = $$ctz(i); -macro uint[<*>].clz(uint[<*>] i) = $$clz(i); +macro uint[<*>].popcount(uint[<*>] i) => $$popcount(i); +macro uint[<*>].ctz(uint[<*>] i) => $$ctz(i); +macro uint[<*>].clz(uint[<*>] i) => $$clz(i); macro uint[<*>] uint[<*>].fshl(uint[<*>] hi, uint[<*>] lo, uint[<*>] shift) => $$fshl(hi, lo, shift); macro uint[<*>] uint[<*>].fshr(uint[<*>] hi, uint[<*>] lo, uint[<*>] shift) => $$fshr(hi, lo, shift); macro uint[<*>] uint[<*>].rotl(uint[<*>] i, uint[<*>] shift) => $$fshl(i, i, shift); macro uint[<*>] uint[<*>].rotr(uint[<*>] i, uint[<*>] shift) => $$fshr(i, i, shift); -macro int[<*>].popcount(int[<*>] i) = $$popcount(i); -macro int[<*>].ctz(int[<*>] i) = $$ctz(i); -macro int[<*>].clz(int[<*>] i) = $$clz(i); +macro int[<*>].popcount(int[<*>] i) => $$popcount(i); +macro int[<*>].ctz(int[<*>] i) => $$ctz(i); +macro int[<*>].clz(int[<*>] i) => $$clz(i); macro int[<*>] int[<*>].fshl(int[<*>] hi, int[<*>] lo, int[<*>] shift) => $$fshl(hi, lo, shift); macro int[<*>] int[<*>].fshr(int[<*>] hi, int[<*>] lo, int[<*>] shift) => $$fshr(hi, lo, shift); macro int[<*>] int[<*>].rotl(int[<*>] i, int[<*>] shift) => $$fshl(i, i, shift); macro int[<*>] int[<*>].rotr(int[<*>] i, int[<*>] shift) => $$fshr(i, i, shift); -macro ushort[<*>].popcount(ushort[<*>] i) = $$popcount(i); -macro ushort[<*>].ctz(ushort[<*>] i) = $$ctz(i); -macro ushort[<*>].clz(ushort[<*>] i) = $$clz(i); +macro ushort[<*>].popcount(ushort[<*>] i) => $$popcount(i); +macro ushort[<*>].ctz(ushort[<*>] i) => $$ctz(i); +macro ushort[<*>].clz(ushort[<*>] i) => $$clz(i); macro ushort[<*>] ushort[<*>].fshl(ushort[<*>] hi, ushort[<*>] lo, ushort[<*>] shift) => $$fshl(hi, lo, shift); macro ushort[<*>] ushort[<*>].fshr(ushort[<*>] hi, ushort[<*>] lo, ushort[<*>] shift) => $$fshr(hi, lo, shift); macro ushort[<*>] ushort[<*>].rotl(ushort[<*>] i, ushort[<*>] shift) => $$fshl(i, i, shift); macro ushort[<*>] ushort[<*>].rotr(ushort[<*>] i, ushort[<*>] shift) => $$fshr(i, i, shift); -macro short[<*>].popcount(short[<*>] i) = $$popcount(i); -macro short[<*>].ctz(short[<*>] i) = $$ctz(i); -macro short[<*>].clz(short[<*>] i) = $$clz(i); +macro short[<*>].popcount(short[<*>] i) => $$popcount(i); +macro short[<*>].ctz(short[<*>] i) => $$ctz(i); +macro short[<*>].clz(short[<*>] i) => $$clz(i); macro short[<*>] short[<*>].fshl(short[<*>] hi, short[<*>] lo, short[<*>] shift) => $$fshl(hi, lo, shift); macro short[<*>] short[<*>].fshr(short[<*>] hi, short[<*>] lo, short[<*>] shift) => $$fshr(hi, lo, shift); macro short[<*>] short[<*>].rotl(short[<*>] i, short[<*>] shift) => $$fshl(i, i, shift); macro short[<*>] short[<*>].rotr(short[<*>] i, short[<*>] shift) => $$fshr(i, i, shift); -macro char[<*>].popcount(char[<*>] i) = $$popcount(i); -macro char[<*>].ctz(char[<*>] i) = $$ctz(i); -macro char[<*>].clz(char[<*>] i) = $$clz(i); +macro char[<*>].popcount(char[<*>] i) => $$popcount(i); +macro char[<*>].ctz(char[<*>] i) => $$ctz(i); +macro char[<*>].clz(char[<*>] i) => $$clz(i); macro char[<*>] char[<*>].fshl(char[<*>] hi, char[<*>] lo, char[<*>] shift) => $$fshl(hi, lo, shift); macro char[<*>] char[<*>].fshr(char[<*>] hi, char[<*>] lo, char[<*>] shift) => $$fshr(hi, lo, shift); macro char[<*>] char[<*>].rotl(char[<*>] i, char[<*>] shift) => $$fshl(i, i, shift); macro char[<*>] char[<*>].rotr(char[<*>] i, char[<*>] shift) => $$fshr(i, i, shift); -macro ichar[<*>].popcount(ichar[<*>] i) = $$popcount(i); -macro ichar[<*>].ctz(ichar[<*>] i) = $$ctz(i); -macro ichar[<*>].clz(ichar[<*>] i) = $$clz(i); +macro ichar[<*>].popcount(ichar[<*>] i) => $$popcount(i); +macro ichar[<*>].ctz(ichar[<*>] i) => $$ctz(i); +macro ichar[<*>].clz(ichar[<*>] i) => $$clz(i); macro ichar[<*>] ichar[<*>].fshl(ichar[<*>] hi, ichar[<*>] lo, ichar[<*>] shift) => $$fshl(hi, lo, shift); macro ichar[<*>] ichar[<*>].fshr(ichar[<*>] hi, ichar[<*>] lo, ichar[<*>] shift) => $$fshr(hi, lo, shift); macro ichar[<*>] ichar[<*>].rotl(ichar[<*>] i, ichar[<*>] shift) => $$fshl(i, i, shift); macro ichar[<*>] ichar[<*>].rotr(ichar[<*>] i, ichar[<*>] shift) => $$fshr(i, i, shift); -macro ulong[<*>].popcount(ulong[<*>] i) = $$popcount(i); -macro ulong[<*>].ctz(ulong[<*>] i) = $$ctz(i); -macro ulong[<*>].clz(ulong[<*>] i) = $$clz(i); +macro ulong[<*>].popcount(ulong[<*>] i) => $$popcount(i); +macro ulong[<*>].ctz(ulong[<*>] i) => $$ctz(i); +macro ulong[<*>].clz(ulong[<*>] i) => $$clz(i); macro ulong[<*>] ulong[<*>].fshl(ulong[<*>] hi, ulong[<*>] lo, ulong[<*>] shift) => $$fshl(hi, lo, shift); macro ulong[<*>] ulong[<*>].fshr(ulong[<*>] hi, ulong[<*>] lo, ulong[<*>] shift) => $$fshr(hi, lo, shift); macro ulong[<*>] ulong[<*>].rotl(ulong[<*>] i, ulong[<*>] shift) => $$fshl(i, i, shift); macro ulong[<*>] ulong[<*>].rotr(ulong[<*>] i, ulong[<*>] shift) => $$fshr(i, i, shift); -macro long[<*>].popcount(long[<*>] i) = $$popcount(i); -macro long[<*>].ctz(long[<*>] i) = $$ctz(i); -macro long[<*>].clz(long[<*>] i) = $$clz(i); +macro long[<*>].popcount(long[<*>] i) => $$popcount(i); +macro long[<*>].ctz(long[<*>] i) => $$ctz(i); +macro long[<*>].clz(long[<*>] i) => $$clz(i); macro long[<*>] long[<*>].fshl(long[<*>] hi, long[<*>] lo, long[<*>] shift) => $$fshl(hi, lo, shift); macro long[<*>] long[<*>].fshr(long[<*>] hi, long[<*>] lo, long[<*>] shift) => $$fshr(hi, lo, shift); macro long[<*>] long[<*>].rotl(long[<*>] i, long[<*>] shift) => $$fshl(i, i, shift); macro long[<*>] long[<*>].rotr(long[<*>] i, long[<*>] shift) => $$fshr(i, i, shift); -macro uint128[<*>].popcount(uint128[<*>] i) = $$popcount(i); -macro uint128[<*>].ctz(uint128[<*>] i) = $$ctz(i); -macro uint128[<*>].clz(uint128[<*>] i) = $$clz(i); +macro uint128[<*>].popcount(uint128[<*>] i) => $$popcount(i); +macro uint128[<*>].ctz(uint128[<*>] i) => $$ctz(i); +macro uint128[<*>].clz(uint128[<*>] i) => $$clz(i); macro uint128[<*>] uint128[<*>].fshl(uint128[<*>] hi, uint128[<*>] lo, uint128[<*>] shift) => $$fshl(hi, lo, shift); macro uint128[<*>] uint128[<*>].fshr(uint128[<*>] hi, uint128[<*>] lo, uint128[<*>] shift) => $$fshr(hi, lo, shift); macro uint128[<*>] uint128[<*>].rotl(uint128[<*>] i, uint128[<*>] shift) => $$fshl(i, i, shift); macro uint128[<*>] uint128[<*>].rotr(uint128[<*>] i, uint128[<*>] shift) => $$fshr(i, i, shift); -macro int128[<*>].popcount(int128[<*>] i) = $$popcount(i); -macro int128[<*>].ctz(int128[<*>] i) = $$ctz(i); -macro int128[<*>].clz(int128[<*>] i) = $$clz(i); +macro int128[<*>].popcount(int128[<*>] i) => $$popcount(i); +macro int128[<*>].ctz(int128[<*>] i) => $$ctz(i); +macro int128[<*>].clz(int128[<*>] i) => $$clz(i); macro int128[<*>] int128[<*>].fshl(int128[<*>] hi, int128[<*>] lo, int128[<*>] shift) => $$fshl(hi, lo, shift); macro int128[<*>] int128[<*>].fshr(int128[<*>] hi, int128[<*>] lo, int128[<*>] shift) => $$fshr(hi, lo, shift); macro int128[<*>] int128[<*>].rotl(int128[<*>] i, int128[<*>] shift) => $$fshl(i, i, shift); macro int128[<*>] int128[<*>].rotr(int128[<*>] i, int128[<*>] shift) => $$fshr(i, i, shift); -macro uint.popcount(uint i) = $$popcount(i); -macro uint.ctz(uint i) = $$ctz(i); -macro uint.clz(uint i) = $$clz(i); +macro uint.popcount(uint i) => $$popcount(i); +macro uint.ctz(uint i) => $$ctz(i); +macro uint.clz(uint i) => $$clz(i); macro uint uint.fshl(uint hi, uint lo, uint shift) => $$fshl(hi, lo, shift); macro uint uint.fshr(uint hi, uint lo, uint shift) => $$fshr(hi, lo, shift); macro uint uint.rotl(uint i, uint shift) => $$fshl(i, i, shift); macro uint uint.rotr(uint i, uint shift) => $$fshr(i, i, shift); -macro int.popcount(int i) = $$popcount(i); -macro int.ctz(int i) = $$ctz(i); -macro int.clz(int i) = $$clz(i); +macro int.popcount(int i) => $$popcount(i); +macro int.ctz(int i) => $$ctz(i); +macro int.clz(int i) => $$clz(i); macro int int.fshl(int hi, int lo, int shift) => $$fshl(hi, lo, shift); macro int int.fshr(int hi, int lo, int shift) => $$fshr(hi, lo, shift); macro int int.rotl(int i, int shift) => $$fshl(i, i, shift); macro int int.rotr(int i, int shift) => $$fshr(i, i, shift); -macro ushort.popcount(ushort i) = $$popcount(i); -macro ushort.ctz(ushort i) = $$ctz(i); -macro ushort.clz(ushort i) = $$clz(i); +macro ushort.popcount(ushort i) => $$popcount(i); +macro ushort.ctz(ushort i) => $$ctz(i); +macro ushort.clz(ushort i) => $$clz(i); macro ushort ushort.fshl(ushort hi, ushort lo, ushort shift) => $$fshl(hi, lo, shift); macro ushort ushort.fshr(ushort hi, ushort lo, ushort shift) => $$fshr(hi, lo, shift); macro ushort ushort.rotl(ushort i, ushort shift) => $$fshl(i, i, shift); macro ushort ushort.rotr(ushort i, ushort shift) => $$fshr(i, i, shift); -macro short.popcount(short i) = $$popcount(i); -macro short.ctz(short i) = $$ctz(i); -macro short.clz(short i) = $$clz(i); +macro short.popcount(short i) => $$popcount(i); +macro short.ctz(short i) => $$ctz(i); +macro short.clz(short i) => $$clz(i); macro short short.fshl(short hi, short lo, short shift) => $$fshl(hi, lo, shift); macro short short.fshr(short hi, short lo, short shift) => $$fshr(hi, lo, shift); macro short short.rotl(short i, short shift) => $$fshl(i, i, shift); macro short short.rotr(short i, short shift) => $$fshr(i, i, shift); -macro char.popcount(char i) = $$popcount(i); -macro char.ctz(char i) = $$ctz(i); -macro char.clz(char i) = $$clz(i); +macro char.popcount(char i) => $$popcount(i); +macro char.ctz(char i) => $$ctz(i); +macro char.clz(char i) => $$clz(i); macro char char.fshl(char hi, char lo, char shift) => $$fshl(hi, lo, shift); macro char char.fshr(char hi, char lo, char shift) => $$fshr(hi, lo, shift); macro char char.rotl(char i, char shift) => $$fshl(i, i, shift); macro char char.rotr(char i, char shift) => $$fshr(i, i, shift); -macro ichar.popcount(ichar i) = $$popcount(i); -macro ichar.ctz(ichar i) = $$ctz(i); -macro ichar.clz(ichar i) = $$clz(i); +macro ichar.popcount(ichar i) => $$popcount(i); +macro ichar.ctz(ichar i) => $$ctz(i); +macro ichar.clz(ichar i) => $$clz(i); macro ichar ichar.fshl(ichar hi, ichar lo, ichar shift) => $$fshl(hi, lo, shift); macro ichar ichar.fshr(ichar hi, ichar lo, ichar shift) => $$fshr(hi, lo, shift); macro ichar ichar.rotl(ichar i, ichar shift) => $$fshl(i, i, shift); macro ichar ichar.rotr(ichar i, ichar shift) => $$fshr(i, i, shift); -macro ulong.popcount(ulong i) = $$popcount(i); -macro ulong.ctz(ulong i) = $$ctz(i); -macro ulong.clz(ulong i) = $$clz(i); +macro ulong.popcount(ulong i) => $$popcount(i); +macro ulong.ctz(ulong i) => $$ctz(i); +macro ulong.clz(ulong i) => $$clz(i); macro ulong ulong.fshl(ulong hi, ulong lo, ulong shift) => $$fshl(hi, lo, shift); macro ulong ulong.fshr(ulong hi, ulong lo, ulong shift) => $$fshr(hi, lo, shift); macro ulong ulong.rotl(ulong i, ulong shift) => $$fshl(i, i, shift); macro ulong ulong.rotr(ulong i, ulong shift) => $$fshr(i, i, shift); -macro long.popcount(long i) = $$popcount(i); -macro long.ctz(long i) = $$ctz(i); -macro long.clz(long i) = $$clz(i); +macro long.popcount(long i) => $$popcount(i); +macro long.ctz(long i) => $$ctz(i); +macro long.clz(long i) => $$clz(i); macro long long.fshl(long hi, long lo, long shift) => $$fshl(hi, lo, shift); macro long long.fshr(long hi, long lo, long shift) => $$fshr(hi, lo, shift); macro long long.rotl(long i, long shift) => $$fshl(i, i, shift); macro long long.rotr(long i, long shift) => $$fshr(i, i, shift); -macro uint128.popcount(uint128 i) = $$popcount(i); -macro uint128.ctz(uint128 i) = $$ctz(i); -macro uint128.clz(uint128 i) = $$clz(i); +macro uint128.popcount(uint128 i) => $$popcount(i); +macro uint128.ctz(uint128 i) => $$ctz(i); +macro uint128.clz(uint128 i) => $$clz(i); macro uint128 uint128.fshl(uint128 hi, uint128 lo, uint128 shift) => $$fshl(hi, lo, shift); macro uint128 uint128.fshr(uint128 hi, uint128 lo, uint128 shift) => $$fshr(hi, lo, shift); macro uint128 uint128.rotl(uint128 i, uint128 shift) => $$fshl(i, i, shift); macro uint128 uint128.rotr(uint128 i, uint128 shift) => $$fshr(i, i, shift); -macro int128.popcount(int128 i) = $$popcount(i); -macro int128.ctz(int128 i) = $$ctz(i); -macro int128.clz(int128 i) = $$clz(i); +macro int128.popcount(int128 i) => $$popcount(i); +macro int128.ctz(int128 i) => $$ctz(i); +macro int128.clz(int128 i) => $$clz(i); macro int128 int128.fshl(int128 hi, int128 lo, int128 shift) => $$fshl(hi, lo, shift); macro int128 int128.fshr(int128 hi, int128 lo, int128 shift) => $$fshr(hi, lo, shift); macro int128 int128.rotl(int128 i, int128 shift) => $$fshl(i, i, shift); diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index 4d249671f..550ac05de 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -164,14 +164,14 @@ macro bool @convertible(#expr, $To) @builtin return $checks($To x = #expr); } -macro uint int.hash(int i) = i; -macro uint uint.hash(uint i) = i; -macro uint short.hash(short s) = s; -macro uint ushort.hash(ushort s) = s; -macro uint char.hash(char c) = c; -macro uint ichar.hash(ichar c) = c; -macro uint long.hash(long i) = (uint)((i >> 32) ^ i); -macro uint ulong.hash(ulong i) = (uint)((i >> 32) ^ i); -macro uint bool.hash(bool b) = (uint)b; -macro uint typeid.hash(typeid t) = (uint)(((uptr)t >> 32) ^ (uptr)t); -macro uint String.hash(String c) = (uint)fnv32a::encode(c); \ No newline at end of file +macro uint int.hash(int i) => i; +macro uint uint.hash(uint i) => i; +macro uint short.hash(short s) => s; +macro uint ushort.hash(ushort s) => s; +macro uint char.hash(char c) => c; +macro uint ichar.hash(ichar c) => c; +macro uint long.hash(long i) => (uint)((i >> 32) ^ i); +macro uint ulong.hash(ulong i) => (uint)((i >> 32) ^ i); +macro uint bool.hash(bool b) => (uint)b; +macro uint typeid.hash(typeid t) => (uint)(((uptr)t >> 32) ^ (uptr)t); +macro uint String.hash(String c) => (uint)fnv32a::encode(c); \ No newline at end of file diff --git a/lib/std/core/str.c3 b/lib/std/core/str.c3 index 6f20581a6..c12d2ae75 100644 --- a/lib/std/core/str.c3 +++ b/lib/std/core/str.c3 @@ -123,17 +123,17 @@ private macro to_integer($Type, String string) return value; } -fn int128! to_int128(String string) = to_integer(int128, string); -fn long! to_long(String string) = to_integer(long, string); -fn int! to_int(String string) = to_integer(int, string); -fn short! to_short(String string) = to_integer(short, string); -fn ichar! to_ichar(String string) = to_integer(ichar, string); +fn int128! to_int128(String string) => to_integer(int128, string); +fn long! to_long(String string) => to_integer(long, string); +fn int! to_int(String string) => to_integer(int, string); +fn short! to_short(String string) => to_integer(short, string); +fn ichar! to_ichar(String string) => to_integer(ichar, string); -fn uint128! to_uint128(String str) = to_integer(uint128, str); -fn ulong! to_ulong(String str) = to_integer(ulong, str); -fn uint! to_uint(String str) = to_integer(uint, str); -fn ushort! to_ushort(String str) = to_integer(ushort, str); -fn char! to_uchar(String str) = to_integer(char, str); +fn uint128! to_uint128(String str) => to_integer(uint128, str); +fn ulong! to_ulong(String str) => to_integer(ulong, str); +fn uint! to_uint(String str) => to_integer(uint, str); +fn ushort! to_ushort(String str) => to_integer(ushort, str); +fn char! to_uchar(String str) => to_integer(char, str); fn String trim(String string, String to_trim = "\t\n\r ") { @@ -156,7 +156,7 @@ fn bool starts_with(String s, String needle) return true; } -fn String[] tsplit(String s, String needle) = split(s, needle, mem::temp_allocator()) @inline; +fn String[] tsplit(String s, String needle) => split(s, needle, mem::temp_allocator()) @inline; fn String[] split(String s, String needle, Allocator* allocator = mem::current_allocator()) { diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 index 6c30199fb..3fcabf515 100644 --- a/lib/std/core/string.c3 +++ b/lib/std/core/string.c3 @@ -139,7 +139,7 @@ fn void VarString.append_char32(VarString* str, Char32 c) data.chars[data.len++] = (char)(0x80 | (c & 0x3F)); } -fn VarString VarString.tcopy(VarString* str) = str.copy(mem::temp_allocator()); +fn VarString VarString.tcopy(VarString* str) => str.copy(mem::temp_allocator()); fn VarString VarString.copy(VarString* str, Allocator* allocator = null) { @@ -174,7 +174,7 @@ fn String VarString.copy_str(VarString* str, Allocator* allocator = mem::current return (String)str.copy_zstr(allocator)[:str.len()]; } -fn String VarString.tcopy_str(VarString* str) = str.copy_str(mem::temp_allocator()) @inline; +fn String VarString.tcopy_str(VarString* str) => str.copy_str(mem::temp_allocator()) @inline; fn bool VarString.equals(VarString str, VarString other_string) { diff --git a/lib/std/core/types.c3 b/lib/std/core/types.c3 index 438a52d03..517d91900 100644 --- a/lib/std/core/types.c3 +++ b/lib/std/core/types.c3 @@ -123,7 +123,7 @@ macro bool is_subarray_convertable($Type) $endswitch; } -macro bool is_int($Type) = $Type.kindof == TypeKind.SIGNED_INT || $Type.kindof == TypeKind.UNSIGNED_INT; +macro bool is_int($Type) => $Type.kindof == TypeKind.SIGNED_INT || $Type.kindof == TypeKind.UNSIGNED_INT; macro bool is_intlike($Type) { @@ -139,7 +139,7 @@ macro bool is_intlike($Type) } -macro bool is_float($Type) = $Type.kindof == TypeKind.FLOAT; +macro bool is_float($Type) => $Type.kindof == TypeKind.FLOAT; macro bool is_floatlike($Type) { @@ -182,7 +182,7 @@ macro bool @has_same(#a, #b, ...) return true; } -macro bool is_promotable_to_floatlike($Type) = types::is_floatlike($Type) || types::is_int($Type); +macro bool is_promotable_to_floatlike($Type) => types::is_floatlike($Type) || types::is_int($Type); macro bool is_same_vector_type($Type1, $Type2) diff --git a/lib/std/core/values.c3 b/lib/std/core/values.c3 index 712d95de9..df1e6e4eb 100644 --- a/lib/std/core/values.c3 +++ b/lib/std/core/values.c3 @@ -1,11 +1,11 @@ module std::core::values; -macro bool @is_int(#value) = types::is_int($typeof(#value)); -macro bool @convertable_to(#a, #b) = $checks($typeof(#b) x = #a); -macro bool @is_floatlike(#value) = types::is_floatlike($typeof(#value)); -macro bool @is_float(#value) = types::is_float($typeof(#value)); -macro bool @is_promotable_to_floatlike(#value) = types::is_promotable_to_floatlike($typeof(#value)); -macro bool @is_same_vector_type(#value1, #value2) = types::is_same_vector_type($typeof(#value1), $typeof(#value2)); +macro bool @is_int(#value) => types::is_int($typeof(#value)); +macro bool @convertable_to(#a, #b) => $checks($typeof(#b) x = #a); +macro bool @is_floatlike(#value) => types::is_floatlike($typeof(#value)); +macro bool @is_float(#value) => types::is_float($typeof(#value)); +macro bool @is_promotable_to_floatlike(#value) => types::is_promotable_to_floatlike($typeof(#value)); +macro bool @is_same_vector_type(#value1, #value2) => types::is_same_vector_type($typeof(#value1), $typeof(#value2)); macro promote_int(x) { $if (values::@is_int(x)): diff --git a/lib/std/libc/libc.c3 b/lib/std/libc/libc.c3 index 03e0afeaf..fc7990bca 100644 --- a/lib/std/libc/libc.c3 +++ b/lib/std/libc/libc.c3 @@ -64,7 +64,7 @@ extern fn void longjmp(JmpBuf* buffer, CInt value); $if (env::OS_TYPE == OsType.WIN32): // TODO win32 aarch64 extern fn CInt _setjmp(void* frameptr, JmpBuf* buffer); -macro CInt setjmp(JmpBuf* buffer) = _setjmp($$frameaddress(), buffer); +macro CInt setjmp(JmpBuf* buffer) => _setjmp($$frameaddress(), buffer); $else: extern fn CInt setjmp(JmpBuf* buffer); $endif; diff --git a/lib/std/libc/os/errno.c3 b/lib/std/libc/os/errno.c3 index 2ffcb675a..338ae41ae 100644 --- a/lib/std/libc/os/errno.c3 +++ b/lib/std/libc/os/errno.c3 @@ -6,14 +6,14 @@ $case LINUX: extern fn int* __errno_location(); -macro int errno() = *__errno_location(); -macro void errno_set(int err) = *(__errno_location()) = err; +macro int errno() => *__errno_location(); +macro void errno_set(int err) => *(__errno_location()) = err; $case MACOSX: extern fn int* __error(); -macro int errno() = *__error(); -macro void errno_set(int err) = *(__error()) = err; +macro int errno() => *__error(); +macro void errno_set(int err) => *(__error()) = err; $case WIN32: @@ -24,14 +24,14 @@ macro int errno() return holder; } -macro void errno_set(int err) = _set_errno(err); +macro void errno_set(int err) => _set_errno(err); extern fn void _get_errno(int* result); extern fn void _set_errno(int err); $default: -macro int errno() = 1; +macro int errno() => 1; fn void errno_set(int err) {} $endswitch; diff --git a/lib/std/math/math.c3 b/lib/std/math/math.c3 index a7624cd17..bb1ee6065 100644 --- a/lib/std/math/math.c3 +++ b/lib/std/math/math.c3 @@ -109,7 +109,7 @@ define matrix4f_perspective = matrix::perspective; /** * @require types::is_numerical($typeof(x)) `The input must be a numerical value or numerical vector` **/ -macro abs(x) = $$abs(x); +macro abs(x) => $$abs(x); /** * @require values::@is_int(x) `The input must be an integer` @@ -149,64 +149,64 @@ $endif; /** * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` **/ -macro ceil(x) = $$ceil(x); +macro ceil(x) => $$ceil(x); /** * @require types::is_numerical($typeof(x)) `The input must be a numerical value or numerical vector` * @require types::@has_same(x, lower, upper) `The input types must be equal` **/ -macro clamp(x, lower, upper) = $$max(lower, $$min(x, upper)); +macro clamp(x, lower, upper) => $$max(lower, $$min(x, upper)); /** * @require values::@is_promotable_to_floatlike(mag) `The input must be a number value or float vector` * @require values::@is_same_vector_type(mag, sgn) `The input types must match` **/ -macro copysign(mag, sgn) = $$copysign(mag, sgn); +macro copysign(mag, sgn) => $$copysign(mag, sgn); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro cos(x) = $$cos(x); +macro cos(x) => $$cos(x); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro cosec(x) = 1 / sin(x); +macro cosec(x) => 1 / sin(x); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro cosech(x) = 2 / (exp(x) - exp(-x)); +macro cosech(x) => 2 / (exp(x) - exp(-x)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro cosh(x) = (exp(x) + exp(-x)) / 2.0; +macro cosh(x) => (exp(x) + exp(-x)) / 2.0; /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro cotan(x) = cos(x) / sin(x); +macro cotan(x) => cos(x) / sin(x); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro cotanh(x) = (exp(2.0 * x) + 1.0) / (exp(2.0 * x) - 1.0); +macro cotanh(x) => (exp(2.0 * x) + 1.0) / (exp(2.0 * x) - 1.0); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro exp(x) = $$exp(values::promote_int(x)); +macro exp(x) => $$exp(values::promote_int(x)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro exp2(x) = $$exp2(values::promote_int(x)); +macro exp2(x) => $$exp2(values::promote_int(x)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number value or float vector` **/ -macro floor(x) = $$floor(values::promote_int(x)); +macro floor(x) => $$floor(values::promote_int(x)); /** * @require values::@is_promotable_to_floatlike(a) `The input must be a number or float vector` @@ -215,7 +215,7 @@ macro floor(x) = $$floor(values::promote_int(x)); * @require types::@is_same_vector_type(a, b) `The input types must be equal` * @require types::@is_same_vector_type(a, c) `The input types must match` **/ -macro fma(a, b, c) = $$fma(a, b, c); +macro fma(a, b, c) => $$fma(a, b, c); /** @@ -223,22 +223,22 @@ macro fma(a, b, c) = $$fma(a, b, c); * @require values::@is_promotable_to_floatlike(y) `The input must be a number or a float vector` * @require types::@is_same_vector_type(x, y) `The input types must match` **/ -macro hypot(x, y) = sqrt(sqr(x) + sqr(y)); +macro hypot(x, y) => sqrt(sqr(x) + sqr(y)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro log(x) = $$log(values::promote_int(x)); +macro log(x) => $$log(values::promote_int(x)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro log2(x) = $$log2(values::promote_int(x)); +macro log2(x) => $$log2(values::promote_int(x)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro log10(x) = $$log10(values::promote_int(x)); +macro log10(x) => $$log10(values::promote_int(x)); /** * @require types::is_numerical($typeof(x)) `The input must be a floating point value or float vector` @@ -278,12 +278,12 @@ macro min(x, y, ...) * @require types::@is_float(a) `The input must be a floating point value` * @require types::@has_same(a, b, c) `The input types must be equal` **/ -macro muladd(a, b, c) = $$fmuladd(a, b, c); +macro muladd(a, b, c) => $$fmuladd(a, b, c); /** * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` **/ -macro nearbyint(x) = $$nearbyint(x); +macro nearbyint(x) => $$nearbyint(x); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` @@ -301,64 +301,64 @@ macro pow(x, exp) /** * @require values::@is_floatlike(x) `The input must be a number or a float vector` **/ -macro rint(x) = $$rint(x); +macro rint(x) => $$rint(x); /** * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` **/ -macro round(x) = $$round(x); +macro round(x) => $$round(x); /** * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` **/ -macro roundeven(x) = $$roundeven(x); +macro roundeven(x) => $$roundeven(x); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro sec(x) = 1 / cos(x); +macro sec(x) => 1 / cos(x); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro sech(x) = 2 / (exp(x) + exp(-x)); +macro sech(x) => 2 / (exp(x) + exp(-x)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro sin(x) = $$sin(values::promote_int(x)); +macro sin(x) => $$sin(values::promote_int(x)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro sinh(x) = (exp(x) - exp(-x)) / 2.0; +macro sinh(x) => (exp(x) - exp(-x)) / 2.0; /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro sqr(x) = values::promote_int(x) * values::promote_int(x); +macro sqr(x) => values::promote_int(x) * values::promote_int(x); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro sqrt(x) = $$sqrt(values::promote_int(x)); +macro sqrt(x) => $$sqrt(values::promote_int(x)); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro tan(x) = sin(x) / cos(x); +macro tan(x) => sin(x) / cos(x); /** * @require values::@is_promotable_to_floatlike(x) `The input must be a number or a float vector` **/ -macro tanh(x) = (exp(2.0 * x) - 1.0) / (exp(2.0 * x) + 1.0); +macro tanh(x) => (exp(2.0 * x) - 1.0) / (exp(2.0 * x) + 1.0); /** * @require values::@is_floatlike(x) `The input must be a floating point value or float vector` **/ -macro trunc(x) = $$trunc(x); +macro trunc(x) => $$trunc(x); -private macro lerp(x, y, amount) = x + (y - x) * amount; +private macro lerp(x, y, amount) => x + (y - x) * amount; private macro reflect(x, y) { var dot = x.dot(y); @@ -371,194 +371,194 @@ private macro normalize(x) return x * (1 / len); } -macro float float.ceil(float x) = $$ceil(x); -macro float float.clamp(float x, float lower, float upper) = $$max(lower, $$min(x, upper)); -macro float float.copysign(float mag, float sgn) = $$copysign(mag, sgn); -macro float float.floor(float x) = $$floor(x); -macro float float.fma(float a, float b, float c) = $$fma(a, b, c); -macro float float.muladd(float a, float b, float c) = $$fmuladd(a, b, c); -macro float float.nearbyint(float x) = $$nearbyint(x); -macro float float.pow(float x, exp) = pow(x, exp); -macro float float.rint(float x) = $$rint(x); -macro float float.round(float x) = $$round(x); -macro float float.roundeven(float x) = $$roundeven(x); -macro float float.trunc(float x) = $$trunc(x); +macro float float.ceil(float x) => $$ceil(x); +macro float float.clamp(float x, float lower, float upper) => $$max(lower, $$min(x, upper)); +macro float float.copysign(float mag, float sgn) => $$copysign(mag, sgn); +macro float float.floor(float x) => $$floor(x); +macro float float.fma(float a, float b, float c) => $$fma(a, b, c); +macro float float.muladd(float a, float b, float c) => $$fmuladd(a, b, c); +macro float float.nearbyint(float x) => $$nearbyint(x); +macro float float.pow(float x, exp) => pow(x, exp); +macro float float.rint(float x) => $$rint(x); +macro float float.round(float x) => $$round(x); +macro float float.roundeven(float x) => $$roundeven(x); +macro float float.trunc(float x) => $$trunc(x); -macro float float[<*>].sum(float[<*>] x, float start = 0.0) = $$reduce_fadd(x, start); -macro float float[<*>].product(float[<*>] x, float start = 1.0) = $$reduce_fmul(x, start); -macro float float[<*>].max(float[<*>] x) = $$reduce_max(x); -macro float float[<*>].min(float[<*>] x) = $$reduce_min(x); -macro float[<*>] float[<*>].ceil(float[<*>] x) = $$ceil(x); -macro float[<*>] float[<*>].clamp(float[<*>] x, float[<*>] lower, float[<*>] upper) = $$max(lower, $$min(x, upper)); -macro float[<*>] float[<*>].copysign(float[<*>] mag, float[<*>] sgn) = $$copysign(mag, sgn); -macro float[<*>] float[<*>].fma(float[<*>] a, float[<*>] b, float[<*>] c) = $$fma(a, b, c); -macro float[<*>] float[<*>].floor(float[<*>] x) = $$floor(x); -macro float[<*>] float[<*>].nearbyint(float[<*>] x) = $$nearbyint(x); -macro float[<*>] float[<*>].pow(float[<*>] x, exp) = pow(x, exp); -macro float[<*>] float[<*>].rint(float[<*>] x) = $$rint(x); -macro float[<*>] float[<*>].round(float[<*>] x) = $$round(x); -macro float[<*>] float[<*>].roundeven(float[<*>] x) = $$roundeven(x); -macro float[<*>] float[<*>].trunc(float[<*>] x) = $$trunc(x); -macro float float[<*>].dot(float[<*>] x, float[<*>] y) = (x * y).sum(); -macro float float[<*>].length(float[<*>] x) = $$sqrt(x.dot(x)); -macro float float[<*>].distance(float[<*>] x, float[<*>] y) = (x - y).length(); -macro float[<*>] float[<*>].normalize(float[<*>] x) = normalize(x); -macro float[<*>] float[<*>].lerp(float[<*>] x, float[<*>] y, float amount) = lerp(x, y, amount); -macro float[<*>] float[<*>].reflect(float[<*>] x, float[<*>] y) = reflect(x, y); -macro bool float[<*>].equals(float[<*>] x, float[<*>] y) = equals_vec(x, y); +macro float float[<*>].sum(float[<*>] x, float start = 0.0) => $$reduce_fadd(x, start); +macro float float[<*>].product(float[<*>] x, float start = 1.0) => $$reduce_fmul(x, start); +macro float float[<*>].max(float[<*>] x) => $$reduce_max(x); +macro float float[<*>].min(float[<*>] x) => $$reduce_min(x); +macro float[<*>] float[<*>].ceil(float[<*>] x) => $$ceil(x); +macro float[<*>] float[<*>].clamp(float[<*>] x, float[<*>] lower, float[<*>] upper) => $$max(lower, $$min(x, upper)); +macro float[<*>] float[<*>].copysign(float[<*>] mag, float[<*>] sgn) => $$copysign(mag, sgn); +macro float[<*>] float[<*>].fma(float[<*>] a, float[<*>] b, float[<*>] c) => $$fma(a, b, c); +macro float[<*>] float[<*>].floor(float[<*>] x) => $$floor(x); +macro float[<*>] float[<*>].nearbyint(float[<*>] x) => $$nearbyint(x); +macro float[<*>] float[<*>].pow(float[<*>] x, exp) => pow(x, exp); +macro float[<*>] float[<*>].rint(float[<*>] x) => $$rint(x); +macro float[<*>] float[<*>].round(float[<*>] x) => $$round(x); +macro float[<*>] float[<*>].roundeven(float[<*>] x) => $$roundeven(x); +macro float[<*>] float[<*>].trunc(float[<*>] x) => $$trunc(x); +macro float float[<*>].dot(float[<*>] x, float[<*>] y) => (x * y).sum(); +macro float float[<*>].length(float[<*>] x) => $$sqrt(x.dot(x)); +macro float float[<*>].distance(float[<*>] x, float[<*>] y) => (x - y).length(); +macro float[<*>] float[<*>].normalize(float[<*>] x) => normalize(x); +macro float[<*>] float[<*>].lerp(float[<*>] x, float[<*>] y, float amount) => lerp(x, y, amount); +macro float[<*>] float[<*>].reflect(float[<*>] x, float[<*>] y) => reflect(x, y); +macro bool float[<*>].equals(float[<*>] x, float[<*>] y) => equals_vec(x, y); -macro bool[<*>] float[<*>].comp_lt(float[<*>] x, float[<*>] y) = $$veccomplt(x, y); -macro bool[<*>] float[<*>].comp_le(float[<*>] x, float[<*>] y) = $$veccomple(x, y); -macro bool[<*>] float[<*>].comp_eq(float[<*>] x, float[<*>] y) = $$veccompeq(x, y); -macro bool[<*>] float[<*>].comp_gt(float[<*>] x, float[<*>] y) = $$veccompgt(x, y); -macro bool[<*>] float[<*>].comp_ge(float[<*>] x, float[<*>] y) = $$veccompge(x, y); -macro bool[<*>] float[<*>].comp_ne(float[<*>] x, float[<*>] y) = $$veccompne(x, y); +macro bool[<*>] float[<*>].comp_lt(float[<*>] x, float[<*>] y) => $$veccomplt(x, y); +macro bool[<*>] float[<*>].comp_le(float[<*>] x, float[<*>] y) => $$veccomple(x, y); +macro bool[<*>] float[<*>].comp_eq(float[<*>] x, float[<*>] y) => $$veccompeq(x, y); +macro bool[<*>] float[<*>].comp_gt(float[<*>] x, float[<*>] y) => $$veccompgt(x, y); +macro bool[<*>] float[<*>].comp_ge(float[<*>] x, float[<*>] y) => $$veccompge(x, y); +macro bool[<*>] float[<*>].comp_ne(float[<*>] x, float[<*>] y) => $$veccompne(x, y); -macro double double.ceil(double x) = $$ceil(x); -macro double double.clamp(double x, double lower, double upper) = $$max(lower, $$min(x, upper)); -macro double double.copysign(double mag, double sgn) = $$copysign(mag, sgn); -macro double double.floor(double x) = $$floor(x); -macro double double.fma(double a, double b, double c) = $$fma(a, b, c); -macro double double.muladd(double a, double b, double c) = $$fmuladd(a, b, c); -macro double double.nearbyint(double x) = $$nearbyint(x); -macro double double.pow(double x, exp) = pow(x, exp); -macro double double.rint(double x) = $$rint(x); -macro double double.round(double x) = $$round(x); -macro double double.roundeven(double x) = $$roundeven(x); -macro double double.trunc(double x) = $$trunc(x); +macro double double.ceil(double x) => $$ceil(x); +macro double double.clamp(double x, double lower, double upper) => $$max(lower, $$min(x, upper)); +macro double double.copysign(double mag, double sgn) => $$copysign(mag, sgn); +macro double double.floor(double x) => $$floor(x); +macro double double.fma(double a, double b, double c) => $$fma(a, b, c); +macro double double.muladd(double a, double b, double c) => $$fmuladd(a, b, c); +macro double double.nearbyint(double x) => $$nearbyint(x); +macro double double.pow(double x, exp) => pow(x, exp); +macro double double.rint(double x) => $$rint(x); +macro double double.round(double x) => $$round(x); +macro double double.roundeven(double x) => $$roundeven(x); +macro double double.trunc(double x) => $$trunc(x); -macro double double[<*>].sum(double[<*>] x, double start = 0.0) = $$reduce_fadd(x, start); -macro double double[<*>].product(double[<*>] x, double start = 1.0) = $$reduce_fmul(x, start); -macro double double[<*>].max(double[<*>] x) = $$reduce_fmax(x); -macro double double[<*>].min(double[<*>] x) = $$reduce_fmin(x); -macro double[<*>] double[<*>].ceil(double[<*>] x) = $$ceil(x); -macro double[<*>] double[<*>].clamp(double[<*>] x, double[<*>] lower, double[<*>] upper) = $$max(lower, $$min(x, upper)); -macro double[<*>] double[<*>].copysign(double[<*>] mag, double[<*>] sgn) = $$copysign(mag, sgn); -macro double[<*>] double[<*>].floor(double[<*>] x) = $$floor(x); -macro double[<*>] double[<*>].fma(double[<*>] a, double[<*>] b, double[<*>] c) = $$fma(a, b, c); -macro double[<*>] double[<*>].nearbyint(double[<*>] x) = $$nearbyint(x); -macro double[<*>] double[<*>].pow(double[<*>] x, exp) = pow(x, exp); -macro double[<*>] double[<*>].rint(double[<*>] x) = $$rint(x); -macro double[<*>] double[<*>].round(double[<*>] x) = $$round(x); -macro double[<*>] double[<*>].roundeven(double[<*>] x) = $$roundeven(x); -macro double[<*>] double[<*>].trunc(double[<*>] x) = $$trunc(x); -macro double double[<*>].dot(double[<*>] x, double[<*>] y) = (x * y).sum(); -macro double double[<*>].length(double[<*>] x) = $$sqrt(x.dot(x)); -macro double double[<*>].distance(double[<*>] x, double[<*>] y) = (x - y).length(); -macro double[<*>] double[<*>].normalize(double[<*>] x) = normalize(x); -macro double[<*>] double[<*>].reflect(double[<*>] x, double[<*>] y) = reflect(x, y); -macro double[<*>] double[<*>].lerp(double[<*>] x, double[<*>] y, double amount) = lerp(x, y, amount); -macro bool double[<*>].equals(double[<*>] x, double[<*>] y) = equals_vec(x, y); +macro double double[<*>].sum(double[<*>] x, double start = 0.0) => $$reduce_fadd(x, start); +macro double double[<*>].product(double[<*>] x, double start = 1.0) => $$reduce_fmul(x, start); +macro double double[<*>].max(double[<*>] x) => $$reduce_fmax(x); +macro double double[<*>].min(double[<*>] x) => $$reduce_fmin(x); +macro double[<*>] double[<*>].ceil(double[<*>] x) => $$ceil(x); +macro double[<*>] double[<*>].clamp(double[<*>] x, double[<*>] lower, double[<*>] upper) => $$max(lower, $$min(x, upper)); +macro double[<*>] double[<*>].copysign(double[<*>] mag, double[<*>] sgn) => $$copysign(mag, sgn); +macro double[<*>] double[<*>].floor(double[<*>] x) => $$floor(x); +macro double[<*>] double[<*>].fma(double[<*>] a, double[<*>] b, double[<*>] c) => $$fma(a, b, c); +macro double[<*>] double[<*>].nearbyint(double[<*>] x) => $$nearbyint(x); +macro double[<*>] double[<*>].pow(double[<*>] x, exp) => pow(x, exp); +macro double[<*>] double[<*>].rint(double[<*>] x) => $$rint(x); +macro double[<*>] double[<*>].round(double[<*>] x) => $$round(x); +macro double[<*>] double[<*>].roundeven(double[<*>] x) => $$roundeven(x); +macro double[<*>] double[<*>].trunc(double[<*>] x) => $$trunc(x); +macro double double[<*>].dot(double[<*>] x, double[<*>] y) => (x * y).sum(); +macro double double[<*>].length(double[<*>] x) => $$sqrt(x.dot(x)); +macro double double[<*>].distance(double[<*>] x, double[<*>] y) => (x - y).length(); +macro double[<*>] double[<*>].normalize(double[<*>] x) => normalize(x); +macro double[<*>] double[<*>].reflect(double[<*>] x, double[<*>] y) => reflect(x, y); +macro double[<*>] double[<*>].lerp(double[<*>] x, double[<*>] y, double amount) => lerp(x, y, amount); +macro bool double[<*>].equals(double[<*>] x, double[<*>] y) => equals_vec(x, y); -macro bool[<*>] double[<*>].comp_lt(double[<*>] x, double[<*>] y) = $$veccomplt(x, y); -macro bool[<*>] double[<*>].comp_le(double[<*>] x, double[<*>] y) = $$veccomple(x, y); -macro bool[<*>] double[<*>].comp_eq(double[<*>] x, double[<*>] y) = $$veccompeq(x, y); -macro bool[<*>] double[<*>].comp_gt(double[<*>] x, double[<*>] y) = $$veccompgt(x, y); -macro bool[<*>] double[<*>].comp_ge(double[<*>] x, double[<*>] y) = $$veccompge(x, y); -macro bool[<*>] double[<*>].comp_ne(double[<*>] x, double[<*>] y) = $$veccompne(x, y); +macro bool[<*>] double[<*>].comp_lt(double[<*>] x, double[<*>] y) => $$veccomplt(x, y); +macro bool[<*>] double[<*>].comp_le(double[<*>] x, double[<*>] y) => $$veccomple(x, y); +macro bool[<*>] double[<*>].comp_eq(double[<*>] x, double[<*>] y) => $$veccompeq(x, y); +macro bool[<*>] double[<*>].comp_gt(double[<*>] x, double[<*>] y) => $$veccompgt(x, y); +macro bool[<*>] double[<*>].comp_ge(double[<*>] x, double[<*>] y) => $$veccompge(x, y); +macro bool[<*>] double[<*>].comp_ne(double[<*>] x, double[<*>] y) => $$veccompne(x, y); -macro ichar ichar[<*>].sum(ichar[<*>] x) = $$reduce_add(x); -macro ichar ichar[<*>].product(ichar[<*>] x) = $$reduce_mul(x); -macro ichar ichar[<*>].and(ichar[<*>] x) = $$reduce_and(x); -macro ichar ichar[<*>].or(ichar[<*>] x) = $$reduce_or(x); -macro ichar ichar[<*>].xor(ichar[<*>] x) = $$reduce_xor(x); -macro ichar ichar[<*>].max(ichar[<*>] x) = $$reduce_max(x); -macro ichar ichar[<*>].min(ichar[<*>] x) = $$reduce_min(x); +macro ichar ichar[<*>].sum(ichar[<*>] x) => $$reduce_add(x); +macro ichar ichar[<*>].product(ichar[<*>] x) => $$reduce_mul(x); +macro ichar ichar[<*>].and(ichar[<*>] x) => $$reduce_and(x); +macro ichar ichar[<*>].or(ichar[<*>] x) => $$reduce_or(x); +macro ichar ichar[<*>].xor(ichar[<*>] x) => $$reduce_xor(x); +macro ichar ichar[<*>].max(ichar[<*>] x) => $$reduce_max(x); +macro ichar ichar[<*>].min(ichar[<*>] x) => $$reduce_min(x); -macro short short[<*>].sum(short[<*>] x) = $$reduce_add(x); -macro short short[<*>].product(short[<*>] x) = $$reduce_mul(x); -macro short short[<*>].and(short[<*>] x) = $$reduce_and(x); -macro short short[<*>].or(short[<*>] x) = $$reduce_or(x); -macro short short[<*>].xor(short[<*>] x) = $$reduce_xor(x); -macro short short[<*>].max(short[<*>] x) = $$reduce_max(x); -macro short short[<*>].min(short[<*>] x) = $$reduce_min(x); +macro short short[<*>].sum(short[<*>] x) => $$reduce_add(x); +macro short short[<*>].product(short[<*>] x) => $$reduce_mul(x); +macro short short[<*>].and(short[<*>] x) => $$reduce_and(x); +macro short short[<*>].or(short[<*>] x) => $$reduce_or(x); +macro short short[<*>].xor(short[<*>] x) => $$reduce_xor(x); +macro short short[<*>].max(short[<*>] x) => $$reduce_max(x); +macro short short[<*>].min(short[<*>] x) => $$reduce_min(x); -macro bool[<*>] int[<*>].comp_lt(int[<*>] x, int[<*>] y) = $$veccomplt(x, y); -macro bool[<*>] int[<*>].comp_le(int[<*>] x, int[<*>] y) = $$veccomple(x, y); -macro bool[<*>] int[<*>].comp_eq(int[<*>] x, int[<*>] y) = $$veccompeq(x, y); -macro bool[<*>] int[<*>].comp_gt(int[<*>] x, int[<*>] y) = $$veccompgt(x, y); -macro bool[<*>] int[<*>].comp_ge(int[<*>] x, int[<*>] y) = $$veccompge(x, y); -macro bool[<*>] int[<*>].comp_ne(int[<*>] x, int[<*>] y) = $$veccompne(x, y); +macro bool[<*>] int[<*>].comp_lt(int[<*>] x, int[<*>] y) => $$veccomplt(x, y); +macro bool[<*>] int[<*>].comp_le(int[<*>] x, int[<*>] y) => $$veccomple(x, y); +macro bool[<*>] int[<*>].comp_eq(int[<*>] x, int[<*>] y) => $$veccompeq(x, y); +macro bool[<*>] int[<*>].comp_gt(int[<*>] x, int[<*>] y) => $$veccompgt(x, y); +macro bool[<*>] int[<*>].comp_ge(int[<*>] x, int[<*>] y) => $$veccompge(x, y); +macro bool[<*>] int[<*>].comp_ne(int[<*>] x, int[<*>] y) => $$veccompne(x, y); -macro int int[<*>].sum(int[<*>] x) = $$reduce_add(x); -macro int int[<*>].product(int[<*>] x) = $$reduce_mul(x); -macro int int[<*>].and(int[<*>] x) = $$reduce_and(x); -macro int int[<*>].or(int[<*>] x) = $$reduce_or(x); -macro int int[<*>].xor(int[<*>] x) = $$reduce_xor(x); -macro int int[<*>].max(int[<*>] x) = $$reduce_max(x); -macro int int[<*>].min(int[<*>] x) = $$reduce_min(x); +macro int int[<*>].sum(int[<*>] x) => $$reduce_add(x); +macro int int[<*>].product(int[<*>] x) => $$reduce_mul(x); +macro int int[<*>].and(int[<*>] x) => $$reduce_and(x); +macro int int[<*>].or(int[<*>] x) => $$reduce_or(x); +macro int int[<*>].xor(int[<*>] x) => $$reduce_xor(x); +macro int int[<*>].max(int[<*>] x) => $$reduce_max(x); +macro int int[<*>].min(int[<*>] x) => $$reduce_min(x); -macro long long[<*>].sum(long[<*>] x) = $$reduce_add(x); -macro long long[<*>].product(long[<*>] x) = $$reduce_mul(x); -macro long long[<*>].and(long[<*>] x) = $$reduce_and(x); -macro long long[<*>].or(long[<*>] x) = $$reduce_or(x); -macro long long[<*>].xor(long[<*>] x) = $$reduce_xor(x); -macro long long[<*>].max(long[<*>] x) = $$reduce_max(x); -macro long long[<*>].min(long[<*>] x) = $$reduce_min(x); +macro long long[<*>].sum(long[<*>] x) => $$reduce_add(x); +macro long long[<*>].product(long[<*>] x) => $$reduce_mul(x); +macro long long[<*>].and(long[<*>] x) => $$reduce_and(x); +macro long long[<*>].or(long[<*>] x) => $$reduce_or(x); +macro long long[<*>].xor(long[<*>] x) => $$reduce_xor(x); +macro long long[<*>].max(long[<*>] x) => $$reduce_max(x); +macro long long[<*>].min(long[<*>] x) => $$reduce_min(x); -macro int128 int128[<*>].sum(int128[<*>] x) = $$reduce_add(x); -macro int128 int128[<*>].product(int128[<*>] x) = $$reduce_mul(x); -macro int128 int128[<*>].and(int128[<*>] x) = $$reduce_and(x); -macro int128 int128[<*>].or(int128[<*>] x) = $$reduce_or(x); -macro int128 int128[<*>].xor(int128[<*>] x) = $$reduce_xor(x); -macro int128 int128[<*>].max(int128[<*>] x) = $$reduce_max(x); -macro int128 int128[<*>].min(int128[<*>] x) = $$reduce_min(x); +macro int128 int128[<*>].sum(int128[<*>] x) => $$reduce_add(x); +macro int128 int128[<*>].product(int128[<*>] x) => $$reduce_mul(x); +macro int128 int128[<*>].and(int128[<*>] x) => $$reduce_and(x); +macro int128 int128[<*>].or(int128[<*>] x) => $$reduce_or(x); +macro int128 int128[<*>].xor(int128[<*>] x) => $$reduce_xor(x); +macro int128 int128[<*>].max(int128[<*>] x) => $$reduce_max(x); +macro int128 int128[<*>].min(int128[<*>] x) => $$reduce_min(x); -macro bool[<*>] bool[<*>].comp_lt(bool[<*>] x, bool[<*>] y) = $$veccomplt(x, y); -macro bool[<*>] bool[<*>].comp_le(bool[<*>] x, bool[<*>] y) = $$veccomple(x, y); -macro bool[<*>] bool[<*>].comp_eq(bool[<*>] x, bool[<*>] y) = $$veccompeq(x, y); -macro bool[<*>] bool[<*>].comp_gt(bool[<*>] x, bool[<*>] y) = $$veccompgt(x, y); -macro bool[<*>] bool[<*>].comp_ge(bool[<*>] x, bool[<*>] y) = $$veccompge(x, y); -macro bool[<*>] bool[<*>].comp_ne(bool[<*>] x, bool[<*>] y) = $$veccompne(x, y); +macro bool[<*>] bool[<*>].comp_lt(bool[<*>] x, bool[<*>] y) => $$veccomplt(x, y); +macro bool[<*>] bool[<*>].comp_le(bool[<*>] x, bool[<*>] y) => $$veccomple(x, y); +macro bool[<*>] bool[<*>].comp_eq(bool[<*>] x, bool[<*>] y) => $$veccompeq(x, y); +macro bool[<*>] bool[<*>].comp_gt(bool[<*>] x, bool[<*>] y) => $$veccompgt(x, y); +macro bool[<*>] bool[<*>].comp_ge(bool[<*>] x, bool[<*>] y) => $$veccompge(x, y); +macro bool[<*>] bool[<*>].comp_ne(bool[<*>] x, bool[<*>] y) => $$veccompne(x, y); -macro bool bool[<*>].sum(bool[<*>] x) = $$reduce_add(x); -macro bool bool[<*>].product(bool[<*>] x) = $$reduce_mul(x); -macro bool bool[<*>].and(bool[<*>] x) = $$reduce_and(x); -macro bool bool[<*>].or(bool[<*>] x) = $$reduce_or(x); -macro bool bool[<*>].xor(bool[<*>] x) = $$reduce_xor(x); -macro bool bool[<*>].max(bool[<*>] x) = $$reduce_max(x); -macro bool bool[<*>].min(bool[<*>] x) = $$reduce_min(x); +macro bool bool[<*>].sum(bool[<*>] x) => $$reduce_add(x); +macro bool bool[<*>].product(bool[<*>] x) => $$reduce_mul(x); +macro bool bool[<*>].and(bool[<*>] x) => $$reduce_and(x); +macro bool bool[<*>].or(bool[<*>] x) => $$reduce_or(x); +macro bool bool[<*>].xor(bool[<*>] x) => $$reduce_xor(x); +macro bool bool[<*>].max(bool[<*>] x) => $$reduce_max(x); +macro bool bool[<*>].min(bool[<*>] x) => $$reduce_min(x); -macro char char[<*>].sum(char[<*>] x) = $$reduce_add(x); -macro char char[<*>].product(char[<*>] x) = $$reduce_mul(x); -macro char char[<*>].and(char[<*>] x) = $$reduce_and(x); -macro char char[<*>].or(char[<*>] x) = $$reduce_or(x); -macro char char[<*>].xor(char[<*>] x) = $$reduce_xor(x); -macro char char[<*>].max(char[<*>] x) = $$reduce_max(x); -macro char char[<*>].min(char[<*>] x) = $$reduce_min(x); +macro char char[<*>].sum(char[<*>] x) => $$reduce_add(x); +macro char char[<*>].product(char[<*>] x) => $$reduce_mul(x); +macro char char[<*>].and(char[<*>] x) => $$reduce_and(x); +macro char char[<*>].or(char[<*>] x) => $$reduce_or(x); +macro char char[<*>].xor(char[<*>] x) => $$reduce_xor(x); +macro char char[<*>].max(char[<*>] x) => $$reduce_max(x); +macro char char[<*>].min(char[<*>] x) => $$reduce_min(x); -macro ushort ushort[<*>].sum(ushort[<*>] x) = $$reduce_add(x); -macro ushort ushort[<*>].product(ushort[<*>] x) = $$reduce_mul(x); -macro ushort ushort[<*>].and(ushort[<*>] x) = $$reduce_and(x); -macro ushort ushort[<*>].or(ushort[<*>] x) = $$reduce_or(x); -macro ushort ushort[<*>].xor(ushort[<*>] x) = $$reduce_xor(x); -macro ushort ushort[<*>].max(ushort[<*>] x) = $$reduce_max(x); -macro ushort ushort[<*>].min(ushort[<*>] x) = $$reduce_min(x); +macro ushort ushort[<*>].sum(ushort[<*>] x) => $$reduce_add(x); +macro ushort ushort[<*>].product(ushort[<*>] x) => $$reduce_mul(x); +macro ushort ushort[<*>].and(ushort[<*>] x) => $$reduce_and(x); +macro ushort ushort[<*>].or(ushort[<*>] x) => $$reduce_or(x); +macro ushort ushort[<*>].xor(ushort[<*>] x) => $$reduce_xor(x); +macro ushort ushort[<*>].max(ushort[<*>] x) => $$reduce_max(x); +macro ushort ushort[<*>].min(ushort[<*>] x) => $$reduce_min(x); -macro uint uint[<*>].sum(uint[<*>] x) = $$reduce_add(x); -macro uint uint[<*>].product(uint[<*>] x) = $$reduce_mul(x); -macro uint uint[<*>].and(uint[<*>] x) = $$reduce_and(x); -macro uint uint[<*>].or(uint[<*>] x) = $$reduce_or(x); -macro uint uint[<*>].xor(uint[<*>] x) = $$reduce_xor(x); -macro uint uint[<*>].max(uint[<*>] x) = $$reduce_max(x); -macro uint uint[<*>].min(uint[<*>] x) = $$reduce_min(x); +macro uint uint[<*>].sum(uint[<*>] x) => $$reduce_add(x); +macro uint uint[<*>].product(uint[<*>] x) => $$reduce_mul(x); +macro uint uint[<*>].and(uint[<*>] x) => $$reduce_and(x); +macro uint uint[<*>].or(uint[<*>] x) => $$reduce_or(x); +macro uint uint[<*>].xor(uint[<*>] x) => $$reduce_xor(x); +macro uint uint[<*>].max(uint[<*>] x) => $$reduce_max(x); +macro uint uint[<*>].min(uint[<*>] x) => $$reduce_min(x); -macro ulong ulong[<*>].sum(ulong[<*>] x) = $$reduce_add(x); -macro ulong ulong[<*>].product(ulong[<*>] x) = $$reduce_mul(x); -macro ulong ulong[<*>].and(ulong[<*>] x) = $$reduce_and(x); -macro ulong ulong[<*>].or(ulong[<*>] x) = $$reduce_or(x); -macro ulong ulong[<*>].xor(ulong[<*>] x) = $$reduce_xor(x); -macro ulong ulong[<*>].max(ulong[<*>] x) = $$reduce_max(x); -macro ulong ulong[<*>].min(ulong[<*>] x) = $$reduce_min(x); +macro ulong ulong[<*>].sum(ulong[<*>] x) => $$reduce_add(x); +macro ulong ulong[<*>].product(ulong[<*>] x) => $$reduce_mul(x); +macro ulong ulong[<*>].and(ulong[<*>] x) => $$reduce_and(x); +macro ulong ulong[<*>].or(ulong[<*>] x) => $$reduce_or(x); +macro ulong ulong[<*>].xor(ulong[<*>] x) => $$reduce_xor(x); +macro ulong ulong[<*>].max(ulong[<*>] x) => $$reduce_max(x); +macro ulong ulong[<*>].min(ulong[<*>] x) => $$reduce_min(x); -macro uint128 uint128[<*>].sum(uint128[<*>] x) = $$reduce_add(x); -macro uint128 uint128[<*>].product(uint128[<*>] x) = $$reduce_mul(x); -macro uint128 uint128[<*>].and(uint128[<*>] x) = $$reduce_and(x); -macro uint128 uint128[<*>].or(uint128[<*>] x) = $$reduce_or(x); -macro uint128 uint128[<*>].xor(uint128[<*>] x) = $$reduce_xor(x); -macro uint128 uint128[<*>].max(uint128[<*>] x) = $$reduce_max(x); -macro uint128 uint128[<*>].min(uint128[<*>] x) = $$reduce_min(x); +macro uint128 uint128[<*>].sum(uint128[<*>] x) => $$reduce_add(x); +macro uint128 uint128[<*>].product(uint128[<*>] x) => $$reduce_mul(x); +macro uint128 uint128[<*>].and(uint128[<*>] x) => $$reduce_and(x); +macro uint128 uint128[<*>].or(uint128[<*>] x) => $$reduce_or(x); +macro uint128 uint128[<*>].xor(uint128[<*>] x) => $$reduce_xor(x); +macro uint128 uint128[<*>].max(uint128[<*>] x) => $$reduce_max(x); +macro uint128 uint128[<*>].min(uint128[<*>] x) => $$reduce_min(x); /** * @checked x & 1 diff --git a/lib/std/math/math.complex.c3 b/lib/std/math/math.complex.c3 index ea2eda2ad..7d51ad3bc 100644 --- a/lib/std/math/math.complex.c3 +++ b/lib/std/math/math.complex.c3 @@ -10,18 +10,15 @@ union Complex } -macro Complex identity() = { 1, 0 }; -macro Complex Complex.add(Complex a, Complex b) = Complex { .v = a.v + b.v }; -macro Complex Complex.add_each(Complex a, Real b) = Complex { .v = a.v + b }; -macro Complex Complex.sub(Complex a, Complex b) = Complex { .v = a.v - b.v }; -macro Complex Complex.sub_each(Complex a, Real b) = Complex { .v = a.v - b }; -macro Complex Complex.scale(Complex a, Real s) = Complex { .v = a.v * s }; -macro Complex Complex.mul(Complex a, Complex b) -{ - return { .r = a.r * b.r - a.c * b.c, .c = a.r * b.c + b.r * a.c }; -} +macro Complex identity() => { 1, 0 }; +macro Complex Complex.add(Complex a, Complex b) => Complex { .v = a.v + b.v }; +macro Complex Complex.add_each(Complex a, Real b) => Complex { .v = a.v + b }; +macro Complex Complex.sub(Complex a, Complex b) => Complex { .v = a.v - b.v }; +macro Complex Complex.sub_each(Complex a, Real b) => Complex { .v = a.v - b }; +macro Complex Complex.scale(Complex a, Real s) => Complex { .v = a.v * s }; +macro Complex Complex.mul(Complex a, Complex b) => { a.r * b.r - a.c * b.c, a.r * b.c + b.r * a.c }; macro Complex Complex.div(Complex a, Complex b) { - Real div = b.r * b.r + b.c * b.c; - return Complex { .r = (a.r * b.r + a.c * b.c) / div, .c = (a.c * b.r - a.r * b.c) / div }; + Real div = b.v.dot(b.v); + return Complex{ (a.r * b.r + a.c * b.c) / div, (a.c * b.r - a.r * b.c) / div }; } diff --git a/lib/std/math/math.matrix.c3 b/lib/std/math/math.matrix.c3 index 8d9b3f0e3..9211cd416 100644 --- a/lib/std/math/math.matrix.c3 +++ b/lib/std/math/math.matrix.c3 @@ -120,17 +120,17 @@ fn Matrix4x4 Matrix4x4.mul(Matrix4x4* a, Matrix4x4 b) }; } -fn Matrix2x2 Matrix2x2.component_mul(Matrix2x2* mat, Real s) = matrix_component_mul(mat, s); -fn Matrix3x3 Matrix3x3.component_mul(Matrix3x3* mat, Real s) = matrix_component_mul(mat, s); -fn Matrix4x4 Matrix4x4.component_mul(Matrix4x4* mat, Real s) = matrix_component_mul(mat, s); +fn Matrix2x2 Matrix2x2.component_mul(Matrix2x2* mat, Real s) => matrix_component_mul(mat, s); +fn Matrix3x3 Matrix3x3.component_mul(Matrix3x3* mat, Real s) => matrix_component_mul(mat, s); +fn Matrix4x4 Matrix4x4.component_mul(Matrix4x4* mat, Real s) => matrix_component_mul(mat, s); -fn Matrix2x2 Matrix2x2.add(Matrix2x2* mat, Matrix2x2 mat2) = matrix_add(mat, mat2); -fn Matrix3x3 Matrix3x3.add(Matrix3x3* mat, Matrix3x3 mat2) = matrix_add(mat, mat2); -fn Matrix4x4 Matrix4x4.add(Matrix4x4* mat, Matrix4x4 mat2) = matrix_add(mat, mat2); +fn Matrix2x2 Matrix2x2.add(Matrix2x2* mat, Matrix2x2 mat2) => matrix_add(mat, mat2); +fn Matrix3x3 Matrix3x3.add(Matrix3x3* mat, Matrix3x3 mat2) => matrix_add(mat, mat2); +fn Matrix4x4 Matrix4x4.add(Matrix4x4* mat, Matrix4x4 mat2) => matrix_add(mat, mat2); -fn Matrix2x2 Matrix2x2.sub(Matrix2x2* mat, Matrix2x2 mat2) = matrix_sub(mat, mat2); -fn Matrix3x3 Matrix3x3.sub(Matrix3x3* mat, Matrix3x3 mat2) = matrix_sub(mat, mat2); -fn Matrix4x4 Matrix4x4.sub(Matrix4x4* mat, Matrix4x4 mat2) = matrix_sub(mat, mat2); +fn Matrix2x2 Matrix2x2.sub(Matrix2x2* mat, Matrix2x2 mat2) => matrix_sub(mat, mat2); +fn Matrix3x3 Matrix3x3.sub(Matrix3x3* mat, Matrix3x3 mat2) => matrix_sub(mat, mat2); +fn Matrix4x4 Matrix4x4.sub(Matrix4x4* mat, Matrix4x4 mat2) => matrix_sub(mat, mat2); @@ -370,9 +370,9 @@ fn Matrix3x3 Matrix3x3.scale(Matrix3x3* m, Real[<2>] v) }); } -fn Real Matrix2x2.trace(Matrix2x2* m) = m.m00 + m.m11; -fn Real Matrix3x3.trace(Matrix3x3* m) = m.m00 + m.m11 + m.m22; -fn Real Matrix4x4.trace(Matrix4x4* m) = m.m00 + m.m11 + m.m22 + m.m33; +fn Real Matrix2x2.trace(Matrix2x2* m) => m.m00 + m.m11; +fn Real Matrix3x3.trace(Matrix3x3* m) => m.m00 + m.m11 + m.m22; +fn Real Matrix4x4.trace(Matrix4x4* m) => m.m00 + m.m11 + m.m22 + m.m33; fn Matrix4x4 Matrix4x4.scale(Matrix4x4* m, Real[<3>] v) { diff --git a/lib/std/math/math_easings.c3 b/lib/std/math/math_easings.c3 index c17db97be..a6c67d2fa 100644 --- a/lib/std/math/math_easings.c3 +++ b/lib/std/math/math_easings.c3 @@ -36,19 +36,19 @@ module std::math::easing; */ // Linear Easing functions -fn float linear_none(float t, float b, float c, float d) @inline = c * t / d + b; -fn float linear_in(float t, float b, float c, float d) @inline = c * t / d + b; -fn float linear_out(float t, float b, float c, float d) @inline = c * t / d + b; -fn float linear_inout(float t, float b, float c, float d) @inline = c * t / d + b; +fn float linear_none(float t, float b, float c, float d) @inline => c * t / d + b; +fn float linear_in(float t, float b, float c, float d) @inline => c * t / d + b; +fn float linear_out(float t, float b, float c, float d) @inline => c * t / d + b; +fn float linear_inout(float t, float b, float c, float d) @inline => c * t / d + b; // Sine Easing functions -fn float sine_in(float t, float b, float c, float d) @inline = -c * math::cos(t / d * (float)math::PI_2) + c + b; -fn float sine_out(float t, float b, float c, float d) @inline = c * math::sin(t / d * (float)math::PI_2) + b; -fn float sine_inout(float t, float b, float c, float d) @inline = (-c / 2) * (math::cos((float)math::PI * t / d) - 1) + b; +fn float sine_in(float t, float b, float c, float d) @inline => -c * math::cos(t / d * (float)math::PI_2) + c + b; +fn float sine_out(float t, float b, float c, float d) @inline => c * math::sin(t / d * (float)math::PI_2) + b; +fn float sine_inout(float t, float b, float c, float d) @inline => (-c / 2) * (math::cos((float)math::PI * t / d) - 1) + b; // Circular Easing functions -fn float circ_in(float t, float b, float c, float d) @inline = -c * (math::sqrt(1 - sq(t / d)) - 1) + b; -fn float circ_out(float t, float b, float c, float d) @inline = c * math::sqrt(1 - sq(t / d - 1)) + b; +fn float circ_in(float t, float b, float c, float d) @inline => -c * (math::sqrt(1 - sq(t / d)) - 1) + b; +fn float circ_out(float t, float b, float c, float d) @inline => c * math::sqrt(1 - sq(t / d - 1)) + b; fn float circ_inout(float t, float b, float c, float d) @inline { t /= d / 2; @@ -58,8 +58,8 @@ fn float circ_inout(float t, float b, float c, float d) @inline } // Cubic Easing functions -fn float cubic_in(float t, float b, float c, float d) @inline = c * cube(t / d) + b; -fn float cubic_out(float t, float b, float c, float d) @inline = c * (cube(t / d - 1) + 1) + b; +fn float cubic_in(float t, float b, float c, float d) @inline => c * cube(t / d) + b; +fn float cubic_out(float t, float b, float c, float d) @inline => c * (cube(t / d - 1) + 1) + b; fn float cubic_inout(float t, float b, float c, float d) @inline { t /= d / 2; @@ -69,7 +69,7 @@ fn float cubic_inout(float t, float b, float c, float d) @inline } // Quadratic Easing functions -fn float quad_in(float t, float b, float c, float d) @inline = c * sq(t / d) + b; +fn float quad_in(float t, float b, float c, float d) @inline => c * sq(t / d) + b; fn float quad_out(float t, float b, float c, float d) @inline { t /= d; @@ -85,7 +85,7 @@ fn float quad_inout(float t, float b, float c, float d) @inline } // Exponential Easing functions -fn float expo_in(float t, float b, float c, float d) @inline = t ? b : c * math::pow(2.0f, 10 * (t / d - 1)) + b; +fn float expo_in(float t, float b, float c, float d) @inline => t ? b : c * math::pow(2.0f, 10 * (t / d - 1)) + b; fn float expo_out(float t, float b, float c, float d) @inline { return (t == d) ? b + c : c * (-math::pow(2.0f, -10 * t / d) + 1) + b; @@ -145,7 +145,7 @@ fn float bounce_out(float t, float b, float c, float d) @inline } } -fn float bounce_in(float t, float b, float c, float d) @inline = c - bounce_out(d - t, 0, c, d) + b; +fn float bounce_in(float t, float b, float c, float d) @inline => c - bounce_out(d - t, 0, c, d) + b; fn float bounce_inout(float t, float b, float c, float d) @inline { return t < d / 2 @@ -196,6 +196,6 @@ fn float elastic_inout(float t, float b, float c, float d) @inline : a * math::pow(2.0f, -10 * t) * math::sin((t * d - s) * (2 * (float)math::PI) / p) * 0.5f + c + b; } -private macro sq(x) = x * x; -private macro cube(x) = x * x * x; +private macro sq(x) => x * x; +private macro cube(x) => x * x * x; diff --git a/lib/std/math/math_i128.c3 b/lib/std/math/math_i128.c3 index e16586e3c..3aad9c13a 100644 --- a/lib/std/math/math_i128.c3 +++ b/lib/std/math/math_i128.c3 @@ -70,14 +70,14 @@ fn int128 __modti3(int128 a, int128 b) @extname("__modti3") @weak return __umodti3(unsigned_a, unsigned_b) ^ sign + (-sign); } -fn float __floattisf(int128 a) @extname("__floattisf") @weak = float_from_i128(float, a); -fn double __floattidf(int128 a) @extname("__floattidf") @weak = float_from_i128(double, a); -fn float __floatuntisf(uint128 a) @extname("__floatuntisf") @weak = float_from_u128(float, a); -fn double __floatuntidf(uint128 a) @extname("__floatuntidf") @weak = float_from_u128(double, a); -fn uint128 __fixunsdfti(double a) @weak @extname("__fixunsdfti") = fixuint(a); -fn uint128 __fixunssfti(float a) @weak @extname("__fixunssfti") = fixuint(a); -fn int128 __fixdfti(double a) @weak @extname("__fixdfti") = fixint(a); -fn int128 __fixsfti(float a) @weak @extname("__fixsfti") = fixint(a); +fn float __floattisf(int128 a) @extname("__floattisf") @weak => float_from_i128(float, a); +fn double __floattidf(int128 a) @extname("__floattidf") @weak => float_from_i128(double, a); +fn float __floatuntisf(uint128 a) @extname("__floatuntisf") @weak => float_from_u128(float, a); +fn double __floatuntidf(uint128 a) @extname("__floatuntidf") @weak => float_from_u128(double, a); +fn uint128 __fixunsdfti(double a) @weak @extname("__fixunsdfti") => fixuint(a); +fn uint128 __fixunssfti(float a) @weak @extname("__fixunssfti") => fixuint(a); +fn int128 __fixdfti(double a) @weak @extname("__fixdfti") => fixint(a); +fn int128 __fixsfti(float a) @weak @extname("__fixsfti") => fixint(a); private macro float_from_i128($Type, a) diff --git a/lib/std/math/math_quaternion.c3 b/lib/std/math/math_quaternion.c3 index 009110359..1ed0f9ecd 100644 --- a/lib/std/math/math_quaternion.c3 +++ b/lib/std/math/math_quaternion.c3 @@ -9,16 +9,16 @@ union Quaternion Real[<4>] v; } -macro Quaternion identity() = { 0, 0, 0, 1 }; -macro Quaternion Quaternion.add(Quaternion a, Quaternion b) = Quaternion { .v = a.v + b.v }; -macro Quaternion Quaternion.add_each(Quaternion a, Real b) = Quaternion { .v = a.v + b }; -macro Quaternion Quaternion.sub(Quaternion a, Quaternion b) = Quaternion { .v = a.v - b.v }; -macro Quaternion Quaternion.sub_each(Quaternion a, Real b) = Quaternion { .v = a.v - b }; -macro Quaternion Quaternion.scale(Quaternion a, Real s) = Quaternion { .v = a.v * s }; -macro Quaternion Quaternion.normalize(Quaternion q) = { .v = q.v.normalize() }; -macro Real Quaternion.length(Quaternion q) = q.v.length(); -macro Quaternion Quaternion.lerp(Quaternion q1, Quaternion q2, Real amount) = { .v = q1.v.lerp(q2.v, amount) }; -fn Quaternion Quaternion.nlerp(Quaternion q1, Quaternion q2, Real amount) = { .v = q1.v.lerp(q2.v, amount).normalize() }; +macro Quaternion identity() => { 0, 0, 0, 1 }; +macro Quaternion Quaternion.add(Quaternion a, Quaternion b) => Quaternion { .v = a.v + b.v }; +macro Quaternion Quaternion.add_each(Quaternion a, Real b) => Quaternion { .v = a.v + b }; +macro Quaternion Quaternion.sub(Quaternion a, Quaternion b) => Quaternion { .v = a.v - b.v }; +macro Quaternion Quaternion.sub_each(Quaternion a, Real b) => Quaternion { .v = a.v - b }; +macro Quaternion Quaternion.scale(Quaternion a, Real s) => Quaternion { .v = a.v * s }; +macro Quaternion Quaternion.normalize(Quaternion q) => { .v = q.v.normalize() }; +macro Real Quaternion.length(Quaternion q) => q.v.length(); +macro Quaternion Quaternion.lerp(Quaternion q1, Quaternion q2, Real amount) => { .v = q1.v.lerp(q2.v, amount) }; +fn Quaternion Quaternion.nlerp(Quaternion q1, Quaternion q2, Real amount) => { .v = q1.v.lerp(q2.v, amount).normalize() }; fn Quaternion Quaternion.invert(Quaternion q) { diff --git a/lib/std/math/math_vector.c3 b/lib/std/math/math_vector.c3 index 2485063e5..3d77c8015 100644 --- a/lib/std/math/math_vector.c3 +++ b/lib/std/math/math_vector.c3 @@ -9,74 +9,74 @@ define Vec2 = double[<2>]; define Vec3 = double[<3>]; define Vec4 = double[<4>]; -macro Vec2f.length_sq(Vec2f v) = v.dot(v); -macro Vec3f.length_sq(Vec3f v) = v.dot(v); -macro Vec4f.length_sq(Vec4f v) = v.dot(v); -macro Vec2.length_sq(Vec2 v) = v.dot(v); -macro Vec3.length_sq(Vec3 v) = v.dot(v); -macro Vec4.length_sq(Vec4 v) = v.dot(v); +macro Vec2f.length_sq(Vec2f v) => v.dot(v); +macro Vec3f.length_sq(Vec3f v) => v.dot(v); +macro Vec4f.length_sq(Vec4f v) => v.dot(v); +macro Vec2.length_sq(Vec2 v) => v.dot(v); +macro Vec3.length_sq(Vec3 v) => v.dot(v); +macro Vec4.length_sq(Vec4 v) => v.dot(v); -macro Vec2f.distance_sq(Vec2f v1, Vec2f v2) = (v1 - v2).length_sq(); -macro Vec3f.distance_sq(Vec3f v1, Vec3f v2) = (v1 - v2).length_sq(); -macro Vec4f.distance_sq(Vec4f v1, Vec4f v2) = (v1 - v2).length_sq(); -macro Vec2.distance_sq(Vec2 v1, Vec2 v2) = (v1 - v2).length_sq(); -macro Vec3.distance_sq(Vec3 v1, Vec3 v2) = (v1 - v2).length_sq(); -macro Vec4.distance_sq(Vec4 v1, Vec4 v2) = (v1 - v2).length_sq(); +macro Vec2f.distance_sq(Vec2f v1, Vec2f v2) => (v1 - v2).length_sq(); +macro Vec3f.distance_sq(Vec3f v1, Vec3f v2) => (v1 - v2).length_sq(); +macro Vec4f.distance_sq(Vec4f v1, Vec4f v2) => (v1 - v2).length_sq(); +macro Vec2.distance_sq(Vec2 v1, Vec2 v2) => (v1 - v2).length_sq(); +macro Vec3.distance_sq(Vec3 v1, Vec3 v2) => (v1 - v2).length_sq(); +macro Vec4.distance_sq(Vec4 v1, Vec4 v2) => (v1 - v2).length_sq(); -macro Vec2f.transform(Vec2f v, Matrix4f mat) = transform2(v, mat); -macro Vec2f.rotate(Vec2f v, float angle) = rotate(v, angle); -macro Vec2f.angle(Vec2f v1, Vec2f v2) = math::atan2(v2[1], v2[0]) - math::atan2(v1[1], v2[0]); +macro Vec2f.transform(Vec2f v, Matrix4f mat) => transform2(v, mat); +macro Vec2f.rotate(Vec2f v, float angle) => rotate(v, angle); +macro Vec2f.angle(Vec2f v1, Vec2f v2) => math::atan2(v2[1], v2[0]) - math::atan2(v1[1], v2[0]); -macro Vec2.transform(Vec2 v, Matrix4 mat) = transform2(v, mat); -macro Vec2.rotate(Vec2 v, double angle) = rotate(v, angle); -macro Vec2.angle(Vec2 v1, Vec2 v2) = math::atan2(v2[1], v2[0]) - math::atan2(v1[1], v2[0]); +macro Vec2.transform(Vec2 v, Matrix4 mat) => transform2(v, mat); +macro Vec2.rotate(Vec2 v, double angle) => rotate(v, angle); +macro Vec2.angle(Vec2 v1, Vec2 v2) => math::atan2(v2[1], v2[0]) - math::atan2(v1[1], v2[0]); -macro Vec2f.clamp_mag(Vec2f v, float min, float max) = clamp_magnitude(v, min, max); -macro Vec3f.clamp_mag(Vec3f v, float min, float max) = clamp_magnitude(v, min, max); -macro Vec4f.clamp_mag(Vec4f v, float min, float max) = clamp_magnitude(v, min, max); -macro Vec2.clamp_mag(Vec2 v, double min, double max) = clamp_magnitude(v, min, max); -macro Vec3.clamp_mag(Vec3 v, double min, double max) = clamp_magnitude(v, min, max); -macro Vec4.clamp_mag(Vec4 v, double min, double max) = clamp_magnitude(v, min, max); +macro Vec2f.clamp_mag(Vec2f v, float min, float max) => clamp_magnitude(v, min, max); +macro Vec3f.clamp_mag(Vec3f v, float min, float max) => clamp_magnitude(v, min, max); +macro Vec4f.clamp_mag(Vec4f v, float min, float max) => clamp_magnitude(v, min, max); +macro Vec2.clamp_mag(Vec2 v, double min, double max) => clamp_magnitude(v, min, max); +macro Vec3.clamp_mag(Vec3 v, double min, double max) => clamp_magnitude(v, min, max); +macro Vec4.clamp_mag(Vec4 v, double min, double max) => clamp_magnitude(v, min, max); -fn Vec2f Vec2f.towards(Vec2f v, Vec2f target, float max_distance) = towards(v, target, max_distance); -fn Vec3f Vec3f.towards(Vec3f v, Vec3f target, float max_distance) = towards(v, target, max_distance); -fn Vec4f Vec4f.towards(Vec4f v, Vec4f target, float max_distance) = towards(v, target, max_distance); -fn Vec2 Vec2.towards(Vec2 v, Vec2 target, double max_distance) = towards(v, target, max_distance); -fn Vec3 Vec3.towards(Vec3 v, Vec3 target, double max_distance) = towards(v, target, max_distance); -fn Vec4 Vec4.towards(Vec4 v, Vec4 target, double max_distance) = towards(v, target, max_distance); +fn Vec2f Vec2f.towards(Vec2f v, Vec2f target, float max_distance) => towards(v, target, max_distance); +fn Vec3f Vec3f.towards(Vec3f v, Vec3f target, float max_distance) => towards(v, target, max_distance); +fn Vec4f Vec4f.towards(Vec4f v, Vec4f target, float max_distance) => towards(v, target, max_distance); +fn Vec2 Vec2.towards(Vec2 v, Vec2 target, double max_distance) => towards(v, target, max_distance); +fn Vec3 Vec3.towards(Vec3 v, Vec3 target, double max_distance) => towards(v, target, max_distance); +fn Vec4 Vec4.towards(Vec4 v, Vec4 target, double max_distance) => towards(v, target, max_distance); -fn Vec3f Vec3f.cross(Vec3f v1, Vec3f v2) = cross3(v1, v2); -fn Vec3 Vec3.cross(Vec3 v1, Vec3 v2) = cross3(v1, v2); +fn Vec3f Vec3f.cross(Vec3f v1, Vec3f v2) => cross3(v1, v2); +fn Vec3 Vec3.cross(Vec3 v1, Vec3 v2) => cross3(v1, v2); -fn Vec3f Vec3f.perpendicular(Vec3f v) = perpendicular3(v); -fn Vec3 Vec3.perpendicular(Vec3 v) = perpendicular3(v); +fn Vec3f Vec3f.perpendicular(Vec3f v) => perpendicular3(v); +fn Vec3 Vec3.perpendicular(Vec3 v) => perpendicular3(v); -fn Vec3f Vec3f.barycenter(Vec3f p, Vec3f a, Vec3f b, Vec3f c) = barycenter3(p, a, b, c); -fn Vec3 Vec3.barycenter(Vec3 p, Vec3 a, Vec3 b, Vec3 c) = barycenter3(p, a, b, c); +fn Vec3f Vec3f.barycenter(Vec3f p, Vec3f a, Vec3f b, Vec3f c) => barycenter3(p, a, b, c); +fn Vec3 Vec3.barycenter(Vec3 p, Vec3 a, Vec3 b, Vec3 c) => barycenter3(p, a, b, c); -fn Vec3f Vec3f.transform(Vec3f v, Matrix4f mat) = transform3(v, mat); -fn Vec3 Vec3.transform(Vec3 v, Matrix4 mat) = transform3(v, mat); +fn Vec3f Vec3f.transform(Vec3f v, Matrix4f mat) => transform3(v, mat); +fn Vec3 Vec3.transform(Vec3 v, Matrix4 mat) => transform3(v, mat); -fn float Vec3f.angle(Vec3f v1, Vec3f v2) = angle3(v1, v2); -fn double Vec3.angle(Vec3 v1, Vec3 v2) = angle3(v1, v2); +fn float Vec3f.angle(Vec3f v1, Vec3f v2) => angle3(v1, v2); +fn double Vec3.angle(Vec3 v1, Vec3 v2) => angle3(v1, v2); -fn Vec3f Vec3f.refract(Vec3f v, Vec3f n, float r) = refract3(v, n, r); -fn Vec3 Vec3.refract(Vec3 v, Vec3 n, double r) = refract3(v, n, r); +fn Vec3f Vec3f.refract(Vec3f v, Vec3f n, float r) => refract3(v, n, r); +fn Vec3 Vec3.refract(Vec3 v, Vec3 n, double r) => refract3(v, n, r); -fn void ortho_normalize(Vec3f* v1, Vec3f* v2) = ortho_normalize3(v1, v2); -fn void ortho_normalized(Vec3* v1, Vec3* v2) = ortho_normalize3(v1, v2); +fn void ortho_normalize(Vec3f* v1, Vec3f* v2) => ortho_normalize3(v1, v2); +fn void ortho_normalized(Vec3* v1, Vec3* v2) => ortho_normalize3(v1, v2); -fn Matrix4f matrix4f_look_at(Vec3f eye, Vec3f target, Vec3f up) = matrix_look_at(Matrix4f, eye, target, up); -fn Matrix4 matrix4_look_at(Vec3 eye, Vec3 target, Vec3 up) = matrix_look_at(Matrix4, eye, target, up); +fn Matrix4f matrix4f_look_at(Vec3f eye, Vec3f target, Vec3f up) => matrix_look_at(Matrix4f, eye, target, up); +fn Matrix4 matrix4_look_at(Vec3 eye, Vec3 target, Vec3 up) => matrix_look_at(Matrix4, eye, target, up); -fn Vec3f Vec3f.rotate_quat(Vec3f v, Quaternionf q) = rotate_by_quat3(v, q); -fn Vec3 Vec3.rotate_quat(Vec3 v, Quaternion q) = rotate_by_quat3(v, q); +fn Vec3f Vec3f.rotate_quat(Vec3f v, Quaternionf q) => rotate_by_quat3(v, q); +fn Vec3 Vec3.rotate_quat(Vec3 v, Quaternion q) => rotate_by_quat3(v, q); -fn Vec3f Vec3f.rotate_axis(Vec3f v, Vec3f axis, float angle) = rotate_axis_angle(v, axis, angle); -fn Vec3 Vec3.rotate_axis(Vec3 v, Vec3 axis, double angle) = rotate_axis_angle(v, axis, angle); +fn Vec3f Vec3f.rotate_axis(Vec3f v, Vec3f axis, float angle) => rotate_axis_angle(v, axis, angle); +fn Vec3 Vec3.rotate_axis(Vec3 v, Vec3 axis, double angle) => rotate_axis_angle(v, axis, angle); -fn Vec3f Vec3f.unproject(Vec3f v, Matrix4f projection, Matrix4f view) = unproject3(v, projection, view); -fn Vec3 Vec3.unproject(Vec3 v, Matrix4 projection, Matrix4 view) = unproject3(v, projection, view); +fn Vec3f Vec3f.unproject(Vec3f v, Matrix4f projection, Matrix4f view) => unproject3(v, projection, view); +fn Vec3 Vec3.unproject(Vec3 v, Matrix4 projection, Matrix4 view) => unproject3(v, projection, view); private macro towards(v, target, max_distance) { diff --git a/lib/std/net/os/win32.c3 b/lib/std/net/os/win32.c3 index b109e5f46..162572a66 100644 --- a/lib/std/net/os/win32.c3 +++ b/lib/std/net/os/win32.c3 @@ -28,6 +28,6 @@ extern fn int wsa_startup(int, void*) @extname("WSAStartup"); extern fn int ioctlsocket(NativeSocket, long cmd, ulong *argp); extern fn int closesocket(NativeSocket); -macro NativeSocket.close(NativeSocket this) = closesocket(this); +macro NativeSocket.close(NativeSocket this) => closesocket(this); $endif; \ No newline at end of file diff --git a/lib/std/os/macos/cf_allocator.c3 b/lib/std/os/macos/cf_allocator.c3 index 4924f6d93..a2372cfeb 100644 --- a/lib/std/os/macos/cf_allocator.c3 +++ b/lib/std/os/macos/cf_allocator.c3 @@ -6,11 +6,11 @@ define CFAllocatorRef = distinct void*; define CFAllocatorContextRef = distinct void*; define CFOptionFlags = usz; -macro CFAllocatorRef default_allocator() = _macos_CFAllocatorGetDefault(); -macro void CFAllocatorRef.dealloc(CFAllocatorRef allocator, void* ptr) = _macos_CFAllocatorDeallocate(allocator, ptr); -macro void* CFAllocatorRef.alloc(CFAllocatorRef allocator, usz size) = _macos_CFAllocatorAllocate(allocator, size, 0); -macro usz CFAllocatorRef.get_preferred_size(CFAllocatorRef allocator, usz req_size) = _macos_CFAllocatorGetPreferredSizeForSize(allocator, req_size, 0); -macro void CFAllocatorRef.set_default(CFAllocatorRef allocator) = _macos_CFAllocatorSetDefault(allocator); +macro CFAllocatorRef default_allocator() => _macos_CFAllocatorGetDefault(); +macro void CFAllocatorRef.dealloc(CFAllocatorRef allocator, void* ptr) => _macos_CFAllocatorDeallocate(allocator, ptr); +macro void* CFAllocatorRef.alloc(CFAllocatorRef allocator, usz size) => _macos_CFAllocatorAllocate(allocator, size, 0); +macro usz CFAllocatorRef.get_preferred_size(CFAllocatorRef allocator, usz req_size) => _macos_CFAllocatorGetPreferredSizeForSize(allocator, req_size, 0); +macro void CFAllocatorRef.set_default(CFAllocatorRef allocator) => _macos_CFAllocatorSetDefault(allocator); extern fn CFAllocatorRef _macos_CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorContextRef context) @extname("CFAllocatorCreate"); extern fn void _macos_CFAllocatorDeallocate(CFAllocatorRef allocator, void* ptr) @extname("CFAllocatorDeallocate"); diff --git a/lib/std/os/macos/objc.c3 b/lib/std/os/macos/objc.c3 index 48d9b16d5..784a78859 100644 --- a/lib/std/os/macos/objc.c3 +++ b/lib/std/os/macos/objc.c3 @@ -12,15 +12,15 @@ fault ObjcFailure CLASS_NOT_FOUND } -macro char* Class.name(Class cls) = _macos_class_getName(cls); -macro Class Class.superclass(Class cls) = _macos_class_getSuperclass(cls); -macro bool Class.responds_to(Class cls, Selector sel) = _macos_class_respondsToSelector(cls, sel); -macro Method Class.method(Class cls, Selector name) = _macos_class_getClassMethod(cls, name); +macro char* Class.name(Class cls) => _macos_class_getName(cls); +macro Class Class.superclass(Class cls) => _macos_class_getSuperclass(cls); +macro bool Class.responds_to(Class cls, Selector sel) => _macos_class_respondsToSelector(cls, sel); +macro Method Class.method(Class cls, Selector name) => _macos_class_getClassMethod(cls, name); -macro bool Selector.equals(Selector a, Selector b) = a == b; -macro bool Class.equals(Class a, Class b) = a == b; +macro bool Selector.equals(Selector a, Selector b) => a == b; +macro bool Class.equals(Class a, Class b) => a == b; -macro Selector selector_register(char* c) = _macos_sel_registerName(c); +macro Selector selector_register(char* c) => _macos_sel_registerName(c); macro Class! class_by_name(char* c) { Class cls = _macos_objc_lookUpClass(c); diff --git a/lib/std/threads/thread.c3 b/lib/std/threads/thread.c3 index 8d4ae2cf2..98e4af76c 100644 --- a/lib/std/threads/thread.c3 +++ b/lib/std/threads/thread.c3 @@ -36,17 +36,17 @@ fault ThreadFault INTERRUPTED, } -macro void! Mutex.init(Mutex* mutex, MutexType type) = NativeMutex.init((NativeMutex*)mutex, type); -macro void! Mutex.destroy(Mutex* mutex) = NativeMutex.destroy((NativeMutex*)mutex); -macro void! Mutex.lock(Mutex* mutex) = NativeMutex.lock((NativeMutex*)mutex); -macro void! Mutex.lock_timeout(Mutex* mutex, ulong ms) = NativeMutex.lock((NativeMutex*)mutex, ms); -macro bool Mutex.try_lock(Mutex* mutex) = NativeMutex.try_lock((NativeMutex*)mutex); -macro bool Mutex.unlock(Mutex* mutex) = NativeMutex.unlock((NativeMutex*)mutex); +macro void! Mutex.init(Mutex* mutex, MutexType type) => NativeMutex.init((NativeMutex*)mutex, type); +macro void! Mutex.destroy(Mutex* mutex) => NativeMutex.destroy((NativeMutex*)mutex); +macro void! Mutex.lock(Mutex* mutex) => NativeMutex.lock((NativeMutex*)mutex); +macro void! Mutex.lock_timeout(Mutex* mutex, ulong ms) => NativeMutex.lock((NativeMutex*)mutex, ms); +macro bool Mutex.try_lock(Mutex* mutex) => NativeMutex.try_lock((NativeMutex*)mutex); +macro bool Mutex.unlock(Mutex* mutex) => NativeMutex.unlock((NativeMutex*)mutex); -macro void! ConditionVariable.init(ConditionVariable* cond) = NativeConditionVariable.init((NativeConditionVariable*)cond); -macro void! ConditionVariable.destroy(ConditionVariable* cond) = NativeConditionVariable.destroy((NativeConditionVariable*)cond); -macro void! ConditionVariable.signal(ConditionVariable* cond) = NativeConditionVariable.signal((NativeConditionVariable*)cond); -macro void! ConditionVariable.broadcast(ConditionVariable* cond) = NativeConditionVariable.broadcast((NativeConditionVariable*)cond); +macro void! ConditionVariable.init(ConditionVariable* cond) => NativeConditionVariable.init((NativeConditionVariable*)cond); +macro void! ConditionVariable.destroy(ConditionVariable* cond) => NativeConditionVariable.destroy((NativeConditionVariable*)cond); +macro void! ConditionVariable.signal(ConditionVariable* cond) => NativeConditionVariable.signal((NativeConditionVariable*)cond); +macro void! ConditionVariable.broadcast(ConditionVariable* cond) => NativeConditionVariable.broadcast((NativeConditionVariable*)cond); macro void! ConditionVariable.wait(ConditionVariable* cond, Mutex* mutex) { return NativeConditionVariable.wait((NativeConditionVariable*)cond, (NativeMutex*)mutex); @@ -57,17 +57,17 @@ macro void! ConditionVariable.wait_timeout(ConditionVariable* cond, Mutex* mutex } -macro void! Thread.create(Thread* thread, ThreadFn thread_fn, void* arg) = NativeThread.create((NativeThread*)thread, thread_fn, arg); -macro void! Thread.detach(Thread thread) = NativeThread.detach((NativeThread)thread); -macro int! Thread.join(Thread thread) = NativeThread.join((NativeThread)thread); -macro bool Thread.equals(Thread thread, Thread other) = NativeThread.equals((NativeThread)this, (NativeThread)other); +macro void! Thread.create(Thread* thread, ThreadFn thread_fn, void* arg) => NativeThread.create((NativeThread*)thread, thread_fn, arg); +macro void! Thread.detach(Thread thread) => NativeThread.detach((NativeThread)thread); +macro int! Thread.join(Thread thread) => NativeThread.join((NativeThread)thread); +macro bool Thread.equals(Thread thread, Thread other) => NativeThread.equals((NativeThread)this, (NativeThread)other); -macro void OnceFlag.call_once(OnceFlag* flag, OnceFn func) = NativeOnceFlag.call_once((NativeOnceFlag*)flag, func); +macro void OnceFlag.call_once(OnceFlag* flag, OnceFn func) => NativeOnceFlag.call_once((NativeOnceFlag*)flag, func); -macro void yield() = os::native_thread_yield(); -macro Thread current() = os::native_thread_current(); -macro void exit(int result) = os::native_thread_exit(result); -macro void! sleep(double s) @maydiscard = os::native_sleep(s); -macro void! sleep_ms(ulong ms) @maydiscard = os::native_sleep_ms(ms); -macro void! sleep_ns(ulong ns) @maydiscard = os::native_sleep_nano(ns); +macro void yield() => os::native_thread_yield(); +macro Thread current() => os::native_thread_current(); +macro void exit(int result) => os::native_thread_exit(result); +macro void! sleep(double s) @maydiscard => os::native_sleep(s); +macro void! sleep_ms(ulong ms) @maydiscard => os::native_sleep_ms(ms); +macro void! sleep_ns(ulong ns) @maydiscard => os::native_sleep_nano(ns); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index b13d30c00..679bef5e3 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -559,6 +559,7 @@ typedef struct bool attr_extname : 1; bool attr_naked : 1; bool attr_test : 1; + Decl** generated_lambda; }; struct { @@ -1139,6 +1140,7 @@ struct Expr_ ExprArgv argv_expr; // 16 ExprGuard rethrow_expr; // 16 Decl *decl_expr; // 8 + Decl *lambda_expr; ExprSliceAssign slice_assign_expr; // 8 ExprBinary binary_expr; // 12 ExprTernary ternary_expr; // 16 @@ -1489,6 +1491,7 @@ typedef struct Module_ Module *top_module; Module **sub_modules; Decl **tests; + Decl **lambdas_to_evaluate; } Module; @@ -1568,6 +1571,7 @@ struct CompilationUnit_ Decl** imports; Decl **types; Decl **functions; + Decl **lambdas; Decl **enums; Decl **attributes; Decl **faulttypes; @@ -1589,6 +1593,7 @@ struct CompilationUnit_ Decl **global_decls; Decl *main_function; HTable local_symbols; + int lambda_count; struct { void *debug_file; @@ -1826,6 +1831,7 @@ typedef struct CopyStruct_ CopyFixup *current_fixup; bool single_static; bool copy_in_use; + bool is_template; } CopyStruct; @@ -2045,10 +2051,13 @@ void copy_begin(void); void copy_end(void); Expr *copy_expr_single(Expr *source_expr); Decl **copy_decl_list_single(Decl **decl_list); +Decl **copy_decl_list_single_for_unit(Decl **decl_list); +Decl *copy_lambda_deep(Decl *decl); Ast *copy_ast_single(Ast *source_ast); Decl **copy_decl_list_macro(Decl **decl_list); Ast *copy_ast_macro(Ast *source_ast); Ast *copy_ast_defer(Ast *source_ast); +TypeInfo *copy_type_info_single(TypeInfo *type_info); void init_asm(void); AsmRegister *asm_reg_by_name(const char *name); @@ -3276,3 +3285,4 @@ INLINE bool expr_is_const_member(Expr *expr) { return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_MEMBER; } + diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 88079f36c..52ba6c392 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -165,6 +165,14 @@ Ast *copy_ast_single(Ast *source_ast) return ast; } +TypeInfo *copy_type_info_single(TypeInfo *type_info) +{ + copy_begin(); + TypeInfo *type_info_copy = copy_type_info(©_struct, type_info); + copy_end(); + return type_info_copy; +} + Ast *copy_ast_macro(Ast *source_ast) { assert(copy_struct.copy_in_use); @@ -293,6 +301,12 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) MACRO_COPY_DECL_LIST(expr->body_expansion_expr.declarations); MACRO_COPY_ASTID(expr->body_expansion_expr.first_stmt); return expr; + case EXPR_LAMBDA: + if (copy_struct.is_template) + { + MACRO_COPY_DECL(expr->decl_expr); + } + return expr; case EXPR_SWIZZLE: MACRO_COPY_EXPRID(expr->swizzle_expr.parent); return expr; @@ -687,6 +701,28 @@ Decl **copy_decl_list_single(Decl **decl_list) return result; } +Decl **copy_decl_list_single_for_unit(Decl **decl_list) +{ + bool old_is_template = copy_struct.is_template; + copy_struct.is_template = true; + copy_begin(); + Decl **result = copy_decl_list_macro(decl_list); + copy_end(); + copy_struct.is_template = old_is_template; + return result; +} + +Decl *copy_lambda_deep(Decl *decl) +{ + bool old_is_template = copy_struct.is_template; + copy_struct.is_template = true; + copy_begin(); + Decl *result = copy_decl(©_struct, decl); + copy_end(); + copy_struct.is_template = old_is_template; + return result; +} + Decl **copy_decl_list(CopyStruct *c, Decl **decl_list) { Decl **result = NULL; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 5581b63ee..44f873d21 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -240,6 +240,7 @@ typedef enum EXPR_HASH_IDENT, EXPR_IDENTIFIER, EXPR_INITIALIZER_LIST, + EXPR_LAMBDA, EXPR_MACRO_BLOCK, EXPR_MACRO_BODY_EXPANSION, EXPR_NOP, diff --git a/src/compiler/expr.c b/src/compiler/expr.c index 6110f1691..50ab31151 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -136,6 +136,7 @@ bool expr_may_addr(Expr *expr) case EXPR_VARIANTSWITCH: case EXPR_VASPLAT: case EXPR_SWIZZLE: + case EXPR_LAMBDA: return false; } UNREACHABLE @@ -201,6 +202,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) case EXPR_OPERATOR_CHARS: case EXPR_STRINGIFY: case EXPR_CT_CHECKS: + case EXPR_LAMBDA: return true; case EXPR_COND: return expr_list_is_constant_eval(expr->cond_expr, eval_kind); @@ -664,6 +666,7 @@ bool expr_is_pure(Expr *expr) case EXPR_CT_ARG: case EXPR_OPERATOR_CHARS: case EXPR_CT_CHECKS: + case EXPR_LAMBDA: return true; case EXPR_VASPLAT: return true; diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c index d7e0b26bb..5b71d2e42 100644 --- a/src/compiler/lexer.c +++ b/src/compiler/lexer.c @@ -1346,7 +1346,7 @@ static bool lexer_scan_token_inner(Lexer *lexer) case '*': return match(lexer, '=') ? return_token(lexer, TOKEN_MULT_ASSIGN, "*=") : return_token(lexer, TOKEN_STAR, "*"); case '=': - if (match(lexer, '>')) return_token(lexer, TOKEN_IMPLIES, "=>"); + if (match(lexer, '>')) return return_token(lexer, TOKEN_IMPLIES, "=>"); return match(lexer, '=') ? return_token(lexer, TOKEN_EQEQ, "==") : return_token(lexer, TOKEN_EQ, "="); case '^': return match(lexer, '=') ? return_token(lexer, TOKEN_BIT_XOR_ASSIGN, "^=") : return_token(lexer, diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 05a8d1dff..0a3c40ff5 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -1193,6 +1193,10 @@ static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context llvm_emit_function_decl(gen_context, func); FOREACH_END(); + FOREACH_BEGIN(Decl *func, unit->lambdas) + llvm_emit_function_decl(gen_context, func); + FOREACH_END(); + if (active_target.type != TARGET_TYPE_TEST && unit->main_function && unit->main_function->is_synthetic) { llvm_emit_function_decl(gen_context, unit->main_function); @@ -1218,6 +1222,10 @@ static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context if (decl->func_decl.body) llvm_emit_function_body(gen_context, decl); FOREACH_END(); + FOREACH_BEGIN(Decl *func, unit->lambdas) + llvm_emit_function_body(gen_context, func); + FOREACH_END(); + if (active_target.type != TARGET_TYPE_TEST && unit->main_function && unit->main_function->is_synthetic) { llvm_emit_function_body(gen_context, unit->main_function); diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index e8bdc5d29..8c70b8309 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -6108,6 +6108,12 @@ static void llmv_emit_test_hook(GenContext *c, BEValue *value, Expr *expr) llvm_value_set_address_abi_aligned(value, get_global, expr->type); } +static void llvm_emit_lambda(GenContext *c, BEValue *value, Expr *expr) +{ + Decl *decl = expr->lambda_expr; + llvm_value_set(value, llvm_get_ref(c, decl), decl->type); +} + static void llvm_emit_swizzle(GenContext *c, BEValue *value, Expr *expr) { llvm_emit_exprid(c, value, expr->swizzle_expr.parent); @@ -6140,6 +6146,9 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_VASPLAT: case EXPR_CT_CHECKS: UNREACHABLE + case EXPR_LAMBDA: + llvm_emit_lambda(c, value, expr); + return; case EXPR_SWIZZLE: llvm_emit_swizzle(c, value, expr); return; diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index b1af9d0c4..3c040a991 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -335,6 +335,50 @@ static bool parse_param_path(ParseContext *c, DesignatorElement ***path) } } +static Expr *parse_lambda(ParseContext *c, Expr *left) +{ + assert(!left && "Unexpected left hand side"); + Expr *expr = EXPR_NEW_TOKEN(EXPR_LAMBDA); + advance_and_verify(c, TOKEN_FN); + Decl *func = decl_calloc(); + func->decl_kind = DECL_FUNC; + func->visibility = VISIBLE_LOCAL; + func->func_decl.generated_lambda = NULL; + TypeInfo *return_type = NULL; + if (!tok_is(c, TOKEN_LPAREN)) + { + ASSIGN_TYPE_OR_RET(return_type, parse_optional_type(c), poisoned_expr); + } + CONSUME_OR_RET(TOKEN_LPAREN, poisoned_expr); + Decl **params = NULL; + Decl **decls = NULL; + Variadic variadic = VARIADIC_NONE; + int vararg_index = -1; + if (!parse_parameters(c, VISIBLE_LOCAL, &decls, NULL, &variadic, &vararg_index, PARAM_PARSE_LAMBDA)) return false; + CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr); + Signature *sig = &func->func_decl.signature; + sig->vararg_index = vararg_index < 0 ? vec_size(decls) : vararg_index; + sig->params = decls; + sig->rtype = return_type ? type_infoid(return_type) : 0; + sig->variadic = variadic; + if (!parse_attributes(c, &func->attributes)) return poisoned_expr; + + if (tok_is(c, TOKEN_IMPLIES)) + { + ASSIGN_ASTID_OR_RET(func->func_decl.body, + parse_short_body(c, func->func_decl.signature.rtype, false), poisoned_expr); + } + else if (tok_is(c, TOKEN_LBRACE)) + { + ASSIGN_ASTID_OR_RET(func->func_decl.body, parse_compound_stmt(c), poisoned_expr); + } + else + { + SEMA_ERROR_HERE("Expected the beginning of a block or a short statement."); + } + expr->lambda_expr = func; + return expr; +} Expr *parse_vasplat(ParseContext *c) { Expr *expr = EXPR_NEW_TOKEN(EXPR_VASPLAT); @@ -736,7 +780,7 @@ static Expr *parse_call_expr(ParseContext *c, Expr *left) SEMA_ERROR_LAST("Expected an ending ')'. Did you forget a ')' before this ';'?"); return poisoned_expr; } - if (!parse_parameters(c, VISIBLE_LOCAL, &body_args, NULL, NULL, NULL, true)) return poisoned_expr; + if (!parse_parameters(c, VISIBLE_LOCAL, &body_args, NULL, NULL, NULL, PARAM_PARSE_CALL)) return poisoned_expr; } if (!tok_is(c, TOKEN_RPAREN)) { @@ -1781,6 +1825,7 @@ ParseRule rules[TOKEN_EOF + 1] = { [TOKEN_AT_IDENT] = { parse_identifier, NULL, PREC_NONE }, //[TOKEN_HASH_TYPE_IDENT] = { parse_type_identifier, NULL, PREC_NONE } + [TOKEN_FN] = { parse_lambda, NULL, PREC_NONE }, [TOKEN_CT_SIZEOF] = { parse_ct_sizeof, NULL, PREC_NONE }, [TOKEN_CT_ALIGNOF] = { parse_ct_call, NULL, PREC_NONE }, [TOKEN_CT_DEFINED] = { parse_ct_call, NULL, PREC_NONE }, diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index a62e5260d..2db80105d 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -1133,7 +1133,7 @@ static inline bool parse_param_decl(ParseContext *c, Visibility parent_visibilit return true; } -static bool parse_next_is_typed_parameter(ParseContext *c, bool is_body_param) +static bool parse_next_is_typed_parameter(ParseContext *c, ParameterParseKind parse_kind) { switch (c->tok) { @@ -1143,9 +1143,13 @@ static bool parse_next_is_typed_parameter(ParseContext *c, bool is_body_param) } case TYPE_TOKENS: case TOKEN_TYPE_IDENT: + case TOKEN_CT_EVALTYPE: + case TOKEN_CT_TYPEOF: + case TOKEN_CT_TYPEFROM: return true; - case CT_TYPE_TOKENS: - return is_body_param; + case TOKEN_CT_TYPE_IDENT: + case TOKEN_CT_VATYPE: + return parse_kind == PARAM_PARSE_LAMBDA || parse_kind == PARAM_PARSE_CALL; default: return false; } @@ -1162,7 +1166,7 @@ INLINE bool is_end_of_param_list(ParseContext *c) * | ELLIPSIS (CT_TYPE_IDENT | non_type_ident ('=' expr)?)? */ bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref, Decl **body_params, - Variadic *variadic, int *vararg_index_ref, bool is_body_params) + Variadic *variadic, int *vararg_index_ref, ParameterParseKind parse_kind) { Decl** params = NULL; bool var_arg_found = false; @@ -1202,7 +1206,7 @@ bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref // Now we have the following possibilities: "foo", "Foo foo", "Foo... foo", "foo...", "Foo" TypeInfo *type = NULL; - if (parse_next_is_typed_parameter(c, is_body_params)) + if (parse_next_is_typed_parameter(c, parse_kind)) { // Parse the type, ASSIGN_TYPE_OR_RET(type, parse_optional_type(c), false); @@ -1381,7 +1385,7 @@ static inline bool parse_fn_parameter_list(ParseContext *c, Visibility parent_vi CONSUME_OR_RET(TOKEN_LPAREN, false); Variadic variadic = VARIADIC_NONE; int vararg_index = -1; - if (!parse_parameters(c, parent_visibility, &decls, NULL, &variadic, &vararg_index, false)) return false; + if (!parse_parameters(c, parent_visibility, &decls, NULL, &variadic, &vararg_index, PARAM_PARSE_FUNC)) return false; CONSUME_OR_RET(TOKEN_RPAREN, false); signature->vararg_index = vararg_index < 0 ? vec_size(decls) : vararg_index; signature->params = decls; @@ -1629,7 +1633,7 @@ static bool parse_macro_arguments(ParseContext *c, Visibility visibility, Decl * Variadic variadic = VARIADIC_NONE; int vararg_index = -1; Decl **params = NULL; - if (!parse_parameters(c, visibility, ¶ms, NULL, &variadic, &vararg_index, false)) return false; + if (!parse_parameters(c, visibility, ¶ms, NULL, &variadic, &vararg_index, PARAM_PARSE_MACRO)) return false; macro->func_decl.signature.params = params; macro->func_decl.signature.vararg_index = vararg_index < 0 ? vec_size(params) : vararg_index; macro->func_decl.signature.variadic = variadic; @@ -1642,7 +1646,7 @@ static bool parse_macro_arguments(ParseContext *c, Visibility visibility, Decl * TRY_CONSUME_OR_RET(TOKEN_AT_IDENT, "Expected an ending ')' or a block parameter on the format '@block(...).", false); if (try_consume(c, TOKEN_LPAREN)) { - if (!parse_parameters(c, visibility, &body_param->body_params, NULL, NULL, NULL, false)) return false; + if (!parse_parameters(c, visibility, &body_param->body_params, NULL, NULL, NULL, PARAM_PARSE_BODY)) return false; CONSUME_OR_RET(TOKEN_RPAREN, false); } macro->func_decl.body_param = declid(body_param); @@ -1856,7 +1860,7 @@ static inline Decl *parse_define_attribute(ParseContext *c, Visibility visibilit if (try_consume(c, TOKEN_LPAREN)) { - if (!parse_parameters(c, visibility, &decl->attr_decl.params, NULL, NULL, NULL, false)) return poisoned_decl; + if (!parse_parameters(c, visibility, &decl->attr_decl.params, NULL, NULL, NULL, PARAM_PARSE_ATTR)) return poisoned_decl; CONSUME_OR_RET(TOKEN_RPAREN, poisoned_decl); } @@ -1985,9 +1989,10 @@ static inline Decl *parse_macro_declaration(ParseContext *c, Visibility visibili if (!parse_macro_arguments(c, visibility, decl)) return poisoned_decl; if (!parse_attributes(c, &decl->attributes)) return poisoned_decl; - if (tok_is(c, TOKEN_EQ) || tok_is(c, TOKEN_IMPLIES)) + if (tok_is(c, TOKEN_IMPLIES)) { - ASSIGN_ASTID_OR_RET(decl->func_decl.body, parse_short_stmt(c, decl->func_decl.signature.rtype), poisoned_decl); + ASSIGN_ASTID_OR_RET(decl->func_decl.body, + parse_short_body(c, decl->func_decl.signature.rtype, true), poisoned_decl); return decl; } ASSIGN_ASTID_OR_RET(decl->func_decl.body, parse_stmt(c), poisoned_decl); @@ -2210,9 +2215,10 @@ static inline Decl *parse_func_definition(ParseContext *c, Visibility visibility return func; } - if (tok_is(c, TOKEN_EQ) || tok_is(c, TOKEN_IMPLIES)) + if (tok_is(c, TOKEN_IMPLIES)) { - ASSIGN_ASTID_OR_RET(func->func_decl.body, parse_short_stmt(c, func->func_decl.signature.rtype), poisoned_decl); + ASSIGN_ASTID_OR_RET(func->func_decl.body, + parse_short_body(c, func->func_decl.signature.rtype, true), poisoned_decl); } else if (tok_is(c, TOKEN_LBRACE)) { diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index d25088c23..d04303b03 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -1383,7 +1383,7 @@ Ast* parse_compound_stmt(ParseContext *c) return ast; } -Ast* parse_short_stmt(ParseContext *c, TypeInfoId return_type) +Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool require_eos) { advance(c); Ast *ast = ast_new_curr(c, AST_COMPOUND_STMT); @@ -1395,13 +1395,17 @@ Ast* parse_short_stmt(ParseContext *c, TypeInfoId return_type) Ast *ret = ast_new_curr(c, AST_RETURN_STMT); ast_append(&next, ret); ASSIGN_EXPR_OR_RET(ret->return_stmt.expr, parse_expr(c), poisoned_ast); - RETURN_AFTER_EOS(ast); } else { - ASSIGN_AST_OR_RET(Ast *stmt, parse_expr_stmt(c), poisoned_ast); + Ast *stmt = new_ast(AST_EXPR_STMT, c->span); + ASSIGN_EXPR_OR_RET(stmt->expr_stmt, parse_expr(c), poisoned_ast); ast_append(&next, stmt); - return ast; } - UNREACHABLE + RANGE_EXTEND_PREV(ast); + if (require_eos) + { + CONSUME_EOS_OR_RET(poisoned_ast); + } + return ast; } \ No newline at end of file diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index 4bdd43cd6..f479438e3 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -5,6 +5,16 @@ // a copy of which can be found in the LICENSE file. +typedef enum +{ + PARAM_PARSE_MACRO, + PARAM_PARSE_FUNC, + PARAM_PARSE_BODY, + PARAM_PARSE_CALL, + PARAM_PARSE_LAMBDA, + PARAM_PARSE_ATTR, +} ParameterParseKind; + #define EXPECT_IDENT_FOR_OR(_name, _res) do { if (!expect_ident(c, _name)) return _res; } while(0) #define EXPECT_OR_RET(_tok, _res) do { if (!expect(c, _tok)) return _res; } while(0) #define CONSUME_OR_RET(_tok, _res) do { if (!expect(c, _tok)) return _res; advance(c); } while(0) @@ -35,7 +45,7 @@ void recover_top_level(ParseContext *c); Expr *parse_cond(ParseContext *c); Expr *parse_assert_expr(ParseContext *c); Ast* parse_compound_stmt(ParseContext *c); -Ast* parse_short_stmt(ParseContext *c, TypeInfoId return_type); +Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool require_eos); Ast *parse_jump_stmt_no_eos(ParseContext *c); bool parse_attribute(ParseContext *c, Attr **attribute_ref); bool parse_attributes(ParseContext *c, Attr ***attributes_ref); @@ -46,9 +56,8 @@ Expr *parse_expression_list(ParseContext *c, bool allow_decls); Decl *parse_decl_after_type(ParseContext *c, TypeInfo *type); Decl *parse_var_decl(ParseContext *c); -bool -parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref, Decl **body_params, - Variadic *variadic, int *vararg_index_ref, bool is_body_params); +bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref, Decl **body_params, + Variadic *variadic, int *vararg_index_ref, ParameterParseKind parse_kind); bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *splat, bool vasplat); Expr *parse_type_compound_literal_expr_after_type(ParseContext *c, TypeInfo *type_info); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index e8b6d1719..45e56071f 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -770,6 +770,7 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type) case EXPR_CT_CHECKS: case EXPR_SUBSCRIPT_ASSIGN: case EXPR_SWIZZLE: + case EXPR_LAMBDA: UNREACHABLE case EXPR_BUILTIN_ACCESS: case EXPR_TEST_HOOK: @@ -937,6 +938,7 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type) case EXPR_OPERATOR_CHARS: case EXPR_CT_CHECKS: case EXPR_SWIZZLE: + case EXPR_LAMBDA: UNREACHABLE case EXPR_TEST_HOOK: return false; diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index e03c94ab2..e28787286 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -9,7 +9,6 @@ static inline bool sema_analyse_func_macro(SemaContext *context, Decl *decl, boo static inline bool sema_analyse_func(SemaContext *context, Decl *decl); static inline bool sema_analyse_macro(SemaContext *context, Decl *decl); static inline bool sema_analyse_signature(SemaContext *context, Signature *sig); -static inline Type *sema_analyse_function_signature(SemaContext *context, Decl *parent, CallABI abi, Signature *signature, bool is_real_function); static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl); static inline bool sema_check_param_uniqueness_and_type(Decl **decls, Decl *current, unsigned current_index, unsigned count); @@ -819,7 +818,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig) } -static inline Type *sema_analyse_function_signature(SemaContext *context, Decl *parent, CallABI abi, Signature *signature, bool is_real_function) +Type *sema_analyse_function_signature(SemaContext *context, Decl *parent, CallABI abi, Signature *signature, bool is_real_function) { // Get param count and variadic type Decl **params = signature->params; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 65291e304..85faef26f 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -371,6 +371,7 @@ static bool sema_binary_is_expr_lvalue(Expr *top_expr, Expr *expr) switch (expr->expr_kind) { case EXPR_SWIZZLE: + case EXPR_LAMBDA: return false; case EXPR_SUBSCRIPT_ASSIGN: case EXPR_CT_IDENT: @@ -6476,6 +6477,151 @@ static inline bool sema_expr_analyse_ct_checks(SemaContext *context, Expr *expr) return true; } + +static inline bool sema_may_reuse_lambda(SemaContext *context, Decl *lambda, Type **types) +{ + Signature *sig = &lambda->func_decl.signature; + if (typeinfotype(sig->rtype)->canonical != types[0]) return false; + FOREACH_BEGIN_IDX(i, Decl *param, sig->params) + TypeInfo *info = param->var.type_info; + if (info->type->canonical != types[i + 1]) return false; + FOREACH_END(); + return true; +} + +static inline Type *sema_evaluate_type_copy(SemaContext *context, TypeInfo *type_info) +{ + if (type_info->resolve_status == RESOLVE_DONE) return type_info->type; + type_info = copy_type_info_single(type_info); + if (!sema_resolve_type_info(context, type_info)) return NULL; + return type_info->type; +} + +static inline Decl *sema_find_cached_lambda(SemaContext *context, Type *func_type, Decl *original) +{ + unsigned cached = vec_size(original->func_decl.generated_lambda); + if (!cached) return NULL; + // If it has a function type, then we just use that for comparison. + if (func_type) + { + Type *raw = func_type->canonical->pointer->function.prototype->raw_type; + FOREACH_BEGIN(Decl *candidate, original->func_decl.generated_lambda) + if (raw == candidate->type->function.prototype->raw_type) return candidate; + FOREACH_END(); + return NULL; + } + Signature *sig = &original->func_decl.signature; + if (!sig->rtype) return false; + Type *rtype = sema_evaluate_type_copy(context, type_infoptr(sig->rtype)); + if (!rtype) return false; + Type *types[200]; + types[0] = rtype; + FOREACH_BEGIN_IDX(i, Decl *param, sig->params) + TypeInfo *info = param->var.type_info; + if (!info) return false; + Type *type = sema_evaluate_type_copy(context, param->var.type_info); + if (!type) return false; + assert(i < 198); + types[i + 1] = type; + FOREACH_END(); + + FOREACH_BEGIN(Decl *candidate, original->func_decl.generated_lambda) + if (sema_may_reuse_lambda(context, candidate, types)) return candidate; + FOREACH_END(); + return NULL; +} + +static inline bool sema_expr_analyse_lambda(SemaContext *context, Type *func_type, Expr *expr) +{ + Decl *decl = expr->lambda_expr; + bool in_macro = context->current_macro; + if (in_macro && decl->resolve_status != RESOLVE_DONE) + { + Decl *decl_cached = sema_find_cached_lambda(context, func_type, decl); + if (decl_cached) + { + expr->type = type_get_ptr(decl_cached->type); + expr->lambda_expr = decl_cached; + return true; + } + } + Decl *original = decl; + if (in_macro) decl = expr->lambda_expr = copy_lambda_deep(decl); + Signature *sig = &decl->func_decl.signature; + Signature *to_sig = func_type ? func_type->canonical->pointer->function.signature : NULL; + if (!sig->rtype) + { + if (!to_sig) goto FAIL_NO_INFER; + sig->rtype = type_infoid(type_info_new_base(typeinfotype(to_sig->rtype), expr->span)); + } + if (to_sig && vec_size(to_sig->params) != vec_size(sig->params)) + { + SEMA_ERROR(expr, "The lambda doesn't match the required type %s.", type_quoted_error_string(func_type)); + return false; + } + FOREACH_BEGIN_IDX(i, Decl *param, sig->params) + if (param->var.type_info) continue; + if (!to_sig) goto FAIL_NO_INFER; + param->var.type_info = type_info_new_base(to_sig->params[i]->type, param->span); + FOREACH_END(); + CompilationUnit *unit = decl->unit = context->unit; + assert(!decl->name); + scratch_buffer_clear(); + switch (context->call_env.kind) + { + case CALL_ENV_CHECKS: + scratch_buffer_append(unit->module->name->module); + scratch_buffer_append("_checks"); + break; + case CALL_ENV_GLOBAL_INIT: + scratch_buffer_append(unit->module->name->module); + scratch_buffer_append("_global"); + break; + case CALL_ENV_FUNCTION: + if (context->current_macro) + { + scratch_buffer_append(unit->module->name->module); + scratch_buffer_append("_"); + scratch_buffer_append(context->current_macro->name); + } + else + { + scratch_buffer_append(decl_get_extname(context->call_env.current_function)); + } + break; + case CALL_ENV_INITIALIZER: + scratch_buffer_append(unit->module->name->module); + scratch_buffer_append("_initializer"); + break; + case CALL_ENV_FINALIZER: + scratch_buffer_append(unit->module->name->module); + scratch_buffer_append("_finalizer"); + break; + case CALL_ENV_ATTR: + scratch_buffer_append(unit->module->name->module); + scratch_buffer_append("_attr"); + break; + } + scratch_buffer_append("$lambda"); + scratch_buffer_append_unsigned_int(++unit->lambda_count); + decl->extname = decl->name = scratch_buffer_copy(); + Type *lambda_type = sema_analyse_function_signature(context, decl, sig->abi, sig, true); + if (!lambda_type) return false; + if (lambda_type) + decl->type = lambda_type; + decl->alignment = type_alloca_alignment(decl->type); + // We will actually compile this into any module using it (from a macro) by necessity, + // so we'll declare it as weak and externally visible. + if (context->compilation_unit != decl->unit) decl->is_external_visible = true; + vec_add(unit->module->lambdas_to_evaluate, decl); + expr->type = type_get_ptr(lambda_type); + if (in_macro) vec_add(original->func_decl.generated_lambda, decl); + return true; +FAIL_NO_INFER: + SEMA_ERROR(decl, "Inferred lambda expressions cannot be used unless the type can be determined."); + return false; +} + static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr) { if (expr->resolve_status == RESOLVE_DONE) return expr_ok(expr); @@ -6842,6 +6988,8 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) case EXPR_VASPLAT: SEMA_ERROR(expr, "'$vasplat' can only be used inside of macros."); return false; + case EXPR_LAMBDA: + return sema_expr_analyse_lambda(context, NULL, expr); case EXPR_CT_CHECKS: return sema_expr_analyse_ct_checks(context, expr); case EXPR_CT_ARG: @@ -7233,6 +7381,9 @@ bool sema_analyse_inferred_expr(SemaContext *context, Type *infer_type, Expr *ex case EXPR_IDENTIFIER: if (!sema_expr_analyse_identifier(context, infer_type, expr)) return expr_poison(expr); break; + case EXPR_LAMBDA: + if (!sema_expr_analyse_lambda(context, infer_type, expr)) return expr_poison(expr); + break; default: expr_insert_widening_type(expr, infer_type); if (!sema_analyse_expr_dispatch(context, expr)) return expr_poison(expr); diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index 3a6b4fc0f..f086b99ec 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -77,6 +77,8 @@ void sema_analysis_pass_decls(Module *module); void sema_analysis_pass_ct_assert(Module *module); void sema_analysis_pass_ct_echo(Module *module); void sema_analysis_pass_functions(Module *module); + +void sema_analysis_pass_lambda(Module *module); void sema_analyze_stage(Module *module, AnalysisStage stage); bool sema_analyse_expr_lvalue(SemaContext *context, Expr *expr); @@ -93,6 +95,7 @@ bool sema_analyse_asm(SemaContext *context, AsmInlineBlock *block, Ast *asm_stmt bool sema_bit_assignment_check(Expr *right, Decl *member); int sema_check_comp_time_bool(SemaContext *context, Expr *expr); bool sema_expr_check_assign(SemaContext *c, Expr *expr); +Type *sema_analyse_function_signature(SemaContext *context, Decl *parent, CallABI abi, Signature *signature, bool is_real_function); bool cast_widen_top_down(SemaContext *context, Expr *expr, Type *type); bool cast_promote_vararg(Expr *arg); diff --git a/src/compiler/sema_passes.c b/src/compiler/sema_passes.c index eb6785860..e0d6ff5a7 100644 --- a/src/compiler/sema_passes.c +++ b/src/compiler/sema_passes.c @@ -439,11 +439,34 @@ void sema_analysis_pass_decls(Module *module) DEBUG_LOG("Pass finished with %d error(s).", global_context.errors_found); } +void sema_analysis_pass_lambda(Module *module) +{ + DEBUG_LOG("Extra pass: Lambda analysis %s", module->name->module); + + VECEACH(module->units, index) + { + while (vec_size(module->lambdas_to_evaluate)) + { + Decl *lambda = VECLAST(module->lambdas_to_evaluate); + CompilationUnit *unit = lambda->unit; + SemaContext context; + sema_context_init(&context, unit); + vec_pop(module->lambdas_to_evaluate); + if (analyse_func_body(&context, lambda)) + { + vec_add(unit->lambdas, lambda); + } + sema_context_destroy(&context); + } + } + + DEBUG_LOG("Pass finished with %d error(s).", global_context.errors_found); +} + void sema_analysis_pass_functions(Module *module) { DEBUG_LOG("Pass: Function analysis %s", module->name->module); - VECEACH(module->units, index) { CompilationUnit *unit = module->units[index]; @@ -463,7 +486,6 @@ void sema_analysis_pass_functions(Module *module) } if (unit->main_function && unit->main_function->is_synthetic) analyse_func_body(&context, unit->main_function); sema_context_destroy(&context); - } DEBUG_LOG("Pass finished with %d error(s).", global_context.errors_found); diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index 49c771af0..4da83826b 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -111,8 +111,6 @@ static inline void halt_on_error(void) if (global_context.errors_found > 0) exit_compiler(EXIT_FAILURE); } - - void sema_analyze_stage(Module *module, AnalysisStage stage) { while (module->stage < stage) @@ -295,16 +293,26 @@ void sema_analysis_run(void) global_context.core_module = compiler_find_or_create_module(&core_path, NULL, false); // We parse the generic modules, just by storing the decls. - VECEACH(global_context.generic_module_list, i) - { - analyze_generic_module(global_context.generic_module_list[i]); - } + FOREACH_BEGIN(Module *module, global_context.generic_module_list) + analyze_generic_module(module); + FOREACH_END(); for (AnalysisStage stage = ANALYSIS_NOT_BEGUN + 1; stage <= ANALYSIS_LAST; stage++) { sema_analyze_to_stage(stage); } +RESOLVE_LAMBDA:; + bool found_lambda = false; + FOREACH_BEGIN(Module *module, global_context.module_list) + if (vec_size(module->lambdas_to_evaluate)) + { + sema_analysis_pass_lambda(module); + found_lambda = true; + } + FOREACH_END(); + if (found_lambda) goto RESOLVE_LAMBDA; + if (active_target.panicfn || !active_target.no_stdlib) { const char *panicfn = active_target.panicfn ? active_target.panicfn : "std::core::builtin::panic"; diff --git a/src/version.h b/src/version.h index 02e0282e7..e1c4d1944 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.18" \ No newline at end of file +#define COMPILER_VERSION "0.4.19" \ No newline at end of file diff --git a/test/test_suite/functions/func_ptr_conversion_alias.c3t b/test/test_suite/functions/func_ptr_conversion_alias.c3t index 5f07f32c0..876cc3450 100644 --- a/test/test_suite/functions/func_ptr_conversion_alias.c3t +++ b/test/test_suite/functions/func_ptr_conversion_alias.c3t @@ -15,6 +15,6 @@ GetCallback x = &tester; define GetCallbackOpt = fn Callback2!(); -fn Callback2! tester2() = null; +fn Callback2! tester2() => null; GetCallbackOpt y = &tester2; \ No newline at end of file diff --git a/test/test_suite/lambda/lambda_in_macro.c3t b/test/test_suite/lambda/lambda_in_macro.c3t new file mode 100644 index 000000000..849774ee7 --- /dev/null +++ b/test/test_suite/lambda/lambda_in_macro.c3t @@ -0,0 +1,45 @@ +// #target: macos-x64 +module test; +import std::io; + +define Callback1 = fn double(double x); +define Callback2 = fn int(int y); + +macro test2(y) +{ + var $Type = $typeof(y); + return fn $Type($typeof(y) x) { return x * x; }; +} + +macro test($Type) +{ + $Type z = fn (x) { return x * x; }; + return z; +} + +fn void main() +{ + io::printfn("val: %d", test(Callback2)(3)); + io::printfn("val: %s", test(Callback1)(3.3)); + io::printfn("val: %s", test(Callback1)(3.3)); + io::printfn("val: %d", test2(1)(3)); + io::printfn("val: %d", test2(1)(3)); + io::printfn("val: %s", test2(1.0)(3.3)); +} + +/* #expect: test.ll + + store ptr @"test_test$lambda1", ptr %z, align 8 + %1 = call i32 %0(i32 3) + store ptr @"test_test$lambda2", ptr %z3, align 8 + %7 = call double %6(double 3.300000e+00) + store ptr @"test_test$lambda2", ptr %z10, align 8 + %13 = call double %12(double 3.300000e+00) + %18 = call i32 @"test_test2$lambda3"(i32 3) + %23 = call i32 @"test_test2$lambda3"(i32 3) + %28 = call double @"test_test2$lambda4"(double 3.300000e+00) + +define internal double @"test_test2$lambda4"(double %0) #0 { +define internal i32 @"test_test2$lambda3"(i32 %0) #0 { +define internal double @"test_test$lambda2"(double %0) #0 { +define internal i32 @"test_test$lambda1"(i32 %0) #0 { diff --git a/test/test_suite/lambda/nested_lambda_def.c3t b/test/test_suite/lambda/nested_lambda_def.c3t new file mode 100644 index 000000000..29dff3356 --- /dev/null +++ b/test/test_suite/lambda/nested_lambda_def.c3t @@ -0,0 +1,81 @@ +// #target: macos-x64 +module abc; +import bar; +import std::io; + +fn int xy(Callback a) => a(); + +fn void main() +{ + const Callback F = bar::get_callback(); + int z = xy(F); + z = xy(F); + io::printfn("val: %d", z); +} + +module foo; +import bar; +import std::io; + +private int xz = 0; + + +macro Callback get_callback() +{ + return fn int() { return bar::get_callback2()(); }; +} + +macro Callback get_callback2() +{ + return fn int() { io::printfn("Hello"); return ++xz; }; +} + +module bar; +import foo; +define Callback = fn int(); + +macro Callback get_callback() +{ + return fn int() { return foo::get_callback()(); }; +} + +macro Callback get_callback2() +{ + return fn int() { return foo::get_callback2()(); }; +} + +/* #expect: abc.ll + + store ptr @"bar_get_callback$lambda1", ptr %F, align 8 + %0 = call i32 @abc_xy(ptr @"bar_get_callback$lambda1") + %1 = call i32 @abc_xy(ptr @"bar_get_callback$lambda1") + +declare i32 @"bar_get_callback$lambda1"() + +// #expect: foo.ll + +define i32 @"foo_get_callback$lambda1"() #0 { + %0 = call i32 @"bar_get_callback2$lambda2"() + +define i32 @"foo_get_callback2$lambda2"() #0 { + %1 = load i32, ptr @foo_xz, align 4 + +declare i32 @"bar_get_callback2$lambda2"() + +// #expect: bar.ll + +define i32 @"bar_get_callback$lambda1"() #0 { +entry: + %0 = call i32 @"foo_get_callback$lambda1"() + ret i32 %0 +} + +define i32 @"bar_get_callback2$lambda2"() #0 { +entry: + %0 = call i32 @"foo_get_callback2$lambda2"() + ret i32 %0 +} + +declare i32 @"foo_get_callback$lambda1"() +declare i32 @"foo_get_callback2$lambda2"() + diff --git a/test/test_suite/lambda/simple_lambda.c3t b/test/test_suite/lambda/simple_lambda.c3t new file mode 100644 index 000000000..69eb751a2 --- /dev/null +++ b/test/test_suite/lambda/simple_lambda.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 +import std::io; +import std::math::vector; +import std::math; + +define Callback = fn int(); + +fn int xy(Callback a) => a(); + +fn void main() +{ + const Callback F = fn int() { io::printfn("Hello"); return 23; }; + int z = xy(F); + io::printfn("%d", z); + int y = xy(fn () { return 3; }); +} + +/* #expect: simple_lambda.ll + +define void @simple_lambda_main() #0 { +entry: + %F = alloca ptr, align 8 + %z = alloca i32, align 4 + store ptr @"simple_lambda_main$lambda1", ptr %F, align 8 + %0 = call i32 @simple_lambda_xy(ptr @"simple_lambda_main$lambda1") + %5 = call i32 @simple_lambda_xy(ptr @"simple_lambda_main$lambda2") + +define internal i32 @"simple_lambda_main$lambda2"() #0 { +define internal i32 @"simple_lambda_main$lambda1"() #0 { \ No newline at end of file diff --git a/test/test_suite/macro_methods/macro_method_first_param.c3 b/test/test_suite/macro_methods/macro_method_first_param.c3 index c670e2446..58267b9a5 100644 --- a/test/test_suite/macro_methods/macro_method_first_param.c3 +++ b/test/test_suite/macro_methods/macro_method_first_param.c3 @@ -1,4 +1,4 @@ struct Foo { int y; } -macro Foo.text(...) = f.y; // #error: The first parameter to this method must \ No newline at end of file +macro Foo.text(...) => f.y; // #error: The first parameter to this method must \ No newline at end of file diff --git a/test/test_suite14/functions/func_ptr_conversion_alias.c3t b/test/test_suite14/functions/func_ptr_conversion_alias.c3t index 5f07f32c0..876cc3450 100644 --- a/test/test_suite14/functions/func_ptr_conversion_alias.c3t +++ b/test/test_suite14/functions/func_ptr_conversion_alias.c3t @@ -15,6 +15,6 @@ GetCallback x = &tester; define GetCallbackOpt = fn Callback2!(); -fn Callback2! tester2() = null; +fn Callback2! tester2() => null; GetCallbackOpt y = &tester2; \ No newline at end of file diff --git a/test/test_suite14/lambda/lambda_in_macro.c3t b/test/test_suite14/lambda/lambda_in_macro.c3t new file mode 100644 index 000000000..e35f8bf90 --- /dev/null +++ b/test/test_suite14/lambda/lambda_in_macro.c3t @@ -0,0 +1,45 @@ +// #target: macos-x64 +module test; +import std::io; + +define Callback1 = fn double(double x); +define Callback2 = fn int(int y); + +macro test2(y) +{ + var $Type = $typeof(y); + return fn $Type($typeof(y) x) { return x * x; }; +} + +macro test($Type) +{ + $Type z = fn (x) { return x * x; }; + return z; +} + +fn void main() +{ + io::printfn("val: %d", test(Callback2)(3)); + io::printfn("val: %s", test(Callback1)(3.3)); + io::printfn("val: %s", test(Callback1)(3.3)); + io::printfn("val: %d", test2(1)(3)); + io::printfn("val: %d", test2(1)(3)); + io::printfn("val: %s", test2(1.0)(3.3)); +} + +/* #expect: test.ll + + store i32 (i32)* @"test_test$lambda1", i32 (i32)** %z, align 8 + %1 = call i32 %0(i32 3) + store double (double)* @"test_test$lambda2", double (double)** %z4, align 8 + %14 = call double %13(double 3.300000e+00) + store double (double)* @"test_test$lambda2", double (double)** %z14, align 8 + %27 = call double %26(double 3.300000e+00) + %39 = call i32 @"test_test2$lambda3"(i32 3) + %51 = call i32 @"test_test2$lambda3"(i32 3) + %63 = call double @"test_test2$lambda4"(double 3.300000e+00) + +define internal double @"test_test2$lambda4"(double %0) #0 { +define internal i32 @"test_test2$lambda3"(i32 %0) #0 { +define internal double @"test_test$lambda2"(double %0) #0 { +define internal i32 @"test_test$lambda1"(i32 %0) #0 { diff --git a/test/test_suite14/lambda/nested_lambda_def.c3t b/test/test_suite14/lambda/nested_lambda_def.c3t new file mode 100644 index 000000000..461bb709c --- /dev/null +++ b/test/test_suite14/lambda/nested_lambda_def.c3t @@ -0,0 +1,87 @@ +// #target: macos-x64 +module abc; +import bar; +import std::io; + +fn int xy(Callback a) => a(); + +fn void main() +{ + const Callback F = bar::get_callback(); + int z = xy(F); + z = xy(F); + io::printfn("val: %d", z); +} + +module foo; +import bar; +import std::io; + +private int xz = 0; + + +macro Callback get_callback() +{ + return fn int() { return bar::get_callback2()(); }; +} + +macro Callback get_callback2() +{ + return fn int() { io::printfn("Hello"); return ++xz; }; +} + +module bar; +import foo; +define Callback = fn int(); + +macro Callback get_callback() +{ + return fn int() { return foo::get_callback()(); }; +} + +macro Callback get_callback2() +{ + return fn int() { return foo::get_callback2()(); }; +} + +/* #expect: abc.ll + + store i32 ()* @"bar_get_callback$lambda1", i32 ()** %F, align 8 + %0 = call i32 @abc_xy(i32 ()* @"bar_get_callback$lambda1") + %1 = call i32 @abc_xy(i32 ()* @"bar_get_callback$lambda1") + +declare i32 @"bar_get_callback$lambda1"() + +// #expect: foo.ll + +define i32 @"foo_get_callback$lambda1"() #0 { +entry: + %0 = call i32 @"bar_get_callback2$lambda2"() + ret i32 %0 +} +define i32 @"foo_get_callback2$lambda2"() #0 { + + %4 = load i32, i32* @foo_xz, align 4 + %add = add i32 %4, 1 + store i32 %add, i32* @foo_xz, align 4 + ret i32 %add +} +declare i32 @"bar_get_callback2$lambda2"() + +// #expect: bar.ll + +define i32 @"bar_get_callback$lambda1"() #0 { +entry: + %0 = call i32 @"foo_get_callback$lambda1"() + ret i32 %0 +} + +define i32 @"bar_get_callback2$lambda2"() #0 { +entry: + %0 = call i32 @"foo_get_callback2$lambda2"() + ret i32 %0 +} + +declare i32 @"foo_get_callback$lambda1"() +declare i32 @"foo_get_callback2$lambda2"() + diff --git a/test/test_suite14/lambda/simple_lambda.c3t b/test/test_suite14/lambda/simple_lambda.c3t new file mode 100644 index 000000000..a0a0f197d --- /dev/null +++ b/test/test_suite14/lambda/simple_lambda.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 +import std::io; +import std::math::vector; +import std::math; + +define Callback = fn int(); + +fn int xy(Callback a) => a(); + +fn void main() +{ + const Callback F = fn int() { io::printfn("Hello"); return 23; }; + int z = xy(F); + io::printfn("%d", z); + int y = xy(fn () { return 3; }); +} + +/* #expect: simple_lambda.ll + +define void @simple_lambda_main() #0 { +entry: + %F = alloca i32 ()*, align 8 + %z = alloca i32, align 4 + store i32 ()* @"simple_lambda_main$lambda1", i32 ()** %F, align 8 + %0 = call i32 @simple_lambda_xy(i32 ()* @"simple_lambda_main$lambda1") + %12 = call i32 @simple_lambda_xy(i32 ()* @"simple_lambda_main$lambda2") + +define internal i32 @"simple_lambda_main$lambda2"() #0 +define internal i32 @"simple_lambda_main$lambda1"() #0 \ No newline at end of file diff --git a/test/test_suite14/macro_methods/macro_method_first_param.c3 b/test/test_suite14/macro_methods/macro_method_first_param.c3 index c670e2446..58267b9a5 100644 --- a/test/test_suite14/macro_methods/macro_method_first_param.c3 +++ b/test/test_suite14/macro_methods/macro_method_first_param.c3 @@ -1,4 +1,4 @@ struct Foo { int y; } -macro Foo.text(...) = f.y; // #error: The first parameter to this method must \ No newline at end of file +macro Foo.text(...) => f.y; // #error: The first parameter to this method must \ No newline at end of file