Biscuit Language (0.10.0)

Builtin

Compiler builtins are automatically loaded into every assembly.

Current running platform

Platform :: enum s32 {
    UNKNOWN;
    WINDOWS;
    DARWIN;
    LINUX;
}

PLATFORM :: <SET_BY_COMPILER>;

Current running architecture

Arch :: enum s32 {
    UNKNOWN;
    X86_64;
    AARCH64;
    ARM64;
}

ARCH :: <SET_BY_COMPILER>;

Current running environment

Env :: enum s32 {
    UNKNOWN;
    MSVC;
    GNU;
    MUSL;
}

ENV :: <SET_BY_COMPILER>;

Compiler version

BLC_VER_MAJOR : s32 : <SET_BY_COMPILER>;
BLC_VER_MINOR : s32 : <SET_BY_COMPILER>;
BLC_VER_PATCH : s32 : <SET_BY_COMPILER>;

TypeKind

TypeKind :: enum {
    TYPE :: 1;
    VOID :: 2;
    INT :: 3;
    REAL :: 4;
    FN :: 5;
    PTR :: 6;
    BOOL :: 7;
    ARRAY :: 8;
    STRUCT :: 9;
    ENUM :: 10;
    NULL :: 11;
    STRING :: 12;
    FN_GROUP :: 16;
}

TypeKind describes kind of BL type returned in TypeInfo structure. This value can be used for safe casting.

Variants

File: a.bl

TypeInfo

TypeInfo :: struct {
    kind: TypeKind;
    size_bytes: usize;
}

Base TypeInfo structure returned by typeinfo operator. This structure pointer can be casted to child type to get more descriptive information about the type.

Members

File: a.bl

TypeInfoInt

TypeInfoInt :: struct {
    bit_count: s32;
    is_signed: bool;
}

Detailed information about integer types: s8, s16, s32, s64, u8, u16, u32, u64, usize.

Members

File: a.bl

TypeInfoReal

TypeInfoReal :: struct {
    bit_count: s32;
}

Detailed information about real types: f32, f64.

Members

File: a.bl

TypeInfoFn

TypeInfoFn :: struct {
    args: []TypeInfoFnArg;
    ret_type: *TypeInfo;
    is_vargs: bool;
}

Detailed information about function types.

Members

File: a.bl

TypeInfoFnGroup

TypeInfoFnGroup :: struct {
    variants: []*TypeInfoFn;
}

Detailed information about function group and contained possible overloads.

Members

File: a.bl

TypeInfoPtr

TypeInfoPtr :: struct {
    pointee_type: *TypeInfo;
}

Detailed information about pointer types.

Members

File: a.bl

TypeInfoArray

TypeInfoArray :: struct {
    name: string;
    elem_type: *TypeInfo;
    len: s64;
}

Detailed information about array types.

Members

File: a.bl

TypeInfoStruct

TypeInfoStruct :: struct {
    name: string;
    members: []TypeInfoStructMember;
    is_slice: bool;
    is_union: bool;
    is_dynamic_array: bool;
}

Detailed information about structure types.

Members

File: a.bl

TypeInfoEnum

TypeInfoEnum :: struct {
    name: string;
    base_type: *TypeInfo;
    variants: []TypeInfoEnumVariant;
    is_flags: bool;
}

Detailed information about enumerator types.

Members

File: a.bl

TypeInfoVoid

TypeInfoVoid :: struct {
}

Placeholder for information about void type.

File: a.bl

TypeInfoNull

TypeInfoNull :: struct {
}

Placeholder for information about null type.

File: a.bl

TypeInfoString

TypeInfoString :: struct {
}

Placeholder for information about string type.

File: a.bl

TypeInfoType

TypeInfoType :: struct {
}

Placeholder for information about type type.

File: a.bl

TypeInfoBool

TypeInfoBool :: struct {
}

Placeholder for information about bool type.

File: a.bl

TypeInfoStructMember

TypeInfoStructMember :: struct {
    name: string;
    base_type: *TypeInfo;
    offset_bytes: s32;
    index: s32;
    tags: s32;
    is_base: bool;
}

Detailed information about structure member.

Members

Foo :: struct {
    i: s32 #tags TAG1;
    j: s32 #tags TAG1, TAG2;
};

Where tags must be compile-time constant of s32 type.

TAG1 :: 0x1;
TAG2 :: 0x2;

File: a.bl

TypeInfoEnumVariant

TypeInfoEnumVariant :: struct {
    name: string;
    value: s64;
}

Detailed information about enumerator variant.

Members

File: a.bl

TypeInfoFnArg

TypeInfoFnArg :: struct {
    name: string;
    base_type: *TypeInfo;
}

Detailed information about function’s argument.

Members

File: a.bl

Any

Any :: struct {
    type_info: *TypeInfo;
    data: *u8;
}

Any type is special builtin type used for passing value of “any” type as function argument.

Members

File: a.bl

TestCase

TestCase :: struct {
    func: *fn () ;
    name: string;
}

Type of test case record found during compilation.

Members

File: a.bl

CodeLocation

CodeLocation :: struct {
    file: string;
    line: s32;
    hash: u32;
}

Type of source code location used by #call_location directive.

Example

foo :: fn (loc: *CodeLocation = #call_location) {
    print("%\n", @loc);
}

main :: fn () s32 {
    foo();
    return 0;
}

Members

File: a.bl

PrintLogFn

PrintLogFn :: *fn (kind: PrintLogKind, file: string, line: s32, format: string, args: ...) 

Type of print log function.

Arguments

File: a.bl

AbortFn

AbortFn :: *fn () 

File: a.bl

Context

Context :: struct {
    print_log_fn: PrintLogFn;
    abort_fn: AbortFn;
    allocator: *Allocator;
}

Default implicit context type. Implicit context is compiler internal global variable containing basic context for whole assembly. This variable is mutable and can be modified by user code.

Members

File: a.bl

command_line_arguments

command_line_arguments : []string = 

Contains all arguments passed from command line. First argument is executable name.

File: a.bl

enum_count

enum_count :: fn (T: type) s64

Compile-time helper function resolving count of enumerator variants, passed type ‘T’ must be an enumerator type (checked by assert).

File: a.bl

is_number

is_number :: fn (T: type) bool

Return true if the T type is a number type.

File: a.bl

is_signed_number

is_signed_number :: fn (T: type) bool

Return true if the T type is a signed number type.

File: a.bl

is_pointer

is_pointer :: fn (T: type) bool

Return true if the T type is a pointer type.

File: a.bl

is_function

is_function :: fn (T: type) bool

Return true if the T type is a function type.

File: a.bl

number_type

number_type :: fn (size_bytes: usize, is_signed: bool) type

Return signed or unsigned builtin number type of the requested size. The size_bytes must be 1, 2, 4 or 8 Bytes.

File: a.bl

Command Line Argument Parser

#import "std/arg_parser"

Generic command line argument parsing tool.

Example

#import "std/arg_parser"

// Command line arguments context.
Args :: struct #base ArgParser.Ctx {
    my_flag: bool;
    my_name: string;
}

g_args: Args;

main :: fn () s32 {
    parser :: ArgParser.new();
    defer ArgParser.delete(parser);
    // After this all positional arguments stored inside the argument parser
    // context are invalid.
    defer ArgParser.ctx_terminate(&g_args);

    // Add new argument.
    ArgParser.add(
        parser, 
        "-f", // Short name (must start with -)
        "--flag", // Long name (must start with -)
        "Specify my flag.", // Help text.
        &fn (parser: ArgParser.Parser, args: []string, ctx: *ArgParser.Ctx) (s32, Error) {
            a: *Args = auto ctx;
            a.my_flag = true;
            return 1, ok(); // Return number of parsed arguments and state.
        });

    ArgParser.add(
        parser,
        "-n",
        "--name",
        "Specify my name.",
        &fn (parser: ArgParser.Parser, args: []string, ctx: *ArgParser.Ctx) (s32, Error) {
            a: *Args = auto ctx;
            if (args.len < 2) {
                return 0, error("Expected name!");
            }
            a.my_name = args[1];
            return 2, ok();
        });

    // Start parsing.
    state :: ArgParser.run(parser, command_line_arguments, &g_args, 1);
    if !is_ok(state) {
        print_err("%", state);
        ArgParser.print_help(parser);
        return 1;
    }

    print("%\n", g_args);
    return 0;
}

ArgParser.Ctx

Ctx :: struct {
    positional: [..]string;
    help: bool;
}

Arguments context base type.

Members

File: arg_parser.bl

ArgParser.Parser

Parser :: *u8

Argument parser opaque handle.

File: arg_parser.bl

ArgParser.HandlerFn

HandlerFn :: *fn (parser: Parser, args: []string, ctx: *Ctx) (_0: s32, _1: Error
)

Argument parser callback function type. In context of add this callback function provides current parser, rest of the input argument slice starting from currently captured argument name and custom argument context ctx. Expected return of such function is count of parsed arguments from args input (at least one for successfully parsed argument with no additional input) and status.

See also: add

todo: Is reference to parent parser needed here?

File: arg_parser.bl

ArgParser.new

new :: fn (help_text :: ) Parser

Create new instance of parser with possibility to set custom help text. Use delete to release parser instance.

File: arg_parser.bl

ArgParser.delete

delete :: fn (_parser: Parser) 

Delete parser instance.

File: arg_parser.bl

ArgParser.ctx_terminate

ctx_terminate :: fn (ctx: *Ctx) 

Release ‘positional’ arguments array inside the context data.

File: arg_parser.bl

ArgParser.run

run :: fn (_parser: Parser, args: []string, ctx: *Ctx, start :: 0) Error

Perform parsing on input args slice and provide ctx as context to the argument parsing callbacks. start specify first element of args slice considered to be an argument. See also: (command_line_arguments)[#argparsercommand_line_arguments] (note: first element contains name of the executable)

File: arg_parser.bl

ArgParser.add

add :: fn (_parser: Parser, short: string, long: string, help: string, handler: HandlerFn) 

Add new argument specified by short and long name to be recognised by parser. The argument description can be specified as help. handler function is called every time parser hits this argument (short or long name match). Argument name must be unique name starting with -. Help command (as -h or --help) is added by default.

Example

ArgParser.add(parser,
    "-d", // short name.
    "--debug", // long name.
    "Enable debug mode.", // Help text.
    &fn (parser: ArgParser.Parser, args: []string, ctx: *ArgParser.Ctx) (s32, Error) {
        a: *MyArgs = auto ctx;
        a.is_debug = true;
        return 1, ok(); // One argument parsed ('-d' or '--debug') 
    });

File: arg_parser.bl

ArgParser.print_help

print_help :: fn (_parser: Parser) 

Print help for all registered commands.

File: arg_parser.bl

arm64.bl

C.opendir

opendir :: fn (name: *char) *DIR #extern

File: arm64.bl

C.fdopendir

fdopendir :: fn (fd: int) *DIR #extern

File: arm64.bl

C.readdir

readdir :: fn (dirp: *DIR) *dirent_t #extern

File: arm64.bl

C.rewinddir

rewinddir :: fn (dirp: *DIR)  #extern

File: arm64.bl

C.stat

stat :: fn (path: *char, buf: *stat_t) int #extern

File: arm64.bl

C.fstat

fstat :: fn (fd: int, stat: *stat_t) int #extern

File: arm64.bl

Array

#import "std/array"

Compiler builtin dynamic array is automatically growing memory storage allocated on heap. The array allocated memory block groves over time when we push new values to the array. It’s guaranteed that all pushed elements are stored in single continuous block of memory. When there is no space reminding in currently allocated block, new one is allocated and all already pushed data are copied from old block to the new one.

Example

main :: fn () s32 {
    arr: [..]s32; // dynamic array
    loop i := 0; i < 10; i += 1 {
        array_push(&arr, i);
    }
    print("arr = %\n", arr);
    return 0;
}

array_init

array_init :: fn (_arr: *[..]?T, allocator : *Allocator: )  #inline

Sets dynamic array to default state. If array contains already allocated memory array_terminate must be called first. Custom allocator can be specified.

It’s usually enough to rely on default implicit initialization in case we don’t need specify custom allocator.

File: array.bl

array_terminate

array_terminate :: fn (_arr: *[..]?T)  #inline

Release memory allocated by dynamic array. This function is supposed to be called when dynamic array is no longer needed. Passed dynamic array is set to default state also.

File: array.bl

array_push

array_push :: fn { impl_push_empty; impl_push; }

Append new value at the dynamic array end. New heap allocation is done here only in cases when there is not enough memory allocated to store all values. Returns pointer to the new appended element.

File: array.bl

array_reserve

array_reserve :: fn (_arr: *[..]?T, n: s64)  #inline

Reserve heap memory for n elements in array.

File: array.bl

array_erase

array_erase :: fn (_arr: *[..]?T, i: s64) 

Erase element on index i. Call to this function can cause reorderingof an dynamic array. Allocated memory is kept even if we erase entire dynamic array. Function invoke panic in case of index overflow.

File: array.bl

array_clear

array_clear :: fn (_arr: *[..]?T)  #inline

Erase all elements in dynamic array but keep allocated memory.

File: array.bl

Array Table

#import "std/array_table"

Dynamically allocated generic array table is auto-growing data container mapping keys to values.

ArrayTable

ArrayTable :: fn (TKey: type, TValue: type) type

Create new array table type.

struct {
    keys: [..]TKey;
    values: [..]TValue;
}

File: array_table.bl

atable_init

atable_init :: fn (tbl: *?T) 

File: array_table.bl

atable_terminate

atable_terminate :: fn (tbl: *?T) 

File: array_table.bl

atable_insert

atable_insert :: fn (tbl: *?T, key: , value: ) 

Insert new record into the ‘tbl’ array table. The ‘key’ value must be unique value (checked by assert).

File: array_table.bl

atable_peek

atable_peek :: fn (tbl: *?T, key: ) 

Get value associated with ‘key’, cause panic if the ‘key’ is not present in the table.

File: array_table.bl

atable_contains

atable_contains :: fn (tbl: *?T, key: ) bool

Check whether ‘key’ exists in table.

File: array_table.bl

atable_erase

atable_erase :: fn (tbl: *?T, key: ) 

Erase record in ‘tbl’ associated with ‘key’. Cause panic in case there is no such ‘key’ in the table. Erasing the record can change ordering of the table.

File: array_table.bl

atable_clear

atable_clear :: fn (tbl: *?T)  #inline

Clear all table records and keep allocated memory.

File: array_table.bl

atable_len

atable_len :: fn (tbl: *?T) s64 #inline

Return count of records in the table.

File: array_table.bl

atable_begin

atable_begin :: fn (tbl: *?T)  #inline

Return table iterator pointing to the first record.

File: array_table.bl

atable_end

atable_end :: fn (tbl: *?T)  #inline

Return table iterator pointing after the last record.

File: array_table.bl

atable_iter_eq

atable_iter_eq :: fn (first: *?T, second: *T) bool #inline

Return ‘true’ in case ‘first’ iterator points to the same record as the ‘second’.

File: array_table.bl

atable_iter_next

atable_iter_next :: fn (iter: *?T)  #inline

Move iterator to the next record.

File: array_table.bl

Buffer Allocator

#import "std/buffer_allocator"

The buffer allocator can be used to allocate memory in preallocated blocks on the stack or heap in case we know the size need. It is perfectly fit for temporary allocation in case we need better control over the memory resource.

The preallocated memory block can have an arbitrary size greater than zero.

The block is not supposed to grow and the allocator does not own it. Used buffer is basically appended on every allocation and free takes no effect in this case. In case there is no more space left in the block, the default context allocator is used as a fallback. The buffer can be used multiple times but it should be managed only by one buffer allocator at a time.

Use the standard allocate_memory and free_memory to use the allocator.

Example

#import "std/buffer_allocator"

buffer: [64]u8;

main :: fn () s32 {
    allocator: std.BufferAllocator;
    std.buffer_allocator_init(&allocator, buffer);

    arr: [..]u8;
    // Initialize the array with our custom allocator.
    array_init(&arr, &allocator);

    loop i := 0; i < 10; i += 1 {
        // We're appending the array using our allocator.
        array_push(&arr, auto i);
    }
   
    // Print out the array content;
    print("arr = %\n", arr);

    // All allocations are done on stack inside the 'buffer'. To test it, we can
    // print out the buffer content. Keep in mind that the array preallocates
    // slightly more memory than needed on the first 'array_push` call (for i.e.
    // 32 elements).
    print("buf = %\n", buffer);

    // Also the address of the first element in the array should point to the first
    // element of the buffer.
    print("%\n", buffer.ptr == arr.ptr);

    return 0;
}

std.BufferAllocator

BufferAllocator :: struct {
    mem: []u8;
    used_bytes: usize;
}

Members

File: buffer_allocator.bl

std.buffer_allocator_init

buffer_allocator_init :: fn (allocator: *BufferAllocator, buffer: []u8) 

Use this function to initialize the allocator with an external preallocated buffer. The allocator does not own the buffer resource so there is no need to terminate the allocator instance when it’s no longer needed.

File: buffer_allocator.bl

Build system

#load "build/build.bl"

Compiler integrated build pipeline. Build pipline can be used to manage whole project compilation process directly in BL. All you need is to create the build file called build.bl and specify the build_entry function inside. When -b flag is used without need of specifying any files, the compiler will lookup build.bl file in the current directory and execute it in compile time. All compilation steps, target input and output can be specified here.

Example of minimal build.bl:

build :: fn () #build_entry {
    // create new executable target
    exe :: add_executable("MyProgram");

    // add 'main.bl' file into the target 'exe'
    add_unit(exe, "main.bl");

    // Start compilation
    compile(exe);
}

Start build pipeline using our build.bl file:

$ blc -build

Compiler will automatically use build.bl file as build script and execute build function in compile time. SDK file build/build.bl containing compiler API for build pipeline manipulation is loaded implicitly.

warning: Build API is available only in compile-time.

Basics

Create new executable target

Target is a single build target defined as consisting of build Units representing source files needed for compilation. It`s basically a target compiled into an executable or binary file. Use add_executable function to specify your target. There are several options related to target, described later in this documentation.

exe :: add_executable("MyProgram");

Add file into target

Use add_unit function to add source files into the target. There is no need to add all files you want to use, general load and import will do so automatically. Only main or entry files must be included.

add_unit(exe, "main.bl");

Specify output directory

Output directory is a directory where all compiler-produced files will be written (i.e. native executables). Use set_output_dir function to specify this directory, current directory is used by default.

set_output_dir(exe, "bin");

Compile target

compile(exe);

Command line argumets

All argumets passed after -build compiler flag are automatically forwarded into command_line_arguments global variable.

Target

Target :: struct {
    kind: TargetKind;
    build_mode: BuildMode;
    debug_info_kind: DebugInfo;
    register_split: bool;
    verify_llvm: bool;
    run_tests: bool;
    no_api: bool;
    copy_dependencies: bool;
    run: bool;
    print_tokens: bool;
    print_ast: bool;
    emit_llvm: bool;
    emit_asm: bool;
    emit_mir: bool;
    no_bin: bool;
    no_llvm: bool;
    no_analyze: bool;
    assert_mode: AssertMode;
    syntax_only: bool;
    vmdbg_enabled: bool;
    vmdbg_break_on: s32;
}

Target is representation of whole program workspace, it’s a consist of Units, every unit represents one source file.

Members

File: build.bl

TargetKind

TargetKind :: enum {
    EXECUTABLE :: 0;
    SHARED_LIBRARY :: 1;
}

Specification of compiler output binary kind.

File: build.bl

BuildMode

BuildMode :: enum s32 {
    DEBUG :: 0;
    RELEASE_FAST :: 1;
    RELEASE_SMALL :: 2;
}

Specify target build mode. Every Target can be compiled with various configuration options. The BuildMode can specify which set of options compiler should use.

Variants

File: build.bl

DebugInfo

DebugInfo :: enum s32 {
    DWARF :: 0;
    CODE_VIEW :: 1;
}

Debug information format.

File: build.bl

AssertMode

AssertMode :: enum s32 {
    DEFAULT :: 0;
    ALWAYS_ENABLED :: 1;
    ALWAYS_DISABLED :: 2;
}

Specification of assert mode used for Target.

Variants

File: build.bl

add_executable

add_executable :: fn (name: string) *Target

Add new executable target into the current compilation queue. Target with specified name is compiled into binary or it can be just executed in compile-time without any output created. Assemblies are compiled after build_entry function execution in order they are added.

Example

build :: fn () #build_entry {
    exe :: add_executable("MyProgram");
    add_unit(exe, "src/main.bl");

    mode :: get_build_mode(exe);
    switch mode {
        BuildMode.DEBUG {
            set_output_dir(exe, "build/debug");
        }

        BuildMode.RELEASE_SMALL,
        BuildMode.RELEASE_FAST {
            set_output_dir(exe, "build/release");
        }
    }
    compile(exe);
}

File: build.bl

add_library

add_library :: fn (name: string) *Target

Add new shared library target target into the current compilation queue.

File: build.bl

add_unit

add_unit :: fn (target: *Target, filepath: string) 

Add new source file into the target. Function does nothing when filepath is already present in the target assembly.

File: build.bl

compile

compile :: fn (target: *Target) Error

Start compilation of the target assembly and return ok or error in case compilation failed.

File: build.bl

compile_all

compile_all :: fn () Error

Compile all created targets one by one in order they were created. See also compile.

File: build.bl

add_lib_path

add_lib_path :: fn (target: *Target, path: string) 

Add path for linker library lookup.

File: build.bl

link_library :: fn (target: *Target, name: string) 

Add system library. Only name is required (without extension and prefix). Compiler will lookup for this library in working directory, system PATH and LINKER_LIB_PATH variable specified in bl.conf file. Linked library can be used also during compile-time execution, in such case all needed symbols are loaded in compile-time.

In general there is no need to link libraries manually, all needed dependencies should be handled by module import mechanism, however there is still an option do it manually.

Library name platform specific rules:

Example

build :: fn () #build_entry {
    exe :: add_executable("MyGame");
    add_unit(exe, "src/main.bl");

    switch PLATFORM {
        Platform.WINDOWS { target_windows(exe); }
        default          { panic("Unknown build target!"); }
    }
    compile(exe);
}

target_windows :: fn (exe: *Target) {
    link_library(exe, "freetype");
    link_library(exe, "zlib");
    link_library(exe, "png");
}

File: build.bl

append_linker_options

append_linker_options :: fn (target: *Target, option: string) 

Appends raw string data directly to linker command. Passed option is added without any processing and compatibility validation.

File: build.bl

set_output_dir

set_output_dir :: fn (target: *Target, dir: string) 

Set build output directory. This is directory where all output files will be written. For example different output directory can be set for any build mode.

Directory path dir. This can contain non-existing directories separated by /, compiler will create all missing directories in passed path.

Specified directory will be used also for build temporary files.

File: build.bl

get_output_dir

get_output_dir :: fn (target: *Target) string

Get output directory specified by set_output_dir or empty string.

File: build.bl

ModuleImportPolicy

ModuleImportPolicy :: enum s32 {
    SYSTEM :: 0;
    BUNDLE :: 1;
    BUNDLE_LATEST :: 2;
}

Specify import module policy in set_module_dir function call. Module dependencies of any target can be treated in different ways depending on use case and needs of programmer. Sometimes program stability and maintainability is more important than use of latest versions of modules. These flags can specify how local modules should be updated.

Variants

File: build.bl

set_module_dir

set_module_dir :: fn (target: *Target, dir: string, policy :: ) 

Sets module directory dir for target. All imported modules will be copied into this directory according to chosen ModuleImportPolicy. Module policy is set to SYSTEM by default even if this function has not been called.

File: build.bl

get_module_dir

get_module_dir :: fn (target: *Target) string

Get module directory specified by set_module_dir or default one.

File: build.bl

get_module_import_policy

get_module_import_policy :: fn (target: *Target) ModuleImportPolicy

Get module import policy specified by set_module_dir or default one.

File: build.bl

Debug

#load "std/debug.bl"

Set of common debugging tools. @Incomplete: documentation of debugbreak builtin.

print_log :: fn (format: string, args: ...)  #inline

Print debug log using _context.print_log_fn function. See also :ref:print.

File: debug.bl

print_warn :: fn (format: string, args: ...)  #inline

Print debug warning using _context.print_log_fn function.

File: debug.bl

print_err :: fn { print_err_e; print_err_msg; }

Print debug error using _context.print_log_fn function.

File: debug.bl

assert

assert :: fn (cond: bool, loc :: ) 

Interrupt execution when cond is false. Assert use _context.print_log_fn to print out error message containing assert location in source code.

important: All calls to the assert function are removed from release builds by default.

warning: There is no argument validation in case the assert call is removed from compilation.

File: debug.bl

static_assert

static_assert :: fn (expr: bool) 

Assertion check evaluated in compile time.

File: debug.bl

panic

panic :: fn { panic_empty; panic_error; panic_msg; }

Abort execution and eventually print panic message if there is one specified. First passed argument in ‘args’ will act like format string and can be eventually followed by any additional values required.

Example

panic(); // abort without any messages
panic(error); // abort with :ref:`Error`.
panic("oops!"); // abort with message prited out.
panic("Failed with error: %", errn); // first argument passed acts like formating string

File: debug.bl

PrintLogKind

PrintLogKind :: enum u8 {
    MESSAGE;
    WARNING;
    ERROR;
    ASSERT;
    PANIC;
}

Kinds of log messages.

Variants

File: debug.bl

measure_elapsed_ms_begin

measure_elapsed_ms_begin :: fn ()  #inline

Start measure elapsed milliseconds in the current scope. This function call will push the current time into the thread-local queue. Measurement must be ended by :ref:measure_elapsed_ms_end call.

Example

measure_elapsed_ms_begin();
defer measure_elapsed_ms_end("Name");

warning: Every measure_elapsed_ms_begin must have corresponding measure_elapsed_ms_end call.

File: debug.bl

measure_elapsed_ms_end

measure_elapsed_ms_end :: fn (name :: ) f64 #inline

Pop the last start time from the runtime measurement queue and log the result time difference when the name is specified. Function return time difference between the current time and last start time.

File: debug.bl

Debug Allocator

#import "std/debug_allocator"

Debug allocator can be used to analyze memory usage of program and eventually analyze possible memory leaks. By init call the global context allocator is replaced by debug allocator, every following allocations are recorded and analyzed in runtime since then. Call terminate to swap default context allocator back to previous one.

Example

#import "std/debug_allocator"

main :: fn () s32 {
    std.debug_allocator_init();
    defer std.debug_allocator_terminate();

    // leaking allocation
    alloc(64);
    return 0;
}
$ ./out.exe
******************* MEMORY REPORT ******************
* Allocated 64 Bytes.
* Count of allocations 1.
****************************************************
Dump memory leaks begin:
    [1] - test.bl:10 (64 bytes)
Dump memory leaks end.

note: Debug allocator is thread safe. Init and terminate must be called from main thread.

std.debug_allocator

debug_allocator :: 

File: debug_allocator.bl

std.debug_allocator_init

debug_allocator_init :: fn () 

Initialize Debug Allocator. This function internally swap current global context allocator to debug one. Deinitialization must be done by debug_allocator_terminate call.

File: debug_allocator.bl

std.debug_allocator_terminate

debug_allocator_terminate :: fn (print_report :: ) 

Terminate Debug Allocator. Prints current memory report when print_report is true.

File: debug_allocator.bl

std.debug_allocator_break

debug_allocator_break :: fn (serial: u64)  #inline

Invoke debug_break before allocation with defined serial ID. note: See also print_memory_report

File: debug_allocator.bl

std.debug_allocator_allocated

debug_allocator_allocated :: fn () usize #inline

Return currently allocated memory in bytes.

File: debug_allocator.bl

std.print_memory_report

print_memory_report :: fn (dump_leaks :: ) 

Print memory report. First block contains currently allocated bytes and current count of allocations. Optional memory leak dump block (enabled by dump_leaks argument) contains:

[allocation serial ID] - <file>:<line> (allocation size in bytes) 
$ ./out.exe
******************* MEMORY REPORT ******************
* Allocated 64 Bytes.
* Count of allocations 1.
****************************************************
Dump memory leaks begin:
    [1] - test.bl:10 (64 bytes)
Dump memory leaks end.

note: Printed report contains all remaining (not freed) allocations in time when function was called. Memory leaks can contain false-positives when function is called before execution end.

hint: Allocation serail ID can be used by debug_allocator_break to interrupt execution before memory is allocated and eventually localize allocation in debbuger.

File: debug_allocator.bl

Dynamic Library Tools

#import "std/dlib"

Dynamic library tools for runtime library loading and symbol resolving.

Dlib.Library

Library :: _DlibImpl.Library

Platform specific library handle.

File: dlib.bl

Dlib.open

open :: fn (lib_name :: ) (_0: Library, _1: Error
) #inline

Dynamically loads library specified by lib_name and return it’s handle or null with error. When lib_name is empty, current binary will be loaded. Use close call to close library when it’s not needed anymore.

File: dlib.bl

Dlib.get_symbol

get_symbol :: fn (lib: Library, sym_name: string) (_0: *u8, _1: Error
) #inline

Resolve named symbol in library and return pointer to it.

File: dlib.bl

Dlib.close

close :: fn (lib: Library)  #inline

Close library opened by open call.

File: dlib.bl

Error handling

#load "std/error.bl"

_Error :: struct {
    msg: string;
    code: s32;
}

Error :: *_Error;

Universal error state representation used across the API.

Example

div :: fn (a: s32, b: s32) (s32, Error) {
    if b == 0 {
        // Return error with message.
        return 0, error("Divide by zero '%/%'!", a, b);
    }
    // Return result and OK state.
    return a / b, ok();
}

main :: fn () s32 {
    loop i := -5; i <= 5; i += 1 {
        result, error :: div(10, i);
        if is_ok(error) {
            print("Result is %.\n", result);
        } else {
            print("Error: %.\n", error);
        }
    }
    return 0;
}

OK

OK :: 0

File: error.bl

Error

Error :: *_Error

File: error.bl

is_ok

is_ok :: fn (err: Error) bool #inline

Check whether err is no-error valid state. Returns false when err is null.

File: error.bl

is_error

is_error :: fn (err: Error, code: s32) bool #inline

Check whether err is representing error code. Returns false when err is null.

File: error.bl

ok

ok :: fn () Error #inline

Creates no-error :ref:Error.

File: error.bl

error

error :: fn { error1; error2; error3; }

Overloaded function setting up error state. Error state is global variable holding :ref:Error instance, error function sets desired values and return pointer to this global. That means the Error must be handled immediately after it’s returned from failing function since every Error state points to the same memory.

Error creating does not require any HEAP memory alocations.

fn (code: s32) Error #inline

Sets error code.


fn (format: string, args: ...) Error #inline

Sets error state with ERR_UNKNOWN code and formatted message.


fn (code: s32, format: string, args: ...) Error

Sets error state with code and formatted message.

File: error.bl

File System

#import "std/fs"

File system module for manipulation with files and directories. This module provides an abstraction over operating system APIs such as creating files and directories, reading and writing, and scanning the filesystem.

Fs.File

File :: _FsImpl.File

File handle type.

File: fs.bl

Fs.FILE_INVALID

FILE_INVALID :: _FsImpl.FILE_INVALID

Invalid file handle. This can be used for file handle validation.

File: fs.bl

Fs.OpenMode

OpenMode :: enum {
    READ;
    WRITE;
    APPEND;
    CREATE;
}

Specify operation with opened file.

Variants

File: fs.bl

Fs.CopyOpt

CopyOpt :: struct {
    recursive: bool;
    override: bool;
    skip_existing: bool;
}

Specify behavior of dir_copy.

Members

File: fs.bl

Fs.InfoKind

InfoKind :: enum {
    FILE;
    DIRECTORY;
}

Specify kind of file system entry.

File: fs.bl

Fs.Info

Info :: struct {
    kind: InfoKind;
    name: string;
}

Helper container to hold information about file system entry.

File: fs.bl

Fs.InfoList

InfoList :: []Info

File: fs.bl

Fs.exist

exist :: fn (filepath: string) bool #inline

Check whether file or directory exists.

File: fs.bl

Fs.open

open :: fn (filepath: string, mode: ...OpenMode) (_0: File, _1: Error
) #inline

Open an file specified by filepath. Function return file handle and OK status when file was opened, otherwise return invalid handle and proper error. File must be closed by close call.

File open mode is optional, any combination of OpenMode can be used. When Create mode is specified, new file is created on filepath only if it does not exist, otherwise already existing file is used. Read mode is used as default when neither Read, Write or Append is specified.

Example

#import "std/fs"

main :: fn () s32 {
    file, err :: Fs.open(#file);
    defer Fs.close(file);
    if !is_ok(err) {
        print_err("%", err);
        return 1;
    }
    return 0;
}

**todo*: Mode should be passed as flags in the future.

File: fs.bl

Fs.close

close :: fn (handle: File)  #inline

Close previously openned file. Does nothing when handle is not valid.

File: fs.bl

Fs.get_uid

get_uid :: fn { _FsImpl.get_uid; _FsImpl.get_uid_by_name; }

@INCOMPLETE

File: fs.bl

Fs.remove

remove :: fn (filepath: string) Error #inline

Try to remove file specified by filepath and return OK on success, otherwise return error.

File: fs.bl

Fs.copy

copy :: fn (src: string, dest: string, override :: ) Error #inline

Copy existing file from src to dest and override existing file in destination if override is true. Return ok or error.

note: src and dest path can be relative path to current working path set by set_cwd.

File: fs.bl

Fs.dir_copy

dir_copy :: fn (src: string, dest: string, opt : *CopyOpt: , filter : DirScanFilterFn: ) (_0: s64, _1: Error
)

Copy from src path to dest path with specified opt options and return count of processed files or error.

Example:

#import "std/fs"

main :: fn () s32 {
    // Copy options
    opt: Fs.CopyOpt;
    // Create destination directory if not exist.
    opt.recursive = true;
    // Override all existing entries.
    opt.override = true;

    // Copy content of 'foo' into 'bar'
    c, err :: Fs.dir_copy("foo", "bar", &opt, &fn (item: *Fs.Info) bool {
        // Filter only txt files
        if String.compare(Fs.get_extension(item.name), "txt") { return true; } 
        return false;
    });
    if !is_ok(err) { print("%\n", err); }
    else { print("Copied % files!\n", c); }
    return 0;
}

@INCOIMPLETE Is using current dir + better descriptions.

File: fs.bl

Fs.size

size :: fn (handle: File) (_0: usize, _1: Error
) #inline

Return file content size in bytes and OK status on success, otherwise return zero and proper error.

File: fs.bl

Fs.read_string

read_string :: fn (handle: File) (_0: string, _1: Error
)

Read whole file content into string. Return new string instance containing file data and OK status on success, otherwise return empty string and error. Returned string is expected to be released by String.delete call if there was no error reported by function. Result string is zero terminated even if file is empty.

Example

#import "std/fs"

main :: fn () s32 {
    // Open this file.
    file, open_err :: Fs.open(#file, Fs.OpenMode.READ);

    // Always check for errors.
    if !is_ok(open_err) {
        panic("Cannot open file with error: '%'!", open_err);
    }
    // Close file at the end of scope.
    defer Fs.close(file);

    // Read it's content.
    content, read_err :: Fs.read_string(file);

    // Check for errors.
    if !is_ok(read_err) {
        panic("Cannot read file with error: '%'!", read_err);
    }
    // Delete content string at the end of scope.
    defer String.delete(content);

    // Print file content to stdout.
    print("%\n", content);
    return 0;
}

File: fs.bl

Fs.read_slice

read_slice :: fn (handle: File) (_0: []u8, _1: Error
)

Read whole file content into slice array. Return new slice instance containting file data and OK status on success, otherwise return empty slice and error. Returned slice is expected to be released by :ref:slice_terminate call if there was no error reported by function.

File: fs.bl

Fs.read

read :: fn (handle: File, dest: *u8, size: s64) (_0: s64, _1: Error
) #inline

Read size bytes from file into raw dest buffer. Return count of bytes written into buffer and OK status when there was no error. dest buffer must be allocated to handle at least size bytes. There is no overflow check.

File: fs.bl

Fs.write

write :: fn (handle: File, src: *u8, size: s64) (_0: s64, _1: Error
) #inline

Write size bytes from raw buffer src into the file. Return count of bytes written into the buffer and OK on success, otherwise return error. The src buffer size must be at least size bytes. No overflow checking is done.

File: fs.bl

Fs.write_string

write_string :: fn (handle: File, str: string) (_0: s64, _1: Error
) #inline

Write content of str into the file, return count of written bytes and OK if there is no error, otherwise return 0 and error.

File: fs.bl

Fs.write_fmt

write_fmt :: fn { fn (buf_size: s32, handle: File, fmt: string, args: ...) (_0: s64, _1: Error
); fn (handle: File, fmt: string, args: ...) (_0: s64, _1: Error
); } #inline

File: fs.bl

Fs.write_slice

write_slice :: fn (handle: File, v: []u8, count : s64: -1) (_0: s64, _1: Error
) #inline

Write content of v slice into the file, return count of written bytes and OK if there is no error, otherwise return 0 and error. Optional argument count specify count of bytes from v to be written, negative value means whole content. When passed count is greater than v.len, count value is set to v.len. Does nothing in case the v.len == 0 (slice is empty) and return 0 and ok.

File: fs.bl

Fs.dir_create

dir_create :: fn (dirpath: string) Error #inline

Create new directory and return OK on success. This function does not create directories recursively.

File: fs.bl

Fs.dir_create_all

dir_create_all :: fn (dirpath: string) Error

File: fs.bl

Fs.dir_remove

dir_remove :: fn (dirpath: string) Error #inline

Remove directory specified by dirpath and return OK on success, otherwise return an error.

File: fs.bl

Fs.dir_remove_all

dir_remove_all :: fn (dirpath: string, remove_root :: , filter : DirScanFilterFn: ) Error

Remove non-empty directory specified by dirpath and return OK on success, otherwise return an error. Root directory is removed if remove_root is true. Custom file filter function can be specified as needed.

note: This function recursively remove all nested folders and files in specified sub tree so it can be expensive.

File: fs.bl

Fs.is_directory

is_directory :: fn (path: string) (_0: bool, _1: Error
) #inline

Check whether path points to valid directory and return true with OK state, otherwise return false and error.

File: fs.bl

Fs.DirScanFilterFn

DirScanFilterFn :: *fn (info: *Info) bool

Type of dir_scan filter function.

File: fs.bl

Fs.dir_scan

dir_scan :: fn (dirpath: string, filter : DirScanFilterFn: ) (_0: InfoList, _1: Error
) #inline

Scan dirpath directory and return list of information for every file system entry found on success. Otherwise return empty list and error. Use info_list_delete to release list when there was no error reported by this function.

Optional filter funtion DirScanFilterFn can be used to filter scan results directly during scanning, it’s called for every found entry and only those for whose filter yields true are added into the output list.

File: fs.bl

Fs.info_list_delete

info_list_delete :: fn (list: InfoList)  #inline

Release allocated file system entry info list.

File: fs.bl

Fs.validate_filename

validate_filename :: fn (name: string) bool #inline

Checks whether name is valid file name on current platform.

File: fs.bl

Fs.get_cwd

get_cwd :: fn () string #inline

Try to obtain current working directory, result must be released by String.delete. Path does not contain last path separator.

File: fs.bl

Fs.set_cwd

set_cwd :: fn (path: string) Error #inline

Sets current working directory and return OK on success, otherwise return error.

File: fs.bl

Fs.get_home

get_home :: fn () string #inline

Try to obtain system home directory, result must be released by String.delete. Path does not contain last path separator.

File: fs.bl

Fs.get_tmp

get_tmp :: fn () string #inline

Try to obtain system temporary directory, result must be released by String.delete. Path does not contain last path separator.

File: fs.bl

Fs.normalize

normalize :: fn (filepath: *string) Error #inline

Try to normalize filepath, basically try to remove all relative path nodes .. and .. Path must be valid path (existing) on system. Original filepath is extended with current working directory. Function return OK on success or proper error on fail. Original string is not modified when error occurs.

File: fs.bl

Fs.remove_extension

remove_extension :: fn (filename: string) string #inline

Remove file extension (token after first .) from the filename and return the rest. Function does not create copy of original filepath.

File: fs.bl

Fs.get_extension

get_extension :: fn (filename: string) string #inline

Get file extension as a new string (token after first .) from the filename or empty string in case no extension was found.

The . separator is not included into result string.

File: fs.bl

Fs.get_directory

get_directory :: fn (filepath: string) string #inline

Get directory path from filepath. Function supports only unix path delimiters. Returns directory path as new string or empty string in case path was not found.

File: fs.bl

GLM

#import "std/glm"

3D math tools.

Glm.v2

v2 :: struct {
    x: f32;
    y: f32;
}

File: glm.bl

Glm.v2_one

v2_one :: 

File: glm.bl

Glm.v2_zero

v2_zero :: 

File: glm.bl

Glm.v3

v3 :: struct {
    x: f32;
    y: f32;
    z: f32;
}

File: glm.bl

Glm.v3_right

v3_right :: 

File: glm.bl

Glm.v3_up

v3_up :: 

File: glm.bl

Glm.v3_forward

v3_forward :: 

File: glm.bl

Glm.v3_one

v3_one :: 

File: glm.bl

Glm.v3_zero

v3_zero :: 

File: glm.bl

Glm.v4

v4 :: struct {
    x: f32;
    y: f32;
    z: f32;
    w: f32;
}

File: glm.bl

Glm.v4_one

v4_one :: 

File: glm.bl

Glm.v4_zero

v4_zero :: 

File: glm.bl

Glm.color_white

color_white :: 

File: glm.bl

Glm.color_black

color_black :: 

File: glm.bl

Glm.color_red

color_red :: 

File: glm.bl

Glm.color_green

color_green :: 

File: glm.bl

Glm.color_blue

color_blue :: 

File: glm.bl

Glm.color_yellow

color_yellow :: 

File: glm.bl

Glm.iv2

iv2 :: struct {
    x: s32;
    y: s32;
}

File: glm.bl

Glm.iv3

iv3 :: struct {
    x: s32;
    y: s32;
    z: s32;
}

File: glm.bl

Glm.mat4

mat4 :: 

File: glm.bl

Glm.quat

quat :: v4

File: glm.bl

Glm.quat_identity

quat_identity :: 

File: glm.bl

Glm.v_sub

v_sub :: fn { v2_sub; v2_sub_s; v3_sub; v3_sub_s; v4_sub; v4_sub_s; }

File: glm.bl

Glm.v_add

v_add :: fn { v2_add; v2_add_s; v3_add; v3_add_s; v4_add; v4_add_s; }

File: glm.bl

Glm.v_mul

v_mul :: fn { v2_mul; v2_mul_s; v3_mul; v3_mul_s; v4_mul; v4_mul_s; }

File: glm.bl

Glm.v_div

v_div :: fn { v2_div; v2_div_s; v3_div; v3_div_s; v4_div; v4_div_s; }

File: glm.bl

Glm.v_length

v_length :: fn { v2_length; v3_length; v4_length; }

File: glm.bl

Glm.v_sqr_lenght

v_sqr_lenght :: fn { v2_sqr_lenght; v3_sqr_lenght; v4_sqr_lenght; }

File: glm.bl

Glm.v_dot

v_dot :: fn { v2_dot; v3_dot; v4_dot; }

File: glm.bl

Glm.v_normalize

v_normalize :: fn { v2_normalize; v3_normalize; v4_normalize; }

File: glm.bl

Glm.v_compare

v_compare :: fn { v2_compare; v3_compare; v4_compare; }

File: glm.bl

Glm.v_negate

v_negate :: fn { v2_negate; v3_negate; v4_negate; }

File: glm.bl

Glm.v_cross

v_cross :: fn { v3_cross; }

File: glm.bl

Glm.v_round

v_round :: fn { v2_round; v3_round; v4_round; }

File: glm.bl

Glm.v_floor

v_floor :: fn { v2_floor; v3_floor; v4_floor; }

File: glm.bl

Glm.v_ceil

v_ceil :: fn { v2_ceil; v3_ceil; v4_ceil; }

File: glm.bl

Glm.mat4_init

mat4_init :: fn (m00: f32, m10: f32, m20: f32, m30: f32, m01: f32, m11: f32, m21: f32, m31: f32, m02: f32, m12: f32, m22: f32, m32: f32, m03: f32, m13: f32, m23: f32, m33: f32, out_mat: *mat4)  #inline

File: glm.bl

Glm.mat4_identity

mat4_identity :: fn (out_mat: *mat4)  #inline

File: glm.bl

Glm.mat4_zero

mat4_zero :: fn (out_mat: *mat4)  #inline

File: glm.bl

Glm.mat4_perspective

mat4_perspective :: fn (fov_rad: f32, aspect: f32, near: f32, far: f32, out_mat: *mat4)  #inline

File: glm.bl

Glm.mat4_ortho

mat4_ortho :: fn (left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, out_mat: *mat4) 

File: glm.bl

Glm.mat4_look_at

mat4_look_at :: fn (eye: v3, target: v3, up: v3, out_mat: *mat4)  #inline

File: glm.bl

Glm.mat4_mul

mat4_mul :: fn (a: *mat4, b: *mat4, out_mat: *mat4) 

File: glm.bl

Glm.mat4_inverse

mat4_inverse :: fn (src_mat: *mat4, out_mat: *mat4)  #inline

File: glm.bl

Glm.mat4_scale_s

mat4_scale_s :: fn (s: f32, out_mat: *mat4)  #inline

File: glm.bl

Glm.mat4_mul_v4

mat4_mul_v4 :: fn (mat: *mat4, v: v4) v4 #inline

File: glm.bl

Glm.mat4_translation

mat4_translation :: fn (translation: v3, out_mat: *mat4)  #inline

File: glm.bl

Glm.mat4_scale

mat4_scale :: fn (s: v3, out_mat: *mat4)  #inline

File: glm.bl

Glm.mat4_get_scale

mat4_get_scale :: fn (mat: *mat4) v3

File: glm.bl

Glm.mat4_get_translation

mat4_get_translation :: fn (mat: *mat4) v3 #inline

File: glm.bl

Glm.mat4_get_quat

mat4_get_quat :: fn (mat: *mat4) quat

File: glm.bl

Glm.quat_normalize

quat_normalize :: fn (q: quat) quat #inline

File: glm.bl

Glm.quat_to_mat4

quat_to_mat4 :: fn (q: quat, out_mat: *mat4) 

File: glm.bl

Glm.quat_look

quat_look :: fn (eye: v3, ori: quat, out_mat: *mat4) 

File: glm.bl

Glm.quat_look_for

quat_look_for :: fn (dir: v3, fwd: v3, up: v3) quat

File: glm.bl

Glm.quat_axis_angle

quat_axis_angle :: fn (axis: v3, angle_rad: f32) quat

File: glm.bl

Glm.quat_imag

quat_imag :: fn (q: quat) v3 #inline

File: glm.bl

Glm.quat_real

quat_real :: fn (q: quat) f32 #inline

File: glm.bl

Glm.quat_mul

quat_mul :: fn (q1: quat, q2: quat) quat

File: glm.bl

Glm.quat_rotate_v3

quat_rotate_v3 :: fn (q: quat, v: v3) v3

File: glm.bl

Glm.quat_forward

quat_forward :: fn (q: quat) v3

File: glm.bl

libc.bl

C.char

char :: s8

File: libc.bl

C.uchar

uchar :: u8

File: libc.bl

C.short

short :: s16

File: libc.bl

C.ushort

ushort :: u16

File: libc.bl

C.int

int :: s32

File: libc.bl

C.uint

uint :: u32

File: libc.bl

C.long

long :: s32

File: libc.bl

C.ulong

ulong :: u32

File: libc.bl

C.longlong

longlong :: s64

File: libc.bl

C.ulonglong

ulonglong :: u64

File: libc.bl

C.void_ptr

void_ptr :: *u8

File: libc.bl

C.size_t

size_t :: u64

File: libc.bl

C.ssize_t

ssize_t :: s64

File: libc.bl

C.STDIN

STDIN :: 0

File: libc.bl

C.STDOUT

STDOUT :: 1

File: libc.bl

C.STDERR

STDERR :: 2

File: libc.bl

C.RAND_MAX

RAND_MAX :: 2147483647

File: libc.bl

C.SIGHUP

SIGHUP :: 1

File: libc.bl

C.SIGINT

SIGINT :: 2

File: libc.bl

C.SIGQUIT

SIGQUIT :: 3

File: libc.bl

C.SIGILL

SIGILL :: 4

File: libc.bl

C.SIGTRAP

SIGTRAP :: 5

File: libc.bl

C.SIGABRT

SIGABRT :: 6

File: libc.bl

C.putenv

putenv :: fn (var: *char) int #extern

File: libc.bl

C.popen

popen :: fn (f: *char, m: *char) void_ptr #extern

File: libc.bl

C.pclose

pclose :: fn (f: void_ptr)  #extern

File: libc.bl

C.write

write :: fn (fd: int, buf: *char, count: size_t) ssize_t #extern

File: libc.bl

C.read

read :: fn (fd: int, buf: *char, count: size_t) ssize_t #extern

File: libc.bl

C.exit

exit :: fn (v: int)  #extern

File: libc.bl

C.realpath

realpath :: fn (path: *char, resolved_path: *char) *char #extern

File: libc.bl

C.raise

raise :: fn (sig: int) int #extern

File: libc.bl

C.signal

signal :: fn (signum: int, handler: *fn (v: int) ) *fn (v: int)  #extern

File: libc.bl

C.malloc

malloc :: fn (size: size_t) void_ptr #extern

File: libc.bl

C.free

free :: fn (ptr: void_ptr)  #extern

File: libc.bl

C.getenv

getenv :: fn (name: *char) *char #extern

File: libc.bl

C.system

system :: fn (command: *char) int #extern

File: libc.bl

C.strlen

strlen :: fn (str: *char) size_t #extern

File: libc.bl

C.strcmp

strcmp :: fn (first: *char, second: *char) int #extern

File: libc.bl

C.wcslen

wcslen :: fn (str: *u16) usize #extern

File: libc.bl

C.strerror

strerror :: fn (errnum: int) *char #extern

File: libc.bl

C.fgets

fgets :: fn (buf: void_ptr, size: int, f: void_ptr) void_ptr #extern

File: libc.bl

C.getchar

getchar :: fn () int #extern

File: libc.bl

C.rand

rand :: fn () s32 #extern

File: libc.bl

C.srand

srand :: fn (seed: u32)  #extern

File: libc.bl

C.qsort

qsort :: fn (base: void_ptr, nitems: size_t, size: size_t, compar: *fn (: void_ptr, : void_ptr) int)  #extern

File: libc.bl

C.asinf

asinf :: fn (arg: f32) f32 #extern

File: libc.bl

C.asin

asin :: fn (arg: f64) f64 #extern

File: libc.bl

C.acosf

acosf :: fn (n: f32) f32 #extern

File: libc.bl

C.acos

acos :: fn (n: f64) f64 #extern

File: libc.bl

C.tanf

tanf :: fn (x: f32) f32 #extern

File: libc.bl

C.tan

tan :: fn (x: f64) f64 #extern

File: libc.bl

C.atan2f

atan2f :: fn (y: f32, x: f32) f32 #extern

File: libc.bl

C.atan2

atan2 :: fn (y: f64, x: f64) f64 #extern

File: libc.bl

C.copysignf

copysignf :: fn (x: f32, y: f32) f32 #extern

File: libc.bl

C.copysign

copysign :: fn (x: f64, y: f64) f64 #extern

File: libc.bl

C.tolower

tolower :: fn (c: int) int #extern

File: libc.bl

C.toupper

toupper :: fn (c: int) int #extern

File: libc.bl

macos.bl

MacOS.CFAllocatorRef

CFAllocatorRef :: *u8

File: macos.bl

MacOS.CFIndex

CFIndex :: s64

File: macos.bl

MacOS.CFStringRef

CFStringRef :: *u8

File: macos.bl

MacOS.CFArrayRef

CFArrayRef :: *u8

File: macos.bl

MacOS.CFArrayCallBacks

CFArrayCallBacks :: u8

File: macos.bl

MacOS.CFTimeInterval

CFTimeInterval :: f64

File: macos.bl

MacOS.CFTypeRef

CFTypeRef :: *u8

File: macos.bl

MacOS.CFRunLoopRef

CFRunLoopRef :: *u8

File: macos.bl

MacOS.CFRunLoopMode

CFRunLoopMode :: CFStringRef

File: macos.bl

MacOS.Boolean

Boolean :: u8

File: macos.bl

MacOS.CFStringEncoding

CFStringEncoding :: enum u32 {
    MacRoman :: 0;
    WindowsLatin1 :: 1280;
    ISOLatin1 :: 513;
    NextStepLatin :: 2817;
    ASCII :: 1536;
    Unicode :: 256;
    UTF8 :: 134217984;
    NonLossyASCII :: 3071;
    UTF16 :: 256;
    UTF16BE :: 268435712;
    UTF16LE :: 335544576;
    UTF32 :: 201326848;
    UTF32BE :: 402653440;
    UTF32LE :: 469762304;
}

File: macos.bl

MacOS.kFSEventStreamEventFlagNone

kFSEventStreamEventFlagNone : u32 : 0

File: macos.bl

MacOS.kFSEventStreamEventFlagMustScanSubDirs

kFSEventStreamEventFlagMustScanSubDirs : u32 : 1

File: macos.bl

MacOS.kFSEventStreamEventFlagUserDropped

kFSEventStreamEventFlagUserDropped : u32 : 2

File: macos.bl

MacOS.kFSEventStreamEventFlagKernelDropped

kFSEventStreamEventFlagKernelDropped : u32 : 4

File: macos.bl

MacOS.kFSEventStreamEventFlagEventIdsWrapped

kFSEventStreamEventFlagEventIdsWrapped : u32 : 8

File: macos.bl

MacOS.kFSEventStreamEventFlagHistoryDone

kFSEventStreamEventFlagHistoryDone : u32 : 16

File: macos.bl

MacOS.kFSEventStreamEventFlagRootChanged

kFSEventStreamEventFlagRootChanged : u32 : 32

File: macos.bl

MacOS.kFSEventStreamEventFlagMount

kFSEventStreamEventFlagMount : u32 : 64

File: macos.bl

MacOS.kFSEventStreamEventFlagUnmount

kFSEventStreamEventFlagUnmount : u32 : 128

File: macos.bl

MacOS.kFSEventStreamEventFlagItemCreated

kFSEventStreamEventFlagItemCreated : u32 : 256

File: macos.bl

MacOS.kFSEventStreamEventFlagItemRemoved

kFSEventStreamEventFlagItemRemoved : u32 : 512

File: macos.bl

MacOS.kFSEventStreamEventFlagItemInodeMetaMod

kFSEventStreamEventFlagItemInodeMetaMod : u32 : 1024

File: macos.bl

MacOS.kFSEventStreamEventFlagItemRenamed

kFSEventStreamEventFlagItemRenamed : u32 : 2048

File: macos.bl

MacOS.kFSEventStreamEventFlagItemModified

kFSEventStreamEventFlagItemModified : u32 : 4096

File: macos.bl

MacOS.kFSEventStreamEventFlagItemFinderInfoMod

kFSEventStreamEventFlagItemFinderInfoMod : u32 : 8192

File: macos.bl

MacOS.kFSEventStreamEventFlagItemChangeOwner

kFSEventStreamEventFlagItemChangeOwner : u32 : 16384

File: macos.bl

MacOS.kFSEventStreamEventFlagItemXattrMod

kFSEventStreamEventFlagItemXattrMod : u32 : 32768

File: macos.bl

MacOS.kFSEventStreamEventFlagItemIsFile

kFSEventStreamEventFlagItemIsFile : u32 : 65536

File: macos.bl

MacOS.kFSEventStreamEventFlagItemIsDir

kFSEventStreamEventFlagItemIsDir : u32 : 131072

File: macos.bl

kFSEventStreamEventFlagItemIsSymlink : u32 : 262144

File: macos.bl

MacOS.kFSEventStreamEventFlagOwnEvent

kFSEventStreamEventFlagOwnEvent : u32 : 524288

File: macos.bl

kFSEventStreamEventFlagItemIsHardlink : u32 : 1048576

File: macos.bl

kFSEventStreamEventFlagItemIsLastHardlink : u32 : 2097152

File: macos.bl

MacOS.kFSEventStreamEventFlagItemCloned

kFSEventStreamEventFlagItemCloned : u32 : 4194304

File: macos.bl

MacOS.kFSEventStreamEventIdSinceNow

kFSEventStreamEventIdSinceNow : FSEventStreamEventId : 18446744073709551615

File: macos.bl

MacOS.kFSEventStreamCreateFlagNone

kFSEventStreamCreateFlagNone : FSEventStreamCreateFlags : 0

File: macos.bl

MacOS.kFSEventStreamCreateFlagUseCFTypes

kFSEventStreamCreateFlagUseCFTypes : FSEventStreamCreateFlags : 1

File: macos.bl

MacOS.kFSEventStreamCreateFlagNoDefer

kFSEventStreamCreateFlagNoDefer : FSEventStreamCreateFlags : 2

File: macos.bl

MacOS.kFSEventStreamCreateFlagWatchRoot

kFSEventStreamCreateFlagWatchRoot : FSEventStreamCreateFlags : 4

File: macos.bl

MacOS.kFSEventStreamCreateFlagIgnoreSelf

kFSEventStreamCreateFlagIgnoreSelf : FSEventStreamCreateFlags : 8

File: macos.bl

MacOS.kFSEventStreamCreateFlagFileEvents

kFSEventStreamCreateFlagFileEvents : FSEventStreamCreateFlags : 16

File: macos.bl

MacOS.kFSEventStreamCreateFlagMarkSelf

kFSEventStreamCreateFlagMarkSelf : FSEventStreamCreateFlags : 32

File: macos.bl

MacOS.kFSEventStreamCreateFlagUseExtendedData

kFSEventStreamCreateFlagUseExtendedData : FSEventStreamCreateFlags : 64

File: macos.bl

MacOS.FSEventStreamRef

FSEventStreamRef :: *u8

File: macos.bl

MacOS.FSEventStreamEventId

FSEventStreamEventId :: u64

File: macos.bl

MacOS.FSEventStreamCreateFlags

FSEventStreamCreateFlags :: u32

File: macos.bl

MacOS.FSEventStreamEventFlags

FSEventStreamEventFlags :: u32

File: macos.bl

MacOS.ConstFSEventStreamRef

ConstFSEventStreamRef :: *u8

File: macos.bl

MacOS.CFAllocatorRetainCallBack

CFAllocatorRetainCallBack :: *fn (info: *u8) *u8

File: macos.bl

MacOS.CFAllocatorReleaseCallBack

CFAllocatorReleaseCallBack :: *fn (info: *u8) 

File: macos.bl

MacOS.CFAllocatorCopyDescriptionCallBack

CFAllocatorCopyDescriptionCallBack :: *fn (info: *u8) CFStringRef

File: macos.bl

MacOS.CFArrayCreate

CFArrayCreate :: fn (allocator: CFAllocatorRef, values: **u8, numValues: CFIndex, callBacks: *CFArrayCallBacks) CFArrayRef #extern

File: macos.bl

MacOS.CFRunLoopGetCurrent

CFRunLoopGetCurrent :: fn () CFRunLoopRef #extern

File: macos.bl

MacOS.CFRunLoopCopyCurrentMode

CFRunLoopCopyCurrentMode :: fn (rl: CFRunLoopRef) CFRunLoopMode #extern

File: macos.bl

MacOS.CFRelease

CFRelease :: fn (cf: CFTypeRef)  #extern

File: macos.bl

MacOS.CFStringCreateWithCString

CFStringCreateWithCString :: fn (alloc: CFAllocatorRef, cStr: *u8, encoding: CFStringEncoding) CFStringRef #extern

File: macos.bl

MacOS.FSEventStreamContext

FSEventStreamContext :: struct {
    version: CFIndex;
    info: *u8;
    retain: CFAllocatorRetainCallBack;
    release: CFAllocatorReleaseCallBack;
    copyDescription: CFAllocatorCopyDescriptionCallBack;
}

File: macos.bl

MacOS.FSEventStreamCallback

FSEventStreamCallback :: *fn (streamRef: ConstFSEventStreamRef, clientCallBackInfo: *u8, numEvents: usize, eventPaths: *u8, eventFlags: *FSEventStreamEventFlags, eventIds: *FSEventStreamEventId) 

File: macos.bl

MacOS.FSEventStreamCreate

FSEventStreamCreate :: fn (allocator: CFAllocatorRef, callback: FSEventStreamCallback, context: *FSEventStreamContext, pathsToWatch: CFArrayRef, sinceWhen: FSEventStreamEventId, latency: CFTimeInterval, flags: FSEventStreamCreateFlags) FSEventStreamRef #extern

File: macos.bl

MacOS.FSEventStreamScheduleWithRunLoop

FSEventStreamScheduleWithRunLoop :: fn (streamRef: FSEventStreamRef, runLoop: CFRunLoopRef, runLoopMode: CFStringRef)  #extern

File: macos.bl

MacOS.FSEventStreamUnscheduleFromRunLoop

FSEventStreamUnscheduleFromRunLoop :: fn (streamRef: FSEventStreamRef, runLoop: CFRunLoopRef, runLoopMode: CFStringRef)  #extern

File: macos.bl

MacOS.FSEventStreamStart

FSEventStreamStart :: fn (streamRef: FSEventStreamRef) Boolean #extern

File: macos.bl

MacOS.FSEventStreamFlushSync

FSEventStreamFlushSync :: fn (streamRef: FSEventStreamRef)  #extern

File: macos.bl

MacOS.FSEventStreamStop

FSEventStreamStop :: fn (streamRef: FSEventStreamRef)  #extern

File: macos.bl

MacOS.FSEventStreamInvalidate

FSEventStreamInvalidate :: fn (streamRef: FSEventStreamRef)  #extern

File: macos.bl

MacOS.FSEventStreamRelease

FSEventStreamRelease :: fn (streamRef: FSEventStreamRef)  #extern

File: macos.bl

MacOS.NSGetExecutablePath

NSGetExecutablePath :: fn (buf: *C.char, bufsize: *C.uint) C.int #extern

File: macos.bl

MacOS.MachTimebaseInfo

MachTimebaseInfo :: struct {
    numer: C.uint;
    denom: C.uint;
}

File: macos.bl

MacOS.mach_timebase_info

mach_timebase_info :: fn (info: *MachTimebaseInfo) C.int #extern

File: macos.bl

MacOS.mach_absolute_time

mach_absolute_time :: fn () u64 #extern

File: macos.bl

Math

#load "std/math.bl"

Math.PI

PI :: 

File: math.bl

Math.TWO_PI

TWO_PI :: 

File: math.bl

Math.HALF_PI

HALF_PI :: 

File: math.bl

Math.F32_EPSILON

F32_EPSILON :: 

File: math.bl

Math.F64_EPSILON

F64_EPSILON :: 

File: math.bl

Math.S8_MIN

S8_MIN : s8 : 

File: math.bl

Math.S8_MAX

S8_MAX : s8 : 127

File: math.bl

Math.S16_MIN

S16_MIN : s16 : 

File: math.bl

Math.S16_MAX

S16_MAX : s16 : 32767

File: math.bl

Math.S32_MIN

S32_MIN : s32 : 

File: math.bl

Math.S32_MAX

S32_MAX : s32 : 2147483647

File: math.bl

Math.S64_MIN

S64_MIN : s64 : 

File: math.bl

Math.S64_MAX

S64_MAX : s64 : 9223372036854775807

File: math.bl

Math.U8_MIN

U8_MIN : u8 : 0

File: math.bl

Math.U8_MAX

U8_MAX : u8 : 255

File: math.bl

Math.U16_MIN

U16_MIN : u16 : 0

File: math.bl

Math.U16_MAX

U16_MAX : u16 : 65535

File: math.bl

Math.U32_MIN

U32_MIN : u32 : 0

File: math.bl

Math.U32_MAX

U32_MAX : u32 : 4294967295

File: math.bl

Math.U64_MIN

U64_MIN : u64 : 0

File: math.bl

Math.U64_MAX

U64_MAX : u64 : 18446744073709551615

File: math.bl

Math.sin

sin :: fn { f32_sin; f64_sin; }

File: math.bl

Math.cos

cos :: fn { f32_cos; f64_cos; }

File: math.bl

Math.floor

floor :: fn { f32_floor; f64_floor; }

File: math.bl

Math.round

round :: fn { f32_round; f64_round; }

File: math.bl

Math.pow

pow :: fn { f32_pow; f64_pow; }

File: math.bl

Math.log

log :: fn { f32_log; f64_log; }

File: math.bl

Math.log2

log2 :: fn { f32_log2; f64_log2; }

File: math.bl

Math.log10

log10 :: fn { f32_log10; f64_log10; }

File: math.bl

Math.sqrt

sqrt :: fn { f32_sqrt; f64_sqrt; }

File: math.bl

Math.ceil

ceil :: fn { f32_ceil; f64_ceil; }

File: math.bl

Math.atan2

atan2 :: fn { C.atan2f; C.atan2; }

File: math.bl

Math.copysign

copysign :: fn { C.copysignf; C.copysign; }

File: math.bl

Math.asin

asin :: fn { C.asinf; C.asin; }

File: math.bl

Math.acos

acos :: fn { C.acosf; C.acos; }

File: math.bl

Math.tan

tan :: fn { C.tanf; C.tan; }

File: math.bl

Math.abs

abs :: fn { f32_abs; f64_abs; }

File: math.bl

Math.compare

compare :: fn { f32_compare; f64_compare; }

File: math.bl

Math.degtorad

degtorad :: fn { f32_degtorad; f64_degtorad; }

File: math.bl

Math.radtodeg

radtodeg :: fn { f32_radtodeg; f64_radtodeg; }

File: math.bl

Math.max

max :: fn (a: ?T, b: T) T #inline

File: math.bl

Math.min

min :: fn (a: ?T, b: T) T #inline

File: math.bl

Math.lerp

lerp :: fn (a: ?T, b: T, fraction: T) T #inline

File: math.bl

Math.clamp

clamp :: fn (v: ?T, minimum: T, maximum: T) T

File: math.bl

Memory

#load "std/memory.bl"

Toolset for manipulation with system memory.

Memory allocator

Memory allocators are used across the entire program to manage allocated memory resources used in runtime. Since memory allocation can be an expensive operation in some cases, it’s good to provide an explicit API, giving information enough to fix bugs, memory leaks and performance issues.

Memory allocator in BL world is just some context :ref:Allocator used by an allocator function, and allocator function itself AllocFn. The allocator context can hold some data needed by allocator function and the allocator function is later used to make memory allocations and deallocations.

Functions like alloc and free internally use allocator set in global executable context _context variable. Global context allocator is by default set to default_allocator and can be changed as needed. Main goal of internal use of the allocator set in the global context (used across all modules) is to have full control over what’s going on and also give some advanced options to programmer (i.e. create his/her own allocator to have truly full control over memory management of the program).

alloc

alloc :: fn (size: usize, loc :: ) *u8

Allocates size of bytes on heap using default allocator. Use free to free allocated memory when it’s no longer needed. Cause panic when allocation is not possible or size is zero. This function use allocator set in _context.allocator

File: memory.bl

calloc

calloc :: fn (num: usize, size: usize, loc :: ) *u8

Same as alloc but allocated memory block is set to zero.

File: memory.bl

free

free :: fn (ptr: *u8, loc :: ) 

Free memory allocated on heap. This function use allocator set in _context.allocator to free allocated data.

warning: Memory block must be freed by same allocator as used for allocation.

note: Does nothing when passed ptr is null.

File: memory.bl

memcpy

memcpy :: fn (dest: *u8, src: *u8, size: usize) 

Copy memory of defined size from src to dest. Destination and source size must be at least size bytes.

File: memory.bl

memset

memset :: fn (_dest: *u8, v: u8, size: usize) *u8

Set memory to desired value and return dest pointer. Destination size must be at least size bytes.

File: memory.bl

zeromem

zeromem :: fn (dest: *u8, size: usize) *u8

Zero out dest memory of size and return the dest pointer.

File: memory.bl

init_default

init_default :: fn (dest: *?T) *T #inline

File: memory.bl

swap

swap :: fn (first: *?T, second: *T)  #inline

Swaps content of memory at address first and second.

File: memory.bl

is_aligned

is_aligned :: fn (ptr: *?T, alignment: usize) bool #inline

Checks whether passed pointer ptr is properly aligned by alignment.

File: memory.bl

align_ptr_up

align_ptr_up :: fn (p: *u8, alignment: usize) (p: *u8, adjustment: usize
)

Align pointer p to alignment and return adjusted pointer and number of bytes needed for adjustment.

warning: Cause panic when alignment is not power of two.

File: memory.bl

slice_init

slice_init :: fn (slice: *[]?T, n: s64, allocator : *Allocator: , loc :: ) 

Allocate heap memory for n elements in _v slice. Allocated block is set to zero default value. Allocated memory must be released by :ref:slice_terminate call.

Zero initialization of allocated memory block can be expensive in case of large allocation.

Example

main :: fn () s32 {
    // Allocate slice of 10 numbers
    sl: []s32;
    slice_init(&sl, 10);

    loop i := 0; i < sl.len; i += 1 {
        sl[i] = i;
    }

    // release memory allocated by init
    slice_terminate(&sl);
    return 0;
}

File: memory.bl

slice_terminate

slice_terminate :: fn (slice: *[]?T, allocator : *Allocator: , loc :: ) 

Release slice memory allocated by slice_init call.

File: memory.bl

slice_range

slice_range :: fn (slice: []?T, start: s64, end : s64: -1) []T #inline

Create slice subset defined as range <start-index, end-index). Notice that end index is excluded from range, so slice_range(other, 0, other.len) is valid and returns new slice pointing to the same data as other slice, and with same size.

Indexing rules:

start >= 0
start < slice.len
end >= 0
end <= slice.len

warning: Function cause panic in case combination of start and end is out of slice range.

File: memory.bl

AllocOp

AllocOp :: enum {
    ALLOCATE;
    FREE;
    RELEASE;
}

Specify allocator opratation.

Variants

File: memory.bl

Allocator

Allocator :: struct {
    handler: AllocFn;
}

Default allocator context base.

File: memory.bl

AllocFn

AllocFn :: *fn (ctx: *Allocator, operation: AllocOp, size: usize, ptr : *u8: , file :: , line :: 0) *u8

Allocator handle function type.

File: memory.bl

allocate_memory

allocate_memory :: fn (allocator: *Allocator, size: usize, loc :: ) *u8 #inline

Allocate memory directly using specified allocator. In case the allocator is null, global application context allocator is used.

File: memory.bl

free_memory

free_memory :: fn (allocator: *Allocator, ptr: *u8, loc :: )  #inline

Free memory previously allocated by specific allocator. In case the allocator is null, global application context allocator is used.

File: memory.bl

release_memory

release_memory :: fn (allocator: *Allocator, loc :: )  #inline

Release all memory allocated by allocator.

warning: This operation is not supported by all allocators.

File: memory.bl

default_allocator

default_allocator :: 

Default memory allocator using libc malloc internally.

File: memory.bl

Print

#import "std/print"

Printing functions collection.

PRINT_MAX_LENGTH :: 4096

Size of buffer used by print function, this is maximum text length which can be printed at once.

File: print.bl

print :: fn (format: string, args: ...) s32

Write string to the standart output (stdout). Format string can include format specifiers % which are replaced by corresponding argument value passed in args. Value-string conversion is done automatically, we can pass values of any type as an arguments, even structures or arrays.

The print function accepts C-like escape sequences as \n, \t, \r, etc.

Pointers to Error are dereferenced automatically; so the print function can print out errors directly.

Count of printed bytes is returned.

Example

main :: fn () s32 {
    print("Hello world!\n");
    print("My name is '%'.\n", "Travis");
    print("Number: %\n", 10);

    Foo :: struct {
        i: s32;
        j: s32;
    };

    foo := {:Foo: 10, 20};
    print("foo = '%'\n", foo);

    return 0;
}

File: print.bl

eprint

eprint :: fn (format: string, args: ...) s32

Write string to the error output (stderr). See also print.

File: print.bl

bprint

bprint :: fn (buf: []u8, format: string, args: ...) s32

Write formatted input to the buffer. When passed buffer has not enough space to handle whole resulting string and terminal character, function will print just part tting into the buffer.

Returns count of characters written into buffer, this count does not include terminal character written at the end of the result string.

note: String written into the buffer is always zero terminated.

See also print.

File: print.bl

tprint

tprint :: fn (format: string, args: ...) string #inline

Write formatted input to the new string using temporary_allocator.

note: There is no need to explicitly release memory used by temporary string.

note: Created string is always zero terminated.

See also print.

File: print.bl

sprint

sprint :: fn (format: string, args: ...) string

Write formatted input to the new heap-allocated string.

note: Use String.delete to free memory used by string.

note: Created string is always zero terminated.

See also print.

File: print.bl

FmtReal

FmtReal :: struct {
    trailing: s8;
    v: Any;
}

Structure to hold information about custom real print formatting. Use fmt_real function to create formatted printable value.

Members

File: print.bl

fmt_real

fmt_real :: fn (v: Any, trailing: s8) FmtReal #inline

Create formatted printable object for real number. Created FmtReal object is valid

File: print.bl

FmtIntBase

FmtIntBase :: enum u8 {
    BIN;
    DEC;
    OCT;
    HEX;
}

Number base used for formatted printing.

Variants

File: print.bl

FmtInt

FmtInt :: struct {
    base: FmtIntBase;
    print_prefix: bool;
    v: Any;
}

Specify number printing format. Use fmt_int helper function to create instance of this type.

Members

File: print.bl

fmt_int

fmt_int :: fn (v: Any, base: FmtIntBase, print_prefix :: ) FmtInt #inline

Create formatted printable object for number. Created FmtInt object is valid for direct printing.

File: print.bl

FmtChar

FmtChar :: struct {
    v: u8;
}

Simple wrapper used for format u8 value as character.

File: print.bl

fmt_char

fmt_char :: fn (v: u8) FmtChar #inline

Create formatter for u8 number to be later printed as character.

Example

print("% = %\n", 'c', fmt_char('c'));

File: print.bl

pthread.bl

pthread_mutex_t

pthread_mutex_t :: struct {
    __sig: C.long;
    __opaque: ;
}

File: pthread.bl

pthread_t

pthread_t :: *u8

File: pthread.bl

pthread_attr_t

pthread_attr_t :: *u8

File: pthread.bl

pthread_start_routine_t

pthread_start_routine_t :: *fn (args: C.void_ptr) C.void_ptr

File: pthread.bl

pthread_create

pthread_create :: fn (thread: *pthread_t, attr: pthread_attr_t, start_routine: pthread_start_routine_t, args: C.void_ptr) C.int #extern

File: pthread.bl

pthread_join

pthread_join :: fn (thread: pthread_t, retval: *C.void_ptr) C.int #extern

File: pthread.bl

pthread_exit

pthread_exit :: fn (retval: C.void_ptr)  #extern

File: pthread.bl

pthread_self

pthread_self :: fn () pthread_t #extern

File: pthread.bl

pthread_mutex_lock

pthread_mutex_lock :: fn (mutex: *pthread_mutex_t) C.int #extern

File: pthread.bl

pthread_mutex_trylock

pthread_mutex_trylock :: fn (mutex: *pthread_mutex_t) C.int #extern

File: pthread.bl

pthread_mutex_unlock

pthread_mutex_unlock :: fn (mutex: *pthread_mutex_t) C.int #extern

File: pthread.bl

pthread_mutex_init

pthread_mutex_init :: fn (mutex: *pthread_mutex_t, attr: C.void_ptr) C.int #extern

File: pthread.bl

pthread_mutex_destroy

pthread_mutex_destroy :: fn (mutex: *pthread_mutex_t) C.int #extern

File: pthread.bl

String

#import "std/string"

Builtin string storage. The string type could represent dynamic and compile time static strings.

string :: struct {
    len: s64;
    ptr: *u8;
}


// Compile-time string literal
my_string :: "This is my string!"; 


// Dynamic string allocated on heap.
// New dynamic string can be created from string literal. 
my_string :: String.new("This is my string!");
defer String.delete(my_string);

BL strings are zero terminated except of sub-string view function (terminator cannot be added because we cannot modify original string).

note: String manipulation functions are related only to dynamic strings and cannot be used with string literals since those are constants allocated on stack.

String.new

new :: fn { fn (allocator : *Allocator: ) string; fn (size: s64, allocator : *Allocator: ) string; fn (v: string, allocator : *Allocator: ) string; fn (cstr: *u8, allocator : *Allocator: ) string; }

Overloaded function creating new dynamic string instance. Created string is guaranteed to be zero terminated.

warning: Every new string must be deleted by String.delete call.

new :: fn () string

Create new empty string object.


new :: fn (size: s64) string

Create new string with preallocated space. This type of string initialization can reduce count of allocations made later by extending string content. String with length up to size require only one memory allocation.

This initialization should be preferred if string length can be predicted.

Example

main :: fn () s32 {
    str :: String.new();
    defer String.delete(str);
    String.append(&str, "Hello");

    print("str = %\n", str);
    return 0;
}

new :: fn (v: string) string

Create copy of v string. Allocates memory to hold exactly size of v string data.


new :: fn (cstr: *u8) string

Create copy of C zero terminated string.

File: string.bl

String.delete

delete :: fn (v: string) 

Delete dynamic string.

File: string.bl

String.reserve

reserve :: fn (v: *string, count: s64) 

Ensure that string’s underlying buffer is capable to hold count of characters and eventually do preallocation if buffer is too small. The reserve does not take in account if the string’s buffer is full or not. The function does nothing if buffer size is enough.

File: string.bl

String.get_allocated_bytes

get_allocated_bytes :: fn (v: string) usize #inline

Get currently allocated memory used by the string in bytes.

File: string.bl

String.clear

clear :: fn (v: *string) 

Clear dynamic string but keep allocated storage.

File: string.bl

String.append

append :: fn { _append_str; _append_any; }

Append dynamic string with any value. Allocation is done in case there is not enough space reminding in string. The v string is supposed to be allocated on heap.

Returns count of characters appended to the string excluding zero terminator.

File: string.bl

String.concatenate

concatenate :: fn (v: *string, args: ...) string

Append string with multiple values passed as args and return @v. New allocation is done in case there is space no left in currently allocated string’s memory to append args.

File: string.bl

String.clear_concat

clear_concat :: fn (v: *string, args: ...) string

Clear the v string and append multiple values passed as args. Returned value is dereference of the original v string after new values are appended. New allocation is done in case there is space no left in currently allocated string’s memory to append args.

hint: Use this function in case you need create only temporary string i.e. file path.

VERSION :: "1.0.0";

path := String.new();
defer String.delete(path);
Fs.set_cwd(String.clear_concat(&path, "my-dir/project-", VERSION));

File: string.bl

String.compare

compare :: fn (first: string, second: string, n :: -1) bool

Compare first and second strings in specified range n and return true if they are same otherwise return false.

Range value n is optional and ignored when it’s less than 0.

File: string.bl

String.compare2

compare2 :: fn (first: string, second: string) s32

@INCOMPLETE

File: string.bl

String.to_f32

to_f32 :: fn (str: string, count :: -1) f32

Convert first count characters of str to f32.

File: string.bl

String.to_s64

to_s64 :: fn (str: string, count :: -1) s64

Convert first count characters from str to s64.

File: string.bl

String.split_by_last

split_by_last :: fn (str: string, delimiter: u8, lhs: *string, rhs : *string: , di : *s32: ) bool

Split input string str into two tokens based on the last occurrence of delimiter. Delimiter is not included in resulting tokens. Result tokens only points into original memory of the str, they are not supposed to be freed.

When delimiter is not present in the input string function return false, lhs and rhs buffers are not modified, otherwise function return true and sets lhs and rhs to valid values.

Token destination pointers lhs and rhs are optional. The di output variable is set to index of the split position when it’s not null.

warning: lhs and rhs sub strings are not guaranteed to be zero terminated and they are not supposed to be freed.

Example

main :: fn () s32 {
    lhs: string;
    rhs: string;
    if String.split_by_last("this/is/my/epic/path", '/', &lhs, &rhs) {
        print("lhs = %\n", lhs);
        print("rhs = %\n", rhs);
    }

    return 0;
}

File: string.bl

String.split_at_index

split_at_index :: fn (str: string, index: s32, lhs : *string: , rhs : *string: ) bool

Split input string str at index position and return true when split was done. Result tokens only points into original memory of the str, they are not supposed to be freed. When index is out of str range function return false, lhs and rhs buffers are not modified.

Token destination pointers lhs and rhs are optional.

warning: lhs and rhs sub strings are not guaranteed to be zero terminated and they are not supposed to be freed.

Example

main :: fn () s32 {
    lhs: string;
    rhs: string;
    if String.split_at_index("foobar", 3, &lhs, &rhs) {
        print("lhs = %\n", lhs);
        print("rhs = %\n", rhs);
    }

    return 0;
}

File: string.bl

String.split_by_first

split_by_first :: fn (str: string, delimiter: u8, lhs: *string, rhs : *string: , di : *s32: ) bool

Split input string str into two tokens based on the first occurrence of delimiter. Delimiter is not included in resulting tokens. Result tokens only points into original memory of the str, they are not supposed to be freed.

When delimiter is not present in the input string function return false, lhs and rhs buffers are not modified, otherwise function return true and sets lhs and rhs to found values.

Token destination pointers lhs and rhs are optional.

warning: lhs and rhs sub strings are not guaranteed to be zero terminated and they are not supposed to be freed.

Example

main :: fn () s32 {
    lhs: string;
    rhs: string;
    if String.split_by_first("this/is/my/epic/path", '/', &lhs, &rhs) {
        print("lhs = %\n", lhs);
        print("rhs = %\n", rhs);
    }

    return 0;
}

File: string.bl

String.insert

insert :: fn { _string_insert; _char_insert; }

Overloaded function inserting one character or other string at desired position.

fn (str: *string, index: s32, v: u8) bool #inline

Insert one character into str at index and return true when character was inserted.

note: The input str can be reallocated when index is equal to input string len and more space is needed.

fn (str: *string, index: s32, v: string) bool

Insert other string into str at index and return true when string was inserted.

note: The input str can be reallocated when index is equal to input string len and more space is needed.

note: Function does nothing (return false) when v string is empty.

File: string.bl

String.erase

erase :: fn (str: *string, index: s32) bool

Erase one character at index position and return true when character was erased. The ’index value is checked to fit in string bounds.

File: string.bl

String.split_by

split_by :: fn (str: string, delimiter: u8) []string

Split the str input string by delimiter and return new slice containing all found sub-strings.

warning: String slice should be terminated by slice_terminate call.

warning: Slice elements are not guaranteed to be zero terminated and they are not supposed to be freed.

File: string.bl

String.count_of

count_of :: fn (str: string, c: u8) s32 #inline

Counts desired character occurrence in the input string.

File: string.bl

String.to_lower

to_lower :: fn (str: string)  #inline

Converts input string to lower case.

File: string.bl

String.to_upper

to_upper :: fn (str: string)  #inline

Converts input string to upper case.

File: string.bl

String.replace_all

replace_all :: fn (str: *string, c: u8, with :: ) s32

Replace all found occurrences of character c in the input string with with character and return count of replacements made. This function cannot be used with constant string literals as input.

If with replacement is 0 character, all c occurrences will be erased from the string.

Function return count of replaced characters or zero.

File: string.bl

String.hash

hash :: fn (str: string) u32

Calculates string u32 hash.

File: string.bl

String.is_null

is_null :: fn (s: string) bool #inline

Helper inline function returning true when string is null. In such case string len could be any value.

File: string.bl

String.is_empty

is_empty :: fn (s: string) bool #inline

Helper inline function returning true when string is empty. In such case string ptr could be any pointer.

File: string.bl

String.empty

empty :: 

File: string.bl

String.is_null_or_empty

is_null_or_empty :: fn (s: string) bool #inline

Helper inline function returning true when string is empty and null.

File: string.bl

String.sub

sub :: fn (s: string, start: s64, len : s64: -1) string #inline

Creates substring from passed string starting at start index of input string and ending at start + len index.

Starting index start must be greater than 0 and less than str.len. len specifies optional length of substring. When not specified, length from start to the end of the str is used.

warning: Result sub-string is not guaranteed to be zero terminated and it’s not supposed to be freed.

File: string.bl

String.is_zero_terminated

is_zero_terminated :: fn (str: string) bool

Checks whether string is zero terminated.

File: string.bl

Thread synchronization

#import "std/sync"

Multiplatform implementation of various thread synchronization tools.

warning: This module is experimental and not fully supported across all platforms.

Sync.Mutex

Mutex :: _SyncImpl.Mutex

Mutex type.

File: sync.bl

Sync.init

init :: fn (mutex: *Mutex)  #inline

Initialize mutex. Call :ref:terminate when mutex is no longer needed.

File: sync.bl

Sync.terminate

terminate :: fn (mutex: *Mutex)  #inline

Terminate mutex.

File: sync.bl

Sync.lock

lock :: fn (mutex: *Mutex)  #inline

Lock mutex and enter critical section.

File: sync.bl

Sync.try_lock

try_lock :: fn (mutex: *Mutex) bool #inline

File: sync.bl

Sync.unlock

unlock :: fn (mutex: *Mutex)  #inline

Unlock previously locked mutex and leave critical section.

File: sync.bl

Table

#import "std/table"

Tables are generic data containers aka hash tables or hash maps that store data elements as pairs of Keys and Values. Table provides fast lookup on large amount of data.

Internally, the table is implemented as double-linked list with metadata stored as buckets. A bucket represents begin of sub-list of data associated with hash value calculated from the key value. Table entries are wrapped into Nodes containing key-value data and some metadata required by the table.

Every table insertion cause memory allocation, this can be a performance bottle-neck in some cases, however, already inserted data never change its address (does not move in memory). Consider using a simple dynamic array in cases data set is not too-big (simple iteration over an array can be faster and more memory efficient than using a table.

No memory is allocated until the first call of insert method. After the first insertion, table operates on pre-allocated chunk of memory used to store buckets (DEFAULT_BUCKET_COUNT). The bucket storage is reallocated to double size in case the maximum load factor (table.len / table.buckets.len) is exceeded (maximum load factor is defined as MAX_LF) and whole table is reorganized to achieve optimal performance (rehashing). This operation can be very expensive on large data sets.

Current table implementation is not heavily optimized, this should be improved later, consider using a custom implementation in performance-critical cases.

warning: Table elements are not sorted in any particular way so the iteration over the table does not correspond to the order in which elements were inserted.

warning: The key types are limited to numbers and strings (this may change in the future).

Example

#import "std/table"

main :: fn () s32 {
    table: std.Table(string, s32);
    defer std.tbl_terminate(&table);

    // Insert some data into the table.
    std.tbl_insert(&table, "Martin", 32);
    std.tbl_insert(&table, "Lisa", 29);
    std.tbl_insert(&table, "John", 40);

    // Lookup data by key.
    found :: std.tbl_lookup(&table, "Martin");
    if found != std.tbl_end(&table) {
        print("[%] %\n", found.key, found.value);
    }

    // Iterate over the table
    loop it := std.tbl_begin(&table); it != std.tbl_end(&table); std.tbl_iter_next(&it) {
        print("[%] %\n", it.key, it.value);
    }

    return 0;
}

std.Table

Table :: fn (TKey: type, TValue: type) type

Create a new Table type. The TKey must be a number or string type.

File: table.bl

std.TableIter

TableIter :: fn (TTable: type) type

Create iterator type from Table type.

File: table.bl

std.tbl_init

tbl_init :: fn (tbl: *?T, elem_count :: , allocator : *Allocator: )  #inline

Initialize the tbl table. It’s not necessary to call this method in case the table is already zero-initialized. The elem_count can be specified as hint telling the table how many elements we’re going to store. Memory to hold an internal meta-data is allocated here. The custom allocator can be set.

File: table.bl

std.tbl_terminate

tbl_terminate :: fn (tbl: *?T) 

Release all memory resources used by the table and set the tbl instance to the default state.

File: table.bl

std.tbl_insert

tbl_insert :: fn { impl_insert_empty; impl_insert; }

Overloaded table insert function adding new element into the table associated with the key. The key value must be unique (not already existing in the table), this is checked in debug mode and panic is invoked in case of collision.

Overloads:

fn (tbl: *?T, key: typeof_key(T), value: typeof_value(T)) TableIter(T) #inline
fn (tbl: *?T, key: typeof_key(T)) TableIter(T) #inline

Function returns iterator pointing to the new element. Every new element is allocated using table allocator (can be specified using tbl_init function). Rehashing of the table can be eventually done in case the table’s load factor goes over MAX_LF.

File: table.bl

std.tbl_erase

tbl_erase :: fn (tbl: *?T, key: )  #inline

Erase table entry associated with key. In case there is no such key found function does nothing.

Returns iterator pointing to the next element or to the tbl_end.

File: table.bl

std.tbl_erase_it

tbl_erase_it :: fn (tbl: *?T, it: )  #inline

Erase table entry associated with it iterator. In case the it points to the table end, the function does nothing.

Returns iterator pointing to the next element or to the tbl_end.

File: table.bl

std.tbl_lookup

tbl_lookup :: fn (tbl: *?T, key: )  #inline

Lookup element associated with the key value in the table and return an iterator pointing to the key-value pair. In case there is no such element in the table, the function returns an iterator pointing to the tbl_end().

File: table.bl

std.tbl_contains

tbl_contains :: fn (tbl: *?T, key: ) bool #inline

Checks whether the table tbl contains the key.

File: table.bl

std.tbl_clear

tbl_clear :: fn (tbl: *?T)  #inline

Clears the table and deletes all inserted entries.

File: table.bl

std.tbl_begin

tbl_begin :: fn (tbl: *?T)  #inline

Return an iterator pointing to the table beginning.

File: table.bl

std.tbl_end

tbl_end :: fn (tbl: *?T)  #inline

Return an iterator pointing to the table ending (one element past the last in the table).

File: table.bl

std.tbl_iter_next

tbl_iter_next :: fn (it: *?T)  #inline

Move the iterator it to the next element.

File: table.bl

std.tbl_iter_prev

tbl_iter_prev :: fn (it: *?T)  #inline

Move the iterator it to the previous element.

File: table.bl

Test

#load "std/test.bl"

Integrated unit testing API.

test_eq

test_eq :: fn { fn (got: string, expected: string, loc :: ) ; fn (got: f32, expected: f32, epsilon : f32: , loc :: ) ; fn (got: f64, expected: f64, epsilon : f64: , loc :: ) ; fn (got: ?T, expected: T, loc :: ) ; }

Overloads

fn (got: string, expected: string, loc := #call_location)
fn (got: f32, expected: f32, epsilon: f32 = Math.F32_EPSILON, loc := #call_location)
fn (got: f64, expected: f64, epsilon: f64 = Math.F64_EPSILON, loc := #call_location)
fn (got: ?T, expected: T, loc := #call_location)

Test whether got value is equal to expected value.

File: test.bl

test_neq

test_neq :: fn { fn (got: string, not_expected: string, loc :: ) ; fn (got: f32, not_expected: f32, epsilon : f32: , loc :: ) ; fn (got: f64, not_expected: f64, epsilon : f64: , loc :: ) ; fn (got: ?T, not_expected: T, loc :: ) ; }

Overloads

fn (got: string, not_expected: string, loc := #call_location)
fn (got: f32, not_expected: f32, epsilon: f32 = Math.F32_EPSILON, loc := #call_location)
fn (got: f64, not_expected: f64, epsilon: f64 = Math.F64_EPSILON, loc := #call_location)
fn (got: ?T, not_expected: T, loc := #call_location)

Test whether got value is not equal to not_expected value.

File: test.bl

test_gt

test_gt :: fn (v1: ?T, v2: T, loc :: ) 

Test whether v1 is greater than v2

File: test.bl

test_lt

test_lt :: fn (v1: ?T, v2: T, loc :: ) 

Test whether v1 is less than v2

File: test.bl

test_true

test_true :: fn (v: bool, loc :: ) 

Test whether v value is true.

File: test.bl

test_false

test_false :: fn (v: bool, loc :: ) 

Test whether v value is false.

File: test.bl

test_null

test_null :: fn (ptr: *?T, loc :: ) 

Test whether ptr pointer value is null.

File: test.bl

test_not_null

test_not_null :: fn (ptr: *?T, loc :: ) 

Test whether ptr pointer value is not null.

File: test.bl

test_ok

test_ok :: fn (err: Error, loc :: )  #inline

Test whether err is OK.

File: test.bl

test_not_ok

test_not_ok :: fn (err: Error, loc :: )  #inline

Test whether err is not OK.

File: test.bl

test_is_error

test_is_error :: fn (got_err: Error, expected_code: s32, loc :: )  #inline

Test whether got_err code is expected_code.

File: test.bl

test_run

test_run :: fn (report_memory_leaks :: ) s32

Execute all registered test cases in current assembly. The test_run function uses compiler builtin testcases() function returning slice of all registered test cases in the current assembly (all functions with hash directive #test).

Test case execution can be used in runtime and compile time, in both cases function remap default behaviour of panic() function call and try to report all failing tests without termination.

Formatted output containing information about every test run status and summary report is produced during execution of this function. In case of test failure all needed information about fail source location is reported into standard output.

Returns number of failed tests.

Example

#load "std/test.bl"

my_test :: fn () #test {
    print("Hello from test case!!!\n");     
}

main :: fn () s32 {
    return test_run(); 
} 

File: test.bl

Thread

#import "std/thread"

This module contains tools for managing multithreading. It’s basically wrapper for Windows thread system and pthread on posix systems.

warning: This module is experimental and not fully supported across all platforms.

Thread.EntryFn

EntryFn :: *fn (ctx: *u8) s32

Thread entry function type.

File: thread.bl

Thread.Handle

Handle :: _ThreadImpl.Handle

Thread handle.

File: thread.bl

Thread.create

create :: fn (entry: EntryFn, ctx : *u8: ) (_0: Handle, _1: Error
) #inline

Create and start new thread with specified entry function. Pointer to customctx can be optionally passed to the entry function here.

File: thread.bl

Thread.join

join :: fn (thread: Handle) (exit_code: s32, err: Error
) #inline

Blocks until thread exits. Return value from worker function is returned as exit_code. When execution is successful all thread resources are released.

File: thread.bl

Thread.join_all

join_all :: fn (threads: []Handle) Error #inline

Blocks until all threads exits.

File: thread.bl

Thread.exit

exit :: fn (exit_code : s32: 0) Error #inline

Exit current thread with optional exit_code return value.

File: thread.bl

Thread.current

current :: fn () Handle #inline

Gets current thread.

File: thread.bl

Temporary Allocator

Temporary allocator is memory allocator supposed to be used in case just temporary memory allocation is needed; i.e. to build up file path from individual path components. The allocated memory is valid until temporary_reset or temporary_release is called.

The allocator makes all allocations in bigger preallocated block; i.e. when allocation is requested for the first time, new block is allocated with predefined size DEFAULT_BLOCK_SIZE, all following allocations use the preallocated block if there is enough space. If the block is full and new requested allocation does not fit, another block is allocated (with size slightly bigger then previous one). When temporary_reset is called, allocator will release all smaller allocated blocks and keeps only the biggest one for later use.

Example

#import "std/tmp_allocator"

main :: fn () s32 {
    // Release allocated memory at the end of the scope.
    defer temporary_release();
    
    loop i := 0; i < 1000; i += 1 {
         // Reset the allocator here (all previous alocation are invalid since now).
        defer temporary_reset();
        
        // Allocate memory using temporary allocator.
        int_ptr := cast(*s32) allocate_memory(&temporary_allocator, sizeof(s32));
        
        // Do something here with allocated memory.
        @int_ptr = i;

        // There is no need to free allocated memory here.
    }
    return 0;
}

note: Temporary allocator has it’s internal context allocated per-thread, so the explicit release of the allocated memory at the thread worker exit is mandatory.

temporary_allocator

temporary_allocator :: 

Temporary allocator instance.

File: tmp_allocator.bl

temporary_reset

temporary_reset :: fn ()  #inline

Reduce allocated memory, but keeps biggest allocated chunk for later use.

warning: All resources previously allocated by this allocator became invalid after reset.

hint: Call this method i.e. in every event loop (update) iteration.

File: tmp_allocator.bl

temporary_release

temporary_release :: fn ()  #inline

Release all memory allocated by temporary allocator, this method is supposed to be called at exit of a program.

warning: All resources previously allocated by this allocator became invalid after release.

hint: Call this method before main returns.

File: tmp_allocator.bl

temporary_allocated_bytes

temporary_allocated_bytes :: fn () usize #inline

Return total memory used by temporary allocator in bytes. note: Reports memory usage only for current thread.

File: tmp_allocator.bl

Utils

#load "std/utils.bl"

Set of various utility functions.

set_flag

set_flag :: fn (flags: *?T, flag: T) T #inline

Set flag in flags input. This function is valid for numeric and enum types (checked by assert).

File: utils.bl

clr_flag

clr_flag :: fn (flags: *?T, flag: T) T #inline

Clear flag in flags input. This function is valid for numeric and enum types (checked by assert).

File: utils.bl

is_flag

is_flag :: fn (flags: ?T, flag: T) bool #inline

Check whether flag is set in flags. This function is valid for numeric and enum types (checked by assert).

File: utils.bl

make_flags

make_flags :: fn (f1: ?T, other: ...T) T

File: utils.bl

cstr_to_str

cstr_to_str :: fn (cstr: *u8) string #inline

Converts zero terminated C style string to BL string. Result string shares original memory of cstr.

File: utils.bl

ptr_shift_bytes

ptr_shift_bytes :: fn (ptr: *?T, bytes: s64) *u8 #inline

Produce right-shift of input ptr by count of bytes.

File: utils.bl

ptr_diff

ptr_diff :: fn (a: *?T1, b: *?T2) s64 #inline

Calculates pointer difference a - b.

File: utils.bl

env_get

env_get :: fn (var: string) string

Reads environment variable specified by var name. Result is empty in case no such variable was found or has no content. It’s caller responsibility to delete result string.

File: utils.bl

env_set

env_set :: fn (var: string, value: string)  #inline

Sets environment variable.

File: utils.bl

random_seed_time

random_seed_time :: fn ()  #inline

Sets seed for Math.rand or utility function random_number based on current system tick time.

File: utils.bl

random_number

random_number :: fn (min :: 0, max :: 1) s32 #inline

Generates random number in specified range <min, max> using standard libc rand generator. Random number generator seed is supposed to be set by :ref:random_seed_time or by Math.srand call.

File: utils.bl

sort

sort :: fn (list: []?T, cmp: *fn (a: *T, b: *T) bool) 

Polymorph slice sorting utility. @INCOMPLETE

File: utils.bl

hash_combine

hash_combine :: fn (first: ?T, second: T, more: ...T) T #inline

Combine two or more hashes into one, T is expected to be an integer type (checked by static assert).

File: utils.bl

winapi.bl

Win32.TRUE

TRUE :: 1

File: winapi.bl

Win32.FALSE

FALSE :: 0

File: winapi.bl

Win32.MAX_PATH

MAX_PATH :: 260

File: winapi.bl

Win32.INVALID_HANDLE_VALUE

INVALID_HANDLE_VALUE :: 

File: winapi.bl

Win32.INFINITE

INFINITE : u32 : 4294967295

File: winapi.bl

Win32.ERROR_FILE_NOT_FOUND

ERROR_FILE_NOT_FOUND :: 2

File: winapi.bl

Win32.ERROR_FILE_EXISTS

ERROR_FILE_EXISTS :: 80

File: winapi.bl

Win32.ERROR_ACCESS_DENIED

ERROR_ACCESS_DENIED :: 5

File: winapi.bl

Win32.ERROR_INVALID_HANDLE

ERROR_INVALID_HANDLE :: 6

File: winapi.bl

Win32.ERROR_DIRECTORY

ERROR_DIRECTORY :: 267

File: winapi.bl

Win32.CP_UTF8

CP_UTF8 : u32 : 65001

File: winapi.bl

Win32.WCHAR

WCHAR :: *C.ushort

File: winapi.bl

Win32.LPWSTR

LPWSTR :: *C.ushort

File: winapi.bl

Win32.LPCWSTR

LPCWSTR :: *C.ushort

File: winapi.bl

Win32.LPCSTR

LPCSTR :: *C.ushort

File: winapi.bl

Win32.LPSTR

LPSTR :: *C.uchar

File: winapi.bl

Win32.LPCTSTR

LPCTSTR :: *C.uchar

File: winapi.bl

Win32.HLOCAL

HLOCAL :: *C.uchar

File: winapi.bl

Win32.UINT

UINT :: C.uint

File: winapi.bl

Win32.DWORD

DWORD :: C.uint

File: winapi.bl

Win32.LPCCH

LPCCH :: C.uchar

File: winapi.bl

Win32.LPCWCH

LPCWCH :: C.ushort

File: winapi.bl

Win32.LPBOOL

LPBOOL :: C.int

File: winapi.bl

Win32.HMODULE

HMODULE :: *C.uchar

File: winapi.bl

Win32.BOOL

BOOL :: C.int

File: winapi.bl

Win32.PBOOL

PBOOL :: *BOOL

File: winapi.bl

Win32.FARPROC

FARPROC :: *C.uchar

File: winapi.bl

Win32.LPVOID

LPVOID :: *C.uchar

File: winapi.bl

Win32.LPOVERLAPPED

LPOVERLAPPED :: *OVERLAPPED

File: winapi.bl

Win32.LPDWORD

LPDWORD :: *DWORD

File: winapi.bl

Win32.HANDLE

HANDLE :: *C.uchar

File: winapi.bl

Win32.ULONG_PTR

ULONG_PTR :: *C.ulong

File: winapi.bl

Win32.SIZE_T

SIZE_T :: C.ulong

File: winapi.bl

Win32.PVOID

PVOID :: *C.uchar

File: winapi.bl

Win32.CHAR

CHAR :: C.uchar

File: winapi.bl

Win32.LONG_PTR

LONG_PTR :: *C.long

File: winapi.bl

Win32.LARGE_INTEGER

LARGE_INTEGER :: C.longlong

File: winapi.bl

Win32.PLARGE_INTEGER

PLARGE_INTEGER :: *LARGE_INTEGER

File: winapi.bl

Win32.HGLOBAL

HGLOBAL :: C.void_ptr

File: winapi.bl

Win32.HWND

HWND :: C.void_ptr

File: winapi.bl

Win32.LONG

LONG :: C.long

File: winapi.bl

Win32.PLONG

PLONG :: *LONG

File: winapi.bl

Win32.WORD

WORD :: C.ushort

File: winapi.bl

Win32.GENERIC_READ

GENERIC_READ : u32 : 2147483648

File: winapi.bl

Win32.GENERIC_WRITE

GENERIC_WRITE : u32 : 1073741824

File: winapi.bl

Win32.FILE_BEGIN

FILE_BEGIN : u32 : 0

File: winapi.bl

Win32.FILE_CURRENT

FILE_CURRENT : u32 : 1

File: winapi.bl

Win32.FILE_END

FILE_END : u32 : 2

File: winapi.bl

Win32.CREATE_NEW

CREATE_NEW : u32 : 1

File: winapi.bl

Win32.CREATE_ALWAYS

CREATE_ALWAYS : u32 : 2

File: winapi.bl

Win32.OPEN_EXISTING

OPEN_EXISTING : u32 : 3

File: winapi.bl

Win32.OPEN_ALWAYS

OPEN_ALWAYS : u32 : 4

File: winapi.bl

Win32.TRUNCATE_EXISTING

TRUNCATE_EXISTING : u32 : 5

File: winapi.bl

Win32.LPOVERLAPPED_COMPLETION_ROUTINE

LPOVERLAPPED_COMPLETION_ROUTINE :: *fn (dwErrorCode: DWORD, dwNumberOfBytesTransfered: DWORD, lpOverlapped: LPOVERLAPPED) 

File: winapi.bl

Win32.FILE_ADD_FILE

FILE_ADD_FILE : u32 : 2

File: winapi.bl

Win32.FILE_ADD_SUBDIRECTORY

FILE_ADD_SUBDIRECTORY : u32 : 4

File: winapi.bl

Win32.FILE_APPEND_DATA

FILE_APPEND_DATA : u32 : 4

File: winapi.bl

Win32.FILE_ATTRIBUTE_ARCHIVE

FILE_ATTRIBUTE_ARCHIVE : u32 : 32

File: winapi.bl

Win32.FILE_ATTRIBUTE_COMPRESSED

FILE_ATTRIBUTE_COMPRESSED : u32 : 2048

File: winapi.bl

Win32.FILE_ATTRIBUTE_DEVICE

FILE_ATTRIBUTE_DEVICE : u32 : 64

File: winapi.bl

Win32.FILE_ATTRIBUTE_DIRECTORY

FILE_ATTRIBUTE_DIRECTORY : u32 : 16

File: winapi.bl

Win32.FILE_ATTRIBUTE_ENCRYPTED

FILE_ATTRIBUTE_ENCRYPTED : u32 : 16384

File: winapi.bl

Win32.FILE_ATTRIBUTE_HIDDEN

FILE_ATTRIBUTE_HIDDEN : u32 : 2

File: winapi.bl

Win32.FILE_ATTRIBUTE_NORMAL

FILE_ATTRIBUTE_NORMAL : u32 : 128

File: winapi.bl

Win32.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED

FILE_ATTRIBUTE_NOT_CONTENT_INDEXED : u32 : 8192

File: winapi.bl

Win32.FILE_ATTRIBUTE_OFFLINE

FILE_ATTRIBUTE_OFFLINE : u32 : 4096

File: winapi.bl

Win32.FILE_ATTRIBUTE_READONLY

FILE_ATTRIBUTE_READONLY : u32 : 1

File: winapi.bl

Win32.FILE_ATTRIBUTE_REPARSE_POINT

FILE_ATTRIBUTE_REPARSE_POINT : u32 : 1024

File: winapi.bl

Win32.FILE_ATTRIBUTE_SPARSE_FILE

FILE_ATTRIBUTE_SPARSE_FILE : u32 : 512

File: winapi.bl

Win32.FILE_ATTRIBUTE_SYSTEM

FILE_ATTRIBUTE_SYSTEM : u32 : 4

File: winapi.bl

Win32.FILE_ATTRIBUTE_TEMPORARY

FILE_ATTRIBUTE_TEMPORARY : u32 : 256

File: winapi.bl

Win32.FILE_ATTRIBUTE_VIRTUAL

FILE_ATTRIBUTE_VIRTUAL : u32 : 65536

File: winapi.bl

Win32.FILE_CREATE_PIPE_INSTANCE

FILE_CREATE_PIPE_INSTANCE : u32 : 4

File: winapi.bl

Win32.FILE_FLAG_BACKUP_SEMANTICS

FILE_FLAG_BACKUP_SEMANTICS : u32 : 33554432

File: winapi.bl

Win32.FILE_FLAG_DELETE_ON_CLOSE

FILE_FLAG_DELETE_ON_CLOSE : u32 : 67108864

File: winapi.bl

Win32.FILE_FLAG_FIRST_PIPE_INSTANCE

FILE_FLAG_FIRST_PIPE_INSTANCE : u32 : 524288

File: winapi.bl

Win32.FILE_FLAG_NO_BUFFERING

FILE_FLAG_NO_BUFFERING : u32 : 536870912

File: winapi.bl

Win32.FILE_FLAG_OPEN_NO_RECALL

FILE_FLAG_OPEN_NO_RECALL : u32 : 1048576

File: winapi.bl

Win32.FILE_FLAG_OPEN_REPARSE_POINT

FILE_FLAG_OPEN_REPARSE_POINT : u32 : 2097152

File: winapi.bl

Win32.FILE_FLAG_OVERLAPPED

FILE_FLAG_OVERLAPPED : u32 : 1073741824

File: winapi.bl

Win32.FILE_FLAG_POSIX_SEMANTICS

FILE_FLAG_POSIX_SEMANTICS : u32 : 16777216

File: winapi.bl

Win32.FILE_FLAG_RANDOM_ACCESS

FILE_FLAG_RANDOM_ACCESS : u32 : 268435456

File: winapi.bl

Win32.FILE_FLAG_SEQUENTIAL_SCAN

FILE_FLAG_SEQUENTIAL_SCAN : u32 : 134217728

File: winapi.bl

Win32.FILE_FLAG_SESSION_AWARE

FILE_FLAG_SESSION_AWARE : u32 : 8388608

File: winapi.bl

Win32.FILE_FLAG_WRITE_THROUGH

FILE_FLAG_WRITE_THROUGH : u32 : 2147483648

File: winapi.bl

Win32.FILE_LIST_DIRECTORY

FILE_LIST_DIRECTORY : u32 : 1

File: winapi.bl

Win32.FILE_READ_DATA

FILE_READ_DATA : u32 : 1

File: winapi.bl

Win32.FILE_SHARE_DELETE

FILE_SHARE_DELETE : u32 : 4

File: winapi.bl

Win32.FILE_SHARE_READ

FILE_SHARE_READ : u32 : 1

File: winapi.bl

Win32.FILE_SHARE_WRITE

FILE_SHARE_WRITE : u32 : 2

File: winapi.bl

Win32.FILE_WRITE_DATA

FILE_WRITE_DATA : u32 : 2

File: winapi.bl

Win32.GHND

GHND : u32 : 66

File: winapi.bl

Win32.GMEM_FIXED

GMEM_FIXED : u32 : 0

File: winapi.bl

Win32.GMEM_MOVEABLE

GMEM_MOVEABLE : u32 : 2

File: winapi.bl

Win32.GMEM_ZEROINIT

GMEM_ZEROINIT : u32 : 64

File: winapi.bl

Win32.GPTR

GPTR : u32 : 64

File: winapi.bl

Win32.CF_TEXT

CF_TEXT : u32 : 1

File: winapi.bl

Win32.FILE_NOTIFY_CHANGE_FILE_NAME

FILE_NOTIFY_CHANGE_FILE_NAME : u32 : 1

File: winapi.bl

Win32.FILE_NOTIFY_CHANGE_DIR_NAME

FILE_NOTIFY_CHANGE_DIR_NAME : u32 : 2

File: winapi.bl

Win32.FILE_NOTIFY_CHANGE_ATTRIBUTES

FILE_NOTIFY_CHANGE_ATTRIBUTES : u32 : 4

File: winapi.bl

Win32.FILE_NOTIFY_CHANGE_SIZE

FILE_NOTIFY_CHANGE_SIZE : u32 : 8

File: winapi.bl

Win32.FILE_NOTIFY_CHANGE_LAST_WRITE

FILE_NOTIFY_CHANGE_LAST_WRITE : u32 : 16

File: winapi.bl

Win32.FILE_NOTIFY_CHANGE_LAST_ACCESS

FILE_NOTIFY_CHANGE_LAST_ACCESS : u32 : 32

File: winapi.bl

Win32.FILE_NOTIFY_CHANGE_CREATION

FILE_NOTIFY_CHANGE_CREATION : u32 : 64

File: winapi.bl

Win32.FILE_NOTIFY_CHANGE_SECURITY

FILE_NOTIFY_CHANGE_SECURITY : u32 : 256

File: winapi.bl

Win32.FILE_NOTIFY_INFORMATION

FILE_NOTIFY_INFORMATION :: struct {
    NextEntryOffset: DWORD;
    Action: DWORD;
    FileNameLength: DWORD;
    FileName: ;
}

File: winapi.bl

Win32.OVERLAPPED

OVERLAPPED :: struct {
    Internal: ULONG_PTR;
    InternalHigh: ULONG_PTR;
    Pointer: PVOID;
    hEvent: HANDLE;
}

File: winapi.bl

Win32.FILETIME

FILETIME :: struct {
    dwLowDateTime: DWORD;
    dwHighDateTime: DWORD;
}

File: winapi.bl

Win32.PFILETIME

PFILETIME :: FILETIME

File: winapi.bl

Win32.LPFILETIME

LPFILETIME :: *FILETIME

File: winapi.bl

Win32.FIND_DATA

FIND_DATA :: struct {
    dwFileAttributes: DWORD;
    ftCreationTime: FILETIME;
    ftLastAccessTime: FILETIME;
    ftLastWriteTime: FILETIME;
    nFileSizeHigh: DWORD;
    nFileSizeLow: DWORD;
    dwReserved0: DWORD;
    dwReserved1: DWORD;
    cFileName: ;
    cAlternateFileName: ;
}

File: winapi.bl

Win32.BY_HANDLE_FILE_INFORMATION

BY_HANDLE_FILE_INFORMATION :: struct {
    dwFileAttributes: DWORD;
    ftCreationTime: FILETIME;
    ftLastAccessTime: FILETIME;
    ftLastWriteTime: FILETIME;
    dwVolumeSerialNumber: DWORD;
    nFileSizeHigh: DWORD;
    nFileSizeLow: DWORD;
    nNumberOfLinks: DWORD;
    nFileIndexHigh: DWORD;
    nFileIndexLow: DWORD;
}

File: winapi.bl

Win32.LPBY_HANDLE_FILE_INFORMATION

LPBY_HANDLE_FILE_INFORMATION :: *BY_HANDLE_FILE_INFORMATION

File: winapi.bl

Win32.FIND_DATAA

FIND_DATAA :: FIND_DATA

File: winapi.bl

Win32.P_FIND_DATAA

P_FIND_DATAA :: *FIND_DATA

File: winapi.bl

Win32.LP_FIND_DATAA

LP_FIND_DATAA :: *FIND_DATA

File: winapi.bl

Win32.INVALID_HANDLE

INVALID_HANDLE :: 

File: winapi.bl

Win32.INVALID_FILE_ATTRIBUTES

INVALID_FILE_ATTRIBUTES :: 

File: winapi.bl

Win32.WAIT_TIMEOUT

WAIT_TIMEOUT :: 258

File: winapi.bl

Win32.WAIT_FAILED

WAIT_FAILED : DWORD : 4294967295

File: winapi.bl

Win32.WAIT_OBJECT_0

WAIT_OBJECT_0 :: 0

File: winapi.bl

Win32.LIST_ENTRY

LIST_ENTRY :: struct {
    Flink: *LIST_ENTRY;
    Blink: *LIST_ENTRY;
}

File: winapi.bl

Win32.RTL_CRITICAL_SECTION_DEBUG

RTL_CRITICAL_SECTION_DEBUG :: struct {
    Type: WORD;
    CreatorBackTraceIndex: WORD;
    CriticalSection: *RTL_CRITICAL_SECTION;
    ProcessLocksList: LIST_ENTRY;
    EntryCount: DWORD;
    ContentionCount: DWORD;
    Flags: DWORD;
    CreatorBackTraceIndexHigh: WORD;
    SpareWORD: WORD;
}

File: winapi.bl

Win32.PRTL_CRITICAL_SECTION_DEBUG

PRTL_CRITICAL_SECTION_DEBUG :: *RTL_CRITICAL_SECTION_DEBUG

File: winapi.bl

Win32.RTL_CRITICAL_SECTION

RTL_CRITICAL_SECTION :: struct {
    DebugInfo: PRTL_CRITICAL_SECTION_DEBUG;
    LockCount: LONG;
    RecursionCount: LONG;
    OwningThread: HANDLE;
    LockSemaphore: HANDLE;
    SpinCount: ULONG_PTR;
}

File: winapi.bl

Win32.LPCRITICAL_SECTION

LPCRITICAL_SECTION :: *RTL_CRITICAL_SECTION

File: winapi.bl

Win32.FORMAT_MESSAGE_IGNORE_INSERTS

FORMAT_MESSAGE_IGNORE_INSERTS : u32 : 512

File: winapi.bl

Win32.FORMAT_MESSAGE_FROM_STRING

FORMAT_MESSAGE_FROM_STRING : u32 : 1024

File: winapi.bl

Win32.FORMAT_MESSAGE_FROM_HMODULE

FORMAT_MESSAGE_FROM_HMODULE : u32 : 2048

File: winapi.bl

Win32.FORMAT_MESSAGE_FROM_SYSTEM

FORMAT_MESSAGE_FROM_SYSTEM : u32 : 4096

File: winapi.bl

Win32.FORMAT_MESSAGE_ARGUMENT_ARRAY

FORMAT_MESSAGE_ARGUMENT_ARRAY : u32 : 8192

File: winapi.bl

Win32.FORMAT_MESSAGE_MAX_WIDTH_MASK

FORMAT_MESSAGE_MAX_WIDTH_MASK : u32 : 255

File: winapi.bl

Win32.FindFirstFile

FindFirstFile :: fn (lpFileName: LPCSTR, lpFindFileData: LP_FIND_DATAA) HANDLE #extern

File: winapi.bl

Win32.FindClose

FindClose :: fn (hFindFile: HANDLE) BOOL #extern

File: winapi.bl

Win32.FindNextFile

FindNextFile :: fn (hFindFile: HANDLE, lpFindFileData: LP_FIND_DATAA) BOOL #extern

File: winapi.bl

Win32.GetFileAttributesA

GetFileAttributesA :: fn (lpFileName: LPCSTR) DWORD #extern

File: winapi.bl

Win32.CreateFile

CreateFile :: fn (lpFileName: LPCSTR, dwDesiredAccess: DWORD, dwShareMode: DWORD, lpSecurityAttributes: LPSECURITY_ATTRIBUTES, dwCreationDisposition: DWORD, dwFlagsAndAttributes: DWORD, hTemplateFile: HANDLE) *u8 #extern

File: winapi.bl

Win32.CreateDirectoryA

CreateDirectoryA :: fn (lpPathName: LPCSTR, lpSecurityAttributes: LPSECURITY_ATTRIBUTES) BOOL #extern

File: winapi.bl

Win32.ReadDirectoryChanges

ReadDirectoryChanges :: fn (hDirectory: HANDLE, lpBuffer: LPVOID, nBufferLength: DWORD, bWatchSubtree: BOOL, dwNotifyFilter: DWORD, lpBytesReturned: LPDWORD, lpOverlapped: LPOVERLAPPED, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE) s32 #extern

File: winapi.bl

Win32.WideCharToMultiByte

WideCharToMultiByte :: fn (CodePage: UINT, dwFlags: *DWORD, lpWideCharStr: *LPCWCH, cchWideChar: s32, lpMultiByteStr: LPSTR, cbMultiByte: s32, lpDefaultChar: *LPCCH, lpUsedDefaultChar: *LPBOOL) s32 #extern

File: winapi.bl

Win32.CreateEvent

CreateEvent :: fn (lpEventAttributes: LPSECURITY_ATTRIBUTES, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCSTR) HANDLE #extern

File: winapi.bl

Win32.SetEvent

SetEvent :: fn (hEvent: HANDLE) BOOL #extern

File: winapi.bl

Win32.FindFirstChangeNotification

FindFirstChangeNotification :: fn (lpPathName: LPCSTR, bWatchSubtree: BOOL, dwNotifyFilter: DWORD) HANDLE #extern

File: winapi.bl

Win32.FindNextChangeNotification

FindNextChangeNotification :: fn (hChangeHandle: HANDLE) BOOL #extern

File: winapi.bl

Win32.FindCloseChangeNotification

FindCloseChangeNotification :: fn (hChangeHandle: HANDLE) BOOL #extern

File: winapi.bl

Win32.WaitForSingleObject

WaitForSingleObject :: fn (hHandle: HANDLE, dwMilliseconds: DWORD) DWORD #extern

File: winapi.bl

Win32.WaitForMultipleObjects

WaitForMultipleObjects :: fn (nCount: DWORD, lpHandles: *HANDLE, bWaitAll: BOOL, dwMilliseconds: DWORD) DWORD #extern

File: winapi.bl

Win32.GetCommandLineW

GetCommandLineW :: fn () LPWSTR #extern

File: winapi.bl

Win32.CommandLineToArgvW

CommandLineToArgvW :: fn (lpCmdLine: LPCWSTR, pNumArgs: *s32) *LPWSTR #extern

File: winapi.bl

Win32.LocalFree

LocalFree :: fn (hMem: HLOCAL) HLOCAL #extern

File: winapi.bl

Win32.Sleep

Sleep :: fn (dwMilliseconds: DWORD)  #extern

File: winapi.bl

Win32.SleepEx

SleepEx :: fn (dwMilliseconds: DWORD, bAlertable: BOOL) DWORD #extern

File: winapi.bl

Win32.GetFullPathNameA

GetFullPathNameA :: fn (lpFileName: LPCSTR, nBufferLength: DWORD, lpBuffer: LPSTR, lpFilePart: *LPSTR) DWORD #extern

File: winapi.bl

Win32.PathFileExistsA

PathFileExistsA :: fn (pszPath: LPCSTR) BOOL #extern

File: winapi.bl

Win32.LoadLibraryA

LoadLibraryA :: fn (lpLibFileName: LPCSTR) HMODULE #extern

File: winapi.bl

Win32.FreeLibrary

FreeLibrary :: fn (hLibModule: HMODULE) BOOL #extern

File: winapi.bl

Win32.GetModuleHandleA

GetModuleHandleA :: fn (lpModuleName: LPCSTR) HMODULE #extern

File: winapi.bl

Win32.GetProcAddress

GetProcAddress :: fn (hModule: HMODULE, lpProcName: LPCSTR) FARPROC #extern

File: winapi.bl

Win32.DebugBreak

DebugBreak :: fn ()  #extern

File: winapi.bl

Win32.IsDebuggerPresent

IsDebuggerPresent :: fn () BOOL #extern

File: winapi.bl

Win32.CheckRemoteDebuggerPresent

CheckRemoteDebuggerPresent :: fn (hProcess: HANDLE, pbDebuggerPresent: PBOOL) BOOL #extern

File: winapi.bl

Win32.GetModuleFileNameA

GetModuleFileNameA :: fn (hModule: HMODULE, lpFilename: LPSTR, nSize: DWORD) DWORD #extern

File: winapi.bl

Win32.SECURITY_ATTRIBUTES

SECURITY_ATTRIBUTES :: struct {
    nLength: DWORD;
    lpSecurityDescriptor: LPVOID;
    bInheritHandle: BOOL;
}

File: winapi.bl

Win32.PSECURITY_ATTRIBUTES

PSECURITY_ATTRIBUTES :: *SECURITY_ATTRIBUTES

File: winapi.bl

Win32.LPSECURITY_ATTRIBUTES

LPSECURITY_ATTRIBUTES :: *SECURITY_ATTRIBUTES

File: winapi.bl

Win32.LPTHREAD_START_ROUTINE

LPTHREAD_START_ROUTINE :: *fn (args: LPVOID) DWORD

File: winapi.bl

Win32.CreateThread

CreateThread :: fn (lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, lpStartAddress: LPTHREAD_START_ROUTINE, lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD) HANDLE #extern

File: winapi.bl

Win32.GetCurrentThread

GetCurrentThread :: fn () HANDLE #extern

File: winapi.bl

Win32.TerminateThread

TerminateThread :: fn (handle: HANDLE, exit_code: DWORD) BOOL #extern

File: winapi.bl

Win32.GetExitCodeThread

GetExitCodeThread :: fn (hThread: HANDLE, lpExitCode: LPDWORD) BOOL #extern

File: winapi.bl

Win32.CreateMutexA

CreateMutexA :: fn (lpMutexAttributes: LPSECURITY_ATTRIBUTES, bInitialOwner: BOOL, lpName: LPCSTR) HANDLE #extern

File: winapi.bl

Win32.ReleaseMutex

ReleaseMutex :: fn (hMutex: HANDLE) BOOL #extern

File: winapi.bl

Win32.GetTickCount

GetTickCount :: fn () DWORD #extern

File: winapi.bl

Win32.QueryPerformanceCounter

QueryPerformanceCounter :: fn (lpPerformanceCount: *LARGE_INTEGER) BOOL #extern

File: winapi.bl

Win32.QueryPerformanceFrequency

QueryPerformanceFrequency :: fn (lpPerformanceCount: *LARGE_INTEGER) BOOL #extern

File: winapi.bl

Win32.GlobalAlloc

GlobalAlloc :: fn (uFlags: UINT, dwBytes: SIZE_T) HGLOBAL #extern

File: winapi.bl

Win32.GlobalFree

GlobalFree :: fn (hMem: HGLOBAL) HGLOBAL #extern

File: winapi.bl

Win32.GlobalLock

GlobalLock :: fn (hMem: HGLOBAL) LPVOID #extern

File: winapi.bl

Win32.GlobalUnlock

GlobalUnlock :: fn (hMem: HGLOBAL) BOOL #extern

File: winapi.bl

Win32.OpenClipboard

OpenClipboard :: fn (hWndNewOwner: HWND) BOOL #extern

File: winapi.bl

Win32.EmptyClipboard

EmptyClipboard :: fn () BOOL #extern

File: winapi.bl

Win32.SetClipboardData

SetClipboardData :: fn (uFormat: UINT, hMem: HANDLE) HANDLE #extern

File: winapi.bl

Win32.GetClipboardData

GetClipboardData :: fn (uFormat: UINT) HANDLE #extern

File: winapi.bl

Win32.CloseClipboard

CloseClipboard :: fn () BOOL #extern

File: winapi.bl

Win32.GetLastError

GetLastError :: fn () DWORD #extern

File: winapi.bl

Win32.CloseHandle

CloseHandle :: fn (hObject: HANDLE) BOOL #extern

File: winapi.bl

Win32.GetTempPathA

GetTempPathA :: fn (nBufferLength: DWORD, lpBuffer: LPSTR) DWORD #extern

File: winapi.bl

Win32.DeleteFileA

DeleteFileA :: fn (lpFileName: LPCSTR) BOOL #extern

File: winapi.bl

Win32.RemoveDirectoryA

RemoveDirectoryA :: fn (lpPathName: LPCSTR) BOOL #extern

File: winapi.bl

Win32.GetCurrentDirectoryA

GetCurrentDirectoryA :: fn (nBufferLength: DWORD, lpBuffer: LPSTR) DWORD #extern

File: winapi.bl

Win32.SetCurrentDirectoryA

SetCurrentDirectoryA :: fn (lpPathName: LPSTR) BOOL #extern

File: winapi.bl

Win32.GetFileSizeEx

GetFileSizeEx :: fn (hFile: HANDLE, lpFileSize: PLARGE_INTEGER) BOOL #extern

File: winapi.bl

Win32.ReadFile

ReadFile :: fn (hFile: HANDLE, lpBuffer: LPVOID, nNumberOfBytesToRead: DWORD, lpNumberOfBytesRead: LPDWORD, lpOverlapped: LPOVERLAPPED) BOOL #extern

File: winapi.bl

Win32.WriteFile

WriteFile :: fn (hFile: HANDLE, lpBuffer: LPVOID, nNumberOfBytesToWrite: DWORD, lpNumberOfBytesWritten: LPDWORD, lpOverlapped: LPOVERLAPPED) BOOL #extern

File: winapi.bl

Win32.CopyFileA

CopyFileA :: fn (lpExistingFileName: LPCTSTR, lpNewFileName: LPCTSTR, bFailIfExists: BOOL) BOOL #extern

File: winapi.bl

Win32.SetEndOfFile

SetEndOfFile :: fn (hFile: HANDLE) BOOL #extern

File: winapi.bl

Win32.SetFilePointer

SetFilePointer :: fn (hFile: HANDLE, lDistanceToMove: LONG, lpDistanceToMoveHigh: PLONG, dwMoveMethod: DWORD) DWORD #extern

File: winapi.bl

Win32.InitializeCriticalSection

InitializeCriticalSection :: fn (lpCriticalSection: LPCRITICAL_SECTION)  #extern

File: winapi.bl

Win32.DeleteCriticalSection

DeleteCriticalSection :: fn (lpCriticalSection: LPCRITICAL_SECTION)  #extern

File: winapi.bl

Win32.EnterCriticalSection

EnterCriticalSection :: fn (lpCriticalSection: LPCRITICAL_SECTION)  #extern

File: winapi.bl

Win32.LeaveCriticalSection

LeaveCriticalSection :: fn (lpCriticalSection: LPCRITICAL_SECTION)  #extern

File: winapi.bl

Win32.TryEnterCriticalSection

TryEnterCriticalSection :: fn (lpCriticalSection: LPCRITICAL_SECTION) BOOL #extern

File: winapi.bl

Win32.GetFileInformationByHandle

GetFileInformationByHandle :: fn (hFile: HANDLE, lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) BOOL #extern

File: winapi.bl

Win32.GetOverlappedResult

GetOverlappedResult :: fn (hFile: HANDLE, lpOverlapped: LPOVERLAPPED, lpNumberOfBytesTransferred: LPDWORD, bWait: BOOL) BOOL #extern

File: winapi.bl

Win32.ResetEvent

ResetEvent :: fn (hEvent: HANDLE) BOOL #extern

File: winapi.bl

Win32.FormatMessageA

FormatMessageA :: fn (dwFlags: DWORD, lpSource: LPVOID, dwMessageId: DWORD, dwLanguageId: DWORD, lpBuffer: LPSTR, nSize: DWORD, Arguments: *u8) DWORD #extern

File: winapi.bl

x86_64.bl

C.opendir

opendir :: fn (name: *char) *DIR #extern

File: x86_64.bl

C.fdopendir

fdopendir :: fn (fd: int) *DIR #extern

File: x86_64.bl

C.readdir

readdir :: fn (dirp: *DIR) *dirent_t #extern

File: x86_64.bl

C.rewinddir

rewinddir :: fn (dirp: *DIR)  #extern

File: x86_64.bl

C.stat

stat :: fn (path: *char, buf: *stat_t) int #extern

File: x86_64.bl

C.fstat

fstat :: fn (fd: int, stat: *stat_t) int #extern

File: x86_64.bl