* The new @if directive.
This commit is contained in:
Christoffer Lerno
2023-06-10 23:16:28 +02:00
committed by GitHub
parent 82c3facb65
commit 4c1edfb941
102 changed files with 1272 additions and 1720 deletions

View File

@@ -7,142 +7,141 @@
**/
module std::collections::enumset<Enum>;
def EnumSetType = $typefrom(private::type_for_enum_elements(Enum.elements)) @private ;
const IS_CHAR_ARRAY = Enum.elements > 128;
$switch
$case (Enum.elements > 128):
def EnumSetType @private = char[(Enum.elements + 7) / 8];
$case (Enum.elements > 64):
def EnumSetType @private = uint128;
$case (Enum.elements > 32 || $$C_INT_SIZE > 32):
def EnumSetType @private = ulong;
$case (Enum.elements > 16 || $$C_INT_SIZE > 16):
def EnumSetType @private = uint;
$case (Enum.elements > 8 || $$C_INT_SIZE > 8):
def EnumSetType @private = ushort;
$default:
def EnumSetType @private = char;
$endswitch
def EnumSet = distinct EnumSetType;
fn void EnumSet.add(EnumSet* this, Enum v)
{
$if IS_CHAR_ARRAY:
(*this)[v / 8] |= (char)(1u << (v % 8));
$else
*this = (EnumSet)((EnumSetType)*this | 1u << (EnumSetType)v);
$endif
$if IS_CHAR_ARRAY:
(*this)[(usz)v / 8] |= (char)(1u << ((usz)v % 8));
$else
*this = (EnumSet)((EnumSetType)*this | 1u << (EnumSetType)v);
$endif
}
fn void EnumSet.clear(EnumSet* this)
{
$if IS_CHAR_ARRAY:
*this = {};
$else
*this = 0;
$endif
$if IS_CHAR_ARRAY:
*this = {};
$else
*this = 0;
$endif
}
fn bool EnumSet.remove(EnumSet* this, Enum v)
{
$if IS_CHAR_ARRAY:
if (!this.has(v) @inline) return false;
(*this)[v / 8] &= (char)~(1 << (v % 8));
return true;
$else
EnumSetType old = (EnumSetType)*this;
EnumSetType new = old & ~(1u << (EnumSetType)v);
*this = (EnumSet)new;
return old != new;
$endif
$if IS_CHAR_ARRAY:
if (!this.has(v) @inline) return false;
(*this)[(usz)v / 8] &= (char)~(1u << ((usz)v % 8));
return true;
$else
EnumSetType old = (EnumSetType)*this;
EnumSetType new = old & ~(1u << (EnumSetType)v);
*this = (EnumSet)new;
return old != new;
$endif
}
fn bool EnumSet.has(EnumSet* this, Enum v)
{
$if IS_CHAR_ARRAY:
return (bool)(((*this)[v / 8] << (v % 8)) & 0x01);
$else
return ((EnumSetType)*this & (1u << (EnumSetType)v)) != 0;
$endif
$if IS_CHAR_ARRAY:
return (bool)(((*this)[(usz)v / 8] << ((usz)v % 8)) & 0x01);
$else
return ((EnumSetType)*this & (1u << (EnumSetType)v)) != 0;
$endif
}
fn void EnumSet.add_all(EnumSet* this, EnumSet s)
{
$if IS_CHAR_ARRAY:
foreach (i, c : s) (*this)[i] |= c;
$else
*this = (EnumSet)((EnumSetType)*this | (EnumSetType)s);
$endif
$if IS_CHAR_ARRAY:
foreach (i, c : s) (*this)[i] |= c;
$else
*this = (EnumSet)((EnumSetType)*this | (EnumSetType)s);
$endif
}
fn void EnumSet.retain_all(EnumSet* this, EnumSet s)
{
$if IS_CHAR_ARRAY:
foreach (i, c : s) (*this)[i] &= c;
$else
*this = (EnumSet)((EnumSetType)*this & (EnumSetType)s);
$endif
$if IS_CHAR_ARRAY:
foreach (i, c : s) (*this)[i] &= c;
$else
*this = (EnumSet)((EnumSetType)*this & (EnumSetType)s);
$endif
}
fn void EnumSet.remove_all(EnumSet* this, EnumSet s)
{
$if IS_CHAR_ARRAY:
foreach (i, c : s) (*this)[i] &= ~c;
$else
*this = (EnumSet)((EnumSetType)*this & ~(EnumSetType)s);
$endif
$if IS_CHAR_ARRAY:
foreach (i, c : s) (*this)[i] &= ~c;
$else
*this = (EnumSet)((EnumSetType)*this & ~(EnumSetType)s);
$endif
}
fn EnumSet EnumSet.and_of(EnumSet* this, EnumSet s)
{
$if IS_CHAR_ARRAY:
EnumSet copy = *this;
copy.retain_all(s);
return copy;
$else
return (EnumSet)((EnumSetType)*this & (EnumSetType)s);
$endif
$if IS_CHAR_ARRAY:
EnumSet copy = *this;
copy.retain_all(s);
return copy;
$else
return (EnumSet)((EnumSetType)*this & (EnumSetType)s);
$endif
}
fn EnumSet EnumSet.or_of(EnumSet* this, EnumSet s)
{
$if IS_CHAR_ARRAY:
EnumSet copy = *this;
copy.add_all(s);
return copy;
$else
return (EnumSet)((EnumSetType)*this | (EnumSetType)s);
$endif
$if IS_CHAR_ARRAY:
EnumSet copy = *this;
copy.add_all(s);
return copy;
$else
return (EnumSet)((EnumSetType)*this | (EnumSetType)s);
$endif
}
fn EnumSet EnumSet.diff_of(EnumSet* this, EnumSet s)
{
$if IS_CHAR_ARRAY:
EnumSet copy = *this;
copy.remove_all(s);
return copy;
$else
return (EnumSet)((EnumSetType)*this & ~(EnumSetType)s);
$endif
$if IS_CHAR_ARRAY:
EnumSet copy = *this;
copy.remove_all(s);
return copy;
$else
return (EnumSet)((EnumSetType)*this & ~(EnumSetType)s);
$endif
}
fn EnumSet EnumSet.xor_of(EnumSet* this, EnumSet s)
{
$if IS_CHAR_ARRAY:
EnumSet copy = *this;
foreach (i, c : s) copy[i] ^= c;
return copy;
$else
return (EnumSet)((EnumSetType)*this ^ (EnumSetType)s);
$endif
$if IS_CHAR_ARRAY:
EnumSet copy = *this;
foreach (i, c : s) copy[i] ^= c;
return copy;
$else
return (EnumSet)((EnumSetType)*this ^ (EnumSetType)s);
$endif
}
module std::collections::enumset::private;
macro typeid type_for_enum_elements(usz $elements)
{
$switch
$case ($elements > 128):
return char[($elements + 7) / 8].typeid;
$case ($elements > 64):
return uint128.typeid;
$case ($elements > 32 || $$C_INT_SIZE > 32):
return ulong.typeid;
$case ($elements > 16 || $$C_INT_SIZE > 16):
return uint.typeid;
$case ($elements > 8 || $$C_INT_SIZE > 8):
return ushort.typeid;
$default:
return char.typeid;
$endswitch;
}

View File

@@ -5,6 +5,8 @@ module std::collections::list<Type>;
import std::math;
def ElementPredicate = fn bool(Type *type);
const ELEMENT_IS_EQUATABLE = types::is_equatable_type(Type);
const ELEMENT_IS_POINTER = Type.kindof == POINTER;
struct List
{
@@ -38,24 +40,28 @@ fn void List.tinit(List* list, usz initial_capacity = 16)
list.init(initial_capacity, mem::temp()) @inline;
}
fn void! List.to_format(List* list, Formatter* formatter) @dynamic
{
switch (list.size)
{
case 0:
formatter.print("[]")!;
case 1:
formatter.printf("[%s]", list.entries[0])!;
default:
formatter.print("[")!;
foreach (i, element : list.entries[:list.size])
{
if (i != 0) formatter.print(", ")!;
formatter.printf("%s", element)!;
}
formatter.print("]")!;
}
}
fn String List.to_string(List* list, Allocator* using = mem::heap()) @dynamic
{
if (!list.size) return "[]".copy(using);
if (list.size == 1) return string::printf("[%s]", list.entries[0], .using = using);
@stack_mem(512 + 128; Allocator* mem)
{
DString str;
str.init(512, mem);
str.append("[");
foreach (i, element : list.entries[:list.size])
{
if (i != 0) str.append(", ");
str.printf("%s", element);
}
str.printf("]");
return str.copy_str(using);
};
return string::printf("%s", *list);
}
fn void List.push(List* list, Type element) @inline
@@ -301,9 +307,8 @@ fn void List.ensure_capacity(List* list, usz added = 1) @inline @private
// Functions for equatable types
$if types::is_equatable_type(Type):
fn usz! List.index_of(List* list, Type type)
fn usz! List.index_of(List* list, Type type) @if(ELEMENT_IS_EQUATABLE)
{
foreach (i, v : list)
{
@@ -312,7 +317,7 @@ fn usz! List.index_of(List* list, Type type)
return SearchResult.MISSING?;
}
fn usz! List.rindex_of(List* list, Type type)
fn usz! List.rindex_of(List* list, Type type) @if(ELEMENT_IS_EQUATABLE)
{
foreach_r (i, v : list)
{
@@ -321,7 +326,7 @@ fn usz! List.rindex_of(List* list, Type type)
return SearchResult.MISSING?;
}
fn bool List.equals(List* list, List other_list)
fn bool List.equals(List* list, List other_list) @if(ELEMENT_IS_EQUATABLE)
{
if (list.size != other_list.size) return false;
foreach (i, v : list)
@@ -338,7 +343,7 @@ fn bool List.equals(List* list, List other_list)
* @param value "The value to search for"
* @return "True if the value is found, false otherwise"
**/
fn bool List.contains(List* list, Type value)
fn bool List.contains(List* list, Type value) @if(ELEMENT_IS_EQUATABLE)
{
foreach (i, v : list)
{
@@ -353,7 +358,7 @@ fn bool List.contains(List* list, Type value)
* @param value "The value to remove"
* @return "the number of deleted elements."
**/
fn usz List.remove(List* list, Type value)
fn usz List.remove(List* list, Type value) @if(ELEMENT_IS_EQUATABLE)
{
usz size = list.size;
for (usz i = size; i > 0; i--)
@@ -368,29 +373,24 @@ fn usz List.remove(List* list, Type value)
return size - list.size;
}
fn void List.remove_all(List* list, List* other_list)
fn void List.remove_all(List* list, List* other_list) @if(ELEMENT_IS_EQUATABLE)
{
if (!other_list.size) return;
foreach (v : other_list) list.remove(v);
}
$endif
$if Type.kindof == POINTER:
/**
* @param [&in] list
* @return "The number non-null values in the list"
**/
fn usz List.compact_count(List* list)
fn usz List.compact_count(List* list) @if(ELEMENT_IS_POINTER)
{
usz vals = 0;
foreach (v : list) if (v) vals++;
return vals;
}
fn usz List.compact(List* list)
fn usz List.compact(List* list) @if(ELEMENT_IS_POINTER)
{
usz size = list.size;
for (usz i = size; i > 0; i--)
@@ -404,5 +404,3 @@ fn usz List.compact(List* list)
}
return size - list.size;
}
$endif

View File

@@ -7,7 +7,7 @@ import std::math;
const uint DEFAULT_INITIAL_CAPACITY = 16;
const uint MAXIMUM_CAPACITY = 1u << 31;
const float DEFAULT_LOAD_FACTOR = 0.75;
const VALUE_IS_EQUATABLE = types::is_equatable(Value);
struct HashMap
{
@@ -216,8 +216,7 @@ fn Value[] HashMap.value_list(HashMap* map, Allocator* using = mem::heap())
return list;
}
$if types::is_equatable(Value):
fn bool HashMap.has_value(HashMap* map, Value v)
fn bool HashMap.has_value(HashMap* map, Value v) @if(VALUE_IS_EQUATABLE)
{
if (!map.count) return false;
foreach (Entry* entry : map.table)
@@ -230,7 +229,6 @@ fn bool HashMap.has_value(HashMap* map, Value v)
}
return false;
}
$endif
// --- private methods

View File

@@ -209,25 +209,25 @@ macro Object* object_from_value(value) @private
{
var $Type = $typeof(value);
$switch
$case types::is_int($Type):
return new_int(value);
$case types::is_float($Type):
return new_float(value);
$case $Type.typeid == String.typeid:
return new_string(value);
$case $Type.typeid == bool.typeid:
return new_bool(value);
$case $Type.typeid == Object*.typeid:
return value;
$case $Type.typeid == void*.typeid:
assert(value == null);
return &NULL_OBJECT;
$case $checks(String s = value):
return new_string(value);
$default:
$error "Unsupported object type.";
$endswitch
$switch
$case types::is_int($Type):
return new_int(value);
$case types::is_float($Type):
return new_float(value);
$case $Type.typeid == String.typeid:
return new_string(value);
$case $Type.typeid == bool.typeid:
return new_bool(value);
$case $Type.typeid == Object*.typeid:
return value;
$case $Type.typeid == void*.typeid:
assert(value == null);
return &NULL_OBJECT;
$case $checks(String s = value):
return new_string(value);
$default:
$error "Unsupported object type.";
$endswitch
}
@@ -468,7 +468,7 @@ fn Object* Object.get_or_create_obj(Object* o, String key)
return container;
}
def ObjectInternalMap @private = HashMap<String, Object*>;
def ObjectInternalList @private = List<Object*>;
def ObjectInternalMapEntry @private = Entry<String, Object*>;
def ObjectInternalMap = HashMap<String, Object*> @private;
def ObjectInternalList = List<Object*> @private;
def ObjectInternalMapEntry = Entry<String, Object*> @private;

View File

@@ -181,11 +181,11 @@ macro enum_by_name($Type, String enum_name) @builtin
**/
macro bool @likely(bool #value, $probability = 1.0) @builtin
{
$if $probability == 1.0:
return $$expect(#value, true);
$else
return $$expect_with_probability(#value, true, $probability);
$endif
$if $probability == 1.0:
return $$expect(#value, true);
$else
return $$expect_with_probability(#value, true, $probability);
$endif
}
/**
@@ -197,11 +197,11 @@ $endif
**/
macro bool @unlikely(bool #value, $probability = 1.0) @builtin
{
$if $probability == 1.0:
return $$expect(#value, false);
$else
return $$expect_with_probability(#value, false, $probability);
$endif
$if $probability == 1.0:
return $$expect(#value, false);
$else
return $$expect_with_probability(#value, false, $probability);
$endif
}
/**
@@ -212,9 +212,9 @@ $endif
macro @expect(#value, expected, $probability = 1.0) @builtin
{
$if $probability == 1.0:
return $$expect(#value, ($typeof(#value))expected);
return $$expect(#value, ($typeof(#value))expected);
$else
return $$expect_with_probability(#value, expected, $probability);
return $$expect_with_probability(#value, expected, $probability);
$endif
}

View File

@@ -8,14 +8,14 @@ module std::core::builtin;
**/
macro less(a, b) @builtin
{
$switch
$switch
$case $defined(a.less):
return a.less(b);
$case $defined(a.compare_to):
return a.compare_to(b) < 0;
$default:
return a < b;
$endswitch
$endswitch
}
/**
@@ -23,14 +23,14 @@ $endswitch
**/
macro less_eq(a, b) @builtin
{
$switch
$switch
$case $defined(a.less):
return !b.less(a);
$case $defined(a.compare_to):
return a.compare_to(b) <= 0;
$default:
return a <= b;
$endswitch
$endswitch
}
/**
@@ -38,14 +38,14 @@ $endswitch
**/
macro greater(a, b) @builtin
{
$switch
$switch
$case $defined(a.less):
return b.less(a);
$case $defined(a.compare_to):
return a.compare_to(b) > 0;
$default:
return a > b;
$endswitch
$endswitch
}
/**
@@ -53,14 +53,14 @@ $endswitch
**/
macro greater_eq(a, b) @builtin
{
$switch
$switch
$case $defined(a.less):
return !a.less(b);
$case $defined(a.compare_to):
return a.compare_to(b) >= 0;
$default:
return a >= b;
$endswitch
$endswitch
}
/**
@@ -68,7 +68,7 @@ $endswitch
**/
macro bool equals(a, b) @builtin
{
$switch
$switch
$case $defined(a.equals):
return a.equals(b);
$case $defined(a.compare_to):
@@ -77,7 +77,7 @@ $switch
return !a.less(b) && !b.less(a);
$default:
return a == b;
$endswitch
$endswitch
}
macro min(x, ...) @builtin

View File

@@ -16,72 +16,40 @@ $assert C_SHORT_SIZE <= C_INT_SIZE;
$assert C_INT_SIZE <= C_LONG_SIZE;
$assert C_LONG_SIZE <= C_LONG_LONG_SIZE;
$switch ($$C_INT_SIZE)
$case 64:
def CInt = long;
def CUInt = ulong;
$case 32:
def CInt = int;
def CUInt = uint;
$case 16:
def CInt = short;
def CUInt = ushort;
$default:
$error "Invalid C int size";
$endswitch
$switch ($$C_LONG_SIZE)
$case 64:
def CLong = long;
def CULong = ulong;
$case 32:
def CLong = int;
def CULong = uint;
$case 16:
def CLong = short;
def CULong = ushort;
$default:
$error "Invalid C long size";
$endswitch
$switch ($$C_SHORT_SIZE)
$case 32:
def CShort = int;
def CUShort = uint;
$case 16:
def CShort = short;
def CUShort = ushort;
$case 8:
def CShort = ichar;
def CUShort = char;
$default:
$error "Invalid C short size";
$endswitch
$switch ($$C_LONG_LONG_SIZE)
$case 128:
def CLongLong = int128;
def CULongLong = uint128;
$case 64:
def CLongLong = long;
def CULongLong = ulong;
$case 32:
def CLongLong = int;
def CULongLong = uint;
$case 16:
def CLongLong = short;
def CULongLong = ushort;
$default:
$error "Invalid C long long size";
$endswitch
def CShort = $typefrom(signed_int_from_bitsize($$C_SHORT_SIZE));
def CUShort = $typefrom(unsigned_int_from_bitsize($$C_SHORT_SIZE));
def CInt = $typefrom(signed_int_from_bitsize($$C_INT_SIZE));
def CUInt = $typefrom(unsigned_int_from_bitsize($$C_INT_SIZE));
def CLong = $typefrom(signed_int_from_bitsize($$C_LONG_SIZE));
def CULong = $typefrom(unsigned_int_from_bitsize($$C_LONG_SIZE));
def CLongLong = $typefrom(signed_int_from_bitsize($$C_LONG_LONG_SIZE));
def CULongLong = $typefrom(unsigned_int_from_bitsize($$C_LONG_LONG_SIZE));
def CSChar = ichar;
def CUChar = char;
$if $$C_CHAR_IS_SIGNED:
def CChar = ichar;
$else
def CChar = char;
$endif
def CChar = $typefrom($$C_CHAR_IS_SIGNED ? ichar.typeid : char.typeid);
// Helper macros
macro typeid signed_int_from_bitsize(usz $bitsize) @private
{
$switch ($bitsize)
$case 128: return int128.typeid;
$case 64: return long.typeid;
$case 32: return int.typeid;
$case 16: return short.typeid;
$case 8: return ichar.typeid;
$default: $error("Invalid bitsize");
$endswitch
}
macro typeid unsigned_int_from_bitsize(usz $bitsize) @private
{
$switch ($bitsize)
$case 128: return uint128.typeid;
$case 64: return ulong.typeid;
$case 32: return uint.typeid;
$case 16: return ushort.typeid;
$case 8: return char.typeid;
$default: $error("Invalid bitsize");
$endswitch
}

View File

@@ -128,6 +128,22 @@ const bool BENCHMARKING = $$BENCHMARKING;
const bool TESTING = $$TESTING;
const MemoryEnvironment MEMORY_ENV = (MemoryEnvironment)$$MEMORY_ENVIRONMENT;
const LINUX_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == LINUX;
const DARWIN_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::os_is_darwin();
const WIN32_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::os_is_win32();
const POSIX_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::os_is_posix();
const OPENBSD_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == OPENBSD;
const FREEBSD_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == FREEBSD;
const NETBSD_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == NETBSD;
const WASI_LIBC @builtin = env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == WASI;
const WASM_NOLIBC @builtin = !env::COMPILER_LIBC_AVAILABLE && env::ARCH_TYPE == ArchType.WASM32 || env::ARCH_TYPE == ArchType.WASM64;
const bool NO_LIBC = !env::COMPILER_LIBC_AVAILABLE;
const bool WIN32 = OS_TYPE == WIN32;
const bool DARWIN = OS_TYPE == IOS || OS_TYPE == MACOS || OS_TYPE == TVOS || OS_TYPE == WATCHOS;
const bool LINUX = OS_TYPE == LINUX;
const bool POSIX = os_is_posix();
const bool WASI = OS_TYPE == WASI;
macro bool os_is_win32()
{
return OS_TYPE == WIN32;
@@ -177,15 +193,15 @@ macro bool os_is_posix()
**/
fn String! get_var(String name)
{
$if COMPILER_LIBC_AVAILABLE && !os_is_win32():
$if COMPILER_LIBC_AVAILABLE && !WIN32_LIBC:
@pool()
{
ZString val = libc::getenv(name.zstr_tcopy());
return val ? val.as_str() : SearchResult.MISSING?;
};
$else
$else
return "";
$endif
$endif
}
@@ -196,7 +212,7 @@ $endif
**/
fn void set_var(String name, String value, bool overwrite = true)
{
$if COMPILER_LIBC_AVAILABLE && !os_is_win32():
$if COMPILER_LIBC_AVAILABLE && !WIN32_LIBC:
@pool()
{
if (libc::setenv(name.zstr_tcopy(), value.zstr_copy(), (int)overwrite))
@@ -204,7 +220,7 @@ $if COMPILER_LIBC_AVAILABLE && !os_is_win32():
unreachable();
}
};
$endif
$endif
}
/**
@@ -213,7 +229,7 @@ $endif
**/
fn void clear_var(String name)
{
$if COMPILER_LIBC_AVAILABLE && !os_is_win32():
$if COMPILER_LIBC_AVAILABLE && !WIN32_LIBC:
@pool()
{
if (libc::unsetenv(name.zstr_tcopy()))
@@ -221,6 +237,6 @@ $if COMPILER_LIBC_AVAILABLE && !os_is_win32():
unreachable();
}
};
$endif
$endif
}

View File

@@ -411,10 +411,10 @@ macro TempAllocator* temp()
macro Allocator* current_allocator() => thread_allocator;
macro Allocator* heap() => thread_allocator;
$if !env::COMPILER_LIBC_AVAILABLE && env::ARCH_TYPE == ArchType.WASM32 || env::ARCH_TYPE == ArchType.WASM64:
module std::core::mem @if(WASM_NOLIBC);
SimpleHeapAllocator wasm_allocator @private;
extern int __heap_base;
static initialize @priority(1)
@@ -425,7 +425,4 @@ static initialize @priority(1)
if (start > mem::DEFAULT_MEM_ALIGNMENT) allocator::wasm_memory.use = start;
wasm_allocator.init(fn (x) => allocator::wasm_memory.allocate_block(x));
thread_allocator = &wasm_allocator;
}
$endif
}

View File

@@ -55,7 +55,7 @@ macro int @main_to_void_main_args(#m, int argc, char** argv)
return 0;
}
$if env::os_is_win32():
module std::core::main_stub @if(env::os_is_win32());
extern fn Char16** _win_command_line_to_argv_w(ushort* cmd_line, int* argc_ptr) @extern("CommandLineToArgvW");
@@ -164,5 +164,3 @@ macro int @wmain_to_void_main_args(#m, int argc, Char16** argv)
#m(args);
return 0;
}
$endif

View File

@@ -88,12 +88,12 @@ fn bool __run_default_test_runner()
return test_runner_create().run();
}
$if !env::COMPILER_LIBC_AVAILABLE && env::ARCH_TYPE == ArchType.WASM32 || env::ARCH_TYPE == ArchType.WASM64:
module std::core::runtime @if(WASM_NOLIBC);
extern fn void __wasm_call_ctors();
fn void wasm_initialize() @extern("_initialize") @wasm
{
// The linker synthesizes this to call constructors.
__wasm_call_ctors();
}
$endif
}

View File

@@ -96,12 +96,12 @@ macro @blk(&block, i) @local
macro @blk0(&block, i) @local
{
$if env::BIG_ENDIAN:
return block.l[i];
$else
return block.l[i] = (block.l[i].rotl(24) & 0xFF00FF00)
| (block.l[i].rotl(8) & 0x00FF00FF);
$endif
$if env::BIG_ENDIAN:
return block.l[i];
$else
return block.l[i] = (block.l[i].rotl(24) & 0xFF00FF00)
| (block.l[i].rotl(8) & 0x00FF00FF);
$endif
}
macro @r0(&block, v, &w, x, y, &z, i) @local

View File

@@ -144,6 +144,7 @@ macro bool! Formatter.print_with_function(Formatter* this, any arg)
return false;
}
fn void! Formatter.out_str(Formatter* this, any arg) @private
{
switch (arg.type.kindof)
@@ -425,3 +426,18 @@ fn usz! Formatter.vprintf(Formatter* this, String format, any[] anys)
return this.idx;
}
fn usz! Formatter.print(Formatter* this, String str)
{
if (!this.out_fn)
{
// use null output function
this.out_fn = &out_null_fn;
}
usz len = str.len;
for (usz i = 0; i < len; i++)
{
this.out(str[i])!;
}
return this.idx;
}

View File

@@ -169,21 +169,21 @@ fn usz! Stream.copy_to(Stream* s, Stream* dst, char[] buffer = {})
if (buffer.len) return copy_through_buffer(s, dst, buffer);
if (WriteToStreamFn func = s.fns.write_stream_fn) return func(s, dst);
if (ReadFromStreamFn func = dst.fns.read_stream_fn) return func(dst, s);
$switch (env::MEMORY_ENV)
$case NORMAL:
@pool()
{
return copy_through_buffer(s, dst, tmalloc(char, 4096));
};
$case SMALL:
@pool()
{
return copy_through_buffer(s, dst, tmalloc(char, 1024));
};
$case TINY:
$case NONE:
return copy_through_buffer(s, dst, &&(char[256]{}));
$endswitch
$switch (env::MEMORY_ENV)
$case NORMAL:
@pool()
{
return copy_through_buffer(s, dst, tmalloc(char, 4096));
};
$case SMALL:
@pool()
{
return copy_through_buffer(s, dst, tmalloc(char, 1024));
};
$case TINY:
$case NONE:
return copy_through_buffer(s, dst, &&(char[256]{}));
$endswitch
}
macro usz! copy_through_buffer(Stream* s, Stream* dst, char[] buffer) @local

View File

@@ -1,44 +1,30 @@
module std::io::os;
import libc;
$switch
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_posix():
macro void! native_chdir(Path p)
{
if (posix::chdir(p.as_zstr()))
{
switch (libc::errno())
{
case errno::EACCES: return IoError.NO_PERMISSION?;
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
case errno::ENOTDIR: return IoError.FILE_NOT_DIR?;
case errno::ENOENT: return IoError.FILE_NOT_FOUND?;
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
default: return IoError.GENERAL_ERROR?;
}
}
}
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
macro void! native_chdir(Path path)
{
@pool()
{
// TODO improve with better error handling.
if (win32::win32_SetCurrentDirectoryW(path.as_str().to_temp_utf16()!!)) return;
};
return IoError.GENERAL_ERROR?;
$switch
$case POSIX_LIBC:
if (posix::chdir(path.as_zstr()))
{
switch (libc::errno())
{
case errno::EACCES: return IoError.NO_PERMISSION?;
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
case errno::ENOTDIR: return IoError.FILE_NOT_DIR?;
case errno::ENOENT: return IoError.FILE_NOT_FOUND?;
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
default: return IoError.GENERAL_ERROR?;
}
}
$case WIN32_LIBC:
@pool()
{
// TODO improve with better error handling.
if (win32::win32_SetCurrentDirectoryW(path.as_str().to_temp_utf16()!!)) return;
};
return IoError.GENERAL_ERROR?;
$default:
unreachable("'getcwd' not available");
$endswitch
}
$default:
fn void! native_chdir(Path path)
{
unreachable("'getcwd' not available");
}
$endswitch

View File

@@ -9,28 +9,13 @@ def FtellFn = fn usz!(void*);
def FwriteFn = fn usz!(void*, char[] buffer);
def FreadFn = fn usz!(void*, char[] buffer);
$if !$defined(native_fopen_fn):
FopenFn native_fopen_fn @weak;
$endif
$if !$defined(native_fclose_fn):
FcloseFn native_fclose_fn @weak;
$endif
$if !$defined(native_freopen_fn):
FreopenFn native_freopen_fn @weak;
$endif
$if !$defined(native_fseek_fn):
FseekFn native_fseek_fn @weak;
$endif
$if !$defined(native_ftell_fn):
FtellFn native_ftell_fn @weak;
$endif
$if !$defined(native_fwrite_fn):
FwriteFn native_fwrite_fn @weak;
$endif
$if !$defined(native_fread_fn):
FreadFn native_fread_fn @weak;
$endif
FopenFn native_fopen_fn @weak @if(!$defined(native_fopen_fn));
FcloseFn native_fclose_fn @weak @if(!$defined(native_fclose_fn));
FreopenFn native_freopen_fn @weak @if(!$defined(native_freopen_fn));
FseekFn native_fseek_fn @weak @if(!$defined(native_fseek_fn));
FtellFn native_ftell_fn @weak @if(!$defined(native_ftell_fn));
FwriteFn native_fwrite_fn @weak @if(!$defined(native_fwrite_fn));
FreadFn native_fread_fn @weak @if(!$defined(native_fread_fn));
/**
* @require mode.len > 0
@@ -38,20 +23,20 @@ $endif
**/
fn void*! native_fopen(String filename, String mode) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fopen_fn) return native_fopen_fn(filename, mode);
unreachable("Tried to call fopen without support.");
$else
@pool()
{
$if env::os_is_win32():
void* file = (CFile)_wfopen(filename.to_temp_utf16(), filename.to_temp_utf16())!;
$else
void* file = libc::fopen(filename.zstr_tcopy(), mode.zstr_tcopy());
@pool()
{
$if env::os_is_win32():
void* file = (CFile)_wfopen(filename.to_temp_utf16(), filename.to_temp_utf16())!;
$else
void* file = libc::fopen(filename.zstr_tcopy(), mode.zstr_tcopy());
$endif
return file ?: file_open_errno()?;
};
$endif
return file ?: file_open_errno()?;
};
$endif
}
/**
@@ -60,71 +45,71 @@ $endif
**/
fn void*! native_freopen(void* file, String filename, String mode) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_freopen_fn) return native_freopen_fn(file, filename, mode);
unreachable("Tried to call freopen without support.");
$else
@pool()
{
$if env::os_is_win32():
file = _wfreopen(filename.to_temp_utf16(), mode.to_temp_utf16(), file)!;
$else
file = libc::freopen(filename.zstr_tcopy(), mode.zstr_tcopy(), file);
@pool()
{
$if env::os_is_win32():
file = _wfreopen(filename.to_temp_utf16(), mode.to_temp_utf16(), file)!;
$else
file = libc::freopen(filename.zstr_tcopy(), mode.zstr_tcopy(), file);
$endif
return file ?: file_open_errno()?;
};
$endif
return file ?: file_open_errno()?;
};
$endif
}
fn void! native_fseek(void* file, isz offset, Seek seek_mode) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fseek_fn) return native_fseek_fn(file, offset, seek_mode);
unreachable("Tried to call fseek without support.");
$else
$if env::os_is_win32():
bool success = _fseeki64(file, (long)offset, (int)seek_mode) == 0;
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fseek_fn) return native_fseek_fn(file, offset, seek_mode);
unreachable("Tried to call fseek without support.");
$else
bool success = libc::fseek(file, (SeekIndex)offset, (CInt)seek_mode) == 0;
$if env::os_is_win32():
bool success = _fseeki64(file, (long)offset, (int)seek_mode) == 0;
$else
bool success = libc::fseek(file, (SeekIndex)offset, (CInt)seek_mode) == 0;
$endif
if (!success) return file_seek_errno()?;
$endif
if (!success) return file_seek_errno()?;
$endif
}
fn usz! native_ftell(CFile file) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_ftell_fn) return native_ftell_fn(file);
unreachable("Tried to call ftell without support.");
$else
$if env::os_is_win32():
long index = _ftelli64(file);
return index >= 0 ? index : file_seek_errno()?;
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_ftell_fn) return native_ftell_fn(file);
unreachable("Tried to call ftell without support.");
$else
SeekIndex index = libc::ftell(file);
return index >= 0 ? index : file_seek_errno()?;
$if env::os_is_win32():
long index = _ftelli64(file);
return index >= 0 ? index : file_seek_errno()?;
$else
SeekIndex index = libc::ftell(file);
return index >= 0 ? index : file_seek_errno()?;
$endif
$endif
$endif
}
fn usz! native_fwrite(CFile file, char[] buffer) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fwrite_fn) return native_fwrite_fn(file, buffer);
unreachable("Tried to call fwrite without support.");
$else
return libc::fwrite(buffer.ptr, 1, buffer.len, file);
$endif
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fwrite_fn) return native_fwrite_fn(file, buffer);
unreachable("Tried to call fwrite without support.");
$else
return libc::fwrite(buffer.ptr, 1, buffer.len, file);
$endif
}
fn usz! native_fread(CFile file, char[] buffer) @inline
{
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fread_fn) return native_fread_fn(file, buffer);
unreachable("Tried to call fread without support.");
$else
return libc::fread(buffer.ptr, 1, buffer.len, file);
$endif
$if !env::COMPILER_LIBC_AVAILABLE:
if (native_fread_fn) return native_fread_fn(file, buffer);
unreachable("Tried to call fread without support.");
$else
return libc::fread(buffer.ptr, 1, buffer.len, file);
$endif
}
macro anyfault file_open_errno() @local
@@ -175,13 +160,10 @@ macro anyfault file_seek_errno() @local
}
// Win functions
$if env::os_is_win32():
extern fn void* _wfopen(Char16*, Char16*) @local;
extern fn void* _wfreopen(Char16*, Char16*, CFile) @local;
extern fn int _fseeki64(CFile, long, int) @local;
extern fn long _ftelli64(CFile) @local;
$endif
extern fn void* _wfopen(Char16*, Char16*) @local @if(WIN32_LIBC);
extern fn void* _wfreopen(Char16*, Char16*, CFile) @local @if(WIN32_LIBC);
extern fn int _fseeki64(CFile, long, int) @local @if(WIN32_LIBC);
extern fn long _ftelli64(CFile) @local @if(WIN32_LIBC);
$if env::os_is_posix():
extern fn CInt access(ZString path, CInt mode);
$endif
// Posix functions
extern fn CInt access(ZString path, CInt mode) @if(POSIX_LIBC);

View File

@@ -1,8 +1,6 @@
module std::io::file::os;
module std::io::file::os @if(DARWIN_LIBC);
import libc;
$if env::os_is_darwin():
struct DarwinTimespec @private
{
long tv_sec;
@@ -97,5 +95,4 @@ fn void! read_stat(Darwin64Stat* stat, String path) @local
}
}
};
}
$endif
}

View File

@@ -1,7 +1,25 @@
module std::io::file::os;
const USE_DARWIN_INODE64 = env::os_is_darwin() && env::ARCH_TYPE == X86_64;
extern fn NativeDirentry* readdir(void*) @extern("readdir") @if(!USE_DARWIN_INODE64) ;
extern fn NativeDirentry* readdir(void*) @extern("readdir$INODE64") @if(USE_DARWIN_INODE64);
struct NativeDirentry
{
usz ino;
usz seekoff @if(env::os_is_darwin());
isz seekoff @if(!env::os_is_darwin());
ushort reclen;
ushort namelen @if(env::os_is_darwin());
char type;
char[1024] name @if(env::os_is_darwin());
char[*] name @if(!env::os_is_darwin());
}
module std::io::file::os @if(!env::os_is_win32());
// native_temp_directory, for non Win32
$if !env::os_is_win32():
fn Path! native_temp_directory(Allocator* using = mem::heap())
{
@@ -13,7 +31,7 @@ fn Path! native_temp_directory(Allocator* using = mem::heap())
return path::new("/tmp", using);
}
$if env::COMPILER_LIBC_AVAILABLE:
module std::io::file::os @if(env::COMPILER_LIBC_AVAILABLE && !env::os_is_win32());
extern fn void* opendir(ZString);
extern fn void closedir(void*);
@@ -80,11 +98,7 @@ fn void! native_rmtree(Path dir)
os::native_rmdir(dir)!;
}
$endif
$endif
$if !env::os_is_darwin() && !env::os_is_win32():
module std::io::file::os @if(!env::os_is_darwin() && !env::os_is_win32());
fn usz! native_file_size(String path)
{
@@ -93,89 +107,38 @@ fn usz! native_file_size(String path)
return f.seek(0, Seek.END)!;
}
$if env::os_is_posix() && env::COMPILER_LIBC_AVAILABLE:
fn bool native_file_or_dir_exists(String path)
{
@pool()
{
return os::access(path.zstr_tcopy(), 0 /* F_OK */) != -1;
};
$if POSIX_LIBC:
@pool()
{
return os::access(path.zstr_tcopy(), 0 /* F_OK */) != -1;
};
$else
unreachable("Tried to call file_or_dir_exists without support.");
return false;
$endif
}
fn bool native_is_file(String path)
{
File! f = file::open(path, "r");
defer (void)f.close();
return @ok(f);
$if POSIX_LIBC:
File! f = file::open(path, "r");
defer (void)f.close();
return @ok(f);
$else
unreachable("Tried to call is_file without support.");
return false;
$endif
}
fn bool native_is_dir(String path)
{
return native_file_or_dir_exists(path) && !native_is_file(path);
$if POSIX_LIBC:
return native_file_or_dir_exists(path) && !native_is_file(path);
$else
unreachable("Tried to call is_dir without support.");
return false;
$endif
}
$else
fn bool native_file_or_dir_exists(String path)
{
unreachable("Tried to call file_or_dir_exists without support.");
}
fn bool native_is_dir(String path)
{
unreachable("Tried to call is_dir without support.");
}
fn bool native_is_file(String path)
{
unreachable("Tried to call is_file without support.");
}
$endif
$endif
$switch (env::OS_TYPE)
$case IOS:
$case MACOS:
$case TVOS:
$case WATCHOS:
$if env::ARCH_TYPE == X86_64:
extern fn NativeDirentry* readdir(void*) @extern("readdir$INODE64");
$else
extern fn NativeDirentry* readdir(void*) @extern("readdir");
$endif
struct NativeDirentry
{
usz ino;
usz seekoff;
ushort reclen;
ushort namelen;
char type;
char[1024] name;
}
$case LINUX:
extern fn NativeDirentry* readdir(void*);
struct NativeDirentry
{
usz ino;
isz seekoff;
ushort reclen;
char type;
char[*] name;
}
$default:
// Fix this as we go along.
extern fn NativeDirentry* readdir(void*);
struct NativeDirentry
{
usz ino;
isz seekoff;
ushort reclen;
char type;
char[*] name;
}
$endswitch

View File

@@ -1,8 +1,6 @@
module std::io::file::os;
module std::io::file::os @if(env::os_is_win32());
import std::os::win32;
$if env::os_is_win32():
const Win32_DWORD FILE_ATTRIBUTE_READONLY = 0x01;
const Win32_DWORD FILE_ATTRIBUTE_HIDDEN = 0x02;
const Win32_DWORD FILE_ATTRIBUTE_SYSTEM = 0x04;
@@ -110,4 +108,3 @@ fn Path! native_temp_directory(Allocator* using = mem::heap())
}
}
*/
$endif

View File

@@ -1,51 +1,42 @@
module std::io::os;
import libc;
$switch
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
macro String! getcwd(Allocator* using = mem::heap())
{
const DEFAULT_BUFFER = 256;
Char16[DEFAULT_BUFFER] buffer;
Char16 *res = win32::_wgetcwd(&buffer, DEFAULT_BUFFER);
bool free = false;
defer if (free) libc::free(res);
if (!res)
{
if (libc::errno() != errno::ERANGE) return IoError.GENERAL_ERROR?;
res = win32::_wgetcwd(null, 0);
free = true;
}
Char16[] str16 = res[:win32::wcslen(res)];
return string::from_utf16(str16, using);
$switch
$case WIN32_LIBC:
const DEFAULT_BUFFER = 256;
Char16[DEFAULT_BUFFER] buffer;
Char16 *res = win32::_wgetcwd(&buffer, DEFAULT_BUFFER);
bool free = false;
defer if (free) libc::free(res);
if (!res)
{
if (libc::errno() != errno::ERANGE) return IoError.GENERAL_ERROR?;
res = win32::_wgetcwd(null, 0);
free = true;
}
Char16[] str16 = res[:win32::wcslen(res)];
return string::from_utf16(str16, using);
$case POSIX_LIBC:
const usz DEFAULT_BUFFER = 256;
char[DEFAULT_BUFFER] buffer;
ZString res = posix::getcwd(&buffer, DEFAULT_BUFFER);
bool free = false;
if (!res)
{
// Improve error
if (libc::errno() != errno::ERANGE) return IoError.GENERAL_ERROR?;
res = posix::getcwd(null, 0);
free = true;
}
defer if (free) libc::free((void*)res);
return res.copy(using);
$default:
unreachable("'getcwd' not available");
return "";
$endswitch
}
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_posix():
macro String! getcwd(Allocator* using = mem::heap())
{
const usz DEFAULT_BUFFER = 256;
char[DEFAULT_BUFFER] buffer;
ZString res = posix::getcwd(&buffer, DEFAULT_BUFFER);
bool free = false;
if (!res)
{
// Improve error
if (libc::errno() != errno::ERANGE) return IoError.GENERAL_ERROR?;
res = posix::getcwd(null, 0);
free = true;
}
defer if (free) libc::free((void*)res);
return res.copy(using);
}
$default:
fn String! getcwd(Allocator* using = mem::heap())
{
unreachable("'getcwd' not available");
}
$endswitch

View File

@@ -4,60 +4,48 @@ import std::io::path;
import std::os::win32;
import std::os::posix;
$switch
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_posix():
macro bool! native_mkdir(Path path, MkdirPermissions permissions)
{
if (!posix::mkdir(path.as_zstr(), permissions == NORMAL ? 0o777 : 0o700)) return true;
switch (libc::errno())
{
case errno::EACCES:
case errno::EPERM:
case errno::EROFS:
case errno::EFAULT: return IoError.NO_PERMISSION?;
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
case errno::EDQUOT:
case errno::ENOSPC: return IoError.OUT_OF_SPACE?;
case errno::EISDIR:
case errno::EEXIST: return false;
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
case errno::ENOTDIR: return IoError.FILE_NOT_FOUND?;
default: return IoError.GENERAL_ERROR?;
}
}
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
macro bool! native_mkdir(Path path, MkdirPermissions permissions)
{
@pool()
{
// TODO security attributes
if (win32::win32_CreateDirectoryW(path.as_str().to_temp_utf16()!!, null)) return true;
switch (win32::win32_GetLastError())
{
case win32::ERROR_ACCESS_DENIED:
return IoError.NO_PERMISSION?;
case win32::ERROR_DISK_FULL:
return IoError.OUT_OF_SPACE?;
case win32::ERROR_ALREADY_EXISTS:
return false;
case win32::ERROR_PATH_NOT_FOUND:
return IoError.FILE_NOT_FOUND?;
default:
return IoError.GENERAL_ERROR?;
}
};
}
$default:
fn bool! native_mkdir(Path path, MkdirPermissions permissions)
{
unreachable("'mkdir' not available");
return false;
}
$endswitch
$switch
$case POSIX_LIBC:
if (!posix::mkdir(path.as_zstr(), permissions == NORMAL ? 0o777 : 0o700)) return true;
switch (libc::errno())
{
case errno::EACCES:
case errno::EPERM:
case errno::EROFS:
case errno::EFAULT: return IoError.NO_PERMISSION?;
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
case errno::EDQUOT:
case errno::ENOSPC: return IoError.OUT_OF_SPACE?;
case errno::EISDIR:
case errno::EEXIST: return false;
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
case errno::ENOTDIR: return IoError.FILE_NOT_FOUND?;
default: return IoError.GENERAL_ERROR?;
}
$case WIN32_LIBC:
@pool()
{
// TODO security attributes
if (win32::win32_CreateDirectoryW(path.as_str().to_temp_utf16()!!, null)) return true;
switch (win32::win32_GetLastError())
{
case win32::ERROR_ACCESS_DENIED:
return IoError.NO_PERMISSION?;
case win32::ERROR_DISK_FULL:
return IoError.OUT_OF_SPACE?;
case win32::ERROR_ALREADY_EXISTS:
return false;
case win32::ERROR_PATH_NOT_FOUND:
return IoError.FILE_NOT_FOUND?;
default:
return IoError.GENERAL_ERROR?;
}
};
$default:
unreachable("'mkdir' not available");
return false;
$endswitch
}

View File

@@ -4,58 +4,46 @@ import std::io::path;
import std::os::win32;
import std::os::posix;
$switch
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_posix():
macro bool! native_rmdir(Path path)
{
if (!posix::rmdir(path.as_zstr())) return true;
switch (libc::errno())
{
case errno::EBUSY: return IoError.BUSY?;
case errno::EACCES:
case errno::EPERM:
case errno::EROFS:
case errno::EFAULT: return IoError.NO_PERMISSION?;
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
case errno::ENOTDIR:
case errno::ENOENT: return false;
case errno::ENOTEMPTY: return IoError.DIR_NOT_EMPTY?;
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
default: return IoError.GENERAL_ERROR?;
}
$switch
$case POSIX_LIBC:
if (!posix::rmdir(path.as_zstr())) return true;
switch (libc::errno())
{
case errno::EBUSY: return IoError.BUSY?;
case errno::EACCES:
case errno::EPERM:
case errno::EROFS:
case errno::EFAULT: return IoError.NO_PERMISSION?;
case errno::ENAMETOOLONG: return IoError.NAME_TOO_LONG?;
case errno::ENOTDIR:
case errno::ENOENT: return false;
case errno::ENOTEMPTY: return IoError.DIR_NOT_EMPTY?;
case errno::ELOOP: return IoError.SYMLINK_FAILED?;
default: return IoError.GENERAL_ERROR?;
}
$case WIN32_LIBC:
@pool()
{
if (win32::win32_RemoveDirectoryW(path.as_str().to_temp_utf16()!!)) return true;
switch (win32::win32_GetLastError())
{
case win32::ERROR_ACCESS_DENIED:
return IoError.NO_PERMISSION?;
case win32::ERROR_CURRENT_DIRECTORY:
return IoError.BUSY?;
case win32::ERROR_DIR_NOT_EMPTY:
return IoError.DIR_NOT_EMPTY?;
case win32::ERROR_DIRECTORY:
case win32::ERROR_PATH_NOT_FOUND:
return false;
default:
return IoError.GENERAL_ERROR?;
}
};
$default:
unreachable("'rmdir' not available");
return false;
$endswitch
}
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
macro bool! native_rmdir(Path path)
{
@pool()
{
if (win32::win32_RemoveDirectoryW(path.as_str().to_temp_utf16()!!)) return true;
switch (win32::win32_GetLastError())
{
case win32::ERROR_ACCESS_DENIED:
return IoError.NO_PERMISSION?;
case win32::ERROR_CURRENT_DIRECTORY:
return IoError.BUSY?;
case win32::ERROR_DIR_NOT_EMPTY:
return IoError.DIR_NOT_EMPTY?;
case win32::ERROR_DIRECTORY:
case win32::ERROR_PATH_NOT_FOUND:
return false;
default:
return IoError.GENERAL_ERROR?;
}
};
}
$default:
fn bool! native_rmdir(Path path)
{
unreachable("'rmdir' not available");
}
$endswitch

View File

@@ -96,11 +96,11 @@ fn bool! rmdir(Path path)
fn void! rmtree(Path path)
{
if (!path.path_string.len) return PathResult.INVALID_PATH?;
$if $defined(os::native_rmtree):
return os::native_rmtree(path);
$else
assert(false, "rmtree is not available");
$endif
$if $defined(os::native_rmtree):
return os::native_rmtree(path);
$else
assert(false, "rmtree is not available");
$endif
}
fn Path! new(String path, Allocator* using = mem::heap(), PathEnv path_env = DEFAULT_PATH_ENV)

View File

@@ -35,7 +35,7 @@ def TerminateFunction = fn void();
def CompareFunction = fn int(void*, void*);
def JmpBuf = uptr[$$JMP_BUF_SIZE];
$if env::COMPILER_LIBC_AVAILABLE:
module libc @if(env::COMPILER_LIBC_AVAILABLE);
extern fn double atof(char* str);
extern fn int atoi(char* str);
@@ -59,13 +59,12 @@ extern fn int rand();
extern fn void srand(uint seed);
extern fn void longjmp(JmpBuf* buffer, CInt value);
$if env::os_is_win32():
// TODO win32 aarch64
extern fn CInt _setjmp(void* frameptr, JmpBuf* buffer);
macro CInt setjmp(JmpBuf* buffer) => _setjmp($$frameaddress(), buffer);
$else
extern fn CInt setjmp(JmpBuf* buffer);
$endif
extern fn CInt _setjmp(void* frameptr, JmpBuf* buffer) @if(env::WIN32);
macro CInt setjmp(JmpBuf* buffer) @if(env::WIN32) => _setjmp($$frameaddress(), buffer);
extern fn CInt setjmp(JmpBuf* buffer) @if(!env::WIN32);
// MB functions omitted
// string
@@ -97,7 +96,110 @@ extern fn void* calloc(usz count, usz size);
extern fn void* free(void*);
extern fn void* realloc(void* ptr, usz size);
$else
extern fn int fclose(CFile stream);
extern fn void clearerr(CFile stream);
extern fn int feof(CFile stream);
extern fn int ferror(CFile stream);
extern fn int fflush(CFile stream);
extern fn int fgetpos(CFile stream, Fpos* pos);
extern fn CFile fopen(ZString filename, ZString mode);
extern fn usz fread(void* ptr, usz size, usz nmemb, CFile stream);
extern fn CFile freopen(ZString filename, ZString mode, CFile stream);
extern fn CFile fmemopen(void* ptr, usz size, ZString mode);
extern fn int fseek(CFile stream, SeekIndex offset, int whence);
extern fn int fsetpos(CFile stream, Fpos* pos);
extern fn SeekIndex ftell(CFile stream);
extern fn usz fwrite(void* ptr, usz size, usz nmemb, CFile stream);
extern fn int remove(char* filename);
extern fn int rename(char* old_name, char* new_name);
extern fn void rewind(CFile stream);
extern fn void setbuf(CFile stream, char* buffer);
extern fn void setvbuf(CFile stream, char* buffer, int mode, usz size);
extern fn CFile tmpnam(char* str);
extern fn int fprintf(CFile stream, char* format, ...);
extern fn int printf(char* format, ...);
extern fn int sprintf(char* str, char* format, ...);
extern fn int snprintf(char* str, usz size, char* format, ...);
extern fn int fscanf(CFile stream, char* format, ...);
extern fn int scanf(char* format, ...);
extern fn int sscanf(char* str, char* format, ...);
extern fn int fgetc(CFile stream);
extern fn char* fgets(char* str, int n, CFile stream);
extern fn int fputc(int c, CFile stream);
extern fn int getc(CFile stream);
extern fn int getchar();
extern fn int putc(int c, CFile stream);
extern fn int putchar(int c);
extern fn int puts(char* str);
extern fn int ungetc(int c, CFile stream);
extern fn void perror(char* str);
extern fn isz getline(char** linep, usz* linecapp, CFile stream);
extern fn int timespec_get(TimeSpec* ts, int base);
extern fn int nanosleep(TimeSpec* req, TimeSpec* remaining);
extern fn ZString asctime(Tm *timeptr);
extern fn Clock_t clock();
extern fn ZString ctime(Time_t *timer);
extern fn double difftime(Time_t time1, Time_t time2);
extern fn Tm* gmtime(Time_t *timer);
extern fn Tm* localtime(Time_t *timer);
extern fn usz strftime(char* str, usz maxsize, char* format, Tm *timeptr);
extern fn Time_t time(Time_t *timer);
// signal
def SignalFunction = fn void(int);
extern fn SignalFunction signal(int sig, SignalFunction function);
// Incomplete
module libc @if(LINUX_LIBC);
extern CFile __stdin @extern("stdin");
extern CFile __stdout @extern("stdout");
extern CFile __stderr @extern("stderr");
extern fn usz malloc_usable_size(void* ptr);
macro usz malloc_size(void* ptr) => malloc_usable_size(ptr);
extern fn void* aligned_alloc(usz align, usz size);
macro CFile stdin() => __stdin;
macro CFile stdout() => __stdout;
macro CFile stderr() => __stderr;
module libc @if(DARWIN_LIBC);
extern CFile __stdinp;
extern CFile __stdoutp;
extern CFile __stderrp;
extern fn usz malloc_size(void* ptr);
extern fn void* aligned_alloc(usz align, usz size);
macro CFile stdin() => __stdinp;
macro CFile stdout() => __stdoutp;
macro CFile stderr() => __stderrp;
module libc @if(WIN32_LIBC);
extern fn CFile __acrt_iob_func(CInt c);
extern fn usz _msize(void* ptr);
macro usz malloc_size(void* ptr) => _msize(ptr);
macro CFile stdin() => __acrt_iob_func(0);
macro CFile stdout() => __acrt_iob_func(1);
macro CFile stderr() => __acrt_iob_func(2);
extern fn Tm* _gmtime64_s(Tm* buf, Time_t *timer);
extern fn Tm* _localtime64_s(Tm* buf, Time_t *timer);
extern fn void _get_timezone(CLong *timezone);
macro Tm* gmtime_r(Time_t *timer, Tm* buf) => _gmtime64_s(buf, timer);
macro Tm* localtime_r(Time_t *timer, Tm* buf) => _localtime64_s(buf, timer);
extern fn Time_t mktime(Tm *timeptr) @extern("_mktime64");
extern fn Time_t timegm(Tm *timeptr) @extern("_mkgmtime64");
module libc @if(env::COMPILER_LIBC_AVAILABLE && !env::WIN32 && !env::LINUX && !env::DARWIN);
macro CFile stdin() { return (CFile*)(uptr)0; }
macro CFile stdout() { return (CFile*)(uptr)1; }
macro CFile stderr() { return (CFile*)(uptr)2; }
module libc @if(env::COMPILER_LIBC_AVAILABLE && !env::WIN32);
extern fn Tm* gmtime_r(Time_t *timer, Tm* buf);
extern fn Tm* localtime_r(Time_t *timer, Tm* buf);
extern fn Time_t mktime(Tm *timeptr);
extern fn Time_t timegm(Tm *timeptr);
module libc @if(!env::COMPILER_LIBC_AVAILABLE);
fn void longjmp(JmpBuf* buffer, CInt value) @weak @extern("longjmp") @nostrip
{
@@ -144,110 +246,6 @@ fn void* memset(void* dest, CInt value, usz n) @weak @extern("memset") @nostrip
return dest;
}
$endif
// stdio
def Fpos = long;
def CFile = void*;
$switch
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == LINUX:
extern CFile __stdin @extern("stdin");
extern CFile __stdout @extern("stdout");
extern CFile __stderr @extern("stderr");
extern fn usz malloc_usable_size(void* ptr);
macro usz malloc_size(void* ptr) { return malloc_usable_size(ptr); }
extern fn void* aligned_alloc(usz align, usz size);
macro CFile stdin() { return __stdin; }
macro CFile stdout() { return __stdout; }
macro CFile stderr() { return __stderr; }
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_darwin():
extern CFile __stdinp;
extern CFile __stdoutp;
extern CFile __stderrp;
extern fn usz malloc_size(void* ptr);
extern fn void* aligned_alloc(usz align, usz size);
macro CFile stdin() { return __stdinp; }
macro CFile stdout() { return __stdoutp; }
macro CFile stderr() { return __stderrp; }
$case env::COMPILER_LIBC_AVAILABLE && env::os_is_win32():
extern fn CFile __acrt_iob_func(CInt c);
extern fn usz _msize(void* ptr);
macro usz malloc_size(void* ptr) { return _msize(ptr); }
macro CFile stdin() { return __acrt_iob_func(0); }
macro CFile stdout() { return __acrt_iob_func(1); }
macro CFile stderr() { return __acrt_iob_func(2); }
$default:
macro CFile stdin() { return (CFile*)(uptr)0; }
macro CFile stdout() { return (CFile*)(uptr)1; }
macro CFile stderr() { return (CFile*)(uptr)2; }
$endswitch
const HAS_MALLOC_SIZE =
env::OS_TYPE == LINUX
|| env::os_is_win32()
|| env::os_is_darwin();
// The following needs to be set per arch+os
// For now I have simply pulled the defaults from MacOS
const int SEEK_SET = 0;
const int SEEK_CUR = 1;
const int SEEK_END = 2;
const int _IOFBF = 0; // Fully buffered
const int _IOLBF = 1; // Line buffered
const int _IONBF = 2; // Unbuffered
const int BUFSIZ = 1024;
const int EOF = -1;
const int FOPEN_MAX = 20;
const int FILENAME_MAX = 1024;
def Errno = distinct CInt;
def SeekIndex = CLong;
$if env::COMPILER_LIBC_AVAILABLE:
extern fn int fclose(CFile stream);
extern fn void clearerr(CFile stream);
extern fn int feof(CFile stream);
extern fn int ferror(CFile stream);
extern fn int fflush(CFile stream);
extern fn int fgetpos(CFile stream, Fpos* pos);
extern fn CFile fopen(ZString filename, ZString mode);
extern fn usz fread(void* ptr, usz size, usz nmemb, CFile stream);
extern fn CFile freopen(ZString filename, ZString mode, CFile stream);
extern fn CFile fmemopen(void* ptr, usz size, ZString mode);
extern fn int fseek(CFile stream, SeekIndex offset, int whence);
extern fn int fsetpos(CFile stream, Fpos* pos);
extern fn SeekIndex ftell(CFile stream);
extern fn usz fwrite(void* ptr, usz size, usz nmemb, CFile stream);
extern fn int remove(char* filename);
extern fn int rename(char* old_name, char* new_name);
extern fn void rewind(CFile stream);
extern fn void setbuf(CFile stream, char* buffer);
extern fn void setvbuf(CFile stream, char* buffer, int mode, usz size);
extern fn CFile tmpnam(char* str);
extern fn int fprintf(CFile stream, char* format, ...);
extern fn int printf(char* format, ...);
extern fn int sprintf(char* str, char* format, ...);
extern fn int snprintf(char* str, usz size, char* format, ...);
extern fn int fscanf(CFile stream, char* format, ...);
extern fn int scanf(char* format, ...);
extern fn int sscanf(char* str, char* format, ...);
extern fn int fgetc(CFile stream);
extern fn char* fgets(char* str, int n, CFile stream);
extern fn int fputc(int c, CFile stream);
extern fn int getc(CFile stream);
extern fn int getchar();
extern fn int putc(int c, CFile stream);
extern fn int putchar(int c);
extern fn int puts(char* str);
extern fn int ungetc(int c, CFile stream);
extern fn void perror(char* str);
extern fn isz getline(char** linep, usz* linecapp, CFile stream);
$else
fn int fseek(CFile stream, SeekIndex offset, int whence) @weak @extern("fseek") @nostrip
{
unreachable("'fseek' not available.");
@@ -315,12 +313,40 @@ fn int puts(ZString str) @weak @extern("puts") @nostrip
unreachable("'puts' not available.");
}
$endif
module libc;
// stdio
def Fpos = long;
def CFile = void*;
const HAS_MALLOC_SIZE =
env::OS_TYPE == LINUX
|| env::os_is_win32()
|| env::os_is_darwin();
// The following needs to be set per arch+os
// For now I have simply pulled the defaults from MacOS
const int SEEK_SET = 0;
const int SEEK_CUR = 1;
const int SEEK_END = 2;
const int _IOFBF = 0; // Fully buffered
const int _IOLBF = 1; // Line buffered
const int _IONBF = 2; // Unbuffered
const int BUFSIZ = 1024;
const int EOF = -1;
const int FOPEN_MAX = 20;
const int FILENAME_MAX = 1024;
def Errno = distinct CInt;
def SeekIndex = CLong;
// vsprintf vprintf not supported
// time.h
struct TmCommon @private
struct Tm
{
int tm_sec; /* seconds after the minute [0-60] */
int tm_min; /* minutes after the hour [0-59] */
@@ -331,112 +357,33 @@ struct TmCommon @private
int tm_wday; /* days since Sunday [0-6] */
int tm_yday; /* days since January 1 [0-365] */
int tm_isdst; /* Daylight Savings Time flag */
TimeOffset tm_gmtoff @if(!env::WIN32); /* offset from UTC in seconds */
char *tm_zone @if(!env::WIN32); /* timezone abbreviation */
int tm_nsec @if(env::WASI);
}
$switch (env::OS_TYPE)
$case WIN32:
def Tm = TmCommon;
$case WASI:
def TimeOffset = int;
struct Tm
{
inline TmCommon common;
TimeOffset tm_gmtoff; /* offset from UTC in seconds */
char *tm_zone; /* timezone abbreviation */
int tm_nsec;
}
$case MACOS:
$case IOS:
$case TVOS:
$case WATCHOS:
$case OPENBSD:
$case FREEBSD:
$default:
def TimeOffset = CLong;
struct Tm
{
inline TmCommon common;
TimeOffset tm_gmtoff; /* offset from UTC in seconds */
char *tm_zone; /* timezone abbreviation */
}
$endswitch
$if env::os_is_win32():
struct TimeSpec
{
Time_t s;
ulong ns;
ulong ns @if(env::WIN32);
CLong ns @if(!env::WIN32);
}
def Time_t = long;
def Clock_t = ulong;
def Time_t = long @if(env::WIN32);
def Time_t = CLong @if(!env::WIN32);
def Clock_t = ulong @if(env::WIN32);
def Clock_t = CULong @if(!env::WIN32);
$else
struct TimeSpec
{
Time_t s;
CLong ns;
}
def Time_t = CLong;
def Clock_t = CULong;
$endif
def TimeOffset = int @if(env::WASI) ;
def TimeOffset = CLong @if(!env::WASI) ;
const int TIME_UTC = 1;
extern fn int timespec_get(TimeSpec* ts, int base);
extern fn int nanosleep(TimeSpec* req, TimeSpec* remaining);
// Likely wrong, must be per platform.
const CLOCKS_PER_SEC = 1000000;
extern fn ZString asctime(Tm *timeptr);
extern fn Clock_t clock();
extern fn ZString ctime(Time_t *timer);
extern fn double difftime(Time_t time1, Time_t time2);
extern fn Tm* gmtime(Time_t *timer);
extern fn Tm* localtime(Time_t *timer);
$if env::os_is_win32():
extern fn Tm* _gmtime64_s(Tm* buf, Time_t *timer);
extern fn Tm* _localtime64_s(Tm* buf, Time_t *timer);
extern fn void _get_timezone(CLong *timezone);
macro Tm* gmtime_r(Time_t *timer, Tm* buf) => _gmtime64_s(buf, timer);
macro Tm* localtime_r(Time_t *timer, Tm* buf) => _localtime64_s(buf, timer);
extern fn Time_t mktime(Tm *timeptr) @extern("_mktime64");
extern fn Time_t timegm(Tm *timeptr) @extern("_mkgmtime64");
$else
extern fn Tm* gmtime_r(Time_t *timer, Tm* buf);
extern fn Tm* localtime_r(Time_t *timer, Tm* buf);
extern fn Time_t mktime(Tm *timeptr);
extern fn Time_t timegm(Tm *timeptr);
$endif
extern fn usz strftime(char* str, usz maxsize, char* format, Tm *timeptr);
extern fn Time_t time(Time_t *timer);
// signal
def SignalFunction = fn void(int);
extern fn SignalFunction signal(int sig, SignalFunction function);
// Incomplete
module libc::errno;
const Errno OK = 0;
@@ -451,11 +398,9 @@ const Errno ENOEXEC = 8; // Exec format error
const Errno EBADF = 9; // Bad file number
const Errno ECHILD = 10; // No child processes
$if env::os_is_darwin():
const Errno EAGAIN = 35; // Try again Macos
$else
const Errno EAGAIN = 11; // Try again
$endif
const Errno EAGAIN @if(env::DARWIN) = 35; // Try again Macos
const Errno EAGAIN @if(!env::DARWIN) = 11; // Try again
const Errno ENOMEM = 12; // Out of memory
const Errno EACCES = 13; // Permission denied
@@ -481,9 +426,7 @@ const Errno EPIPE = 32; // Broken pipe
const Errno EDOM = 33; // Math argument out of domain of func
const Errno ERANGE = 34; // Math result not representable
$switch (env::OS_TYPE)
$case MACOS:
module libc::errno @if(env::DARWIN);
const Errno EDEADLK = 11; // Resource deadlock would occur MacOS
const Errno ENAMETOOLONG = 63; // File name too long MacOS
const Errno ELOOP = 62; // Too many symbolic links encountered
@@ -494,8 +437,13 @@ const Errno ENETUNREACH = 51; // Network is unreachable MacOS
const Errno ENETRESET = 52; // Network dropped connection because of reset MacOS
const Errno EOPNOTSUPP = 45; // Operation not supported on transport endpoint
const Errno ENOTEMPTY = 66; // Directory not empty
const Errno ETIMEDOUT = 60; // Connection timed out
const Errno EINPROGRESS = 36; // Operation now in progress MacOS
const Errno EALREADY = 37; // Operation already in progress MacOS
const Errno EDQUOT = 69; // Quota exceeded, MacOS
const Errno EWOULDBLOCK = 35; // Operation would block
$case WIN32:
module libc::errno @if(env::WIN32);
const Errno EDEADLK = 36; // Resource deadlock would occur Win32
const Errno ENAMETOOLONG = 38; // File name too long Win32
const Errno ELOOP = 114; // Too many symbolic links encountered
@@ -506,8 +454,13 @@ const Errno ENETUNREACH = 118; // Network is unreachable
const Errno ENETRESET = 117; // Network dropped connection because of reset
const Errno EOPNOTSUPP = 130; // Operation not supported on transport endpoint
const Errno ENOTEMPTY = 41; // Directory not empty
const Errno ETIMEDOUT = 138; // Connection timed out
const Errno EALREADY = 103; // Operation already in progress
const Errno EINPROGRESS = 112; // Operation now in progress Win32
const Errno EDQUOT = -122; // Quota exceeded, not in Win32
const Errno EWOULDBLOCK = 140; // Operation would block
$default:
module libc::errno @if(!env::WIN32 && !env::DARWIN);
const Errno EDEADLK = 35; // Resource deadlock would occur Linux (others?)
const Errno ENAMETOOLONG = 36; // File name too long Linux (others?)
const Errno ELOOP = 40; // Too many symbolic links encountered
@@ -518,9 +471,11 @@ const Errno ENETUNREACH = 101; // Network is unreachable
const Errno ENETRESET = 102; // Network dropped connection because of reset
const Errno EOPNOTSUPP = 95; // Operation not supported on transport endpoint
const Errno ENOTEMPTY = 39; // Directory not empty
$endswitch
const Errno ETIMEDOUT = 110; // Connection timed out
const Errno EALREADY = 114; // Operation already in progress
const Errno EINPROGRESS = 115; // Operation now in progress
const Errno EDQUOT = 122; // Quota exceeded
const Errno EWOULDBLOCK = 41; // Operation would block
/*
@@ -594,29 +549,6 @@ const Errno EHOSTDOWN = 112; /* Host is down */
const Errno EHOSTUNREACH = 113; /* No route to host */
*/
$switch (env::OS_TYPE)
$case MACOS:
const Errno ETIMEDOUT = 60; // Connection timed out
const Errno EINPROGRESS = 36; // Operation now in progress MacOS
const Errno EALREADY = 37; // Operation already in progress MacOS
const Errno EDQUOT = 69; // Quota exceeded, MacOS
const Errno EWOULDBLOCK = 35; // Operation would block
$case WIN32:
const Errno ETIMEDOUT = 138; // Connection timed out
const Errno EALREADY = 103; // Operation already in progress
const Errno EINPROGRESS = 112; // Operation now in progress Win32
const Errno EDQUOT = -122; // Quota exceeded, not in Win32
const Errno EWOULDBLOCK = 140; // Operation would block
$default:
const Errno ETIMEDOUT = 110; // Connection timed out
const Errno EALREADY = 114; // Operation already in progress
const Errno EINPROGRESS = 115; // Operation now in progress
const Errno EDQUOT = 122; // Quota exceeded
const Errno EWOULDBLOCK = 41; // Operation would block
$endswitch
/*
const Errno ESTALE = 116; /* Stale NFS file handle */

View File

@@ -1,38 +1,28 @@
module libc::os;
// Linux
extern fn int* __errno_location() @if(LINUX_LIBC);
macro int errno() @if(LINUX_LIBC) => *__errno_location();
macro void errno_set(int err) @if(LINUX_LIBC) => *(__errno_location()) = err;
$switch
// Darwin
extern fn int* __error() @if(DARWIN_LIBC);
macro int errno() @if(DARWIN_LIBC) => *__error();
macro void errno_set(int err) @if(DARWIN_LIBC) => *(__error()) = err;
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == LINUX:
extern fn int* __errno_location();
macro int errno() => *__errno_location();
macro void errno_set(int err) => *(__errno_location()) = err;
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == MACOS:
extern fn int* __error();
macro int errno() => *__error();
macro void errno_set(int err) => *(__error()) = err;
$case env::COMPILER_LIBC_AVAILABLE && env::OS_TYPE == WIN32:
macro int errno()
// Win32
macro int errno() @if(WIN32_LIBC)
{
int holder;
_get_errno(&holder);
return holder;
}
macro void errno_set(int err) @if(WIN32_LIBC) => _set_errno(err);
extern fn void _get_errno(int* result) @if(WIN32_LIBC);
extern fn void _set_errno(int err) @if(WIN32_LIBC);
macro void errno_set(int err) => _set_errno(err);
extern fn void _get_errno(int* result);
extern fn void _set_errno(int err);
$default:
tlocal int _errno_c3 = 0;
fn void errno_set(int err) => _errno_c3 = err;
fn int errno() => _errno_c3;
$endswitch
// Default
const ERRNO_DEFAULT @local = !LINUX_LIBC && !DARWIN_LIBC && !WIN32_LIBC;
tlocal int _errno_c3 @if(ERRNO_DEFAULT) = 0;
fn void errno_set(int err) @if(ERRNO_DEFAULT) => _errno_c3 = err;
fn int errno() @if(ERRNO_DEFAULT) => _errno_c3;

View File

@@ -471,14 +471,14 @@ macro sqrt(x) => $$sqrt(values::promote_int(x));
macro tan(x)
{
var $Type = $typeof(x);
$switch
$case types::is_vector($Type):
return $$sin(x) / $$cos(x);
$case $Type.typeid == float.typeid:
return _tanf(x);
$default:
return _tan(x);
$endswitch
$switch
$case types::is_vector($Type):
return $$sin(x) / $$cos(x);
$case $Type.typeid == float.typeid:
return _tanf(x);
$default:
return _tan(x);
$endswitch
}
/**
@@ -487,11 +487,11 @@ $endswitch
macro bool is_finite(x)
{
$switch ($typeof(x))
$case float:
$case float16:
return bitcast((float)x, uint) & 0x7fffffff < 0x7f800000;
$default:
return bitcast((double)x, ulong) & (~0u64 >> 1) < 0x7ffu64 << 52;
$case float:
$case float16:
return bitcast((float)x, uint) & 0x7fffffff < 0x7f800000;
$default:
return bitcast((double)x, ulong) & (~0u64 >> 1) < 0x7ffu64 << 52;
$endswitch
}

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
/* origin: FreeBSD /usr/src/lib/msun/src/k_cos.c */
/*
@@ -31,4 +29,3 @@ fn double __cos(double x, double y) @extern("__cos") @weak @nostrip
return w + (((1.0 - w) - hz) + (z * r - x * y));
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
/* origin: FreeBSD /usr/src/lib/msun/src/k_cosf.c */
/*
@@ -32,5 +30,3 @@ fn float __cosdf(double x) @extern("__cosdf") @weak @nostrip
double r = C2 + z * C3;
return (float)(((1.0f + z * C0) + w * C1) + (w * z) * r);
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
/* origin: FreeBSD /usr/src/lib/msun/src/k_sin.c */
/*
@@ -31,5 +29,3 @@ fn double __sin(double x, double y, int iy) @extern("__sin") @weak @nostrip
? x + v * (S1 + z * r)
: x - ((z * (0.5 * y - v * r) - y) - v * S1);
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
/* origin: FreeBSD /usr/src/lib/msun/src/k_sinf.c */
/*
@@ -31,4 +29,3 @@ fn float __sindf(double x) @extern("__sindf") @weak @nostrip
return (float)((x + s * (S1F + z * S2F)) + s * w * r);
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
/* origin: FreeBSD /usr/src/lib/msun/src/k_tan.c */
/*
@@ -79,5 +77,3 @@ fn double __tan(double x, double y, int odd) @extern("__tan") @weak @nostrip
double a0 = bitcast(d, double);
return a0 + a * (1.0 + a0 * w0 + a0 * v);
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
/* origin: FreeBSD /usr/src/lib/msun/src/k_tanf.c */
/*
@@ -52,5 +50,3 @@ fn float __tandf(double x, int odd) @extern("__tandf") @weak @nostrip
r = (x + s * u) + (s * w) * (t + w * r);
return (float)(odd ? -1.0 / r : r);
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc::atan;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
const double[*] ATANHI @private = {
4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
@@ -320,5 +318,3 @@ fn float _atan2f(float y, float x) @weak @extern("atan2f") @nostrip
default: return (z - PI_LO_F) - PI_F; /* atan(-,-) */
}
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
fn double _ceil(double x) @weak @extern("ceil") @nostrip
{
@@ -42,4 +40,3 @@ fn float _ceilf(float x) @weak @extern("ceilf") @nostrip
return bitcast(u, float);
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
fn float _cosf(float x) @extern("cosf") @weak @nostrip
{
@@ -54,7 +52,7 @@ fn float _cosf(float x) @extern("cosf") @weak @nostrip
* ====================================================
*/
fn double _cos(double x) @extern("cos") @weak @nostrip
fn double _cos(double x) @weak @nostrip
{
// High word of x.
uint ix = (uint)(bitcast(x, ulong) >> 32);
@@ -87,5 +85,3 @@ fn double _cos(double x) @extern("cos") @weak @nostrip
}
}
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
macro uint _top12f(float x) @private => bitcast(x, uint) >> 20;
@@ -141,4 +139,3 @@ fn double _exp2(double x) @extern("exp2") @weak @nostrip
is no spurious underflow here even without fma. */
return scale + scale * tmp;
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
fn double _floor(double x) @weak @extern("floor") @nostrip
{
@@ -42,4 +40,3 @@ fn float _floorf(float x) @weak @extern("floorf") @nostrip
return bitcast(u, float);
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
fn float powf_broken(float x, float f) @extern("powf") @weak @nostrip
{
@@ -11,5 +9,3 @@ fn double pow_broken(double x, double y) @extern("pow") @weak @nostrip
{
unreachable("'pow' not supported");
}
$endif

View File

@@ -1,8 +1,6 @@
module std::math::nolibc;
module std::math::nolibc @if(env::NO_LIBC);
import std::math;
$if !env::COMPILER_LIBC_AVAILABLE:
/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2f.c */
/*
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
@@ -537,4 +535,3 @@ fn int __rem_pio2(double x, double *y)
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
fn double _round(double x) @extern("round") @weak @nostrip
{
@@ -53,4 +51,3 @@ fn float _roundf(float x) @extern("roundf") @weak @nostrip
return y;
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
fn double _scalbn(double x, int n) @weak @extern("scalbn") @nostrip
{
@@ -27,5 +25,3 @@ fn double _scalbn(double x, int n) @weak @extern("scalbn") @nostrip
}
return x * bitcast(((ulong)(0x3ff + n)) << 52, double);
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
/* origin: FreeBSD /usr/src/lib/msun/src/s_sinf.c */
/*
@@ -119,4 +117,3 @@ fn double sin(double x) @extern("sin") @weak @nostrip
}
}
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
/* origin: FreeBSD /usr/src/lib/msun/src/s_sinf.c */
/*
@@ -156,4 +154,3 @@ fn void sincos(double x, double *sin, double *cos) @extern("sincos") @weak @nost
}
}
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
/* origin: FreeBSD /usr/src/lib/msun/src/s_tan.c */
/*
@@ -100,4 +98,3 @@ fn float tanf(float x) @extern("tanf") @weak @nostrip
}
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc::trig;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
fn double sincos_broken(double x) @extern("sincos") @weak @nostrip
{
@@ -8,4 +6,3 @@ fn double sincos_broken(double x) @extern("sincos") @weak @nostrip
}
$endif

View File

@@ -1,6 +1,4 @@
module std::math::nolibc;
$if !env::COMPILER_LIBC_AVAILABLE:
module std::math::nolibc @if(env::NO_LIBC);
fn double _trunc(double x) @weak @extern("trunc") @nostrip
{
@@ -28,4 +26,3 @@ fn float _truncf(float x) @weak @extern("truncf") @nostrip
return bitcast(i, float);
}
$endif

View File

@@ -1,21 +1,32 @@
module std::net::os;
$if $defined(PLATFORM_AF_INET):
struct AddrInfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
usz ai_addrlen;
void* ai_addr;
char* ai_canonname;
AddrInfo* ai_next;
}
$if !$defined(PLATFORM_O_NONBLOCK):
const PLATFORM_O_NONBLOCK = 0;
$endif
const bool SUPPORTS_INET = env::WIN32 || env::DARWIN || env::LINUX;
const PLATFORM_O_NONBLOCK @if(!$defined(PLATFORM_O_NONBLOCK)) = 0;
const AI_PASSIVE = 0x1;
const AI_CANONNAME = 0x2;
const AI_NUMERICHOST = 0x4;
const int AF_UNSPEC = 0;
const int AF_INET = PLATFORM_AF_INET;
const int AF_APPLETALK = PLATFORM_AF_APPLETALK;
const int AF_IPX = PLATFORM_AF_IPX;
const int AF_INET6 = PLATFORM_AF_INET6;
const int AF_INET @if(SUPPORTS_INET) = PLATFORM_AF_INET;
const int AF_APPLETALK @if(SUPPORTS_INET) = PLATFORM_AF_APPLETALK;
const int AF_IPX @if(SUPPORTS_INET) = PLATFORM_AF_IPX;
const int AF_INET6 @if(SUPPORTS_INET) = PLATFORM_AF_INET6;
const O_NONBLOCK = PLATFORM_O_NONBLOCK;
$endif

View File

@@ -1,8 +1,6 @@
module std::net::os;
module std::net::os @if(env::DARWIN);
import libc;
$if env::os_is_darwin():
const AI_NUMERICSERV = 0x1000;
const AI_ALL = 0x100;
const AI_V4MAPPED_CFG = 0x200;
@@ -11,18 +9,6 @@ const AI_V4MAPPED = 0x800;
const AI_UNUSABLE = 0x10000000;
const AI_DEFAULT = AI_V4MAPPED_CFG | AI_ADDRCONFIG;
struct AddrInfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
usz ai_addrlen;
void* ai_addr;
char* ai_canonname;
AddrInfo* ai_next;
}
const int PLATFORM_AF_UNIX = 1;
const int PLATFORM_AF_INET = 2;
const int PLATFORM_AF_IMPLINK = 3;
@@ -61,7 +47,4 @@ const int PLATFORM_AF_IEEE80211 = 37;
const int PLATFORM_AF_UTUN = 38;
const int PLATFORM_AF_VSOCK = 40;
const int PLATFORM_AF_MAX = 41;
const int PLATFORM_O_NONBLOCK = 0x30;
$endif
const int PLATFORM_O_NONBLOCK = 0x30;

View File

@@ -1,20 +1,6 @@
module std::net::os;
module std::net::os @if(env::LINUX);
import libc;
$if env::OS_TYPE == LINUX:
struct AddrInfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
usz ai_addrlen;
void* ai_addr;
char* ai_canonname;
AddrInfo* ai_next;
}
const int PLATFORM_AF_UNIX = 1;
const int PLATFORM_AF_INET = 2;
const int PLATFORM_AF_AX25 = 3;
@@ -26,6 +12,4 @@ const int PLATFORM_AF_AAL5 = 8;
const int PLATFORM_AF_X25 = 9;
const int PLATFORM_AF_INET6 = 10;
const PLATFORM_O_NONBLOCK = 0o4000;
$endif
const PLATFORM_O_NONBLOCK = 0o4000;

View File

@@ -1,8 +1,6 @@
module std::net::os;
module std::net::os @if(env::POSIX && SUPPORTS_INET);
import libc;
$if !env::os_is_win32() && $defined(AddrInfo):
const int F_GETFL = 3;
const int F_SETFL = 4;
@@ -37,6 +35,4 @@ macro void! NativeSocket.set_non_blocking(NativeSocket this)
macro bool NativeSocket.is_non_blocking(NativeSocket this)
{
return fcntl(this, F_GETFL, 0) & O_NONBLOCK == O_NONBLOCK;
}
$endif
}

View File

@@ -1,6 +1,4 @@
module std::net::os;
$if env::os_is_win32():
module std::net::os @if(env::WIN32);
const int PLATFORM_AF_INET = 1;
const int PLATFORM_AF_IPX = 6;
@@ -10,18 +8,6 @@ const int PLATFORM_AF_INET6 = 23;
const int PLATFORM_AF_IRDA = 26;
const int PLATFORM_AF_BTH = 32;
struct AddrInfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
usz ai_addrlen;
char* ai_canonname;
void* ai_addr;
AddrInfo* ai_next;
}
def NativeSocket = distinct uptr;
extern fn int wsa_startup(int, void*) @extern("WSAStartup");
@@ -29,5 +15,3 @@ extern fn int ioctlsocket(NativeSocket, long cmd, ulong *argp);
extern fn int closesocket(NativeSocket);
macro NativeSocket.close(NativeSocket this) => closesocket(this);
$endif

View File

@@ -1,6 +1,4 @@
module std::os::macos::cf;
$if env::os_is_darwin():
module std::os::macos::cf @if(DARWIN_LIBC);
def CFAllocatorRef = distinct void*;
def CFAllocatorContextRef = distinct void*;
@@ -18,4 +16,3 @@ extern fn CFAllocatorRef _macos_CFAllocatorGetDefault() @extern("CFAllocatorGetD
extern fn void _macos_CFAllocatorSetDefault(CFAllocatorRef allocator) @extern("CFAllocatorSetDefault");
extern fn void* _macos_CFAllocatorAllocate(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) @extern("CFAllocatorAllocate");
extern fn CFIndex _macos_CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) @extern("CFAllocatorGetPreferredSizeForSize");
$endif

View File

@@ -1,6 +1,4 @@
module std::os::macos::cf;
$if env::os_is_darwin():
module std::os::macos::cf @if(DARWIN_LIBC);
def CFArrayRef = distinct void*;
def CFArrayCallBacksRef = distinct void*;
@@ -11,4 +9,3 @@ extern fn CFIndex _macos_CFArrayGetCount(CFArrayRef array) @extern("CFArrayGetCo
extern fn void _macos_CFArrayAppendArray(CFMutableArrayRef theArray, CFArrayRef otherArray, CFRange otherRange) @extern("CFArrayAppendArray");
extern fn CFMutableArrayRef _macos_CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, CFArrayCallBacksRef callBacks) @extern("CFArrayCreateMutable");
extern fn void _macos_CFArrayAppendValue(CFMutableArrayRef theArray, void *value) @extern("CFArrayAppendValue");
$endif

View File

@@ -1,6 +1,4 @@
module std::os::macos::cf;
$if env::os_is_darwin():
module std::os::macos::cf @if(DARWIN_LIBC);
def CFTypeRef = distinct void*;
def CFIndex = isz;
@@ -12,5 +10,3 @@ struct CFRange
extern fn CFTypeRef _macos_CFRetain(CFTypeRef cf) @extern("CFRetain");
extern fn void _macos_CFRelease(CFTypeRef cf) @extern("CFRelease");
$endif

View File

@@ -1,6 +1,4 @@
module std::os::macos::objc;
$if env::os_is_darwin():
module std::os::macos::objc @if(DARWIN_LIBC);
def Class = distinct void*;
def Method = distinct void*;
@@ -45,5 +43,5 @@ extern fn Method _macos_class_getClassMethod(Class cls, Selector name) @extern("
extern fn bool _macos_class_respondsToSelector(Class cls, Selector name) @extern("class_respondsToSelector");
extern fn Selector _macos_sel_registerName(char* str) @extern("sel_registerName");
extern fn Class _macos_objc_lookUpClass(char* name) @extern("objc_lookUpClass");
$endif

View File

@@ -1,10 +1,6 @@
module std::os::posix;
$if env::os_is_posix() && env::COMPILER_LIBC_AVAILABLE:
module std::os::posix @if(POSIX_LIBC);
extern fn int rmdir(ZString);
extern fn int mkdir(ZString, ushort mode_t);
extern fn int chdir(ZString);
extern fn ZString getcwd(char* pwd, usz len);
$endif

View File

@@ -1,6 +1,4 @@
module std::os::win32;
$if env::os_is_win32():
module std::os::win32 @if(WIN32_LIBC);
enum Win32_GET_FILEEX_INFO_LEVELS
{
@@ -63,4 +61,3 @@ extern bool _win32_CreateSymbolicLinkW(Char16* symlink_file, Char16* target_file
extern bool _win32_CopyFileW(Char16* from_file, Char16* to_file, bool no_overwrite) @extern("CopyFileW");
extern ulong _win32_GetFullPathNameW(Char16* file_name, ulong buffer_len, Char16* buffer, Char16** file_part) @extern("GetFullPathNameW");
*/
$endif

View File

@@ -1,6 +1,4 @@
module std::os::win32;
$if env::os_is_win32():
module std::os::win32 @if(WIN32_LIBC);
extern fn Win32_DWORD win32_GetLastError() @extern("GetLastError");
@@ -224,4 +222,3 @@ const Win32_DWORD ERROR_MR_MID_NOT_FOUND = 0x13D;
const Win32_DWORD ERROR_SCOPE_NOT_FOUND = 0x13E;
const Win32_DWORD ERROR_UNDEFINED_SCOPE = 0x13F;
$endif

View File

@@ -1,6 +1,4 @@
module std::os::win32;
$if env::os_is_win32():
module std::os::win32 @if(WIN32_LIBC);
extern fn bool win32_CreateProcessW(
Win32_LPCWSTR lpApplicationName,
@@ -14,5 +12,3 @@ extern fn bool win32_CreateProcessW(
Win32_LPSTARTUPINFOW lpStartupInfo,
Win32_LPPROCESS_INFORMATION lpProcessInformation
) @extern("CreateProcessW");
$endif

View File

@@ -1,16 +1,12 @@
module std::os::win32;
module std::os::win32 @if(WIN32_LIBC);
def WSAError = distinct int;
$if env::os_is_win32():
extern fn WSAError win32_WSAGetLastError() @extern("WSAGetLastError");
extern fn void win32_WSASetLastError(WSAError error) @extern("WSASetLastError");
$endif
module std::os::win32::wsa;
module std::os::win32::wsa @if(env::WIN32);
$if env::os_is_win32():
const WSAError INVALID_HANDLE = 6;
const WSAError NOT_ENOUGHT_MEMORY = 8;
const WSAError INVALID_PARAMETER = 87;
@@ -32,5 +28,4 @@ const WSAError EMSGSIZE = 10040;
const WSAError EPROTOTYPE = 10041;
const WSAError ENOPROTOOPT = 10042;
const WSAError EPROTONOSUPPORT = 10043;
const WSAError ESOCKTNOSUPPORT = 10044;
$endif
const WSAError ESOCKTNOSUPPORT = 10044;

View File

@@ -1,8 +1,6 @@
module std::thread::os;
module std::thread::os @if(thread::THREAD_MODEL == ThreadModel.POSIX);
import libc;
$if thread::THREAD_MODEL == ThreadModel.POSIX:
const PTHREAD_MUTEX_NORMAL = 0;
const PTHREAD_MUTEX_ERRORCHECK = 1;
const PTHREAD_MUTEX_RECURSIVE = 2;
@@ -13,23 +11,6 @@ def NativeThread = Pthread;
def NativeOnceFlag = PthreadOnce;
def Pthread = distinct void*;
$if env::OS_TYPE == LINUX:
def PthreadMutex = distinct ulong[5];
def PthreadAttribute = distinct ulong[7];
def PthreadMutexAttribute = distinct uint;
def PthreadCondAttribute = distinct uint;
def PthreadCond = distinct ulong[6];
def PthreadOnce = distinct uint;
$else
def PthreadMutex = distinct ulong[8];
def PthreadMutexAttribute = distinct ulong[2];
def PthreadAttribute = distinct ulong[8];
def PthreadCond = distinct ulong[6];
def PthreadCondAttribute = distinct ulong[8];
def PthreadOnce = distinct ulong[2];
$endif
def PosixThreadFn = fn void*(void*);
extern fn int pthread_attr_destroy(PthreadAttribute*);
@@ -236,4 +217,18 @@ fn void! native_sleep(double s)
if (libc::nanosleep(&to, null)) return ThreadFault.INTERRUPTED?;
}
$endif
module std::thread::os @if(thread::THREAD_MODEL == ThreadModel.POSIX && !env::LINUX);
def PthreadMutex = distinct ulong[8];
def PthreadMutexAttribute = distinct ulong[2];
def PthreadAttribute = distinct ulong[8];
def PthreadCond = distinct ulong[6];
def PthreadCondAttribute = distinct ulong[8];
def PthreadOnce = distinct ulong[2];
module std::thread::os @if(thread::THREAD_MODEL == ThreadModel.POSIX && env::LINUX);
def PthreadMutex = distinct ulong[5];
def PthreadAttribute = distinct ulong[7];
def PthreadMutexAttribute = distinct uint;
def PthreadCondAttribute = distinct uint;
def PthreadCond = distinct ulong[6];
def PthreadOnce = distinct uint;

View File

@@ -1,6 +1,4 @@
module std::thread::os;
$if thread::THREAD_MODEL == ThreadModel.WIN32:
module std::thread::os @if(thread::THREAD_MODEL == ThreadModel.WIN32);
def NativeThread = Win32_HANDLE;
@@ -345,5 +343,3 @@ fn void! native_sleep_nano(ulong ns)
{
return native_sleep_ms(ns < 1000_000 ? 1 : ns / 1000_000);
}
$endif

View File

@@ -2,11 +2,11 @@ module std::time::clock;
fn Clock now()
{
$if $defined(native_clock):
return os::native_clock();
$else
return 0;
$endif
$if $defined(native_clock):
return os::native_clock();
$else
return 0;
$endif
}
fn NanoDuration Clock.mark(Clock* this)

View File

@@ -36,14 +36,14 @@ fn TzDateTime DateTime.to_local(DateTime* this)
dt.weekday = !tm.tm_wday ? Weekday.SUNDAY : (Weekday)tm.tm_wday + 1;
dt.year_day = (ushort)tm.tm_yday;
dt.time = this.time;
$if $defined(tm.tm_gmtoff):
dt.gmt_offset = (int)tm.tm_gmtoff;
$else
$assert $defined(libc::_get_timezone);
CLong timezone;
libc::_get_timezone(&timezone);
dt.gmt_offset = (int)-timezone;
$endif
$if $defined(tm.tm_gmtoff):
dt.gmt_offset = (int)tm.tm_gmtoff;
$else
$assert $defined(libc::_get_timezone);
CLong timezone;
libc::_get_timezone(&timezone);
dt.gmt_offset = (int)-timezone;
$endif
return dt;
}

View File

@@ -1,6 +1,4 @@
module std::time::os;
$if env::os_is_darwin():
module std::time::os @if(DARWIN_LIBC);
struct Darwin_mach_timebase_info
{
@@ -23,6 +21,3 @@ fn Clock native_clock()
}
return (Clock)(mach_absolute_time() * timebase.numer / timebase.denom);
}
$endif

View File

@@ -1,17 +1,31 @@
module std::time::os;
module std::time::os @if(POSIX_LIBC);
import libc;
$if env::os_is_posix() && env::COMPILER_LIBC_AVAILABLE:
extern fn void clock_gettime(int type, TimeSpec *time);
$switch (env::OS_TYPE)
$case OPENBSD:
fn Time native_timestamp()
{
TimeSpec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return (Time)(ts.s * 1_000_000i64 + ts.ns / 1_000i64);
}
fn Clock native_clock() @if(!DARWIN_LIBC)
{
TimeSpec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (Clock)((ulong)ts.s * 1_000_000_000u64 + (ulong)ts.ns);
}
module std::time::os @if(OPENBSD_LIBC);
const CLOCK_REALTIME = 0;
const CLOCK_PROCESS_CPUTIME_ID = 2;
const CLOCK_MONOTONIC = 3;
const CLOCK_THREAD_CPUTIME_ID = 4;
const CLOCK_UPTIME = 5;
const CLOCK_BOOTTIME = 6;
$case FREEBSD:
module std::time::os @if(FREEBSD_LIBC);
const CLOCK_REALTIME = 0;
const CLOCK_VIRTUAL = 1;
const CLOCK_PROF = 2;
@@ -29,21 +43,21 @@ const CLOCK_PROCESS_CPUTIME_ID = 15;
const CLOCK_BOOTTIME = CLOCK_UPTIME;
const CLOCK_REALTIME_COARSE = CLOCK_REALTIME_FAST;
const CLOCK_MONOTONIC_COARSE = CLOCK_MONOTONIC_FAST;
$case NETBSD:
module std::time::os @if(NETBSD_LIBC);
const CLOCK_REALTIME = 0;
const CLOCK_VIRTUAL = 1;
const CLOCK_PROF = 2;
const CLOCK_MONOTONIC = 3;
const CLOCK_THREAD_CPUTIME_ID = 0x20000000;
const CLOCK_PROCESS_CPUTIME_ID = 0x40000000;
$case WASI:
module std::time::os @if(WASI_LIBC);
// Not implemented
const CLOCK_REALTIME = 0;
const CLOCK_MONOTONIC = 0;
$case MACOS:
$case TVOS:
$case IOS:
$case WATCHOS:
module std::time::os @if(DARWIN_LIBC);
const CLOCK_REALTIME = 0;
const CLOCK_MONOTONIC = 6;
const CLOCK_MONOTONIC_RAW = 4;
@@ -52,8 +66,8 @@ const CLOCK_UPTIME_RAW = 8;
const CLOCK_UPTIME_RAW_APPROX = 9;
const CLOCK_PROCESS_CPUTIME_ID = 12;
const CLOCK_THREAD_CPUTIME_ID = 16;
$case LINUX:
$default:
module std::time::os @if(LINUX_LIBC);
const CLOCK_REALTIME = 0;
const CLOCK_MONOTONIC = 1;
const CLOCK_PROCESS_CPUTIME_ID = 2;
@@ -65,24 +79,4 @@ const CLOCK_BOOTTIME = 7;
const CLOCK_REALTIME_ALARM = 8;
const CLOCK_BOOTTIME_ALARM = 9;
const CLOCK_TAI = 11;
$endswitch
extern fn void clock_gettime(int type, TimeSpec *time);
fn Time native_timestamp()
{
TimeSpec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return (Time)(ts.s * 1_000_000i64 + ts.ns / 1_000i64);
}
$if !env::os_is_darwin():
fn Clock native_clock()
{
TimeSpec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (Clock)((ulong)ts.s * 1_000_000_000u64 + (ulong)ts.ns);
}
$endif
$endif

View File

@@ -1,8 +1,6 @@
module std::time::os;
module std::time::os @if(WIN32_LIBC);
import std::os::win32;
$if env::os_is_win32() && env::COMPILER_LIBC_AVAILABLE:
extern fn void win32_GetSystemTimeAsFileTime(Win32_FILETIME* time) @extern("GetSystemTimeAsFileTime");
extern fn Win32_BOOL win32_QueryPerformanceFrequency(Win32_LARGE_INTEGER* lpFrequency) @extern("QueryPerformanceFrequency");
extern fn Win32_BOOL win32_QueryPerformanceCounter(Win32_LARGE_INTEGER* lpPerformanceCount) @extern("QueryPerformanceCounter");
@@ -28,6 +26,4 @@ fn Time native_timestamp()
win32_GetSystemTimeAsFileTime(&ft);
ulong result = (ulong)ft.dwHighDateTime << 32 | ft.dwLowDateTime;
return (Time)(result / WINDOWS_TICK_US - WIN_TO_UNIX_EPOCH_US);
}
$endif
}

View File

@@ -1,9 +1,9 @@
module std::time;
def Time @inline = distinct long;
def TimeDuration @inline = distinct long;
def Clock @inline = distinct ulong;
def NanoDuration @inline = distinct long;
def Time = distinct long @inline;
def TimeDuration = distinct long @inline;
def Clock = distinct ulong @inline;
def NanoDuration = distinct long @inline;
const TimeDuration MICROSECONDS_PER_SECOND = 1_000_000;
const TimeDuration MICROSECONDS_PER_MINUTE = MICROSECONDS_PER_SECOND * 60;
@@ -61,11 +61,11 @@ enum Month : char
fn Time now()
{
$if $defined(native_timestamp):
return os::native_timestamp();
$else
return 0;
$endif
$if $defined(native_timestamp):
return os::native_timestamp();
$else
return 0;
$endif
}
fn Time Time.add_seconds(Time time, long seconds) => time + (Time)(seconds * (long)MICROSECONDS_PER_SECOND);