explicitly return from blocks

instead of last statement being expression value

closes #629
This commit is contained in:
Andrew Kelley 2017-12-22 00:50:30 -05:00
parent 8bc523219c
commit d917815d81
114 changed files with 1203 additions and 1231 deletions

View File

@ -49,7 +49,7 @@ fn gen(in: &io.InStream, out: &io.OutStream) {
if (err == error.EndOfStream) { if (err == error.EndOfStream) {
return; return;
} }
std.debug.panic("{}", err) std.debug.panic("{}", err);
}; };
switch (state) { switch (state) {
State.Start => switch (byte) { State.Start => switch (byte) {

View File

@ -3021,14 +3021,13 @@ const assert = @import("std").debug.assert;</code></pre>
<pre><code class="zig">const assert = @import("std").debug.assert; <pre><code class="zig">const assert = @import("std").debug.assert;
// Functions are declared like this // Functions are declared like this
// The last expression in the function can be used as the return value.
fn add(a: i8, b: i8) -&gt; i8 { fn add(a: i8, b: i8) -&gt; i8 {
if (a == 0) { if (a == 0) {
// You can still return manually if needed. // You can still return manually if needed.
return b; return b;
} }
a + b return a + b;
} }
// The export specifier makes a function externally visible in the generated // The export specifier makes a function externally visible in the generated
@ -5847,7 +5846,7 @@ ParamDeclList = "(" list(ParamDecl, ",") ")"
ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...") ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...")
Block = option(Symbol ":") "{" many(Statement) option(Expression) "}" Block = option(Symbol ":") "{" many(Statement) "}"
Statement = LocalVarDecl ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" Statement = LocalVarDecl ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";"

View File

@ -1,3 +1,3 @@
export fn add(a: i32, b: i32) -> i32 { export fn add(a: i32, b: i32) -> i32 {
a + b return a + b;
} }

View File

@ -111,11 +111,11 @@ pub const Parser = struct {
} }
pub fn parse(self: &Parser) -> %&ast.NodeRoot { pub fn parse(self: &Parser) -> %&ast.NodeRoot {
const result = self.parseInner() %% |err| { const result = self.parseInner() %% |err| x: {
if (self.cleanup_root_node) |root_node| { if (self.cleanup_root_node) |root_node| {
self.freeAst(root_node); self.freeAst(root_node);
} }
err break :x err;
}; };
self.cleanup_root_node = null; self.cleanup_root_node = null;
return result; return result;
@ -125,12 +125,12 @@ pub const Parser = struct {
var stack = self.initUtilityArrayList(State); var stack = self.initUtilityArrayList(State);
defer self.deinitUtilityArrayList(stack); defer self.deinitUtilityArrayList(stack);
const root_node = { const root_node = x: {
const root_node = %return self.createRoot(); const root_node = %return self.createRoot();
%defer self.allocator.destroy(root_node); %defer self.allocator.destroy(root_node);
// This stack append has to succeed for freeAst to work // This stack append has to succeed for freeAst to work
%return stack.append(State.TopLevel); %return stack.append(State.TopLevel);
root_node break :x root_node;
}; };
assert(self.cleanup_root_node == null); assert(self.cleanup_root_node == null);
self.cleanup_root_node = root_node; self.cleanup_root_node = root_node;
@ -462,7 +462,7 @@ pub const Parser = struct {
} else if (token.id == Token.Id.Keyword_noalias) { } else if (token.id == Token.Id.Keyword_noalias) {
param_decl.noalias_token = token; param_decl.noalias_token = token;
token = self.getNextToken(); token = self.getNextToken();
}; }
if (token.id == Token.Id.Identifier) { if (token.id == Token.Id.Identifier) {
const next_token = self.getNextToken(); const next_token = self.getNextToken();
if (next_token.id == Token.Id.Colon) { if (next_token.id == Token.Id.Colon) {
@ -793,14 +793,14 @@ pub const Parser = struct {
} }
fn getNextToken(self: &Parser) -> Token { fn getNextToken(self: &Parser) -> Token {
return if (self.put_back_count != 0) { if (self.put_back_count != 0) {
const put_back_index = self.put_back_count - 1; const put_back_index = self.put_back_count - 1;
const put_back_token = self.put_back_tokens[put_back_index]; const put_back_token = self.put_back_tokens[put_back_index];
self.put_back_count = put_back_index; self.put_back_count = put_back_index;
put_back_token return put_back_token;
} else { } else {
self.tokenizer.next() return self.tokenizer.next();
}; }
} }
const RenderAstFrame = struct { const RenderAstFrame = struct {
@ -873,7 +873,7 @@ pub const Parser = struct {
Token.Id.Keyword_pub => %return stream.print("pub "), Token.Id.Keyword_pub => %return stream.print("pub "),
Token.Id.Keyword_export => %return stream.print("export "), Token.Id.Keyword_export => %return stream.print("export "),
else => unreachable, else => unreachable,
}; }
} }
if (fn_proto.extern_token) |extern_token| { if (fn_proto.extern_token) |extern_token| {
%return stream.print("{} ", self.tokenizer.getTokenSlice(extern_token)); %return stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
@ -1102,7 +1102,7 @@ fn testParse(source: []const u8, allocator: &mem.Allocator) -> %[]u8 {
// TODO test for memory leaks // TODO test for memory leaks
// TODO test for valid frees // TODO test for valid frees
fn testCanonical(source: []const u8) { fn testCanonical(source: []const u8) {
const needed_alloc_count = { const needed_alloc_count = x: {
// Try it once with unlimited memory, make sure it works // Try it once with unlimited memory, make sure it works
var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]); var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, @maxValue(usize)); var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, @maxValue(usize));
@ -1116,7 +1116,7 @@ fn testCanonical(source: []const u8) {
@panic("test failed"); @panic("test failed");
} }
failing_allocator.allocator.free(result_source); failing_allocator.allocator.free(result_source);
failing_allocator.index break :x failing_allocator.index;
}; };
// TODO make this pass // TODO make this pass

View File

@ -26,7 +26,6 @@ struct ScopeFnDef;
struct TypeTableEntry; struct TypeTableEntry;
struct VariableTableEntry; struct VariableTableEntry;
struct ErrorTableEntry; struct ErrorTableEntry;
struct LabelTableEntry;
struct BuiltinFnEntry; struct BuiltinFnEntry;
struct TypeStructField; struct TypeStructField;
struct CodeGen; struct CodeGen;
@ -54,7 +53,6 @@ struct IrExecutable {
size_t *backward_branch_count; size_t *backward_branch_count;
size_t backward_branch_quota; size_t backward_branch_quota;
bool invalid; bool invalid;
ZigList<LabelTableEntry *> all_labels;
ZigList<IrGotoItem> goto_list; ZigList<IrGotoItem> goto_list;
bool is_inline; bool is_inline;
FnTableEntry *fn_entry; FnTableEntry *fn_entry;
@ -452,7 +450,6 @@ struct AstNodeParamDecl {
struct AstNodeBlock { struct AstNodeBlock {
Buf *name; Buf *name;
ZigList<AstNode *> statements; ZigList<AstNode *> statements;
bool last_statement_is_result_expression;
}; };
enum ReturnKind { enum ReturnKind {
@ -1644,12 +1641,6 @@ struct ErrorTableEntry {
ConstExprValue *cached_error_name_val; ConstExprValue *cached_error_name_val;
}; };
struct LabelTableEntry {
AstNode *decl_node;
IrBasicBlock *bb;
bool used;
};
enum ScopeId { enum ScopeId {
ScopeIdDecls, ScopeIdDecls,
ScopeIdBlock, ScopeIdBlock,
@ -1693,7 +1684,12 @@ struct ScopeDecls {
struct ScopeBlock { struct ScopeBlock {
Scope base; Scope base;
HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table; Buf *name;
IrBasicBlock *end_block;
IrInstruction *is_comptime;
ZigList<IrInstruction *> *incoming_values;
ZigList<IrBasicBlock *> *incoming_blocks;
bool safety_off; bool safety_off;
AstNode *safety_set_node; AstNode *safety_set_node;
bool fast_math_off; bool fast_math_off;

View File

@ -110,7 +110,7 @@ ScopeBlock *create_block_scope(AstNode *node, Scope *parent) {
assert(node->type == NodeTypeBlock); assert(node->type == NodeTypeBlock);
ScopeBlock *scope = allocate<ScopeBlock>(1); ScopeBlock *scope = allocate<ScopeBlock>(1);
init_scope(&scope->base, ScopeIdBlock, node, parent); init_scope(&scope->base, ScopeIdBlock, node, parent);
scope->label_table.init(1); scope->name = node->data.block.name;
return scope; return scope;
} }

View File

@ -478,10 +478,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
AstNode *statement = node->data.block.statements.at(i); AstNode *statement = node->data.block.statements.at(i);
print_indent(ar); print_indent(ar);
render_node_grouped(ar, statement); render_node_grouped(ar, statement);
if (!(i == node->data.block.statements.length - 1 && fprintf(ar->f, ";");
node->data.block.last_statement_is_result_expression)) {
fprintf(ar->f, ";");
}
fprintf(ar->f, "\n"); fprintf(ar->f, "\n");
} }
ar->indent -= ar->indent_size; ar->indent -= ar->indent_size;

View File

@ -3514,7 +3514,11 @@ static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *s
static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node) { static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node) {
assert(block_node->type == NodeTypeBlock); assert(block_node->type == NodeTypeBlock);
ZigList<IrInstruction *> incoming_values = {0};
ZigList<IrBasicBlock *> incoming_blocks = {0};
ScopeBlock *scope_block = create_block_scope(block_node, parent_scope); ScopeBlock *scope_block = create_block_scope(block_node, parent_scope);
Scope *outer_block_scope = &scope_block->base; Scope *outer_block_scope = &scope_block->base;
Scope *child_scope = outer_block_scope; Scope *child_scope = outer_block_scope;
@ -3528,9 +3532,15 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
return ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); return ir_mark_gen(ir_build_const_void(irb, child_scope, block_node));
} }
if (block_node->data.block.name != nullptr) {
scope_block->incoming_blocks = &incoming_blocks;
scope_block->incoming_values = &incoming_values;
scope_block->end_block = ir_build_basic_block(irb, parent_scope, "BlockEnd");
scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope));
}
bool is_continuation_unreachable = false; bool is_continuation_unreachable = false;
IrInstruction *noreturn_return_value = nullptr; IrInstruction *noreturn_return_value = nullptr;
IrInstruction *return_value = nullptr;
for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) {
AstNode *statement_node = block_node->data.block.statements.at(i); AstNode *statement_node = block_node->data.block.statements.at(i);
@ -3548,39 +3558,31 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
// variable declarations start a new scope // variable declarations start a new scope
IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value; IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value;
child_scope = decl_var_instruction->var->child_scope; child_scope = decl_var_instruction->var->child_scope;
} else { } else if (statement_value != irb->codegen->invalid_instruction) {
// label, defer, variable declaration will never be the result expression // this statement's value must be void
if (block_node->data.block.last_statement_is_result_expression && ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, statement_node, statement_value));
i == block_node->data.block.statements.length - 1) {
// this is the result value statement
return_value = statement_value;
} else {
// there are more statements ahead of this one. this statement's value must be void
if (statement_value != irb->codegen->invalid_instruction) {
ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, statement_node, statement_value));
}
}
} }
} }
if (is_continuation_unreachable) { if (is_continuation_unreachable) {
assert(noreturn_return_value != nullptr); assert(noreturn_return_value != nullptr);
return noreturn_return_value; if (block_node->data.block.name == nullptr || incoming_blocks.length == 0) {
} return noreturn_return_value;
// control flow falls out of block }
if (block_node->data.block.last_statement_is_result_expression) {
// return value was determined by the last statement
assert(return_value != nullptr);
} else { } else {
// return value is implicitly void incoming_blocks.append(irb->current_basic_block);
assert(return_value == nullptr); incoming_values.append(ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)));
return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node));
} }
ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); if (block_node->data.block.name != nullptr) {
ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
return return_value; ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime));
ir_set_cursor_at_end(irb, scope_block->end_block);
return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
} else {
ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
return ir_mark_gen(ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)));
}
} }
static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) { static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) {
@ -5952,6 +5954,31 @@ static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNo
return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval); return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval);
} }
static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {
IrInstruction *is_comptime;
if (ir_should_inline(irb->exec, break_scope)) {
is_comptime = ir_build_const_bool(irb, break_scope, node, true);
} else {
is_comptime = block_scope->is_comptime;
}
IrInstruction *result_value;
if (node->data.break_expr.expr) {
result_value = ir_gen_node(irb, node->data.break_expr.expr, break_scope);
if (result_value == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
} else {
result_value = ir_build_const_void(irb, break_scope, node);
}
IrBasicBlock *dest_block = block_scope->end_block;
ir_gen_defers_for_block(irb, break_scope, dest_block->scope, false);
block_scope->incoming_blocks->append(irb->current_basic_block);
block_scope->incoming_values->append(result_value);
return ir_build_br(irb, break_scope, node, dest_block, is_comptime);
}
static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *node) { static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *node) {
assert(node->type == NodeTypeBreak); assert(node->type == NodeTypeBreak);
@ -5959,14 +5986,14 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *
// * function definition scope or global scope => error, break outside loop // * function definition scope or global scope => error, break outside loop
// * defer expression scope => error, cannot break out of defer expression // * defer expression scope => error, cannot break out of defer expression
// * loop scope => OK // * loop scope => OK
// * (if it's a labeled break) labeled block => OK
Scope *search_scope = break_scope; Scope *search_scope = break_scope;
ScopeLoop *loop_scope; ScopeLoop *loop_scope;
bool saw_any_loop_scope = false;
for (;;) { for (;;) {
if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) {
if (saw_any_loop_scope) { if (node->data.break_expr.name != nullptr) {
add_node_error(irb->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.break_expr.name))); add_node_error(irb->codegen, node, buf_sprintf("label not found: '%s'", buf_ptr(node->data.break_expr.name)));
return irb->codegen->invalid_instruction; return irb->codegen->invalid_instruction;
} else { } else {
add_node_error(irb->codegen, node, buf_sprintf("break expression outside loop")); add_node_error(irb->codegen, node, buf_sprintf("break expression outside loop"));
@ -5977,13 +6004,20 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *
return irb->codegen->invalid_instruction; return irb->codegen->invalid_instruction;
} else if (search_scope->id == ScopeIdLoop) { } else if (search_scope->id == ScopeIdLoop) {
ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope;
saw_any_loop_scope = true;
if (node->data.break_expr.name == nullptr || if (node->data.break_expr.name == nullptr ||
(this_loop_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_loop_scope->name))) (this_loop_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_loop_scope->name)))
{ {
loop_scope = this_loop_scope; loop_scope = this_loop_scope;
break; break;
} }
} else if (search_scope->id == ScopeIdBlock) {
ScopeBlock *this_block_scope = (ScopeBlock *)search_scope;
if (node->data.break_expr.name != nullptr &&
(this_block_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_block_scope->name)))
{
assert(this_block_scope->end_block != nullptr);
return ir_gen_return_from_block(irb, break_scope, node, this_block_scope);
}
} }
search_scope = search_scope->parent; search_scope = search_scope->parent;
} }
@ -6022,10 +6056,9 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast
Scope *search_scope = continue_scope; Scope *search_scope = continue_scope;
ScopeLoop *loop_scope; ScopeLoop *loop_scope;
bool saw_any_loop_scope = false;
for (;;) { for (;;) {
if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) {
if (saw_any_loop_scope) { if (node->data.continue_expr.name != nullptr) {
add_node_error(irb->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.continue_expr.name))); add_node_error(irb->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.continue_expr.name)));
return irb->codegen->invalid_instruction; return irb->codegen->invalid_instruction;
} else { } else {
@ -6037,7 +6070,6 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast
return irb->codegen->invalid_instruction; return irb->codegen->invalid_instruction;
} else if (search_scope->id == ScopeIdLoop) { } else if (search_scope->id == ScopeIdLoop) {
ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope;
saw_any_loop_scope = true;
if (node->data.continue_expr.name == nullptr || if (node->data.continue_expr.name == nullptr ||
(this_loop_scope->name != nullptr && buf_eql_buf(node->data.continue_expr.name, this_loop_scope->name))) (this_loop_scope->name != nullptr && buf_eql_buf(node->data.continue_expr.name, this_loop_scope->name)))
{ {

View File

@ -748,7 +748,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
node->data.fn_call_expr.is_builtin = true; node->data.fn_call_expr.is_builtin = true;
return node; return node;
} else if (token->id == TokenIdSymbol) { }
AstNode *block_expr_node = ast_parse_block_expr(pc, token_index, false);
if (block_expr_node) {
return block_expr_node;
}
if (token->id == TokenIdSymbol) {
*token_index += 1; *token_index += 1;
AstNode *node = ast_create_node(pc, NodeTypeSymbol, token); AstNode *node = ast_create_node(pc, NodeTypeSymbol, token);
node->data.symbol_expr.symbol = token_buf(token); node->data.symbol_expr.symbol = token_buf(token);
@ -760,11 +767,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
return grouped_expr_node; return grouped_expr_node;
} }
AstNode *block_expr_node = ast_parse_block_expr(pc, token_index, false);
if (block_expr_node) {
return block_expr_node;
}
AstNode *array_type_node = ast_parse_array_type_expr(pc, token_index, false); AstNode *array_type_node = ast_parse_array_type_expr(pc, token_index, false);
if (array_type_node) { if (array_type_node) {
return array_type_node; return array_type_node;
@ -2145,9 +2147,6 @@ static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool
return nullptr; return nullptr;
} }
/*
Label: token(Symbol) token(Colon)
*/
static bool statement_terminates_without_semicolon(AstNode *node) { static bool statement_terminates_without_semicolon(AstNode *node) {
switch (node->type) { switch (node->type) {
case NodeTypeIfBoolExpr: case NodeTypeIfBoolExpr:
@ -2179,7 +2178,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
} }
/* /*
Block = option(Symbol ":") "{" many(Statement) option(Expression) "}" Block = option(Symbol ":") "{" many(Statement) "}"
Statement = Label | VariableDeclaration ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" | ExportDecl Statement = Label | VariableDeclaration ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" | ExportDecl
*/ */
static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mandatory) { static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mandatory) {
@ -2220,6 +2219,12 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
} }
for (;;) { for (;;) {
last_token = &pc->tokens->at(*token_index);
if (last_token->id == TokenIdRBrace) {
*token_index += 1;
return node;
}
AstNode *statement_node = ast_parse_local_var_decl(pc, token_index); AstNode *statement_node = ast_parse_local_var_decl(pc, token_index);
if (!statement_node) if (!statement_node)
statement_node = ast_parse_defer_expr(pc, token_index); statement_node = ast_parse_defer_expr(pc, token_index);
@ -2228,32 +2233,14 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
if (!statement_node) if (!statement_node)
statement_node = ast_parse_expression(pc, token_index, false); statement_node = ast_parse_expression(pc, token_index, false);
bool semicolon_expected = true; if (!statement_node) {
if (statement_node) { ast_invalid_token_error(pc, last_token);
node->data.block.statements.append(statement_node);
if (statement_terminates_without_semicolon(statement_node)) {
semicolon_expected = false;
} else {
if (statement_node->type == NodeTypeDefer) {
// defer without a block body requires a semicolon
Token *token = &pc->tokens->at(*token_index);
ast_expect_token(pc, token, TokenIdSemicolon);
}
}
} }
node->data.block.last_statement_is_result_expression = statement_node && statement_node->type != NodeTypeDefer; node->data.block.statements.append(statement_node);
last_token = &pc->tokens->at(*token_index); if (!statement_terminates_without_semicolon(statement_node)) {
if (last_token->id == TokenIdRBrace) { ast_eat_token(pc, token_index, TokenIdSemicolon);
*token_index += 1;
return node;
} else if (!semicolon_expected) {
continue;
} else if (last_token->id == TokenIdSemicolon) {
*token_index += 1;
} else {
ast_invalid_token_error(pc, last_token);
} }
} }
zig_unreachable(); zig_unreachable();

View File

@ -171,6 +171,20 @@ static AstNode * trans_create_node(Context *c, NodeType id) {
return node; return node;
} }
static AstNode *trans_create_node_break(Context *c, Buf *label_name, AstNode *value_node) {
AstNode *node = trans_create_node(c, NodeTypeBreak);
node->data.break_expr.name = label_name;
node->data.break_expr.expr = value_node;
return node;
}
static AstNode *trans_create_node_return(Context *c, AstNode *value_node) {
AstNode *node = trans_create_node(c, NodeTypeReturnExpr);
node->data.return_expr.kind = ReturnKindUnconditional;
node->data.return_expr.expr = value_node;
return node;
}
static AstNode *trans_create_node_if(Context *c, AstNode *cond_node, AstNode *then_node, AstNode *else_node) { static AstNode *trans_create_node_if(Context *c, AstNode *cond_node, AstNode *then_node, AstNode *else_node) {
AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
node->data.if_bool_expr.condition = cond_node; node->data.if_bool_expr.condition = cond_node;
@ -372,8 +386,7 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *r
AstNode *block = trans_create_node(c, NodeTypeBlock); AstNode *block = trans_create_node(c, NodeTypeBlock);
block->data.block.statements.resize(1); block->data.block.statements.resize(1);
block->data.block.statements.items[0] = fn_call_node; block->data.block.statements.items[0] = trans_create_node_return(c, fn_call_node);
block->data.block.last_statement_is_result_expression = true;
fn_def->data.fn_def.body = block; fn_def->data.fn_def.body = block;
return fn_def; return fn_def;
@ -1140,13 +1153,15 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco
} else { } else {
// worst case // worst case
// c: lhs = rhs // c: lhs = rhs
// zig: { // zig: x: {
// zig: const _tmp = rhs; // zig: const _tmp = rhs;
// zig: lhs = _tmp; // zig: lhs = _tmp;
// zig: _tmp // zig: break :x _tmp
// zig: } // zig: }
TransScopeBlock *child_scope = trans_scope_block_create(c, scope); TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
Buf *label_name = buf_create_from_str("x");
child_scope->node->data.block.name = label_name;
// const _tmp = rhs; // const _tmp = rhs;
AstNode *rhs_node = trans_expr(c, ResultUsedYes, &child_scope->base, rhs, TransRValue); AstNode *rhs_node = trans_expr(c, ResultUsedYes, &child_scope->base, rhs, TransRValue);
@ -1163,9 +1178,9 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco
trans_create_node_bin_op(c, lhs_node, BinOpTypeAssign, trans_create_node_bin_op(c, lhs_node, BinOpTypeAssign,
trans_create_node_symbol(c, tmp_var_name))); trans_create_node_symbol(c, tmp_var_name)));
// _tmp // break :x _tmp
child_scope->node->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); AstNode *tmp_symbol_node = trans_create_node_symbol(c, tmp_var_name);
child_scope->node->data.block.last_statement_is_result_expression = true; child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, tmp_symbol_node));
return child_scope->node; return child_scope->node;
} }
@ -1270,6 +1285,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
case BO_Comma: case BO_Comma:
{ {
TransScopeBlock *scope_block = trans_scope_block_create(c, scope); TransScopeBlock *scope_block = trans_scope_block_create(c, scope);
Buf *label_name = buf_create_from_str("x");
scope_block->node->data.block.name = label_name;
AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, stmt->getLHS(), TransRValue); AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, stmt->getLHS(), TransRValue);
if (lhs == nullptr) if (lhs == nullptr)
return nullptr; return nullptr;
@ -1278,9 +1296,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
AstNode *rhs = trans_expr(c, result_used, &scope_block->base, stmt->getRHS(), TransRValue); AstNode *rhs = trans_expr(c, result_used, &scope_block->base, stmt->getRHS(), TransRValue);
if (rhs == nullptr) if (rhs == nullptr)
return nullptr; return nullptr;
scope_block->node->data.block.statements.append(maybe_suppress_result(c, result_used, rhs)); scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs)));
scope_block->node->data.block.last_statement_is_result_expression = true;
return scope_block->node; return scope_block->node;
} }
case BO_MulAssign: case BO_MulAssign:
@ -1320,14 +1336,16 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
} else { } else {
// need more complexity. worst case, this looks like this: // need more complexity. worst case, this looks like this:
// c: lhs >>= rhs // c: lhs >>= rhs
// zig: { // zig: x: {
// zig: const _ref = &lhs; // zig: const _ref = &lhs;
// zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs)); // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs));
// zig: *_ref // zig: break :x *_ref
// zig: } // zig: }
// where u5 is the appropriate type // where u5 is the appropriate type
TransScopeBlock *child_scope = trans_scope_block_create(c, scope); TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
Buf *label_name = buf_create_from_str("x");
child_scope->node->data.block.name = label_name;
// const _ref = &lhs; // const _ref = &lhs;
AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue); AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue);
@ -1369,11 +1387,11 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
child_scope->node->data.block.statements.append(assign_statement); child_scope->node->data.block.statements.append(assign_statement);
if (result_used == ResultUsedYes) { if (result_used == ResultUsedYes) {
// *_ref // break :x *_ref
child_scope->node->data.block.statements.append( child_scope->node->data.block.statements.append(
trans_create_node_prefix_op(c, PrefixOpDereference, trans_create_node_break(c, label_name,
trans_create_node_symbol(c, tmp_var_name))); trans_create_node_prefix_op(c, PrefixOpDereference,
child_scope->node->data.block.last_statement_is_result_expression = true; trans_create_node_symbol(c, tmp_var_name))));
} }
return child_scope->node; return child_scope->node;
@ -1394,13 +1412,15 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
} else { } else {
// need more complexity. worst case, this looks like this: // need more complexity. worst case, this looks like this:
// c: lhs += rhs // c: lhs += rhs
// zig: { // zig: x: {
// zig: const _ref = &lhs; // zig: const _ref = &lhs;
// zig: *_ref = *_ref + rhs; // zig: *_ref = *_ref + rhs;
// zig: *_ref // zig: break :x *_ref
// zig: } // zig: }
TransScopeBlock *child_scope = trans_scope_block_create(c, scope); TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
Buf *label_name = buf_create_from_str("x");
child_scope->node->data.block.name = label_name;
// const _ref = &lhs; // const _ref = &lhs;
AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue); AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base, stmt->getLHS(), TransLValue);
@ -1427,11 +1447,11 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
rhs)); rhs));
child_scope->node->data.block.statements.append(assign_statement); child_scope->node->data.block.statements.append(assign_statement);
// *_ref // break :x *_ref
child_scope->node->data.block.statements.append( child_scope->node->data.block.statements.append(
trans_create_node_prefix_op(c, PrefixOpDereference, trans_create_node_break(c, label_name,
trans_create_node_symbol(c, tmp_var_name))); trans_create_node_prefix_op(c, PrefixOpDereference,
child_scope->node->data.block.last_statement_is_result_expression = true; trans_create_node_symbol(c, tmp_var_name))));
return child_scope->node; return child_scope->node;
} }
@ -1726,13 +1746,15 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
} }
// worst case // worst case
// c: expr++ // c: expr++
// zig: { // zig: x: {
// zig: const _ref = &expr; // zig: const _ref = &expr;
// zig: const _tmp = *_ref; // zig: const _tmp = *_ref;
// zig: *_ref += 1; // zig: *_ref += 1;
// zig: _tmp // zig: break :x _tmp
// zig: } // zig: }
TransScopeBlock *child_scope = trans_scope_block_create(c, scope); TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
Buf *label_name = buf_create_from_str("x");
child_scope->node->data.block.name = label_name;
// const _ref = &expr; // const _ref = &expr;
AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue); AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue);
@ -1758,9 +1780,8 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
trans_create_node_unsigned(c, 1)); trans_create_node_unsigned(c, 1));
child_scope->node->data.block.statements.append(assign_statement); child_scope->node->data.block.statements.append(assign_statement);
// _tmp // break :x _tmp
child_scope->node->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, trans_create_node_symbol(c, tmp_var_name)));
child_scope->node->data.block.last_statement_is_result_expression = true;
return child_scope->node; return child_scope->node;
} }
@ -1781,12 +1802,14 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
} }
// worst case // worst case
// c: ++expr // c: ++expr
// zig: { // zig: x: {
// zig: const _ref = &expr; // zig: const _ref = &expr;
// zig: *_ref += 1; // zig: *_ref += 1;
// zig: *_ref // zig: break :x *_ref
// zig: } // zig: }
TransScopeBlock *child_scope = trans_scope_block_create(c, scope); TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
Buf *label_name = buf_create_from_str("x");
child_scope->node->data.block.name = label_name;
// const _ref = &expr; // const _ref = &expr;
AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue); AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue);
@ -1805,11 +1828,10 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
trans_create_node_unsigned(c, 1)); trans_create_node_unsigned(c, 1));
child_scope->node->data.block.statements.append(assign_statement); child_scope->node->data.block.statements.append(assign_statement);
// *_ref // break :x *_ref
AstNode *deref_expr = trans_create_node_prefix_op(c, PrefixOpDereference, AstNode *deref_expr = trans_create_node_prefix_op(c, PrefixOpDereference,
trans_create_node_symbol(c, ref_var_name)); trans_create_node_symbol(c, ref_var_name));
child_scope->node->data.block.statements.append(deref_expr); child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, deref_expr));
child_scope->node->data.block.last_statement_is_result_expression = true;
return child_scope->node; return child_scope->node;
} }

View File

@ -8,7 +8,7 @@ pub fn ArrayList(comptime T: type) -> type {
} }
pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{
struct { return struct {
const Self = this; const Self = this;
/// Use toSlice instead of slicing this directly, because if you don't /// Use toSlice instead of slicing this directly, because if you don't
@ -20,11 +20,11 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{
/// Deinitialize with `deinit` or use `toOwnedSlice`. /// Deinitialize with `deinit` or use `toOwnedSlice`.
pub fn init(allocator: &Allocator) -> Self { pub fn init(allocator: &Allocator) -> Self {
Self { return Self {
.items = []align(A) T{}, .items = []align(A) T{},
.len = 0, .len = 0,
.allocator = allocator, .allocator = allocator,
} };
} }
pub fn deinit(l: &Self) { pub fn deinit(l: &Self) {
@ -107,7 +107,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{
return null; return null;
return self.pop(); return self.pop();
} }
} };
} }
test "basic ArrayList test" { test "basic ArrayList test" {

View File

@ -30,9 +30,9 @@ pub const Buffer = struct {
/// * ::replaceContentsBuffer /// * ::replaceContentsBuffer
/// * ::resize /// * ::resize
pub fn initNull(allocator: &Allocator) -> Buffer { pub fn initNull(allocator: &Allocator) -> Buffer {
Buffer { return Buffer {
.list = ArrayList(u8).init(allocator), .list = ArrayList(u8).init(allocator),
} };
} }
/// Must deinitialize with deinit. /// Must deinitialize with deinit.
@ -120,7 +120,7 @@ pub const Buffer = struct {
} }
pub fn eql(self: &const Buffer, m: []const u8) -> bool { pub fn eql(self: &const Buffer, m: []const u8) -> bool {
mem.eql(u8, self.toSliceConst(), m) return mem.eql(u8, self.toSliceConst(), m);
} }
pub fn startsWith(self: &const Buffer, m: []const u8) -> bool { pub fn startsWith(self: &const Buffer, m: []const u8) -> bool {

View File

@ -221,11 +221,11 @@ pub const Builder = struct {
} }
pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) -> Version { pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) -> Version {
Version { return Version {
.major = major, .major = major,
.minor = minor, .minor = minor,
.patch = patch, .patch = patch,
} };
} }
pub fn addCIncludePath(self: &Builder, path: []const u8) { pub fn addCIncludePath(self: &Builder, path: []const u8) {
@ -432,16 +432,16 @@ pub const Builder = struct {
const release_safe = self.option(bool, "release-safe", "optimizations on and safety on") ?? false; const release_safe = self.option(bool, "release-safe", "optimizations on and safety on") ?? false;
const release_fast = self.option(bool, "release-fast", "optimizations on and safety off") ?? false; const release_fast = self.option(bool, "release-fast", "optimizations on and safety off") ?? false;
const mode = if (release_safe and !release_fast) { const mode = if (release_safe and !release_fast)
builtin.Mode.ReleaseSafe builtin.Mode.ReleaseSafe
} else if (release_fast and !release_safe) { else if (release_fast and !release_safe)
builtin.Mode.ReleaseFast builtin.Mode.ReleaseFast
} else if (!release_fast and !release_safe) { else if (!release_fast and !release_safe)
builtin.Mode.Debug builtin.Mode.Debug
} else { else x: {
warn("Both -Drelease-safe and -Drelease-fast specified"); warn("Both -Drelease-safe and -Drelease-fast specified");
self.markInvalidUserInput(); self.markInvalidUserInput();
builtin.Mode.Debug break :x builtin.Mode.Debug;
}; };
self.release_mode = mode; self.release_mode = mode;
return mode; return mode;
@ -506,7 +506,7 @@ pub const Builder = struct {
} }
fn typeToEnum(comptime T: type) -> TypeId { fn typeToEnum(comptime T: type) -> TypeId {
switch (@typeId(T)) { return switch (@typeId(T)) {
builtin.TypeId.Int => TypeId.Int, builtin.TypeId.Int => TypeId.Int,
builtin.TypeId.Float => TypeId.Float, builtin.TypeId.Float => TypeId.Float,
builtin.TypeId.Bool => TypeId.Bool, builtin.TypeId.Bool => TypeId.Bool,
@ -515,7 +515,7 @@ pub const Builder = struct {
[]const []const u8 => TypeId.List, []const []const u8 => TypeId.List,
else => @compileError("Unsupported type: " ++ @typeName(T)), else => @compileError("Unsupported type: " ++ @typeName(T)),
}, },
} };
} }
fn markInvalidUserInput(self: &Builder) { fn markInvalidUserInput(self: &Builder) {
@ -590,8 +590,7 @@ pub const Builder = struct {
return error.UncleanExit; return error.UncleanExit;
}, },
}; }
} }
pub fn makePath(self: &Builder, path: []const u8) -> %void { pub fn makePath(self: &Builder, path: []const u8) -> %void {
@ -662,13 +661,12 @@ pub const Builder = struct {
if (builtin.environ == builtin.Environ.msvc) { if (builtin.environ == builtin.Environ.msvc) {
return "cl.exe"; return "cl.exe";
} else { } else {
return os.getEnvVarOwned(self.allocator, "CC") %% |err| { return os.getEnvVarOwned(self.allocator, "CC") %% |err|
if (err == error.EnvironmentVariableNotFound) { if (err == error.EnvironmentVariableNotFound)
([]const u8)("cc") ([]const u8)("cc")
} else { else
debug.panic("Unable to get environment variable: {}", err); debug.panic("Unable to get environment variable: {}", err)
} ;
};
} }
} }
@ -1079,11 +1077,10 @@ pub const LibExeObjStep = struct {
} }
pub fn getOutputPath(self: &LibExeObjStep) -> []const u8 { pub fn getOutputPath(self: &LibExeObjStep) -> []const u8 {
if (self.output_path) |output_path| { return if (self.output_path) |output_path|
output_path output_path
} else { else
%%os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) %%os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename);
}
} }
pub fn setOutputHPath(self: &LibExeObjStep, file_path: []const u8) { pub fn setOutputHPath(self: &LibExeObjStep, file_path: []const u8) {
@ -1096,11 +1093,10 @@ pub const LibExeObjStep = struct {
} }
pub fn getOutputHPath(self: &LibExeObjStep) -> []const u8 { pub fn getOutputHPath(self: &LibExeObjStep) -> []const u8 {
if (self.output_h_path) |output_h_path| { return if (self.output_h_path) |output_h_path|
output_h_path output_h_path
} else { else
%%os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) %%os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename);
}
} }
pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) { pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) {
@ -1618,7 +1614,7 @@ pub const TestStep = struct {
pub fn init(builder: &Builder, root_src: []const u8) -> TestStep { pub fn init(builder: &Builder, root_src: []const u8) -> TestStep {
const step_name = builder.fmt("test {}", root_src); const step_name = builder.fmt("test {}", root_src);
TestStep { return TestStep {
.step = Step.init(step_name, builder.allocator, make), .step = Step.init(step_name, builder.allocator, make),
.builder = builder, .builder = builder,
.root_src = root_src, .root_src = root_src,
@ -1629,7 +1625,7 @@ pub const TestStep = struct {
.link_libs = BufSet.init(builder.allocator), .link_libs = BufSet.init(builder.allocator),
.target = Target { .Native = {} }, .target = Target { .Native = {} },
.exec_cmd_args = null, .exec_cmd_args = null,
} };
} }
pub fn setVerbose(self: &TestStep, value: bool) { pub fn setVerbose(self: &TestStep, value: bool) {
@ -1936,16 +1932,16 @@ pub const Step = struct {
done_flag: bool, done_flag: bool,
pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)->%void) -> Step { pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)->%void) -> Step {
Step { return Step {
.name = name, .name = name,
.makeFn = makeFn, .makeFn = makeFn,
.dependencies = ArrayList(&Step).init(allocator), .dependencies = ArrayList(&Step).init(allocator),
.loop_flag = false, .loop_flag = false,
.done_flag = false, .done_flag = false,
} };
} }
pub fn initNoOp(name: []const u8, allocator: &Allocator) -> Step { pub fn initNoOp(name: []const u8, allocator: &Allocator) -> Step {
init(name, allocator, makeNoOp) return init(name, allocator, makeNoOp);
} }
pub fn make(self: &Step) -> %void { pub fn make(self: &Step) -> %void {

View File

@ -17,7 +17,7 @@ pub fn cmp(a: &const u8, b: &const u8) -> i8 {
return -1; return -1;
} else { } else {
return 0; return 0;
}; }
} }
pub fn toSliceConst(str: &const u8) -> []const u8 { pub fn toSliceConst(str: &const u8) -> []const u8 {

View File

@ -32,7 +32,7 @@ fn getStderrStream() -> %&io.OutStream {
const st = &stderr_file_out_stream.stream; const st = &stderr_file_out_stream.stream;
stderr_stream = st; stderr_stream = st;
return st; return st;
}; }
} }
/// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.
@ -52,9 +52,9 @@ pub fn assert(ok: bool) {
// we insert an explicit call to @panic instead of unreachable. // we insert an explicit call to @panic instead of unreachable.
// TODO we should use `assertOrPanic` in tests and remove this logic. // TODO we should use `assertOrPanic` in tests and remove this logic.
if (builtin.is_test) { if (builtin.is_test) {
@panic("assertion failure") @panic("assertion failure");
} else { } else {
unreachable // assertion failure unreachable; // assertion failure
} }
} }
} }
@ -175,7 +175,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty
return_address, compile_unit_name); return_address, compile_unit_name);
}, },
else => return err, else => return err,
}; }
} }
}, },
builtin.ObjectFormat.coff => { builtin.ObjectFormat.coff => {
@ -357,7 +357,7 @@ const Die = struct {
FormValue.String => |value| value, FormValue.String => |value| value,
FormValue.StrPtr => |offset| getString(st, offset), FormValue.StrPtr => |offset| getString(st, offset),
else => error.InvalidDebugInfo, else => error.InvalidDebugInfo,
} };
} }
}; };
@ -403,7 +403,7 @@ const LineNumberProgram = struct {
pub fn init(is_stmt: bool, include_dirs: []const []const u8, pub fn init(is_stmt: bool, include_dirs: []const []const u8,
file_entries: &ArrayList(FileEntry), target_address: usize) -> LineNumberProgram file_entries: &ArrayList(FileEntry), target_address: usize) -> LineNumberProgram
{ {
LineNumberProgram { return LineNumberProgram {
.address = 0, .address = 0,
.file = 1, .file = 1,
.line = 1, .line = 1,
@ -421,7 +421,7 @@ const LineNumberProgram = struct {
.prev_is_stmt = undefined, .prev_is_stmt = undefined,
.prev_basic_block = undefined, .prev_basic_block = undefined,
.prev_end_sequence = undefined, .prev_end_sequence = undefined,
} };
} }
pub fn checkLineMatch(self: &LineNumberProgram) -> %?LineInfo { pub fn checkLineMatch(self: &LineNumberProgram) -> %?LineInfo {
@ -430,14 +430,11 @@ const LineNumberProgram = struct {
return error.MissingDebugInfo; return error.MissingDebugInfo;
} else if (self.prev_file - 1 >= self.file_entries.len) { } else if (self.prev_file - 1 >= self.file_entries.len) {
return error.InvalidDebugInfo; return error.InvalidDebugInfo;
} else { } else &self.file_entries.items[self.prev_file - 1];
&self.file_entries.items[self.prev_file - 1]
};
const dir_name = if (file_entry.dir_index >= self.include_dirs.len) { const dir_name = if (file_entry.dir_index >= self.include_dirs.len) {
return error.InvalidDebugInfo; return error.InvalidDebugInfo;
} else { } else self.include_dirs[file_entry.dir_index];
self.include_dirs[file_entry.dir_index]
};
const file_name = %return os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name); const file_name = %return os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name);
%defer self.file_entries.allocator.free(file_name); %defer self.file_entries.allocator.free(file_name);
return LineInfo { return LineInfo {
@ -494,28 +491,21 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size:
} }
fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue { fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue {
FormValue { .Const = Constant { return FormValue { .Const = Constant {
.signed = signed, .signed = signed,
.payload = %return readAllocBytes(allocator, in_stream, size), .payload = %return readAllocBytes(allocator, in_stream, size),
}} }};
} }
fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) -> %u64 { fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) -> %u64 {
return if (is_64) { return if (is_64) %return in_stream.readIntLe(u64)
%return in_stream.readIntLe(u64) else u64(%return in_stream.readIntLe(u32)) ;
} else {
u64(%return in_stream.readIntLe(u32))
};
} }
fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 { fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 {
return if (@sizeOf(usize) == 4) { return if (@sizeOf(usize) == 4) u64(%return in_stream.readIntLe(u32))
u64(%return in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) %return in_stream.readIntLe(u64)
} else if (@sizeOf(usize) == 8) { else unreachable;
%return in_stream.readIntLe(u64)
} else {
unreachable;
};
} }
fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue {
@ -534,9 +524,9 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4), DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
DW.FORM_block => { DW.FORM_block => x: {
const block_len = %return readULeb128(in_stream); const block_len = %return readULeb128(in_stream);
parseFormValueBlockLen(allocator, in_stream, block_len) return parseFormValueBlockLen(allocator, in_stream, block_len);
}, },
DW.FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1), DW.FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1),
DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2), DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2),
@ -545,7 +535,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
DW.FORM_udata, DW.FORM_sdata => { DW.FORM_udata, DW.FORM_sdata => {
const block_len = %return readULeb128(in_stream); const block_len = %return readULeb128(in_stream);
const signed = form_id == DW.FORM_sdata; const signed = form_id == DW.FORM_sdata;
parseFormValueConstant(allocator, in_stream, signed, block_len) return parseFormValueConstant(allocator, in_stream, signed, block_len);
}, },
DW.FORM_exprloc => { DW.FORM_exprloc => {
const size = %return readULeb128(in_stream); const size = %return readULeb128(in_stream);
@ -562,7 +552,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, u64), DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, u64),
DW.FORM_ref_udata => { DW.FORM_ref_udata => {
const ref_len = %return readULeb128(in_stream); const ref_len = %return readULeb128(in_stream);
parseFormValueRefLen(allocator, in_stream, ref_len) return parseFormValueRefLen(allocator, in_stream, ref_len);
}, },
DW.FORM_ref_addr => FormValue { .RefAddr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, DW.FORM_ref_addr => FormValue { .RefAddr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
@ -572,10 +562,10 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
DW.FORM_strp => FormValue { .StrPtr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) }, DW.FORM_strp => FormValue { .StrPtr = %return parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_indirect => { DW.FORM_indirect => {
const child_form_id = %return readULeb128(in_stream); const child_form_id = %return readULeb128(in_stream);
parseFormValue(allocator, in_stream, child_form_id, is_64) return parseFormValue(allocator, in_stream, child_form_id, is_64);
}, },
else => error.InvalidDebugInfo, else => error.InvalidDebugInfo,
} };
} }
fn parseAbbrevTable(st: &ElfStackTrace) -> %AbbrevTable { fn parseAbbrevTable(st: &ElfStackTrace) -> %AbbrevTable {
@ -852,11 +842,9 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
const version = %return in_stream.readInt(st.elf.endian, u16); const version = %return in_stream.readInt(st.elf.endian, u16);
if (version < 2 or version > 5) return error.InvalidDebugInfo; if (version < 2 or version > 5) return error.InvalidDebugInfo;
const debug_abbrev_offset = if (is_64) { const debug_abbrev_offset =
%return in_stream.readInt(st.elf.endian, u64) if (is_64) %return in_stream.readInt(st.elf.endian, u64)
} else { else %return in_stream.readInt(st.elf.endian, u32);
%return in_stream.readInt(st.elf.endian, u32)
};
const address_size = %return in_stream.readByte(); const address_size = %return in_stream.readByte();
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
@ -872,28 +860,28 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
if (compile_unit_die.tag_id != DW.TAG_compile_unit) if (compile_unit_die.tag_id != DW.TAG_compile_unit)
return error.InvalidDebugInfo; return error.InvalidDebugInfo;
const pc_range = { const pc_range = x: {
if (compile_unit_die.getAttrAddr(DW.AT_low_pc)) |low_pc| { if (compile_unit_die.getAttrAddr(DW.AT_low_pc)) |low_pc| {
if (compile_unit_die.getAttr(DW.AT_high_pc)) |high_pc_value| { if (compile_unit_die.getAttr(DW.AT_high_pc)) |high_pc_value| {
const pc_end = switch (*high_pc_value) { const pc_end = switch (*high_pc_value) {
FormValue.Address => |value| value, FormValue.Address => |value| value,
FormValue.Const => |value| { FormValue.Const => |value| b: {
const offset = %return value.asUnsignedLe(); const offset = %return value.asUnsignedLe();
low_pc + offset break :b (low_pc + offset);
}, },
else => return error.InvalidDebugInfo, else => return error.InvalidDebugInfo,
}; };
PcRange { break :x PcRange {
.start = low_pc, .start = low_pc,
.end = pc_end, .end = pc_end,
} };
} else { } else {
null break :x null;
} }
} else |err| { } else |err| {
if (err != error.MissingDebugInfo) if (err != error.MissingDebugInfo)
return err; return err;
null break :x null;
} }
}; };
@ -949,12 +937,12 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> %&const CompileUn
fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 { fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 {
const first_32_bits = %return in_stream.readIntLe(u32); const first_32_bits = %return in_stream.readIntLe(u32);
*is_64 = (first_32_bits == 0xffffffff); *is_64 = (first_32_bits == 0xffffffff);
return if (*is_64) { if (*is_64) {
%return in_stream.readIntLe(u64) return in_stream.readIntLe(u64);
} else { } else {
if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
u64(first_32_bits) return u64(first_32_bits);
}; }
} }
fn readULeb128(in_stream: &io.InStream) -> %u64 { fn readULeb128(in_stream: &io.InStream) -> %u64 {

View File

@ -2,15 +2,15 @@ const mem = @import("mem.zig");
const builtin = @import("builtin"); const builtin = @import("builtin");
pub fn swapIfLe(comptime T: type, x: T) -> T { pub fn swapIfLe(comptime T: type, x: T) -> T {
swapIf(false, T, x) return swapIf(false, T, x);
} }
pub fn swapIfBe(comptime T: type, x: T) -> T { pub fn swapIfBe(comptime T: type, x: T) -> T {
swapIf(true, T, x) return swapIf(true, T, x);
} }
pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T { pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T {
if (builtin.endian == endian) swap(T, x) else x return if (builtin.endian == endian) swap(T, x) else x;
} }
pub fn swap(comptime T: type, x: T) -> T { pub fn swap(comptime T: type, x: T) -> T {

View File

@ -439,10 +439,10 @@ const Slab = struct {
}; };
fn slab(str: []const u8, exp: i32) -> Slab { fn slab(str: []const u8, exp: i32) -> Slab {
Slab { return Slab {
.str = str, .str = str,
.exp = exp, .exp = exp,
} };
} }
pub const enum3_data = []Slab { pub const enum3_data = []Slab {

View File

@ -251,11 +251,10 @@ pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []cons
%return output(context, float_decimal.digits[0..1]); %return output(context, float_decimal.digits[0..1]);
%return output(context, "."); %return output(context, ".");
if (float_decimal.digits.len > 1) { if (float_decimal.digits.len > 1) {
const num_digits = if (@typeOf(value) == f32) { const num_digits = if (@typeOf(value) == f32)
math.min(usize(9), float_decimal.digits.len) math.min(usize(9), float_decimal.digits.len)
} else { else
float_decimal.digits.len float_decimal.digits.len;
};
%return output(context, float_decimal.digits[1 .. num_digits]); %return output(context, float_decimal.digits[1 .. num_digits]);
} else { } else {
%return output(context, "0"); %return output(context, "0");

View File

@ -12,7 +12,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
comptime hash: fn(key: K)->u32, comptime hash: fn(key: K)->u32,
comptime eql: fn(a: K, b: K)->bool) -> type comptime eql: fn(a: K, b: K)->bool) -> type
{ {
struct { return struct {
entries: []Entry, entries: []Entry,
size: usize, size: usize,
max_distance_from_start_index: usize, max_distance_from_start_index: usize,
@ -51,19 +51,19 @@ pub fn HashMap(comptime K: type, comptime V: type,
return entry; return entry;
} }
} }
unreachable // no next item unreachable; // no next item
} }
}; };
pub fn init(allocator: &Allocator) -> Self { pub fn init(allocator: &Allocator) -> Self {
Self { return Self {
.entries = []Entry{}, .entries = []Entry{},
.allocator = allocator, .allocator = allocator,
.size = 0, .size = 0,
.max_distance_from_start_index = 0, .max_distance_from_start_index = 0,
// it doesn't actually matter what we set this to since we use wrapping integer arithmetic // it doesn't actually matter what we set this to since we use wrapping integer arithmetic
.modification_count = undefined, .modification_count = undefined,
} };
} }
pub fn deinit(hm: &Self) { pub fn deinit(hm: &Self) {
@ -133,7 +133,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
entry.distance_from_start_index -= 1; entry.distance_from_start_index -= 1;
entry = next_entry; entry = next_entry;
} }
unreachable // shifting everything in the table unreachable; // shifting everything in the table
}} }}
return null; return null;
} }
@ -169,7 +169,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
const start_index = hm.keyToIndex(key); const start_index = hm.keyToIndex(key);
var roll_over: usize = 0; var roll_over: usize = 0;
var distance_from_start_index: usize = 0; var distance_from_start_index: usize = 0;
while (roll_over < hm.entries.len) : ({roll_over += 1; distance_from_start_index += 1}) { while (roll_over < hm.entries.len) : ({roll_over += 1; distance_from_start_index += 1;}) {
const index = (start_index + roll_over) % hm.entries.len; const index = (start_index + roll_over) % hm.entries.len;
const entry = &hm.entries[index]; const entry = &hm.entries[index];
@ -210,7 +210,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
}; };
return result; return result;
} }
unreachable // put into a full map unreachable; // put into a full map
} }
fn internalGet(hm: &Self, key: K) -> ?&Entry { fn internalGet(hm: &Self, key: K) -> ?&Entry {
@ -228,7 +228,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
fn keyToIndex(hm: &Self, key: K) -> usize { fn keyToIndex(hm: &Self, key: K) -> usize {
return usize(hash(key)) % hm.entries.len; return usize(hash(key)) % hm.entries.len;
} }
} };
} }
test "basicHashMapTest" { test "basicHashMapTest" {
@ -251,9 +251,9 @@ test "basicHashMapTest" {
} }
fn hash_i32(x: i32) -> u32 { fn hash_i32(x: i32) -> u32 {
@bitCast(u32, x) return @bitCast(u32, x);
} }
fn eql_i32(a: i32, b: i32) -> bool { fn eql_i32(a: i32, b: i32) -> bool {
a == b return a == b;
} }

View File

@ -17,22 +17,21 @@ pub var c_allocator = Allocator {
}; };
fn cAlloc(self: &Allocator, n: usize, alignment: u29) -> %[]u8 { fn cAlloc(self: &Allocator, n: usize, alignment: u29) -> %[]u8 {
if (c.malloc(usize(n))) |buf| { return if (c.malloc(usize(n))) |buf|
@ptrCast(&u8, buf)[0..n] @ptrCast(&u8, buf)[0..n]
} else { else
error.OutOfMemory error.OutOfMemory;
}
} }
fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 { fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 {
if (new_size <= old_mem.len) { if (new_size <= old_mem.len) {
old_mem[0..new_size] return old_mem[0..new_size];
} else { } else {
const old_ptr = @ptrCast(&c_void, old_mem.ptr); const old_ptr = @ptrCast(&c_void, old_mem.ptr);
if (c.realloc(old_ptr, usize(new_size))) |buf| { if (c.realloc(old_ptr, usize(new_size))) |buf| {
@ptrCast(&u8, buf)[0..new_size] return @ptrCast(&u8, buf)[0..new_size];
} else { } else {
error.OutOfMemory return error.OutOfMemory;
} }
} }
} }

View File

@ -50,35 +50,32 @@ error Unseekable;
error EndOfFile; error EndOfFile;
pub fn getStdErr() -> %File { pub fn getStdErr() -> %File {
const handle = if (is_windows) { const handle = if (is_windows)
%return os.windowsGetStdHandle(system.STD_ERROR_HANDLE) %return os.windowsGetStdHandle(system.STD_ERROR_HANDLE)
} else if (is_posix) { else if (is_posix)
system.STDERR_FILENO system.STDERR_FILENO
} else { else
unreachable unreachable;
};
return File.openHandle(handle); return File.openHandle(handle);
} }
pub fn getStdOut() -> %File { pub fn getStdOut() -> %File {
const handle = if (is_windows) { const handle = if (is_windows)
%return os.windowsGetStdHandle(system.STD_OUTPUT_HANDLE) %return os.windowsGetStdHandle(system.STD_OUTPUT_HANDLE)
} else if (is_posix) { else if (is_posix)
system.STDOUT_FILENO system.STDOUT_FILENO
} else { else
unreachable unreachable;
};
return File.openHandle(handle); return File.openHandle(handle);
} }
pub fn getStdIn() -> %File { pub fn getStdIn() -> %File {
const handle = if (is_windows) { const handle = if (is_windows)
%return os.windowsGetStdHandle(system.STD_INPUT_HANDLE) %return os.windowsGetStdHandle(system.STD_INPUT_HANDLE)
} else if (is_posix) { else if (is_posix)
system.STDIN_FILENO system.STDIN_FILENO
} else { else
unreachable unreachable;
};
return File.openHandle(handle); return File.openHandle(handle);
} }
@ -261,7 +258,7 @@ pub const File = struct {
system.EBADF => error.BadFd, system.EBADF => error.BadFd,
system.ENOMEM => error.SystemResources, system.ENOMEM => error.SystemResources,
else => os.unexpectedErrorPosix(err), else => os.unexpectedErrorPosix(err),
} };
} }
return usize(stat.size); return usize(stat.size);

View File

@ -5,7 +5,7 @@ const Allocator = mem.Allocator;
/// Generic doubly linked list. /// Generic doubly linked list.
pub fn LinkedList(comptime T: type) -> type { pub fn LinkedList(comptime T: type) -> type {
struct { return struct {
const Self = this; const Self = this;
/// Node inside the linked list wrapping the actual data. /// Node inside the linked list wrapping the actual data.
@ -15,11 +15,11 @@ pub fn LinkedList(comptime T: type) -> type {
data: T, data: T,
pub fn init(data: &const T) -> Node { pub fn init(data: &const T) -> Node {
Node { return Node {
.prev = null, .prev = null,
.next = null, .next = null,
.data = *data, .data = *data,
} };
} }
}; };
@ -32,11 +32,11 @@ pub fn LinkedList(comptime T: type) -> type {
/// Returns: /// Returns:
/// An empty linked list. /// An empty linked list.
pub fn init() -> Self { pub fn init() -> Self {
Self { return Self {
.first = null, .first = null,
.last = null, .last = null,
.len = 0, .len = 0,
} };
} }
/// Insert a new node after an existing one. /// Insert a new node after an existing one.
@ -166,7 +166,7 @@ pub fn LinkedList(comptime T: type) -> type {
/// Returns: /// Returns:
/// A pointer to the new node. /// A pointer to the new node.
pub fn allocateNode(list: &Self, allocator: &Allocator) -> %&Node { pub fn allocateNode(list: &Self, allocator: &Allocator) -> %&Node {
allocator.create(Node) return allocator.create(Node);
} }
/// Deallocate a node. /// Deallocate a node.
@ -191,7 +191,7 @@ pub fn LinkedList(comptime T: type) -> type {
*node = Node.init(data); *node = Node.init(data);
return node; return node;
} }
} };
} }
test "basic linked list test" { test "basic linked list test" {

View File

@ -7,11 +7,11 @@ const assert = @import("../debug.zig").assert;
pub fn acos(x: var) -> @typeOf(x) { pub fn acos(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(acos32, x), f32 => @inlineCall(acos32, x),
f64 => @inlineCall(acos64, x), f64 => @inlineCall(acos64, x),
else => @compileError("acos not implemented for " ++ @typeName(T)), else => @compileError("acos not implemented for " ++ @typeName(T)),
} };
} }
fn r32(z: f32) -> f32 { fn r32(z: f32) -> f32 {
@ -22,7 +22,7 @@ fn r32(z: f32) -> f32 {
const p = z * (pS0 + z * (pS1 + z * pS2)); const p = z * (pS0 + z * (pS1 + z * pS2));
const q = 1.0 + z * qS1; const q = 1.0 + z * qS1;
p / q return p / q;
} }
fn acos32(x: f32) -> f32 { fn acos32(x: f32) -> f32 {
@ -69,7 +69,7 @@ fn acos32(x: f32) -> f32 {
const df = @bitCast(f32, jx & 0xFFFFF000); const df = @bitCast(f32, jx & 0xFFFFF000);
const c = (z - df * df) / (s + df); const c = (z - df * df) / (s + df);
const w = r32(z) * s + c; const w = r32(z) * s + c;
2 * (df + w) return 2 * (df + w);
} }
fn r64(z: f64) -> f64 { fn r64(z: f64) -> f64 {
@ -86,7 +86,7 @@ fn r64(z: f64) -> f64 {
const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
p / q return p / q;
} }
fn acos64(x: f64) -> f64 { fn acos64(x: f64) -> f64 {
@ -138,7 +138,7 @@ fn acos64(x: f64) -> f64 {
const df = @bitCast(f64, jx & 0xFFFFFFFF00000000); const df = @bitCast(f64, jx & 0xFFFFFFFF00000000);
const c = (z - df * df) / (s + df); const c = (z - df * df) / (s + df);
const w = r64(z) * s + c; const w = r64(z) * s + c;
2 * (df + w) return 2 * (df + w);
} }
test "math.acos" { test "math.acos" {

View File

@ -9,11 +9,11 @@ const assert = @import("../debug.zig").assert;
pub fn acosh(x: var) -> @typeOf(x) { pub fn acosh(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(acosh32, x), f32 => @inlineCall(acosh32, x),
f64 => @inlineCall(acosh64, x), f64 => @inlineCall(acosh64, x),
else => @compileError("acosh not implemented for " ++ @typeName(T)), else => @compileError("acosh not implemented for " ++ @typeName(T)),
} };
} }
// acosh(x) = log(x + sqrt(x * x - 1)) // acosh(x) = log(x + sqrt(x * x - 1))
@ -23,15 +23,15 @@ fn acosh32(x: f32) -> f32 {
// |x| < 2, invalid if x < 1 or nan // |x| < 2, invalid if x < 1 or nan
if (i < 0x3F800000 + (1 << 23)) { if (i < 0x3F800000 + (1 << 23)) {
math.log1p(x - 1 + math.sqrt((x - 1) * (x - 1) + 2 * (x - 1))) return math.log1p(x - 1 + math.sqrt((x - 1) * (x - 1) + 2 * (x - 1)));
} }
// |x| < 0x1p12 // |x| < 0x1p12
else if (i < 0x3F800000 + (12 << 23)) { else if (i < 0x3F800000 + (12 << 23)) {
math.ln(2 * x - 1 / (x + math.sqrt(x * x - 1))) return math.ln(2 * x - 1 / (x + math.sqrt(x * x - 1)));
} }
// |x| >= 0x1p12 // |x| >= 0x1p12
else { else {
math.ln(x) + 0.693147180559945309417232121458176568 return math.ln(x) + 0.693147180559945309417232121458176568;
} }
} }
@ -41,15 +41,15 @@ fn acosh64(x: f64) -> f64 {
// |x| < 2, invalid if x < 1 or nan // |x| < 2, invalid if x < 1 or nan
if (e < 0x3FF + 1) { if (e < 0x3FF + 1) {
math.log1p(x - 1 + math.sqrt((x - 1) * (x - 1) + 2 * (x - 1))) return math.log1p(x - 1 + math.sqrt((x - 1) * (x - 1) + 2 * (x - 1)));
} }
// |x| < 0x1p26 // |x| < 0x1p26
else if (e < 0x3FF + 26) { else if (e < 0x3FF + 26) {
math.ln(2 * x - 1 / (x + math.sqrt(x * x - 1))) return math.ln(2 * x - 1 / (x + math.sqrt(x * x - 1)));
} }
// |x| >= 0x1p26 or nan // |x| >= 0x1p26 or nan
else { else {
math.ln(x) + 0.693147180559945309417232121458176568 return math.ln(x) + 0.693147180559945309417232121458176568;
} }
} }

View File

@ -8,11 +8,11 @@ const assert = @import("../debug.zig").assert;
pub fn asin(x: var) -> @typeOf(x) { pub fn asin(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(asin32, x), f32 => @inlineCall(asin32, x),
f64 => @inlineCall(asin64, x), f64 => @inlineCall(asin64, x),
else => @compileError("asin not implemented for " ++ @typeName(T)), else => @compileError("asin not implemented for " ++ @typeName(T)),
} };
} }
fn r32(z: f32) -> f32 { fn r32(z: f32) -> f32 {
@ -23,7 +23,7 @@ fn r32(z: f32) -> f32 {
const p = z * (pS0 + z * (pS1 + z * pS2)); const p = z * (pS0 + z * (pS1 + z * pS2));
const q = 1.0 + z * qS1; const q = 1.0 + z * qS1;
p / q return p / q;
} }
fn asin32(x: f32) -> f32 { fn asin32(x: f32) -> f32 {
@ -58,9 +58,9 @@ fn asin32(x: f32) -> f32 {
const fx = pio2 - 2 * (s + s * r32(z)); const fx = pio2 - 2 * (s + s * r32(z));
if (hx >> 31 != 0) { if (hx >> 31 != 0) {
-fx return -fx;
} else { } else {
fx return fx;
} }
} }
@ -78,7 +78,7 @@ fn r64(z: f64) -> f64 {
const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4))); const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
p / q return p / q;
} }
fn asin64(x: f64) -> f64 { fn asin64(x: f64) -> f64 {
@ -119,7 +119,7 @@ fn asin64(x: f64) -> f64 {
// |x| > 0.975 // |x| > 0.975
if (ix >= 0x3FEF3333) { if (ix >= 0x3FEF3333) {
fx = pio2_hi - 2 * (s + s * r) fx = pio2_hi - 2 * (s + s * r);
} else { } else {
const jx = @bitCast(u64, s); const jx = @bitCast(u64, s);
const df = @bitCast(f64, jx & 0xFFFFFFFF00000000); const df = @bitCast(f64, jx & 0xFFFFFFFF00000000);
@ -128,9 +128,9 @@ fn asin64(x: f64) -> f64 {
} }
if (hx >> 31 != 0) { if (hx >> 31 != 0) {
-fx return -fx;
} else { } else {
fx return fx;
} }
} }

View File

@ -9,11 +9,11 @@ const assert = @import("../debug.zig").assert;
pub fn asinh(x: var) -> @typeOf(x) { pub fn asinh(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(asinh32, x), f32 => @inlineCall(asinh32, x),
f64 => @inlineCall(asinh64, x), f64 => @inlineCall(asinh64, x),
else => @compileError("asinh not implemented for " ++ @typeName(T)), else => @compileError("asinh not implemented for " ++ @typeName(T)),
} };
} }
// asinh(x) = sign(x) * log(|x| + sqrt(x * x + 1)) ~= x - x^3/6 + o(x^5) // asinh(x) = sign(x) * log(|x| + sqrt(x * x + 1)) ~= x - x^3/6 + o(x^5)
@ -46,7 +46,7 @@ fn asinh32(x: f32) -> f32 {
math.forceEval(x + 0x1.0p120); math.forceEval(x + 0x1.0p120);
} }
if (s != 0) -rx else rx return if (s != 0) -rx else rx;
} }
fn asinh64(x: f64) -> f64 { fn asinh64(x: f64) -> f64 {
@ -77,7 +77,7 @@ fn asinh64(x: f64) -> f64 {
math.forceEval(x + 0x1.0p120); math.forceEval(x + 0x1.0p120);
} }
if (s != 0) -rx else rx return if (s != 0) -rx else rx;
} }
test "math.asinh" { test "math.asinh" {

View File

@ -8,11 +8,11 @@ const assert = @import("../debug.zig").assert;
pub fn atan(x: var) -> @typeOf(x) { pub fn atan(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(atan32, x), f32 => @inlineCall(atan32, x),
f64 => @inlineCall(atan64, x), f64 => @inlineCall(atan64, x),
else => @compileError("atan not implemented for " ++ @typeName(T)), else => @compileError("atan not implemented for " ++ @typeName(T)),
} };
} }
fn atan32(x_: f32) -> f32 { fn atan32(x_: f32) -> f32 {
@ -100,10 +100,10 @@ fn atan32(x_: f32) -> f32 {
const s2 = w * (aT[1] + w * aT[3]); const s2 = w * (aT[1] + w * aT[3]);
if (id == null) { if (id == null) {
x - x * (s1 + s2) return x - x * (s1 + s2);
} else { } else {
const zz = atanhi[??id] - ((x * (s1 + s2) - atanlo[??id]) - x); const zz = atanhi[??id] - ((x * (s1 + s2) - atanlo[??id]) - x);
if (sign != 0) -zz else zz return if (sign != 0) -zz else zz;
} }
} }
@ -199,10 +199,10 @@ fn atan64(x_: f64) -> f64 {
const s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9])))); const s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9]))));
if (id == null) { if (id == null) {
x - x * (s1 + s2) return x - x * (s1 + s2);
} else { } else {
const zz = atanhi[??id] - ((x * (s1 + s2) - atanlo[??id]) - x); const zz = atanhi[??id] - ((x * (s1 + s2) - atanlo[??id]) - x);
if (sign != 0) -zz else zz return if (sign != 0) -zz else zz;
} }
} }

View File

@ -22,11 +22,11 @@ const math = @import("index.zig");
const assert = @import("../debug.zig").assert; const assert = @import("../debug.zig").assert;
fn atan2(comptime T: type, x: T, y: T) -> T { fn atan2(comptime T: type, x: T, y: T) -> T {
switch (T) { return switch (T) {
f32 => @inlineCall(atan2_32, x, y), f32 => @inlineCall(atan2_32, x, y),
f64 => @inlineCall(atan2_64, x, y), f64 => @inlineCall(atan2_64, x, y),
else => @compileError("atan2 not implemented for " ++ @typeName(T)), else => @compileError("atan2 not implemented for " ++ @typeName(T)),
} };
} }
fn atan2_32(y: f32, x: f32) -> f32 { fn atan2_32(y: f32, x: f32) -> f32 {
@ -97,11 +97,11 @@ fn atan2_32(y: f32, x: f32) -> f32 {
} }
// z = atan(|y / x|) with correct underflow // z = atan(|y / x|) with correct underflow
var z = { var z = z: {
if ((m & 2) != 0 and iy + (26 << 23) < ix) { if ((m & 2) != 0 and iy + (26 << 23) < ix) {
0.0 break :z 0.0;
} else { } else {
math.atan(math.fabs(y / x)) break :z math.atan(math.fabs(y / x));
} }
}; };
@ -187,11 +187,11 @@ fn atan2_64(y: f64, x: f64) -> f64 {
} }
// z = atan(|y / x|) with correct underflow // z = atan(|y / x|) with correct underflow
var z = { var z = z: {
if ((m & 2) != 0 and iy +% (64 << 20) < ix) { if ((m & 2) != 0 and iy +% (64 << 20) < ix) {
0.0 break :z 0.0;
} else { } else {
math.atan(math.fabs(y / x)) break :z math.atan(math.fabs(y / x));
} }
}; };

View File

@ -9,11 +9,11 @@ const assert = @import("../debug.zig").assert;
pub fn atanh(x: var) -> @typeOf(x) { pub fn atanh(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(atanh_32, x), f32 => @inlineCall(atanh_32, x),
f64 => @inlineCall(atanh_64, x), f64 => @inlineCall(atanh_64, x),
else => @compileError("atanh not implemented for " ++ @typeName(T)), else => @compileError("atanh not implemented for " ++ @typeName(T)),
} };
} }
// atanh(x) = log((1 + x) / (1 - x)) / 2 = log1p(2x / (1 - x)) / 2 ~= x + x^3 / 3 + o(x^5) // atanh(x) = log((1 + x) / (1 - x)) / 2 = log1p(2x / (1 - x)) / 2 ~= x + x^3 / 3 + o(x^5)
@ -32,7 +32,7 @@ fn atanh_32(x: f32) -> f32 {
if (u < 0x3F800000 - (32 << 23)) { if (u < 0x3F800000 - (32 << 23)) {
// underflow // underflow
if (u < (1 << 23)) { if (u < (1 << 23)) {
math.forceEval(y * y) math.forceEval(y * y);
} }
} }
// |x| < 0.5 // |x| < 0.5
@ -43,7 +43,7 @@ fn atanh_32(x: f32) -> f32 {
y = 0.5 * math.log1p(2 * (y / (1 - y))); y = 0.5 * math.log1p(2 * (y / (1 - y)));
} }
if (s != 0) -y else y return if (s != 0) -y else y;
} }
fn atanh_64(x: f64) -> f64 { fn atanh_64(x: f64) -> f64 {
@ -72,7 +72,7 @@ fn atanh_64(x: f64) -> f64 {
y = 0.5 * math.log1p(2 * (y / (1 - y))); y = 0.5 * math.log1p(2 * (y / (1 - y)));
} }
if (s != 0) -y else y return if (s != 0) -y else y;
} }
test "math.atanh" { test "math.atanh" {

View File

@ -9,11 +9,11 @@ const assert = @import("../debug.zig").assert;
pub fn cbrt(x: var) -> @typeOf(x) { pub fn cbrt(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(cbrt32, x), f32 => @inlineCall(cbrt32, x),
f64 => @inlineCall(cbrt64, x), f64 => @inlineCall(cbrt64, x),
else => @compileError("cbrt not implemented for " ++ @typeName(T)), else => @compileError("cbrt not implemented for " ++ @typeName(T)),
} };
} }
fn cbrt32(x: f32) -> f32 { fn cbrt32(x: f32) -> f32 {
@ -53,7 +53,7 @@ fn cbrt32(x: f32) -> f32 {
r = t * t * t; r = t * t * t;
t = t * (f64(x) + x + r) / (x + r + r); t = t * (f64(x) + x + r) / (x + r + r);
f32(t) return f32(t);
} }
fn cbrt64(x: f64) -> f64 { fn cbrt64(x: f64) -> f64 {
@ -109,7 +109,7 @@ fn cbrt64(x: f64) -> f64 {
var w = t + t; var w = t + t;
q = (q - t) / (w + q); q = (q - t) / (w + q);
t + t * q return t + t * q;
} }
test "math.cbrt" { test "math.cbrt" {

View File

@ -10,11 +10,11 @@ const assert = @import("../debug.zig").assert;
pub fn ceil(x: var) -> @typeOf(x) { pub fn ceil(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(ceil32, x), f32 => @inlineCall(ceil32, x),
f64 => @inlineCall(ceil64, x), f64 => @inlineCall(ceil64, x),
else => @compileError("ceil not implemented for " ++ @typeName(T)), else => @compileError("ceil not implemented for " ++ @typeName(T)),
} };
} }
fn ceil32(x: f32) -> f32 { fn ceil32(x: f32) -> f32 {
@ -39,13 +39,13 @@ fn ceil32(x: f32) -> f32 {
u += m; u += m;
} }
u &= ~m; u &= ~m;
@bitCast(f32, u) return @bitCast(f32, u);
} else { } else {
math.forceEval(x + 0x1.0p120); math.forceEval(x + 0x1.0p120);
if (u >> 31 != 0) { if (u >> 31 != 0) {
return -0.0; return -0.0;
} else { } else {
1.0 return 1.0;
} }
} }
} }
@ -70,14 +70,14 @@ fn ceil64(x: f64) -> f64 {
if (e <= 0x3FF-1) { if (e <= 0x3FF-1) {
math.forceEval(y); math.forceEval(y);
if (u >> 63 != 0) { if (u >> 63 != 0) {
return -0.0; // Compiler requires return. return -0.0;
} else { } else {
1.0 return 1.0;
} }
} else if (y < 0) { } else if (y < 0) {
x + y + 1 return x + y + 1;
} else { } else {
x + y return x + y;
} }
} }

View File

@ -2,11 +2,11 @@ const math = @import("index.zig");
const assert = @import("../debug.zig").assert; const assert = @import("../debug.zig").assert;
pub fn copysign(comptime T: type, x: T, y: T) -> T { pub fn copysign(comptime T: type, x: T, y: T) -> T {
switch (T) { return switch (T) {
f32 => @inlineCall(copysign32, x, y), f32 => @inlineCall(copysign32, x, y),
f64 => @inlineCall(copysign64, x, y), f64 => @inlineCall(copysign64, x, y),
else => @compileError("copysign not implemented for " ++ @typeName(T)), else => @compileError("copysign not implemented for " ++ @typeName(T)),
} };
} }
fn copysign32(x: f32, y: f32) -> f32 { fn copysign32(x: f32, y: f32) -> f32 {
@ -15,7 +15,7 @@ fn copysign32(x: f32, y: f32) -> f32 {
const h1 = ux & (@maxValue(u32) / 2); const h1 = ux & (@maxValue(u32) / 2);
const h2 = uy & (u32(1) << 31); const h2 = uy & (u32(1) << 31);
@bitCast(f32, h1 | h2) return @bitCast(f32, h1 | h2);
} }
fn copysign64(x: f64, y: f64) -> f64 { fn copysign64(x: f64, y: f64) -> f64 {
@ -24,7 +24,7 @@ fn copysign64(x: f64, y: f64) -> f64 {
const h1 = ux & (@maxValue(u64) / 2); const h1 = ux & (@maxValue(u64) / 2);
const h2 = uy & (u64(1) << 63); const h2 = uy & (u64(1) << 63);
@bitCast(f64, h1 | h2) return @bitCast(f64, h1 | h2);
} }
test "math.copysign" { test "math.copysign" {

View File

@ -9,11 +9,11 @@ const assert = @import("../debug.zig").assert;
pub fn cos(x: var) -> @typeOf(x) { pub fn cos(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(cos32, x), f32 => @inlineCall(cos32, x),
f64 => @inlineCall(cos64, x), f64 => @inlineCall(cos64, x),
else => @compileError("cos not implemented for " ++ @typeName(T)), else => @compileError("cos not implemented for " ++ @typeName(T)),
} };
} }
// sin polynomial coefficients // sin polynomial coefficients
@ -73,18 +73,18 @@ fn cos32(x_: f32) -> f32 {
const z = ((x - y * pi4a) - y * pi4b) - y * pi4c; const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
const w = z * z; const w = z * z;
const r = { const r = r: {
if (j == 1 or j == 2) { if (j == 1 or j == 2) {
z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0))))) break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
} else { } else {
1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0))))) break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
} }
}; };
if (sign) { if (sign) {
-r return -r;
} else { } else {
r return r;
} }
} }
@ -124,18 +124,18 @@ fn cos64(x_: f64) -> f64 {
const z = ((x - y * pi4a) - y * pi4b) - y * pi4c; const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
const w = z * z; const w = z * z;
const r = { const r = r: {
if (j == 1 or j == 2) { if (j == 1 or j == 2) {
z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0))))) break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
} else { } else {
1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0))))) break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
} }
}; };
if (sign) { if (sign) {
-r return -r;
} else { } else {
r return r;
} }
} }

View File

@ -11,11 +11,11 @@ const assert = @import("../debug.zig").assert;
pub fn cosh(x: var) -> @typeOf(x) { pub fn cosh(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(cosh32, x), f32 => @inlineCall(cosh32, x),
f64 => @inlineCall(cosh64, x), f64 => @inlineCall(cosh64, x),
else => @compileError("cosh not implemented for " ++ @typeName(T)), else => @compileError("cosh not implemented for " ++ @typeName(T)),
} };
} }
// cosh(x) = (exp(x) + 1 / exp(x)) / 2 // cosh(x) = (exp(x) + 1 / exp(x)) / 2
@ -43,7 +43,7 @@ fn cosh32(x: f32) -> f32 {
} }
// |x| > log(FLT_MAX) or nan // |x| > log(FLT_MAX) or nan
expo2(ax) return expo2(ax);
} }
fn cosh64(x: f64) -> f64 { fn cosh64(x: f64) -> f64 {
@ -76,7 +76,7 @@ fn cosh64(x: f64) -> f64 {
} }
// |x| > log(CBL_MAX) or nan // |x| > log(CBL_MAX) or nan
expo2(ax) return expo2(ax);
} }
test "math.cosh" { test "math.cosh" {

View File

@ -8,11 +8,11 @@ const assert = @import("../debug.zig").assert;
pub fn exp(x: var) -> @typeOf(x) { pub fn exp(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(exp32, x), f32 => @inlineCall(exp32, x),
f64 => @inlineCall(exp64, x), f64 => @inlineCall(exp64, x),
else => @compileError("exp not implemented for " ++ @typeName(T)), else => @compileError("exp not implemented for " ++ @typeName(T)),
} };
} }
fn exp32(x_: f32) -> f32 { fn exp32(x_: f32) -> f32 {
@ -86,9 +86,9 @@ fn exp32(x_: f32) -> f32 {
const y = 1 + (x * c / (2 - c) - lo + hi); const y = 1 + (x * c / (2 - c) - lo + hi);
if (k == 0) { if (k == 0) {
y return y;
} else { } else {
math.scalbn(y, k) return math.scalbn(y, k);
} }
} }
@ -172,9 +172,9 @@ fn exp64(x_: f64) -> f64 {
const y = 1 + (x * c / (2 - c) - lo + hi); const y = 1 + (x * c / (2 - c) - lo + hi);
if (k == 0) { if (k == 0) {
y return y;
} else { } else {
math.scalbn(y, k) return math.scalbn(y, k);
} }
} }

View File

@ -8,11 +8,11 @@ const assert = @import("../debug.zig").assert;
pub fn exp2(x: var) -> @typeOf(x) { pub fn exp2(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(exp2_32, x), f32 => @inlineCall(exp2_32, x),
f64 => @inlineCall(exp2_64, x), f64 => @inlineCall(exp2_64, x),
else => @compileError("exp2 not implemented for " ++ @typeName(T)), else => @compileError("exp2 not implemented for " ++ @typeName(T)),
} };
} }
const exp2ft = []const f64 { const exp2ft = []const f64 {
@ -88,7 +88,7 @@ fn exp2_32(x: f32) -> f32 {
var r: f64 = exp2ft[i0]; var r: f64 = exp2ft[i0];
const t: f64 = r * z; const t: f64 = r * z;
r = r + t * (P1 + z * P2) + t * (z * z) * (P3 + z * P4); r = r + t * (P1 + z * P2) + t * (z * z) * (P3 + z * P4);
f32(r * uk) return f32(r * uk);
} }
const exp2dt = []f64 { const exp2dt = []f64 {
@ -414,7 +414,7 @@ fn exp2_64(x: f64) -> f64 {
z -= exp2dt[2 * i0 + 1]; z -= exp2dt[2 * i0 + 1];
const r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5)))); const r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));
math.scalbn(r, ik) return math.scalbn(r, ik);
} }
test "math.exp2" { test "math.exp2" {

View File

@ -9,11 +9,11 @@ const assert = @import("../debug.zig").assert;
pub fn expm1(x: var) -> @typeOf(x) { pub fn expm1(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(expm1_32, x), f32 => @inlineCall(expm1_32, x),
f64 => @inlineCall(expm1_64, x), f64 => @inlineCall(expm1_64, x),
else => @compileError("exp1m not implemented for " ++ @typeName(T)), else => @compileError("exp1m not implemented for " ++ @typeName(T)),
} };
} }
fn expm1_32(x_: f32) -> f32 { fn expm1_32(x_: f32) -> f32 {

View File

@ -2,11 +2,11 @@ const math = @import("index.zig");
pub fn expo2(x: var) -> @typeOf(x) { pub fn expo2(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => expo2f(x), f32 => expo2f(x),
f64 => expo2d(x), f64 => expo2d(x),
else => @compileError("expo2 not implemented for " ++ @typeName(T)), else => @compileError("expo2 not implemented for " ++ @typeName(T)),
} };
} }
fn expo2f(x: f32) -> f32 { fn expo2f(x: f32) -> f32 {
@ -15,7 +15,7 @@ fn expo2f(x: f32) -> f32 {
const u = (0x7F + k / 2) << 23; const u = (0x7F + k / 2) << 23;
const scale = @bitCast(f32, u); const scale = @bitCast(f32, u);
math.exp(x - kln2) * scale * scale return math.exp(x - kln2) * scale * scale;
} }
fn expo2d(x: f64) -> f64 { fn expo2d(x: f64) -> f64 {
@ -24,5 +24,5 @@ fn expo2d(x: f64) -> f64 {
const u = (0x3FF + k / 2) << 20; const u = (0x3FF + k / 2) << 20;
const scale = @bitCast(f64, u64(u) << 32); const scale = @bitCast(f64, u64(u) << 32);
math.exp(x - kln2) * scale * scale return math.exp(x - kln2) * scale * scale;
} }

View File

@ -8,23 +8,23 @@ const assert = @import("../debug.zig").assert;
pub fn fabs(x: var) -> @typeOf(x) { pub fn fabs(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(fabs32, x), f32 => @inlineCall(fabs32, x),
f64 => @inlineCall(fabs64, x), f64 => @inlineCall(fabs64, x),
else => @compileError("fabs not implemented for " ++ @typeName(T)), else => @compileError("fabs not implemented for " ++ @typeName(T)),
} };
} }
fn fabs32(x: f32) -> f32 { fn fabs32(x: f32) -> f32 {
var u = @bitCast(u32, x); var u = @bitCast(u32, x);
u &= 0x7FFFFFFF; u &= 0x7FFFFFFF;
@bitCast(f32, u) return @bitCast(f32, u);
} }
fn fabs64(x: f64) -> f64 { fn fabs64(x: f64) -> f64 {
var u = @bitCast(u64, x); var u = @bitCast(u64, x);
u &= @maxValue(u64) >> 1; u &= @maxValue(u64) >> 1;
@bitCast(f64, u) return @bitCast(f64, u);
} }
test "math.fabs" { test "math.fabs" {

View File

@ -10,11 +10,11 @@ const math = @import("index.zig");
pub fn floor(x: var) -> @typeOf(x) { pub fn floor(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(floor32, x), f32 => @inlineCall(floor32, x),
f64 => @inlineCall(floor64, x), f64 => @inlineCall(floor64, x),
else => @compileError("floor not implemented for " ++ @typeName(T)), else => @compileError("floor not implemented for " ++ @typeName(T)),
} };
} }
fn floor32(x: f32) -> f32 { fn floor32(x: f32) -> f32 {
@ -40,13 +40,13 @@ fn floor32(x: f32) -> f32 {
if (u >> 31 != 0) { if (u >> 31 != 0) {
u += m; u += m;
} }
@bitCast(f32, u & ~m) return @bitCast(f32, u & ~m);
} else { } else {
math.forceEval(x + 0x1.0p120); math.forceEval(x + 0x1.0p120);
if (u >> 31 == 0) { if (u >> 31 == 0) {
return 0.0; // Compiler requires return return 0.0;
} else { } else {
-1.0 return -1.0;
} }
} }
} }
@ -71,14 +71,14 @@ fn floor64(x: f64) -> f64 {
if (e <= 0x3FF-1) { if (e <= 0x3FF-1) {
math.forceEval(y); math.forceEval(y);
if (u >> 63 != 0) { if (u >> 63 != 0) {
return -1.0; // Compiler requires return. return -1.0;
} else { } else {
0.0 return 0.0;
} }
} else if (y > 0) { } else if (y > 0) {
x + y - 1 return x + y - 1;
} else { } else {
x + y return x + y;
} }
} }

View File

@ -2,11 +2,11 @@ const math = @import("index.zig");
const assert = @import("../debug.zig").assert; const assert = @import("../debug.zig").assert;
pub fn fma(comptime T: type, x: T, y: T, z: T) -> T { pub fn fma(comptime T: type, x: T, y: T, z: T) -> T {
switch (T) { return switch (T) {
f32 => @inlineCall(fma32, x, y, z), f32 => @inlineCall(fma32, x, y, z),
f64 => @inlineCall(fma64, x, y ,z), f64 => @inlineCall(fma64, x, y ,z),
else => @compileError("fma not implemented for " ++ @typeName(T)), else => @compileError("fma not implemented for " ++ @typeName(T)),
} };
} }
fn fma32(x: f32, y: f32, z: f32) -> f32 { fn fma32(x: f32, y: f32, z: f32) -> f32 {
@ -16,10 +16,10 @@ fn fma32(x: f32, y: f32, z: f32) -> f32 {
const e = (u >> 52) & 0x7FF; const e = (u >> 52) & 0x7FF;
if ((u & 0x1FFFFFFF) != 0x10000000 or e == 0x7FF or xy_z - xy == z) { if ((u & 0x1FFFFFFF) != 0x10000000 or e == 0x7FF or xy_z - xy == z) {
f32(xy_z) return f32(xy_z);
} else { } else {
// TODO: Handle inexact case with double-rounding // TODO: Handle inexact case with double-rounding
f32(xy_z) return f32(xy_z);
} }
} }
@ -64,9 +64,9 @@ fn fma64(x: f64, y: f64, z: f64) -> f64 {
const adj = add_adjusted(r.lo, xy.lo); const adj = add_adjusted(r.lo, xy.lo);
if (spread + math.ilogb(r.hi) > -1023) { if (spread + math.ilogb(r.hi) > -1023) {
math.scalbn(r.hi + adj, spread) return math.scalbn(r.hi + adj, spread);
} else { } else {
add_and_denorm(r.hi, adj, spread) return add_and_denorm(r.hi, adj, spread);
} }
} }
@ -77,7 +77,7 @@ fn dd_add(a: f64, b: f64) -> dd {
ret.hi = a + b; ret.hi = a + b;
const s = ret.hi - a; const s = ret.hi - a;
ret.lo = (a - (ret.hi - s)) + (b - s); ret.lo = (a - (ret.hi - s)) + (b - s);
ret return ret;
} }
fn dd_mul(a: f64, b: f64) -> dd { fn dd_mul(a: f64, b: f64) -> dd {
@ -99,7 +99,7 @@ fn dd_mul(a: f64, b: f64) -> dd {
ret.hi = p + q; ret.hi = p + q;
ret.lo = p - ret.hi + q + la * lb; ret.lo = p - ret.hi + q + la * lb;
ret return ret;
} }
fn add_adjusted(a: f64, b: f64) -> f64 { fn add_adjusted(a: f64, b: f64) -> f64 {
@ -113,7 +113,7 @@ fn add_adjusted(a: f64, b: f64) -> f64 {
sum.hi = @bitCast(f64, uhii); sum.hi = @bitCast(f64, uhii);
} }
} }
sum.hi return sum.hi;
} }
fn add_and_denorm(a: f64, b: f64, scale: i32) -> f64 { fn add_and_denorm(a: f64, b: f64, scale: i32) -> f64 {
@ -127,7 +127,7 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) -> f64 {
sum.hi = @bitCast(f64, uhii); sum.hi = @bitCast(f64, uhii);
} }
} }
math.scalbn(sum.hi, scale) return math.scalbn(sum.hi, scale);
} }
test "math.fma" { test "math.fma" {

View File

@ -8,21 +8,21 @@ const math = @import("index.zig");
const assert = @import("../debug.zig").assert; const assert = @import("../debug.zig").assert;
fn frexp_result(comptime T: type) -> type { fn frexp_result(comptime T: type) -> type {
struct { return struct {
significand: T, significand: T,
exponent: i32, exponent: i32,
} };
} }
pub const frexp32_result = frexp_result(f32); pub const frexp32_result = frexp_result(f32);
pub const frexp64_result = frexp_result(f64); pub const frexp64_result = frexp_result(f64);
pub fn frexp(x: var) -> frexp_result(@typeOf(x)) { pub fn frexp(x: var) -> frexp_result(@typeOf(x)) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(frexp32, x), f32 => @inlineCall(frexp32, x),
f64 => @inlineCall(frexp64, x), f64 => @inlineCall(frexp64, x),
else => @compileError("frexp not implemented for " ++ @typeName(T)), else => @compileError("frexp not implemented for " ++ @typeName(T)),
} };
} }
fn frexp32(x: f32) -> frexp32_result { fn frexp32(x: f32) -> frexp32_result {
@ -59,7 +59,7 @@ fn frexp32(x: f32) -> frexp32_result {
y &= 0x807FFFFF; y &= 0x807FFFFF;
y |= 0x3F000000; y |= 0x3F000000;
result.significand = @bitCast(f32, y); result.significand = @bitCast(f32, y);
result return result;
} }
fn frexp64(x: f64) -> frexp64_result { fn frexp64(x: f64) -> frexp64_result {
@ -96,7 +96,7 @@ fn frexp64(x: f64) -> frexp64_result {
y &= 0x800FFFFFFFFFFFFF; y &= 0x800FFFFFFFFFFFFF;
y |= 0x3FE0000000000000; y |= 0x3FE0000000000000;
result.significand = @bitCast(f64, y); result.significand = @bitCast(f64, y);
result return result;
} }
test "math.frexp" { test "math.frexp" {

View File

@ -9,11 +9,11 @@ const math = @import("index.zig");
const assert = @import("../debug.zig").assert; const assert = @import("../debug.zig").assert;
pub fn hypot(comptime T: type, x: T, y: T) -> T { pub fn hypot(comptime T: type, x: T, y: T) -> T {
switch (T) { return switch (T) {
f32 => @inlineCall(hypot32, x, y), f32 => @inlineCall(hypot32, x, y),
f64 => @inlineCall(hypot64, x, y), f64 => @inlineCall(hypot64, x, y),
else => @compileError("hypot not implemented for " ++ @typeName(T)), else => @compileError("hypot not implemented for " ++ @typeName(T)),
} };
} }
fn hypot32(x: f32, y: f32) -> f32 { fn hypot32(x: f32, y: f32) -> f32 {
@ -48,7 +48,7 @@ fn hypot32(x: f32, y: f32) -> f32 {
yy *= 0x1.0p-90; yy *= 0x1.0p-90;
} }
z * math.sqrt(f32(f64(x) * x + f64(y) * y)) return z * math.sqrt(f32(f64(x) * x + f64(y) * y));
} }
fn sq(hi: &f64, lo: &f64, x: f64) { fn sq(hi: &f64, lo: &f64, x: f64) {
@ -109,7 +109,7 @@ fn hypot64(x: f64, y: f64) -> f64 {
sq(&hx, &lx, x); sq(&hx, &lx, x);
sq(&hy, &ly, y); sq(&hy, &ly, y);
z * math.sqrt(ly + lx + hy + hx) return z * math.sqrt(ly + lx + hy + hx);
} }
test "math.hypot" { test "math.hypot" {

View File

@ -9,11 +9,11 @@ const assert = @import("../debug.zig").assert;
pub fn ilogb(x: var) -> i32 { pub fn ilogb(x: var) -> i32 {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(ilogb32, x), f32 => @inlineCall(ilogb32, x),
f64 => @inlineCall(ilogb64, x), f64 => @inlineCall(ilogb64, x),
else => @compileError("ilogb not implemented for " ++ @typeName(T)), else => @compileError("ilogb not implemented for " ++ @typeName(T)),
} };
} }
// NOTE: Should these be exposed publically? // NOTE: Should these be exposed publically?
@ -53,7 +53,7 @@ fn ilogb32(x: f32) -> i32 {
} }
} }
e - 0x7F return e - 0x7F;
} }
fn ilogb64(x: f64) -> i32 { fn ilogb64(x: f64) -> i32 {
@ -88,7 +88,7 @@ fn ilogb64(x: f64) -> i32 {
} }
} }
e - 0x3FF return e - 0x3FF;
} }
test "math.ilogb" { test "math.ilogb" {

View File

@ -36,7 +36,7 @@ pub const inf = @import("inf.zig").inf;
pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) -> bool { pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) -> bool {
assert(@typeId(T) == TypeId.Float); assert(@typeId(T) == TypeId.Float);
fabs(x - y) < epsilon return fabs(x - y) < epsilon;
} }
// TODO: Hide the following in an internal module. // TODO: Hide the following in an internal module.
@ -175,7 +175,7 @@ test "math" {
pub fn min(x: var, y: var) -> @typeOf(x + y) { pub fn min(x: var, y: var) -> @typeOf(x + y) {
if (x < y) x else y return if (x < y) x else y;
} }
test "math.min" { test "math.min" {
@ -183,7 +183,7 @@ test "math.min" {
} }
pub fn max(x: var, y: var) -> @typeOf(x + y) { pub fn max(x: var, y: var) -> @typeOf(x + y) {
if (x > y) x else y return if (x > y) x else y;
} }
test "math.max" { test "math.max" {
@ -193,19 +193,19 @@ test "math.max" {
error Overflow; error Overflow;
pub fn mul(comptime T: type, a: T, b: T) -> %T { pub fn mul(comptime T: type, a: T, b: T) -> %T {
var answer: T = undefined; var answer: T = undefined;
if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer return if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer;
} }
error Overflow; error Overflow;
pub fn add(comptime T: type, a: T, b: T) -> %T { pub fn add(comptime T: type, a: T, b: T) -> %T {
var answer: T = undefined; var answer: T = undefined;
if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer;
} }
error Overflow; error Overflow;
pub fn sub(comptime T: type, a: T, b: T) -> %T { pub fn sub(comptime T: type, a: T, b: T) -> %T {
var answer: T = undefined; var answer: T = undefined;
if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer return if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer;
} }
pub fn negate(x: var) -> %@typeOf(x) { pub fn negate(x: var) -> %@typeOf(x) {
@ -215,7 +215,7 @@ pub fn negate(x: var) -> %@typeOf(x) {
error Overflow; error Overflow;
pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) -> %T { pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) -> %T {
var answer: T = undefined; var answer: T = undefined;
if (@shlWithOverflow(T, a, shift_amt, &answer)) error.Overflow else answer return if (@shlWithOverflow(T, a, shift_amt, &answer)) error.Overflow else answer;
} }
/// Shifts left. Overflowed bits are truncated. /// Shifts left. Overflowed bits are truncated.
@ -267,7 +267,7 @@ test "math.shr" {
} }
pub fn Log2Int(comptime T: type) -> type { pub fn Log2Int(comptime T: type) -> type {
@IntType(false, log2(T.bit_count)) return @IntType(false, log2(T.bit_count));
} }
test "math overflow functions" { test "math overflow functions" {

View File

@ -2,9 +2,9 @@ const math = @import("index.zig");
const assert = @import("../debug.zig").assert; const assert = @import("../debug.zig").assert;
pub fn inf(comptime T: type) -> T { pub fn inf(comptime T: type) -> T {
switch (T) { return switch (T) {
f32 => @bitCast(f32, math.inf_u32), f32 => @bitCast(f32, math.inf_u32),
f64 => @bitCast(f64, math.inf_u64), f64 => @bitCast(f64, math.inf_u64),
else => @compileError("inf not implemented for " ++ @typeName(T)), else => @compileError("inf not implemented for " ++ @typeName(T)),
} };
} }

View File

@ -6,11 +6,11 @@ pub fn isFinite(x: var) -> bool {
switch (T) { switch (T) {
f32 => { f32 => {
const bits = @bitCast(u32, x); const bits = @bitCast(u32, x);
bits & 0x7FFFFFFF < 0x7F800000 return bits & 0x7FFFFFFF < 0x7F800000;
}, },
f64 => { f64 => {
const bits = @bitCast(u64, x); const bits = @bitCast(u64, x);
bits & (@maxValue(u64) >> 1) < (0x7FF << 52) return bits & (@maxValue(u64) >> 1) < (0x7FF << 52);
}, },
else => { else => {
@compileError("isFinite not implemented for " ++ @typeName(T)); @compileError("isFinite not implemented for " ++ @typeName(T));

View File

@ -6,11 +6,11 @@ pub fn isInf(x: var) -> bool {
switch (T) { switch (T) {
f32 => { f32 => {
const bits = @bitCast(u32, x); const bits = @bitCast(u32, x);
bits & 0x7FFFFFFF == 0x7F800000 return bits & 0x7FFFFFFF == 0x7F800000;
}, },
f64 => { f64 => {
const bits = @bitCast(u64, x); const bits = @bitCast(u64, x);
bits & (@maxValue(u64) >> 1) == (0x7FF << 52) return bits & (@maxValue(u64) >> 1) == (0x7FF << 52);
}, },
else => { else => {
@compileError("isInf not implemented for " ++ @typeName(T)); @compileError("isInf not implemented for " ++ @typeName(T));
@ -22,10 +22,10 @@ pub fn isPositiveInf(x: var) -> bool {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { switch (T) {
f32 => { f32 => {
@bitCast(u32, x) == 0x7F800000 return @bitCast(u32, x) == 0x7F800000;
}, },
f64 => { f64 => {
@bitCast(u64, x) == 0x7FF << 52 return @bitCast(u64, x) == 0x7FF << 52;
}, },
else => { else => {
@compileError("isPositiveInf not implemented for " ++ @typeName(T)); @compileError("isPositiveInf not implemented for " ++ @typeName(T));
@ -37,10 +37,10 @@ pub fn isNegativeInf(x: var) -> bool {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { switch (T) {
f32 => { f32 => {
@bitCast(u32, x) == 0xFF800000 return @bitCast(u32, x) == 0xFF800000;
}, },
f64 => { f64 => {
@bitCast(u64, x) == 0xFFF << 52 return @bitCast(u64, x) == 0xFFF << 52;
}, },
else => { else => {
@compileError("isNegativeInf not implemented for " ++ @typeName(T)); @compileError("isNegativeInf not implemented for " ++ @typeName(T));

View File

@ -6,11 +6,11 @@ pub fn isNan(x: var) -> bool {
switch (T) { switch (T) {
f32 => { f32 => {
const bits = @bitCast(u32, x); const bits = @bitCast(u32, x);
bits & 0x7FFFFFFF > 0x7F800000 return bits & 0x7FFFFFFF > 0x7F800000;
}, },
f64 => { f64 => {
const bits = @bitCast(u64, x); const bits = @bitCast(u64, x);
(bits & (@maxValue(u64) >> 1)) > (u64(0x7FF) << 52) return (bits & (@maxValue(u64) >> 1)) > (u64(0x7FF) << 52);
}, },
else => { else => {
@compileError("isNan not implemented for " ++ @typeName(T)); @compileError("isNan not implemented for " ++ @typeName(T));
@ -21,7 +21,7 @@ pub fn isNan(x: var) -> bool {
// Note: A signalling nan is identical to a standard right now by may have a different bit // Note: A signalling nan is identical to a standard right now by may have a different bit
// representation in the future when required. // representation in the future when required.
pub fn isSignalNan(x: var) -> bool { pub fn isSignalNan(x: var) -> bool {
isNan(x) return isNan(x);
} }
test "math.isNan" { test "math.isNan" {

View File

@ -6,11 +6,11 @@ pub fn isNormal(x: var) -> bool {
switch (T) { switch (T) {
f32 => { f32 => {
const bits = @bitCast(u32, x); const bits = @bitCast(u32, x);
(bits + 0x00800000) & 0x7FFFFFFF >= 0x01000000 return (bits + 0x00800000) & 0x7FFFFFFF >= 0x01000000;
}, },
f64 => { f64 => {
const bits = @bitCast(u64, x); const bits = @bitCast(u64, x);
(bits + (1 << 52)) & (@maxValue(u64) >> 1) >= (1 << 53) return (bits + (1 << 52)) & (@maxValue(u64) >> 1) >= (1 << 53);
}, },
else => { else => {
@compileError("isNormal not implemented for " ++ @typeName(T)); @compileError("isNormal not implemented for " ++ @typeName(T));

View File

@ -14,7 +14,7 @@ pub fn ln(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (@typeId(T)) { switch (@typeId(T)) {
TypeId.FloatLiteral => { TypeId.FloatLiteral => {
return @typeOf(1.0)(ln_64(x)) return @typeOf(1.0)(ln_64(x));
}, },
TypeId.Float => { TypeId.Float => {
return switch (T) { return switch (T) {
@ -84,7 +84,7 @@ pub fn ln_32(x_: f32) -> f32 {
const hfsq = 0.5 * f * f; const hfsq = 0.5 * f * f;
const dk = f32(k); const dk = f32(k);
s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
} }
pub fn ln_64(x_: f64) -> f64 { pub fn ln_64(x_: f64) -> f64 {
@ -116,7 +116,7 @@ pub fn ln_64(x_: f64) -> f64 {
// subnormal, scale x // subnormal, scale x
k -= 54; k -= 54;
x *= 0x1.0p54; x *= 0x1.0p54;
hx = u32(@bitCast(u64, ix) >> 32) hx = u32(@bitCast(u64, ix) >> 32);
} }
else if (hx >= 0x7FF00000) { else if (hx >= 0x7FF00000) {
return x; return x;
@ -142,7 +142,7 @@ pub fn ln_64(x_: f64) -> f64 {
const R = t2 + t1; const R = t2 + t1;
const dk = f64(k); const dk = f64(k);
s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
} }
test "math.ln" { test "math.ln" {

View File

@ -29,7 +29,7 @@ pub fn log(comptime T: type, base: T, x: T) -> T {
f32 => return f32(math.ln(f64(x)) / math.ln(f64(base))), f32 => return f32(math.ln(f64(x)) / math.ln(f64(base))),
f64 => return math.ln(x) / math.ln(f64(base)), f64 => return math.ln(x) / math.ln(f64(base)),
else => @compileError("log not implemented for " ++ @typeName(T)), else => @compileError("log not implemented for " ++ @typeName(T)),
}; }
}, },
else => { else => {

View File

@ -14,7 +14,7 @@ pub fn log10(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (@typeId(T)) { switch (@typeId(T)) {
TypeId.FloatLiteral => { TypeId.FloatLiteral => {
return @typeOf(1.0)(log10_64(x)) return @typeOf(1.0)(log10_64(x));
}, },
TypeId.Float => { TypeId.Float => {
return switch (T) { return switch (T) {
@ -90,7 +90,7 @@ pub fn log10_32(x_: f32) -> f32 {
const lo = f - hi - hfsq + s * (hfsq + R); const lo = f - hi - hfsq + s * (hfsq + R);
const dk = f32(k); const dk = f32(k);
dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;
} }
pub fn log10_64(x_: f64) -> f64 { pub fn log10_64(x_: f64) -> f64 {
@ -124,7 +124,7 @@ pub fn log10_64(x_: f64) -> f64 {
// subnormal, scale x // subnormal, scale x
k -= 54; k -= 54;
x *= 0x1.0p54; x *= 0x1.0p54;
hx = u32(@bitCast(u64, x) >> 32) hx = u32(@bitCast(u64, x) >> 32);
} }
else if (hx >= 0x7FF00000) { else if (hx >= 0x7FF00000) {
return x; return x;
@ -167,7 +167,7 @@ pub fn log10_64(x_: f64) -> f64 {
val_lo += (y - ww) + val_hi; val_lo += (y - ww) + val_hi;
val_hi = ww; val_hi = ww;
val_lo + val_hi return val_lo + val_hi;
} }
test "math.log10" { test "math.log10" {

View File

@ -11,11 +11,11 @@ const assert = @import("../debug.zig").assert;
pub fn log1p(x: var) -> @typeOf(x) { pub fn log1p(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(log1p_32, x), f32 => @inlineCall(log1p_32, x),
f64 => @inlineCall(log1p_64, x), f64 => @inlineCall(log1p_64, x),
else => @compileError("log1p not implemented for " ++ @typeName(T)), else => @compileError("log1p not implemented for " ++ @typeName(T)),
} };
} }
fn log1p_32(x: f32) -> f32 { fn log1p_32(x: f32) -> f32 {
@ -91,7 +91,7 @@ fn log1p_32(x: f32) -> f32 {
const hfsq = 0.5 * f * f; const hfsq = 0.5 * f * f;
const dk = f32(k); const dk = f32(k);
s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;
} }
fn log1p_64(x: f64) -> f64 { fn log1p_64(x: f64) -> f64 {
@ -172,7 +172,7 @@ fn log1p_64(x: f64) -> f64 {
const R = t2 + t1; const R = t2 + t1;
const dk = f64(k); const dk = f64(k);
s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;
} }
test "math.log1p" { test "math.log1p" {

View File

@ -14,7 +14,7 @@ pub fn log2(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (@typeId(T)) { switch (@typeId(T)) {
TypeId.FloatLiteral => { TypeId.FloatLiteral => {
return @typeOf(1.0)(log2_64(x)) return @typeOf(1.0)(log2_64(x));
}, },
TypeId.Float => { TypeId.Float => {
return switch (T) { return switch (T) {
@ -26,7 +26,7 @@ pub fn log2(x: var) -> @typeOf(x) {
TypeId.IntLiteral => comptime { TypeId.IntLiteral => comptime {
var result = 0; var result = 0;
var x_shifted = x; var x_shifted = x;
while ({x_shifted >>= 1; x_shifted != 0}) : (result += 1) {} while (b: {x_shifted >>= 1; break :b x_shifted != 0;}) : (result += 1) {}
return result; return result;
}, },
TypeId.Int => { TypeId.Int => {
@ -94,7 +94,7 @@ pub fn log2_32(x_: f32) -> f32 {
u &= 0xFFFFF000; u &= 0xFFFFF000;
hi = @bitCast(f32, u); hi = @bitCast(f32, u);
const lo = f - hi - hfsq + s * (hfsq + R); const lo = f - hi - hfsq + s * (hfsq + R);
(lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + f32(k) return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + f32(k);
} }
pub fn log2_64(x_: f64) -> f64 { pub fn log2_64(x_: f64) -> f64 {
@ -165,7 +165,7 @@ pub fn log2_64(x_: f64) -> f64 {
val_lo += (y - ww) + val_hi; val_lo += (y - ww) + val_hi;
val_hi = ww; val_hi = ww;
val_lo + val_hi return val_lo + val_hi;
} }
test "math.log2" { test "math.log2" {

View File

@ -7,21 +7,21 @@ const math = @import("index.zig");
const assert = @import("../debug.zig").assert; const assert = @import("../debug.zig").assert;
fn modf_result(comptime T: type) -> type { fn modf_result(comptime T: type) -> type {
struct { return struct {
fpart: T, fpart: T,
ipart: T, ipart: T,
} };
} }
pub const modf32_result = modf_result(f32); pub const modf32_result = modf_result(f32);
pub const modf64_result = modf_result(f64); pub const modf64_result = modf_result(f64);
pub fn modf(x: var) -> modf_result(@typeOf(x)) { pub fn modf(x: var) -> modf_result(@typeOf(x)) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(modf32, x), f32 => @inlineCall(modf32, x),
f64 => @inlineCall(modf64, x), f64 => @inlineCall(modf64, x),
else => @compileError("modf not implemented for " ++ @typeName(T)), else => @compileError("modf not implemented for " ++ @typeName(T)),
} };
} }
fn modf32(x: f32) -> modf32_result { fn modf32(x: f32) -> modf32_result {
@ -66,7 +66,7 @@ fn modf32(x: f32) -> modf32_result {
const uf = @bitCast(f32, u & ~mask); const uf = @bitCast(f32, u & ~mask);
result.ipart = uf; result.ipart = uf;
result.fpart = x - uf; result.fpart = x - uf;
result return result;
} }
fn modf64(x: f64) -> modf64_result { fn modf64(x: f64) -> modf64_result {
@ -110,7 +110,7 @@ fn modf64(x: f64) -> modf64_result {
const uf = @bitCast(f64, u & ~mask); const uf = @bitCast(f64, u & ~mask);
result.ipart = uf; result.ipart = uf;
result.fpart = x - uf; result.fpart = x - uf;
result return result;
} }
test "math.modf" { test "math.modf" {

View File

@ -1,19 +1,19 @@
const math = @import("index.zig"); const math = @import("index.zig");
pub fn nan(comptime T: type) -> T { pub fn nan(comptime T: type) -> T {
switch (T) { return switch (T) {
f32 => @bitCast(f32, math.nan_u32), f32 => @bitCast(f32, math.nan_u32),
f64 => @bitCast(f64, math.nan_u64), f64 => @bitCast(f64, math.nan_u64),
else => @compileError("nan not implemented for " ++ @typeName(T)), else => @compileError("nan not implemented for " ++ @typeName(T)),
} };
} }
// Note: A signalling nan is identical to a standard right now by may have a different bit // Note: A signalling nan is identical to a standard right now by may have a different bit
// representation in the future when required. // representation in the future when required.
pub fn snan(comptime T: type) -> T { pub fn snan(comptime T: type) -> T {
switch (T) { return switch (T) {
f32 => @bitCast(f32, math.nan_u32), f32 => @bitCast(f32, math.nan_u32),
f64 => @bitCast(f64, math.nan_u64), f64 => @bitCast(f64, math.nan_u64),
else => @compileError("snan not implemented for " ++ @typeName(T)), else => @compileError("snan not implemented for " ++ @typeName(T)),
} };
} }

View File

@ -166,12 +166,12 @@ pub fn pow(comptime T: type, x: T, y: T) -> T {
ae = -ae; ae = -ae;
} }
math.scalbn(a1, ae) return math.scalbn(a1, ae);
} }
fn isOddInteger(x: f64) -> bool { fn isOddInteger(x: f64) -> bool {
const r = math.modf(x); const r = math.modf(x);
r.fpart == 0.0 and i64(r.ipart) & 1 == 1 return r.fpart == 0.0 and i64(r.ipart) & 1 == 1;
} }
test "math.pow" { test "math.pow" {

View File

@ -10,11 +10,11 @@ const math = @import("index.zig");
pub fn round(x: var) -> @typeOf(x) { pub fn round(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(round32, x), f32 => @inlineCall(round32, x),
f64 => @inlineCall(round64, x), f64 => @inlineCall(round64, x),
else => @compileError("round not implemented for " ++ @typeName(T)), else => @compileError("round not implemented for " ++ @typeName(T)),
} };
} }
fn round32(x_: f32) -> f32 { fn round32(x_: f32) -> f32 {
@ -48,9 +48,9 @@ fn round32(x_: f32) -> f32 {
} }
if (u >> 31 != 0) { if (u >> 31 != 0) {
-y return -y;
} else { } else {
y return y;
} }
} }
@ -85,9 +85,9 @@ fn round64(x_: f64) -> f64 {
} }
if (u >> 63 != 0) { if (u >> 63 != 0) {
-y return -y;
} else { } else {
y return y;
} }
} }

View File

@ -3,11 +3,11 @@ const assert = @import("../debug.zig").assert;
pub fn scalbn(x: var, n: i32) -> @typeOf(x) { pub fn scalbn(x: var, n: i32) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(scalbn32, x, n), f32 => @inlineCall(scalbn32, x, n),
f64 => @inlineCall(scalbn64, x, n), f64 => @inlineCall(scalbn64, x, n),
else => @compileError("scalbn not implemented for " ++ @typeName(T)), else => @compileError("scalbn not implemented for " ++ @typeName(T)),
} };
} }
fn scalbn32(x: f32, n_: i32) -> f32 { fn scalbn32(x: f32, n_: i32) -> f32 {
@ -37,7 +37,7 @@ fn scalbn32(x: f32, n_: i32) -> f32 {
} }
const u = u32(n +% 0x7F) << 23; const u = u32(n +% 0x7F) << 23;
y * @bitCast(f32, u) return y * @bitCast(f32, u);
} }
fn scalbn64(x: f64, n_: i32) -> f64 { fn scalbn64(x: f64, n_: i32) -> f64 {
@ -67,7 +67,7 @@ fn scalbn64(x: f64, n_: i32) -> f64 {
} }
const u = u64(n +% 0x3FF) << 52; const u = u64(n +% 0x3FF) << 52;
y * @bitCast(f64, u) return y * @bitCast(f64, u);
} }
test "math.scalbn" { test "math.scalbn" {

View File

@ -3,21 +3,21 @@ const assert = @import("../debug.zig").assert;
pub fn signbit(x: var) -> bool { pub fn signbit(x: var) -> bool {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(signbit32, x), f32 => @inlineCall(signbit32, x),
f64 => @inlineCall(signbit64, x), f64 => @inlineCall(signbit64, x),
else => @compileError("signbit not implemented for " ++ @typeName(T)), else => @compileError("signbit not implemented for " ++ @typeName(T)),
} };
} }
fn signbit32(x: f32) -> bool { fn signbit32(x: f32) -> bool {
const bits = @bitCast(u32, x); const bits = @bitCast(u32, x);
bits >> 31 != 0 return bits >> 31 != 0;
} }
fn signbit64(x: f64) -> bool { fn signbit64(x: f64) -> bool {
const bits = @bitCast(u64, x); const bits = @bitCast(u64, x);
bits >> 63 != 0 return bits >> 63 != 0;
} }
test "math.signbit" { test "math.signbit" {

View File

@ -10,11 +10,11 @@ const assert = @import("../debug.zig").assert;
pub fn sin(x: var) -> @typeOf(x) { pub fn sin(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(sin32, x), f32 => @inlineCall(sin32, x),
f64 => @inlineCall(sin64, x), f64 => @inlineCall(sin64, x),
else => @compileError("sin not implemented for " ++ @typeName(T)), else => @compileError("sin not implemented for " ++ @typeName(T)),
} };
} }
// sin polynomial coefficients // sin polynomial coefficients
@ -75,18 +75,18 @@ fn sin32(x_: f32) -> f32 {
const z = ((x - y * pi4a) - y * pi4b) - y * pi4c; const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
const w = z * z; const w = z * z;
const r = { const r = r: {
if (j == 1 or j == 2) { if (j == 1 or j == 2) {
1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0))))) break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
} else { } else {
z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0))))) break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
} }
}; };
if (sign) { if (sign) {
-r return -r;
} else { } else {
r return r;
} }
} }
@ -127,25 +127,25 @@ fn sin64(x_: f64) -> f64 {
const z = ((x - y * pi4a) - y * pi4b) - y * pi4c; const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
const w = z * z; const w = z * z;
const r = { const r = r: {
if (j == 1 or j == 2) { if (j == 1 or j == 2) {
1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0))))) break :r 1.0 - 0.5 * w + w * w * (C5 + w * (C4 + w * (C3 + w * (C2 + w * (C1 + w * C0)))));
} else { } else {
z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0))))) break :r z + z * w * (S5 + w * (S4 + w * (S3 + w * (S2 + w * (S1 + w * S0)))));
} }
}; };
if (sign) { if (sign) {
-r return -r;
} else { } else {
r return r;
} }
} }
test "math.sin" { test "math.sin" {
assert(sin(f32(0.0)) == sin32(0.0)); assert(sin(f32(0.0)) == sin32(0.0));
assert(sin(f64(0.0)) == sin64(0.0)); assert(sin(f64(0.0)) == sin64(0.0));
assert(comptime {math.sin(f64(2))} == math.sin(f64(2))); assert(comptime (math.sin(f64(2))) == math.sin(f64(2)));
} }
test "math.sin32" { test "math.sin32" {

View File

@ -11,11 +11,11 @@ const expo2 = @import("expo2.zig").expo2;
pub fn sinh(x: var) -> @typeOf(x) { pub fn sinh(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(sinh32, x), f32 => @inlineCall(sinh32, x),
f64 => @inlineCall(sinh64, x), f64 => @inlineCall(sinh64, x),
else => @compileError("sinh not implemented for " ++ @typeName(T)), else => @compileError("sinh not implemented for " ++ @typeName(T)),
} };
} }
// sinh(x) = (exp(x) - 1 / exp(x)) / 2 // sinh(x) = (exp(x) - 1 / exp(x)) / 2
@ -49,7 +49,7 @@ fn sinh32(x: f32) -> f32 {
} }
// |x| > log(FLT_MAX) or nan // |x| > log(FLT_MAX) or nan
2 * h * expo2(ax) return 2 * h * expo2(ax);
} }
fn sinh64(x: f64) -> f64 { fn sinh64(x: f64) -> f64 {
@ -83,7 +83,7 @@ fn sinh64(x: f64) -> f64 {
} }
// |x| > log(DBL_MAX) or nan // |x| > log(DBL_MAX) or nan
2 * h * expo2(ax) return 2 * h * expo2(ax);
} }
test "math.sinh" { test "math.sinh" {

View File

@ -14,7 +14,7 @@ pub fn sqrt(x: var) -> (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @
const T = @typeOf(x); const T = @typeOf(x);
switch (@typeId(T)) { switch (@typeId(T)) {
TypeId.FloatLiteral => { TypeId.FloatLiteral => {
return T(sqrt64(x)) return T(sqrt64(x));
}, },
TypeId.Float => { TypeId.Float => {
return switch (T) { return switch (T) {
@ -64,7 +64,7 @@ fn sqrt32(x: f32) -> f32 {
// subnormal // subnormal
var i: i32 = 0; var i: i32 = 0;
while (ix & 0x00800000 == 0) : (i += 1) { while (ix & 0x00800000 == 0) : (i += 1) {
ix <<= 1 ix <<= 1;
} }
m -= i - 1; m -= i - 1;
} }
@ -112,7 +112,7 @@ fn sqrt32(x: f32) -> f32 {
ix = (q >> 1) + 0x3f000000; ix = (q >> 1) + 0x3f000000;
ix += m << 23; ix += m << 23;
@bitCast(f32, ix) return @bitCast(f32, ix);
} }
// NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound // NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound
@ -153,7 +153,7 @@ fn sqrt64(x: f64) -> f64 {
// subnormal // subnormal
var i: u32 = 0; var i: u32 = 0;
while (ix0 & 0x00100000 == 0) : (i += 1) { while (ix0 & 0x00100000 == 0) : (i += 1) {
ix0 <<= 1 ix0 <<= 1;
} }
m -= i32(i) - 1; m -= i32(i) - 1;
ix0 |= ix1 >> u5(32 - i); ix0 |= ix1 >> u5(32 - i);
@ -245,7 +245,7 @@ fn sqrt64(x: f64) -> f64 {
iix0 = iix0 +% (m << 20); iix0 = iix0 +% (m << 20);
const uz = (u64(iix0) << 32) | ix1; const uz = (u64(iix0) << 32) | ix1;
@bitCast(f64, uz) return @bitCast(f64, uz);
} }
test "math.sqrt" { test "math.sqrt" {

View File

@ -10,11 +10,11 @@ const assert = @import("../debug.zig").assert;
pub fn tan(x: var) -> @typeOf(x) { pub fn tan(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(tan32, x), f32 => @inlineCall(tan32, x),
f64 => @inlineCall(tan64, x), f64 => @inlineCall(tan64, x),
else => @compileError("tan not implemented for " ++ @typeName(T)), else => @compileError("tan not implemented for " ++ @typeName(T)),
} };
} }
const Tp0 = -1.30936939181383777646E4; const Tp0 = -1.30936939181383777646E4;
@ -62,11 +62,11 @@ fn tan32(x_: f32) -> f32 {
const z = ((x - y * pi4a) - y * pi4b) - y * pi4c; const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
const w = z * z; const w = z * z;
var r = { var r = r: {
if (w > 1e-14) { if (w > 1e-14) {
z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4)) break :r z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4));
} else { } else {
z break :r z;
} }
}; };
@ -77,7 +77,7 @@ fn tan32(x_: f32) -> f32 {
r = -r; r = -r;
} }
r return r;
} }
fn tan64(x_: f64) -> f64 { fn tan64(x_: f64) -> f64 {
@ -111,11 +111,11 @@ fn tan64(x_: f64) -> f64 {
const z = ((x - y * pi4a) - y * pi4b) - y * pi4c; const z = ((x - y * pi4a) - y * pi4b) - y * pi4c;
const w = z * z; const w = z * z;
var r = { var r = r: {
if (w > 1e-14) { if (w > 1e-14) {
z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4)) break :r z + z * (w * ((Tp0 * w + Tp1) * w + Tp2) / ((((w + Tq1) * w + Tq2) * w + Tq3) * w + Tq4));
} else { } else {
z break :r z;
} }
}; };
@ -126,7 +126,7 @@ fn tan64(x_: f64) -> f64 {
r = -r; r = -r;
} }
r return r;
} }
test "math.tan" { test "math.tan" {

View File

@ -11,11 +11,11 @@ const expo2 = @import("expo2.zig").expo2;
pub fn tanh(x: var) -> @typeOf(x) { pub fn tanh(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(tanh32, x), f32 => @inlineCall(tanh32, x),
f64 => @inlineCall(tanh64, x), f64 => @inlineCall(tanh64, x),
else => @compileError("tanh not implemented for " ++ @typeName(T)), else => @compileError("tanh not implemented for " ++ @typeName(T)),
} };
} }
// tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x)) // tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))
@ -59,9 +59,9 @@ fn tanh32(x: f32) -> f32 {
} }
if (u >> 31 != 0) { if (u >> 31 != 0) {
-t return -t;
} else { } else {
t return t;
} }
} }
@ -104,9 +104,9 @@ fn tanh64(x: f64) -> f64 {
} }
if (u >> 63 != 0) { if (u >> 63 != 0) {
-t return -t;
} else { } else {
t return t;
} }
} }

View File

@ -9,11 +9,11 @@ const assert = @import("../debug.zig").assert;
pub fn trunc(x: var) -> @typeOf(x) { pub fn trunc(x: var) -> @typeOf(x) {
const T = @typeOf(x); const T = @typeOf(x);
switch (T) { return switch (T) {
f32 => @inlineCall(trunc32, x), f32 => @inlineCall(trunc32, x),
f64 => @inlineCall(trunc64, x), f64 => @inlineCall(trunc64, x),
else => @compileError("trunc not implemented for " ++ @typeName(T)), else => @compileError("trunc not implemented for " ++ @typeName(T)),
} };
} }
fn trunc32(x: f32) -> f32 { fn trunc32(x: f32) -> f32 {
@ -30,10 +30,10 @@ fn trunc32(x: f32) -> f32 {
m = u32(@maxValue(u32)) >> u5(e); m = u32(@maxValue(u32)) >> u5(e);
if (u & m == 0) { if (u & m == 0) {
x return x;
} else { } else {
math.forceEval(x + 0x1p120); math.forceEval(x + 0x1p120);
@bitCast(f32, u & ~m) return @bitCast(f32, u & ~m);
} }
} }
@ -51,10 +51,10 @@ fn trunc64(x: f64) -> f64 {
m = u64(@maxValue(u64)) >> u6(e); m = u64(@maxValue(u64)) >> u6(e);
if (u & m == 0) { if (u & m == 0) {
x return x;
} else { } else {
math.forceEval(x + 0x1p120); math.forceEval(x + 0x1p120);
@bitCast(f64, u & ~m) return @bitCast(f64, u & ~m);
} }
} }

View File

@ -354,11 +354,11 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) -> bool {
/// split(" abc def ghi ", " ") /// split(" abc def ghi ", " ")
/// Will return slices for "abc", "def", "ghi", null, in that order. /// Will return slices for "abc", "def", "ghi", null, in that order.
pub fn split(buffer: []const u8, split_bytes: []const u8) -> SplitIterator { pub fn split(buffer: []const u8, split_bytes: []const u8) -> SplitIterator {
SplitIterator { return SplitIterator {
.index = 0, .index = 0,
.buffer = buffer, .buffer = buffer,
.split_bytes = split_bytes, .split_bytes = split_bytes,
} };
} }
test "mem.split" { test "mem.split" {
@ -552,7 +552,7 @@ test "std.mem.reverse" {
var arr = []i32{ 5, 3, 1, 2, 4 }; var arr = []i32{ 5, 3, 1, 2, 4 };
reverse(i32, arr[0..]); reverse(i32, arr[0..]);
assert(eql(i32, arr, []i32{ 4, 2, 1, 3, 5 })) assert(eql(i32, arr, []i32{ 4, 2, 1, 3, 5 }));
} }
/// In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1) /// In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1)
@ -567,5 +567,5 @@ test "std.mem.rotate" {
var arr = []i32{ 5, 3, 1, 2, 4 }; var arr = []i32{ 5, 3, 1, 2, 4 };
rotate(i32, arr[0..], 2); rotate(i32, arr[0..], 2);
assert(eql(i32, arr, []i32{ 1, 2, 4, 5, 3 })) assert(eql(i32, arr, []i32{ 1, 2, 4, 5, 3 }));
} }

View File

@ -72,7 +72,7 @@ pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address {
// if (family != AF_INET) // if (family != AF_INET)
// buf[cnt++] = (struct address){ .family = AF_INET6, .addr = { [15] = 1 } }; // buf[cnt++] = (struct address){ .family = AF_INET6, .addr = { [15] = 1 } };
// //
unreachable // TODO unreachable; // TODO
} }
// TODO // TODO
@ -84,7 +84,7 @@ pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address {
// else => {}, // else => {},
//}; //};
unreachable // TODO unreachable; // TODO
} }
pub fn connectAddr(addr: &Address, port: u16) -> %Connection { pub fn connectAddr(addr: &Address, port: u16) -> %Connection {
@ -96,23 +96,23 @@ pub fn connectAddr(addr: &Address, port: u16) -> %Connection {
} }
const socket_fd = i32(socket_ret); const socket_fd = i32(socket_ret);
const connect_ret = if (addr.family == linux.AF_INET) { const connect_ret = if (addr.family == linux.AF_INET) x: {
var os_addr: linux.sockaddr_in = undefined; var os_addr: linux.sockaddr_in = undefined;
os_addr.family = addr.family; os_addr.family = addr.family;
os_addr.port = endian.swapIfLe(u16, port); os_addr.port = endian.swapIfLe(u16, port);
@memcpy((&u8)(&os_addr.addr), &addr.addr[0], 4); @memcpy((&u8)(&os_addr.addr), &addr.addr[0], 4);
@memset(&os_addr.zero[0], 0, @sizeOf(@typeOf(os_addr.zero))); @memset(&os_addr.zero[0], 0, @sizeOf(@typeOf(os_addr.zero)));
linux.connect(socket_fd, (&linux.sockaddr)(&os_addr), @sizeOf(linux.sockaddr_in)) break :x linux.connect(socket_fd, (&linux.sockaddr)(&os_addr), @sizeOf(linux.sockaddr_in));
} else if (addr.family == linux.AF_INET6) { } else if (addr.family == linux.AF_INET6) x: {
var os_addr: linux.sockaddr_in6 = undefined; var os_addr: linux.sockaddr_in6 = undefined;
os_addr.family = addr.family; os_addr.family = addr.family;
os_addr.port = endian.swapIfLe(u16, port); os_addr.port = endian.swapIfLe(u16, port);
os_addr.flowinfo = 0; os_addr.flowinfo = 0;
os_addr.scope_id = addr.scope_id; os_addr.scope_id = addr.scope_id;
@memcpy(&os_addr.addr[0], &addr.addr[0], 16); @memcpy(&os_addr.addr[0], &addr.addr[0], 16);
linux.connect(socket_fd, (&linux.sockaddr)(&os_addr), @sizeOf(linux.sockaddr_in6)) break :x linux.connect(socket_fd, (&linux.sockaddr)(&os_addr), @sizeOf(linux.sockaddr_in6));
} else { } else {
unreachable unreachable;
}; };
const connect_err = linux.getErrno(connect_ret); const connect_err = linux.getErrno(connect_ret);
if (connect_err > 0) { if (connect_err > 0) {
@ -165,13 +165,13 @@ pub fn parseIpLiteral(buf: []const u8) -> %Address {
fn hexDigit(c: u8) -> u8 { fn hexDigit(c: u8) -> u8 {
// TODO use switch with range // TODO use switch with range
if ('0' <= c and c <= '9') { if ('0' <= c and c <= '9') {
c - '0' return c - '0';
} else if ('A' <= c and c <= 'Z') { } else if ('A' <= c and c <= 'Z') {
c - 'A' + 10 return c - 'A' + 10;
} else if ('a' <= c and c <= 'z') { } else if ('a' <= c and c <= 'z') {
c - 'a' + 10 return c - 'a' + 10;
} else { } else {
@maxValue(u8) return @maxValue(u8);
} }
} }

View File

@ -115,7 +115,7 @@ pub const ChildProcess = struct {
return self.spawnWindows(); return self.spawnWindows();
} else { } else {
return self.spawnPosix(); return self.spawnPosix();
}; }
} }
pub fn spawnAndWait(self: &ChildProcess) -> %Term { pub fn spawnAndWait(self: &ChildProcess) -> %Term {
@ -249,12 +249,12 @@ pub const ChildProcess = struct {
fn waitUnwrappedWindows(self: &ChildProcess) -> %void { fn waitUnwrappedWindows(self: &ChildProcess) -> %void {
const result = os.windowsWaitSingle(self.handle, windows.INFINITE); const result = os.windowsWaitSingle(self.handle, windows.INFINITE);
self.term = (%Term)({ self.term = (%Term)(x: {
var exit_code: windows.DWORD = undefined; var exit_code: windows.DWORD = undefined;
if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) { if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) {
Term { .Unknown = 0 } break :x Term { .Unknown = 0 };
} else { } else {
Term { .Exited = @bitCast(i32, exit_code)} break :x Term { .Exited = @bitCast(i32, exit_code)};
} }
}); });
@ -300,7 +300,7 @@ pub const ChildProcess = struct {
defer { defer {
os.close(self.err_pipe[0]); os.close(self.err_pipe[0]);
os.close(self.err_pipe[1]); os.close(self.err_pipe[1]);
}; }
// Write @maxValue(ErrInt) to the write end of the err_pipe. This is after // Write @maxValue(ErrInt) to the write end of the err_pipe. This is after
// waitpid, so this write is guaranteed to be after the child // waitpid, so this write is guaranteed to be after the child
@ -319,15 +319,15 @@ pub const ChildProcess = struct {
} }
fn statusToTerm(status: i32) -> Term { fn statusToTerm(status: i32) -> Term {
return if (posix.WIFEXITED(status)) { return if (posix.WIFEXITED(status))
Term { .Exited = posix.WEXITSTATUS(status) } Term { .Exited = posix.WEXITSTATUS(status) }
} else if (posix.WIFSIGNALED(status)) { else if (posix.WIFSIGNALED(status))
Term { .Signal = posix.WTERMSIG(status) } Term { .Signal = posix.WTERMSIG(status) }
} else if (posix.WIFSTOPPED(status)) { else if (posix.WIFSTOPPED(status))
Term { .Stopped = posix.WSTOPSIG(status) } Term { .Stopped = posix.WSTOPSIG(status) }
} else { else
Term { .Unknown = status } Term { .Unknown = status }
}; ;
} }
fn spawnPosix(self: &ChildProcess) -> %void { fn spawnPosix(self: &ChildProcess) -> %void {
@ -344,22 +344,22 @@ pub const ChildProcess = struct {
%defer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); }; %defer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); };
const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
const dev_null_fd = if (any_ignore) { const dev_null_fd = if (any_ignore)
%return os.posixOpen("/dev/null", posix.O_RDWR, 0, null) %return os.posixOpen("/dev/null", posix.O_RDWR, 0, null)
} else { else
undefined undefined
}; ;
defer { if (any_ignore) os.close(dev_null_fd); }; defer { if (any_ignore) os.close(dev_null_fd); }
var env_map_owned: BufMap = undefined; var env_map_owned: BufMap = undefined;
var we_own_env_map: bool = undefined; var we_own_env_map: bool = undefined;
const env_map = if (self.env_map) |env_map| { const env_map = if (self.env_map) |env_map| x: {
we_own_env_map = false; we_own_env_map = false;
env_map break :x env_map;
} else { } else x: {
we_own_env_map = true; we_own_env_map = true;
env_map_owned = %return os.getEnvMap(self.allocator); env_map_owned = %return os.getEnvMap(self.allocator);
&env_map_owned break :x &env_map_owned;
}; };
defer { if (we_own_env_map) env_map_owned.deinit(); } defer { if (we_own_env_map) env_map_owned.deinit(); }
@ -450,13 +450,13 @@ pub const ChildProcess = struct {
self.stdout_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or
self.stderr_behavior == StdIo.Ignore); self.stderr_behavior == StdIo.Ignore);
const nul_handle = if (any_ignore) { const nul_handle = if (any_ignore)
%return os.windowsOpen("NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ, %return os.windowsOpen("NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ,
windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL, null) windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL, null)
} else { else
undefined undefined
}; ;
defer { if (any_ignore) os.close(nul_handle); }; defer { if (any_ignore) os.close(nul_handle); }
if (any_ignore) { if (any_ignore) {
%return windowsSetHandleInfo(nul_handle, windows.HANDLE_FLAG_INHERIT, 0); %return windowsSetHandleInfo(nul_handle, windows.HANDLE_FLAG_INHERIT, 0);
} }
@ -542,30 +542,30 @@ pub const ChildProcess = struct {
}; };
var piProcInfo: windows.PROCESS_INFORMATION = undefined; var piProcInfo: windows.PROCESS_INFORMATION = undefined;
const cwd_slice = if (self.cwd) |cwd| { const cwd_slice = if (self.cwd) |cwd|
%return cstr.addNullByte(self.allocator, cwd) %return cstr.addNullByte(self.allocator, cwd)
} else { else
null null
}; ;
defer if (cwd_slice) |cwd| self.allocator.free(cwd); defer if (cwd_slice) |cwd| self.allocator.free(cwd);
const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null; const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null;
const maybe_envp_buf = if (self.env_map) |env_map| { const maybe_envp_buf = if (self.env_map) |env_map|
%return os.createWindowsEnvBlock(self.allocator, env_map) %return os.createWindowsEnvBlock(self.allocator, env_map)
} else { else
null null
}; ;
defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf); defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf);
const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null; const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null;
// the cwd set in ChildProcess is in effect when choosing the executable path // the cwd set in ChildProcess is in effect when choosing the executable path
// to match posix semantics // to match posix semantics
const app_name = if (self.cwd) |cwd| { const app_name = if (self.cwd) |cwd| x: {
const resolved = %return os.path.resolve(self.allocator, cwd, self.argv[0]); const resolved = %return os.path.resolve(self.allocator, cwd, self.argv[0]);
defer self.allocator.free(resolved); defer self.allocator.free(resolved);
%return cstr.addNullByte(self.allocator, resolved) break :x %return cstr.addNullByte(self.allocator, resolved);
} else { } else x: {
%return cstr.addNullByte(self.allocator, self.argv[0]) break :x %return cstr.addNullByte(self.allocator, self.argv[0]);
}; };
defer self.allocator.free(app_name); defer self.allocator.free(app_name);
@ -741,7 +741,7 @@ fn makePipe() -> %[2]i32 {
return switch (err) { return switch (err) {
posix.EMFILE, posix.ENFILE => error.SystemResources, posix.EMFILE, posix.ENFILE => error.SystemResources,
else => os.unexpectedErrorPosix(err), else => os.unexpectedErrorPosix(err),
} };
} }
return fds; return fds;
} }
@ -800,10 +800,10 @@ fn handleTerm(pid: i32, status: i32) {
} }
} }
const sigchld_set = { const sigchld_set = x: {
var signal_set = posix.empty_sigset; var signal_set = posix.empty_sigset;
posix.sigaddset(&signal_set, posix.SIGCHLD); posix.sigaddset(&signal_set, posix.SIGCHLD);
signal_set break :x signal_set;
}; };
fn block_SIGCHLD() { fn block_SIGCHLD() {

View File

@ -97,63 +97,63 @@ pub const SIGINFO = 29; /// information request
pub const SIGUSR1 = 30; /// user defined signal 1 pub const SIGUSR1 = 30; /// user defined signal 1
pub const SIGUSR2 = 31; /// user defined signal 2 pub const SIGUSR2 = 31; /// user defined signal 2
fn wstatus(x: i32) -> i32 { x & 0o177 } fn wstatus(x: i32) -> i32 { return x & 0o177; }
const wstopped = 0o177; const wstopped = 0o177;
pub fn WEXITSTATUS(x: i32) -> i32 { x >> 8 } pub fn WEXITSTATUS(x: i32) -> i32 { return x >> 8; }
pub fn WTERMSIG(x: i32) -> i32 { wstatus(x) } pub fn WTERMSIG(x: i32) -> i32 { return wstatus(x); }
pub fn WSTOPSIG(x: i32) -> i32 { x >> 8 } pub fn WSTOPSIG(x: i32) -> i32 { return x >> 8; }
pub fn WIFEXITED(x: i32) -> bool { wstatus(x) == 0 } pub fn WIFEXITED(x: i32) -> bool { return wstatus(x) == 0; }
pub fn WIFSTOPPED(x: i32) -> bool { wstatus(x) == wstopped and WSTOPSIG(x) != 0x13 } pub fn WIFSTOPPED(x: i32) -> bool { return wstatus(x) == wstopped and WSTOPSIG(x) != 0x13; }
pub fn WIFSIGNALED(x: i32) -> bool { wstatus(x) != wstopped and wstatus(x) != 0 } pub fn WIFSIGNALED(x: i32) -> bool { return wstatus(x) != wstopped and wstatus(x) != 0; }
/// Get the errno from a syscall return value, or 0 for no error. /// Get the errno from a syscall return value, or 0 for no error.
pub fn getErrno(r: usize) -> usize { pub fn getErrno(r: usize) -> usize {
const signed_r = @bitCast(isize, r); const signed_r = @bitCast(isize, r);
if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0 return if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0;
} }
pub fn close(fd: i32) -> usize { pub fn close(fd: i32) -> usize {
errnoWrap(c.close(fd)) return errnoWrap(c.close(fd));
} }
pub fn abort() -> noreturn { pub fn abort() -> noreturn {
c.abort() return c.abort();
} }
pub fn exit(code: i32) -> noreturn { pub fn exit(code: i32) -> noreturn {
c.exit(code) return c.exit(code);
} }
pub fn isatty(fd: i32) -> bool { pub fn isatty(fd: i32) -> bool {
c.isatty(fd) != 0 return c.isatty(fd) != 0;
} }
pub fn fstat(fd: i32, buf: &c.Stat) -> usize { pub fn fstat(fd: i32, buf: &c.Stat) -> usize {
errnoWrap(c.@"fstat$INODE64"(fd, buf)) return errnoWrap(c.@"fstat$INODE64"(fd, buf));
} }
pub fn lseek(fd: i32, offset: isize, whence: c_int) -> usize { pub fn lseek(fd: i32, offset: isize, whence: c_int) -> usize {
errnoWrap(c.lseek(fd, offset, whence)) return errnoWrap(c.lseek(fd, offset, whence));
} }
pub fn open(path: &const u8, flags: u32, mode: usize) -> usize { pub fn open(path: &const u8, flags: u32, mode: usize) -> usize {
errnoWrap(c.open(path, @bitCast(c_int, flags), mode)) return errnoWrap(c.open(path, @bitCast(c_int, flags), mode));
} }
pub fn raise(sig: i32) -> usize { pub fn raise(sig: i32) -> usize {
errnoWrap(c.raise(sig)) return errnoWrap(c.raise(sig));
} }
pub fn read(fd: i32, buf: &u8, nbyte: usize) -> usize { pub fn read(fd: i32, buf: &u8, nbyte: usize) -> usize {
errnoWrap(c.read(fd, @ptrCast(&c_void, buf), nbyte)) return errnoWrap(c.read(fd, @ptrCast(&c_void, buf), nbyte));
} }
pub fn stat(noalias path: &const u8, noalias buf: &stat) -> usize { pub fn stat(noalias path: &const u8, noalias buf: &stat) -> usize {
errnoWrap(c.stat(path, buf)) return errnoWrap(c.stat(path, buf));
} }
pub fn write(fd: i32, buf: &const u8, nbyte: usize) -> usize { pub fn write(fd: i32, buf: &const u8, nbyte: usize) -> usize {
errnoWrap(c.write(fd, @ptrCast(&const c_void, buf), nbyte)) return errnoWrap(c.write(fd, @ptrCast(&const c_void, buf), nbyte));
} }
pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32,
@ -166,79 +166,79 @@ pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32,
} }
pub fn munmap(address: &u8, length: usize) -> usize { pub fn munmap(address: &u8, length: usize) -> usize {
errnoWrap(c.munmap(@ptrCast(&c_void, address), length)) return errnoWrap(c.munmap(@ptrCast(&c_void, address), length));
} }
pub fn unlink(path: &const u8) -> usize { pub fn unlink(path: &const u8) -> usize {
errnoWrap(c.unlink(path)) return errnoWrap(c.unlink(path));
} }
pub fn getcwd(buf: &u8, size: usize) -> usize { pub fn getcwd(buf: &u8, size: usize) -> usize {
if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(*c._errno())) else 0 return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(*c._errno())) else 0;
} }
pub fn waitpid(pid: i32, status: &i32, options: u32) -> usize { pub fn waitpid(pid: i32, status: &i32, options: u32) -> usize {
comptime assert(i32.bit_count == c_int.bit_count); comptime assert(i32.bit_count == c_int.bit_count);
errnoWrap(c.waitpid(pid, @ptrCast(&c_int, status), @bitCast(c_int, options))) return errnoWrap(c.waitpid(pid, @ptrCast(&c_int, status), @bitCast(c_int, options)));
} }
pub fn fork() -> usize { pub fn fork() -> usize {
errnoWrap(c.fork()) return errnoWrap(c.fork());
} }
pub fn pipe(fds: &[2]i32) -> usize { pub fn pipe(fds: &[2]i32) -> usize {
comptime assert(i32.bit_count == c_int.bit_count); comptime assert(i32.bit_count == c_int.bit_count);
errnoWrap(c.pipe(@ptrCast(&c_int, fds))) return errnoWrap(c.pipe(@ptrCast(&c_int, fds)));
} }
pub fn mkdir(path: &const u8, mode: u32) -> usize { pub fn mkdir(path: &const u8, mode: u32) -> usize {
errnoWrap(c.mkdir(path, mode)) return errnoWrap(c.mkdir(path, mode));
} }
pub fn symlink(existing: &const u8, new: &const u8) -> usize { pub fn symlink(existing: &const u8, new: &const u8) -> usize {
errnoWrap(c.symlink(existing, new)) return errnoWrap(c.symlink(existing, new));
} }
pub fn rename(old: &const u8, new: &const u8) -> usize { pub fn rename(old: &const u8, new: &const u8) -> usize {
errnoWrap(c.rename(old, new)) return errnoWrap(c.rename(old, new));
} }
pub fn chdir(path: &const u8) -> usize { pub fn chdir(path: &const u8) -> usize {
errnoWrap(c.chdir(path)) return errnoWrap(c.chdir(path));
} }
pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8)
-> usize -> usize
{ {
errnoWrap(c.execve(path, argv, envp)) return errnoWrap(c.execve(path, argv, envp));
} }
pub fn dup2(old: i32, new: i32) -> usize { pub fn dup2(old: i32, new: i32) -> usize {
errnoWrap(c.dup2(old, new)) return errnoWrap(c.dup2(old, new));
} }
pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -> usize { pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -> usize {
errnoWrap(c.readlink(path, buf_ptr, buf_len)) return errnoWrap(c.readlink(path, buf_ptr, buf_len));
} }
pub fn nanosleep(req: &const timespec, rem: ?&timespec) -> usize { pub fn nanosleep(req: &const timespec, rem: ?&timespec) -> usize {
errnoWrap(c.nanosleep(req, rem)) return errnoWrap(c.nanosleep(req, rem));
} }
pub fn realpath(noalias filename: &const u8, noalias resolved_name: &u8) -> usize { pub fn realpath(noalias filename: &const u8, noalias resolved_name: &u8) -> usize {
if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(*c._errno())) else 0 return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(*c._errno())) else 0;
} }
pub fn setreuid(ruid: u32, euid: u32) -> usize { pub fn setreuid(ruid: u32, euid: u32) -> usize {
errnoWrap(c.setreuid(ruid, euid)) return errnoWrap(c.setreuid(ruid, euid));
} }
pub fn setregid(rgid: u32, egid: u32) -> usize { pub fn setregid(rgid: u32, egid: u32) -> usize {
errnoWrap(c.setregid(rgid, egid)) return errnoWrap(c.setregid(rgid, egid));
} }
pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) -> usize { pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) -> usize {
errnoWrap(c.sigprocmask(@bitCast(c_int, flags), set, oldset)) return errnoWrap(c.sigprocmask(@bitCast(c_int, flags), set, oldset));
} }
pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigaction) -> usize { pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigaction) -> usize {
@ -285,9 +285,5 @@ pub fn sigaddset(set: &sigset_t, signo: u5) {
/// that the kernel represents it to libc. Errno was a mistake, let's make /// that the kernel represents it to libc. Errno was a mistake, let's make
/// it go away forever. /// it go away forever.
fn errnoWrap(value: isize) -> usize { fn errnoWrap(value: isize) -> usize {
@bitCast(usize, if (value == -1) { return @bitCast(usize, if (value == -1) -isize(*c._errno()) else value);
-isize(*c._errno())
} else {
value
})
} }

View File

@ -84,7 +84,7 @@ pub fn getRandomBytes(buf: []u8) -> %void {
posix.EFAULT => unreachable, posix.EFAULT => unreachable,
posix.EINTR => continue, posix.EINTR => continue,
else => unexpectedErrorPosix(err), else => unexpectedErrorPosix(err),
} };
} }
return; return;
}, },
@ -151,18 +151,17 @@ pub coldcc fn exit(status: i32) -> noreturn {
} }
switch (builtin.os) { switch (builtin.os) {
Os.linux, Os.darwin, Os.macosx, Os.ios => { Os.linux, Os.darwin, Os.macosx, Os.ios => {
posix.exit(status) posix.exit(status);
}, },
Os.windows => { Os.windows => {
// Map a possibly negative status code to a non-negative status for the systems default // Map a possibly negative status code to a non-negative status for the systems default
// integer width. // integer width.
const p_status = if (@sizeOf(c_uint) < @sizeOf(u32)) { const p_status = if (@sizeOf(c_uint) < @sizeOf(u32))
@truncate(c_uint, @bitCast(u32, status)) @truncate(c_uint, @bitCast(u32, status))
} else { else
c_uint(@bitCast(u32, status)) c_uint(@bitCast(u32, status));
};
windows.ExitProcess(p_status) windows.ExitProcess(p_status);
}, },
else => @compileError("Unsupported OS"), else => @compileError("Unsupported OS"),
} }
@ -289,7 +288,7 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al
posix.EPERM => error.AccessDenied, posix.EPERM => error.AccessDenied,
posix.EEXIST => error.PathAlreadyExists, posix.EEXIST => error.PathAlreadyExists,
else => unexpectedErrorPosix(err), else => unexpectedErrorPosix(err),
} };
} }
return i32(result); return i32(result);
} }
@ -680,7 +679,7 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) -> %void
windows.ERROR.ACCESS_DENIED => error.AccessDenied, windows.ERROR.ACCESS_DENIED => error.AccessDenied,
windows.ERROR.FILENAME_EXCED_RANGE, windows.ERROR.INVALID_PARAMETER => error.NameTooLong, windows.ERROR.FILENAME_EXCED_RANGE, windows.ERROR.INVALID_PARAMETER => error.NameTooLong,
else => unexpectedErrorWindows(err), else => unexpectedErrorWindows(err),
} };
} }
} }
@ -1006,7 +1005,7 @@ pub const Dir = struct {
continue; continue;
}, },
else => return unexpectedErrorPosix(err), else => return unexpectedErrorPosix(err),
}; }
} }
if (result == 0) if (result == 0)
return null; return null;

View File

@ -367,14 +367,14 @@ pub const TFD_CLOEXEC = O_CLOEXEC;
pub const TFD_TIMER_ABSTIME = 1; pub const TFD_TIMER_ABSTIME = 1;
pub const TFD_TIMER_CANCEL_ON_SET = (1 << 1); pub const TFD_TIMER_CANCEL_ON_SET = (1 << 1);
fn unsigned(s: i32) -> u32 { @bitCast(u32, s) } fn unsigned(s: i32) -> u32 { return @bitCast(u32, s); }
fn signed(s: u32) -> i32 { @bitCast(i32, s) } fn signed(s: u32) -> i32 { return @bitCast(i32, s); }
pub fn WEXITSTATUS(s: i32) -> i32 { signed((unsigned(s) & 0xff00) >> 8) } pub fn WEXITSTATUS(s: i32) -> i32 { return signed((unsigned(s) & 0xff00) >> 8); }
pub fn WTERMSIG(s: i32) -> i32 { signed(unsigned(s) & 0x7f) } pub fn WTERMSIG(s: i32) -> i32 { return signed(unsigned(s) & 0x7f); }
pub fn WSTOPSIG(s: i32) -> i32 { WEXITSTATUS(s) } pub fn WSTOPSIG(s: i32) -> i32 { return WEXITSTATUS(s); }
pub fn WIFEXITED(s: i32) -> bool { WTERMSIG(s) == 0 } pub fn WIFEXITED(s: i32) -> bool { return WTERMSIG(s) == 0; }
pub fn WIFSTOPPED(s: i32) -> bool { (u16)(((unsigned(s)&0xffff)*%0x10001)>>8) > 0x7f00 } pub fn WIFSTOPPED(s: i32) -> bool { return (u16)(((unsigned(s)&0xffff)*%0x10001)>>8) > 0x7f00; }
pub fn WIFSIGNALED(s: i32) -> bool { (unsigned(s)&0xffff)-%1 < 0xff } pub fn WIFSIGNALED(s: i32) -> bool { return (unsigned(s)&0xffff)-%1 < 0xff; }
pub const winsize = extern struct { pub const winsize = extern struct {
@ -387,31 +387,31 @@ pub const winsize = extern struct {
/// Get the errno from a syscall return value, or 0 for no error. /// Get the errno from a syscall return value, or 0 for no error.
pub fn getErrno(r: usize) -> usize { pub fn getErrno(r: usize) -> usize {
const signed_r = @bitCast(isize, r); const signed_r = @bitCast(isize, r);
if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0 return if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0;
} }
pub fn dup2(old: i32, new: i32) -> usize { pub fn dup2(old: i32, new: i32) -> usize {
arch.syscall2(arch.SYS_dup2, usize(old), usize(new)) return arch.syscall2(arch.SYS_dup2, usize(old), usize(new));
} }
pub fn chdir(path: &const u8) -> usize { pub fn chdir(path: &const u8) -> usize {
arch.syscall1(arch.SYS_chdir, @ptrToInt(path)) return arch.syscall1(arch.SYS_chdir, @ptrToInt(path));
} }
pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) -> usize { pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) -> usize {
arch.syscall3(arch.SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp)) return arch.syscall3(arch.SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp));
} }
pub fn fork() -> usize { pub fn fork() -> usize {
arch.syscall0(arch.SYS_fork) return arch.syscall0(arch.SYS_fork);
} }
pub fn getcwd(buf: &u8, size: usize) -> usize { pub fn getcwd(buf: &u8, size: usize) -> usize {
arch.syscall2(arch.SYS_getcwd, @ptrToInt(buf), size) return arch.syscall2(arch.SYS_getcwd, @ptrToInt(buf), size);
} }
pub fn getdents(fd: i32, dirp: &u8, count: usize) -> usize { pub fn getdents(fd: i32, dirp: &u8, count: usize) -> usize {
arch.syscall3(arch.SYS_getdents, usize(fd), @ptrToInt(dirp), count) return arch.syscall3(arch.SYS_getdents, usize(fd), @ptrToInt(dirp), count);
} }
pub fn isatty(fd: i32) -> bool { pub fn isatty(fd: i32) -> bool {
@ -420,123 +420,123 @@ pub fn isatty(fd: i32) -> bool {
} }
pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -> usize { pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -> usize {
arch.syscall3(arch.SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len) return arch.syscall3(arch.SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
} }
pub fn mkdir(path: &const u8, mode: u32) -> usize { pub fn mkdir(path: &const u8, mode: u32) -> usize {
arch.syscall2(arch.SYS_mkdir, @ptrToInt(path), mode) return arch.syscall2(arch.SYS_mkdir, @ptrToInt(path), mode);
} }
pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize)
-> usize -> usize
{ {
arch.syscall6(arch.SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd), return arch.syscall6(arch.SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd),
@bitCast(usize, offset)) @bitCast(usize, offset));
} }
pub fn munmap(address: &u8, length: usize) -> usize { pub fn munmap(address: &u8, length: usize) -> usize {
arch.syscall2(arch.SYS_munmap, @ptrToInt(address), length) return arch.syscall2(arch.SYS_munmap, @ptrToInt(address), length);
} }
pub fn read(fd: i32, buf: &u8, count: usize) -> usize { pub fn read(fd: i32, buf: &u8, count: usize) -> usize {
arch.syscall3(arch.SYS_read, usize(fd), @ptrToInt(buf), count) return arch.syscall3(arch.SYS_read, usize(fd), @ptrToInt(buf), count);
} }
pub fn rmdir(path: &const u8) -> usize { pub fn rmdir(path: &const u8) -> usize {
arch.syscall1(arch.SYS_rmdir, @ptrToInt(path)) return arch.syscall1(arch.SYS_rmdir, @ptrToInt(path));
} }
pub fn symlink(existing: &const u8, new: &const u8) -> usize { pub fn symlink(existing: &const u8, new: &const u8) -> usize {
arch.syscall2(arch.SYS_symlink, @ptrToInt(existing), @ptrToInt(new)) return arch.syscall2(arch.SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
} }
pub fn pread(fd: i32, buf: &u8, count: usize, offset: usize) -> usize { pub fn pread(fd: i32, buf: &u8, count: usize, offset: usize) -> usize {
arch.syscall4(arch.SYS_pread, usize(fd), @ptrToInt(buf), count, offset) return arch.syscall4(arch.SYS_pread, usize(fd), @ptrToInt(buf), count, offset);
} }
pub fn pipe(fd: &[2]i32) -> usize { pub fn pipe(fd: &[2]i32) -> usize {
pipe2(fd, 0) return pipe2(fd, 0);
} }
pub fn pipe2(fd: &[2]i32, flags: usize) -> usize { pub fn pipe2(fd: &[2]i32, flags: usize) -> usize {
arch.syscall2(arch.SYS_pipe2, @ptrToInt(fd), flags) return arch.syscall2(arch.SYS_pipe2, @ptrToInt(fd), flags);
} }
pub fn write(fd: i32, buf: &const u8, count: usize) -> usize { pub fn write(fd: i32, buf: &const u8, count: usize) -> usize {
arch.syscall3(arch.SYS_write, usize(fd), @ptrToInt(buf), count) return arch.syscall3(arch.SYS_write, usize(fd), @ptrToInt(buf), count);
} }
pub fn pwrite(fd: i32, buf: &const u8, count: usize, offset: usize) -> usize { pub fn pwrite(fd: i32, buf: &const u8, count: usize, offset: usize) -> usize {
arch.syscall4(arch.SYS_pwrite, usize(fd), @ptrToInt(buf), count, offset) return arch.syscall4(arch.SYS_pwrite, usize(fd), @ptrToInt(buf), count, offset);
} }
pub fn rename(old: &const u8, new: &const u8) -> usize { pub fn rename(old: &const u8, new: &const u8) -> usize {
arch.syscall2(arch.SYS_rename, @ptrToInt(old), @ptrToInt(new)) return arch.syscall2(arch.SYS_rename, @ptrToInt(old), @ptrToInt(new));
} }
pub fn open(path: &const u8, flags: u32, perm: usize) -> usize { pub fn open(path: &const u8, flags: u32, perm: usize) -> usize {
arch.syscall3(arch.SYS_open, @ptrToInt(path), flags, perm) return arch.syscall3(arch.SYS_open, @ptrToInt(path), flags, perm);
} }
pub fn create(path: &const u8, perm: usize) -> usize { pub fn create(path: &const u8, perm: usize) -> usize {
arch.syscall2(arch.SYS_creat, @ptrToInt(path), perm) return arch.syscall2(arch.SYS_creat, @ptrToInt(path), perm);
} }
pub fn openat(dirfd: i32, path: &const u8, flags: usize, mode: usize) -> usize { pub fn openat(dirfd: i32, path: &const u8, flags: usize, mode: usize) -> usize {
arch.syscall4(arch.SYS_openat, usize(dirfd), @ptrToInt(path), flags, mode) return arch.syscall4(arch.SYS_openat, usize(dirfd), @ptrToInt(path), flags, mode);
} }
pub fn close(fd: i32) -> usize { pub fn close(fd: i32) -> usize {
arch.syscall1(arch.SYS_close, usize(fd)) return arch.syscall1(arch.SYS_close, usize(fd));
} }
pub fn lseek(fd: i32, offset: isize, ref_pos: usize) -> usize { pub fn lseek(fd: i32, offset: isize, ref_pos: usize) -> usize {
arch.syscall3(arch.SYS_lseek, usize(fd), @bitCast(usize, offset), ref_pos) return arch.syscall3(arch.SYS_lseek, usize(fd), @bitCast(usize, offset), ref_pos);
} }
pub fn exit(status: i32) -> noreturn { pub fn exit(status: i32) -> noreturn {
_ = arch.syscall1(arch.SYS_exit, @bitCast(usize, isize(status))); _ = arch.syscall1(arch.SYS_exit, @bitCast(usize, isize(status)));
unreachable unreachable;
} }
pub fn getrandom(buf: &u8, count: usize, flags: u32) -> usize { pub fn getrandom(buf: &u8, count: usize, flags: u32) -> usize {
arch.syscall3(arch.SYS_getrandom, @ptrToInt(buf), count, usize(flags)) return arch.syscall3(arch.SYS_getrandom, @ptrToInt(buf), count, usize(flags));
} }
pub fn kill(pid: i32, sig: i32) -> usize { pub fn kill(pid: i32, sig: i32) -> usize {
arch.syscall2(arch.SYS_kill, @bitCast(usize, isize(pid)), usize(sig)) return arch.syscall2(arch.SYS_kill, @bitCast(usize, isize(pid)), usize(sig));
} }
pub fn unlink(path: &const u8) -> usize { pub fn unlink(path: &const u8) -> usize {
arch.syscall1(arch.SYS_unlink, @ptrToInt(path)) return arch.syscall1(arch.SYS_unlink, @ptrToInt(path));
} }
pub fn waitpid(pid: i32, status: &i32, options: i32) -> usize { pub fn waitpid(pid: i32, status: &i32, options: i32) -> usize {
arch.syscall4(arch.SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0) return arch.syscall4(arch.SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
} }
pub fn nanosleep(req: &const timespec, rem: ?&timespec) -> usize { pub fn nanosleep(req: &const timespec, rem: ?&timespec) -> usize {
arch.syscall2(arch.SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem)) return arch.syscall2(arch.SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem));
} }
pub fn setuid(uid: u32) -> usize { pub fn setuid(uid: u32) -> usize {
arch.syscall1(arch.SYS_setuid, uid) return arch.syscall1(arch.SYS_setuid, uid);
} }
pub fn setgid(gid: u32) -> usize { pub fn setgid(gid: u32) -> usize {
arch.syscall1(arch.SYS_setgid, gid) return arch.syscall1(arch.SYS_setgid, gid);
} }
pub fn setreuid(ruid: u32, euid: u32) -> usize { pub fn setreuid(ruid: u32, euid: u32) -> usize {
arch.syscall2(arch.SYS_setreuid, ruid, euid) return arch.syscall2(arch.SYS_setreuid, ruid, euid);
} }
pub fn setregid(rgid: u32, egid: u32) -> usize { pub fn setregid(rgid: u32, egid: u32) -> usize {
arch.syscall2(arch.SYS_setregid, rgid, egid) return arch.syscall2(arch.SYS_setregid, rgid, egid);
} }
pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) -> usize { pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) -> usize {
arch.syscall4(arch.SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG/8) return arch.syscall4(arch.SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG/8);
} }
pub fn sigaction(sig: u6, noalias act: &const Sigaction, noalias oact: ?&Sigaction) -> usize { pub fn sigaction(sig: u6, noalias act: &const Sigaction, noalias oact: ?&Sigaction) -> usize {
@ -652,69 +652,69 @@ pub const iovec = extern struct {
}; };
pub fn getsockname(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize { pub fn getsockname(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize {
arch.syscall3(arch.SYS_getsockname, usize(fd), @ptrToInt(addr), @ptrToInt(len)) return arch.syscall3(arch.SYS_getsockname, usize(fd), @ptrToInt(addr), @ptrToInt(len));
} }
pub fn getpeername(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize { pub fn getpeername(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize {
arch.syscall3(arch.SYS_getpeername, usize(fd), @ptrToInt(addr), @ptrToInt(len)) return arch.syscall3(arch.SYS_getpeername, usize(fd), @ptrToInt(addr), @ptrToInt(len));
} }
pub fn socket(domain: i32, socket_type: i32, protocol: i32) -> usize { pub fn socket(domain: i32, socket_type: i32, protocol: i32) -> usize {
arch.syscall3(arch.SYS_socket, usize(domain), usize(socket_type), usize(protocol)) return arch.syscall3(arch.SYS_socket, usize(domain), usize(socket_type), usize(protocol));
} }
pub fn setsockopt(fd: i32, level: i32, optname: i32, optval: &const u8, optlen: socklen_t) -> usize { pub fn setsockopt(fd: i32, level: i32, optname: i32, optval: &const u8, optlen: socklen_t) -> usize {
arch.syscall5(arch.SYS_setsockopt, usize(fd), usize(level), usize(optname), usize(optval), @ptrToInt(optlen)) return arch.syscall5(arch.SYS_setsockopt, usize(fd), usize(level), usize(optname), usize(optval), @ptrToInt(optlen));
} }
pub fn getsockopt(fd: i32, level: i32, optname: i32, noalias optval: &u8, noalias optlen: &socklen_t) -> usize { pub fn getsockopt(fd: i32, level: i32, optname: i32, noalias optval: &u8, noalias optlen: &socklen_t) -> usize {
arch.syscall5(arch.SYS_getsockopt, usize(fd), usize(level), usize(optname), @ptrToInt(optval), @ptrToInt(optlen)) return arch.syscall5(arch.SYS_getsockopt, usize(fd), usize(level), usize(optname), @ptrToInt(optval), @ptrToInt(optlen));
} }
pub fn sendmsg(fd: i32, msg: &const arch.msghdr, flags: u32) -> usize { pub fn sendmsg(fd: i32, msg: &const arch.msghdr, flags: u32) -> usize {
arch.syscall3(arch.SYS_sendmsg, usize(fd), @ptrToInt(msg), flags) return arch.syscall3(arch.SYS_sendmsg, usize(fd), @ptrToInt(msg), flags);
} }
pub fn connect(fd: i32, addr: &const sockaddr, len: socklen_t) -> usize { pub fn connect(fd: i32, addr: &const sockaddr, len: socklen_t) -> usize {
arch.syscall3(arch.SYS_connect, usize(fd), @ptrToInt(addr), usize(len)) return arch.syscall3(arch.SYS_connect, usize(fd), @ptrToInt(addr), usize(len));
} }
pub fn recvmsg(fd: i32, msg: &arch.msghdr, flags: u32) -> usize { pub fn recvmsg(fd: i32, msg: &arch.msghdr, flags: u32) -> usize {
arch.syscall3(arch.SYS_recvmsg, usize(fd), @ptrToInt(msg), flags) return arch.syscall3(arch.SYS_recvmsg, usize(fd), @ptrToInt(msg), flags);
} }
pub fn recvfrom(fd: i32, noalias buf: &u8, len: usize, flags: u32, pub fn recvfrom(fd: i32, noalias buf: &u8, len: usize, flags: u32,
noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) -> usize noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) -> usize
{ {
arch.syscall6(arch.SYS_recvfrom, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)) return arch.syscall6(arch.SYS_recvfrom, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
} }
pub fn shutdown(fd: i32, how: i32) -> usize { pub fn shutdown(fd: i32, how: i32) -> usize {
arch.syscall2(arch.SYS_shutdown, usize(fd), usize(how)) return arch.syscall2(arch.SYS_shutdown, usize(fd), usize(how));
} }
pub fn bind(fd: i32, addr: &const sockaddr, len: socklen_t) -> usize { pub fn bind(fd: i32, addr: &const sockaddr, len: socklen_t) -> usize {
arch.syscall3(arch.SYS_bind, usize(fd), @ptrToInt(addr), usize(len)) return arch.syscall3(arch.SYS_bind, usize(fd), @ptrToInt(addr), usize(len));
} }
pub fn listen(fd: i32, backlog: i32) -> usize { pub fn listen(fd: i32, backlog: i32) -> usize {
arch.syscall2(arch.SYS_listen, usize(fd), usize(backlog)) return arch.syscall2(arch.SYS_listen, usize(fd), usize(backlog));
} }
pub fn sendto(fd: i32, buf: &const u8, len: usize, flags: u32, addr: ?&const sockaddr, alen: socklen_t) -> usize { pub fn sendto(fd: i32, buf: &const u8, len: usize, flags: u32, addr: ?&const sockaddr, alen: socklen_t) -> usize {
arch.syscall6(arch.SYS_sendto, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), usize(alen)) return arch.syscall6(arch.SYS_sendto, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), usize(alen));
} }
pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) -> usize { pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) -> usize {
arch.syscall4(arch.SYS_socketpair, usize(domain), usize(socket_type), usize(protocol), @ptrToInt(&fd[0])) return arch.syscall4(arch.SYS_socketpair, usize(domain), usize(socket_type), usize(protocol), @ptrToInt(&fd[0]));
} }
pub fn accept(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize { pub fn accept(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize {
accept4(fd, addr, len, 0) return accept4(fd, addr, len, 0);
} }
pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags: u32) -> usize { pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags: u32) -> usize {
arch.syscall4(arch.SYS_accept4, usize(fd), @ptrToInt(addr), @ptrToInt(len), flags) return arch.syscall4(arch.SYS_accept4, usize(fd), @ptrToInt(addr), @ptrToInt(len), flags);
} }
// error NameTooLong; // error NameTooLong;
@ -749,7 +749,7 @@ pub const Stat = arch.Stat;
pub const timespec = arch.timespec; pub const timespec = arch.timespec;
pub fn fstat(fd: i32, stat_buf: &Stat) -> usize { pub fn fstat(fd: i32, stat_buf: &Stat) -> usize {
arch.syscall2(arch.SYS_fstat, usize(fd), @ptrToInt(stat_buf)) return arch.syscall2(arch.SYS_fstat, usize(fd), @ptrToInt(stat_buf));
} }
pub const epoll_data = u64; pub const epoll_data = u64;
@ -760,19 +760,19 @@ pub const epoll_event = extern struct {
}; };
pub fn epoll_create() -> usize { pub fn epoll_create() -> usize {
arch.syscall1(arch.SYS_epoll_create, usize(1)) return arch.syscall1(arch.SYS_epoll_create, usize(1));
} }
pub fn epoll_ctl(epoll_fd: i32, op: i32, fd: i32, ev: &epoll_event) -> usize { pub fn epoll_ctl(epoll_fd: i32, op: i32, fd: i32, ev: &epoll_event) -> usize {
arch.syscall4(arch.SYS_epoll_ctl, usize(epoll_fd), usize(op), usize(fd), @ptrToInt(ev)) return arch.syscall4(arch.SYS_epoll_ctl, usize(epoll_fd), usize(op), usize(fd), @ptrToInt(ev));
} }
pub fn epoll_wait(epoll_fd: i32, events: &epoll_event, maxevents: i32, timeout: i32) -> usize { pub fn epoll_wait(epoll_fd: i32, events: &epoll_event, maxevents: i32, timeout: i32) -> usize {
arch.syscall4(arch.SYS_epoll_wait, usize(epoll_fd), @ptrToInt(events), usize(maxevents), usize(timeout)) return arch.syscall4(arch.SYS_epoll_wait, usize(epoll_fd), @ptrToInt(events), usize(maxevents), usize(timeout));
} }
pub fn timerfd_create(clockid: i32, flags: u32) -> usize { pub fn timerfd_create(clockid: i32, flags: u32) -> usize {
arch.syscall2(arch.SYS_timerfd_create, usize(clockid), usize(flags)) return arch.syscall2(arch.SYS_timerfd_create, usize(clockid), usize(flags));
} }
pub const itimerspec = extern struct { pub const itimerspec = extern struct {
@ -781,11 +781,11 @@ pub const itimerspec = extern struct {
}; };
pub fn timerfd_gettime(fd: i32, curr_value: &itimerspec) -> usize { pub fn timerfd_gettime(fd: i32, curr_value: &itimerspec) -> usize {
arch.syscall2(arch.SYS_timerfd_gettime, usize(fd), @ptrToInt(curr_value)) return arch.syscall2(arch.SYS_timerfd_gettime, usize(fd), @ptrToInt(curr_value));
} }
pub fn timerfd_settime(fd: i32, flags: u32, new_value: &const itimerspec, old_value: ?&itimerspec) -> usize { pub fn timerfd_settime(fd: i32, flags: u32, new_value: &const itimerspec, old_value: ?&itimerspec) -> usize {
arch.syscall4(arch.SYS_timerfd_settime, usize(fd), usize(flags), @ptrToInt(new_value), @ptrToInt(old_value)) return arch.syscall4(arch.SYS_timerfd_settime, usize(fd), usize(flags), @ptrToInt(new_value), @ptrToInt(old_value));
} }
test "import linux_test" { test "import linux_test" {

View File

@ -371,52 +371,52 @@ pub const F_GETOWN_EX = 16;
pub const F_GETOWNER_UIDS = 17; pub const F_GETOWNER_UIDS = 17;
pub fn syscall0(number: usize) -> usize { pub fn syscall0(number: usize) -> usize {
asm volatile ("syscall" return asm volatile ("syscall"
: [ret] "={rax}" (-> usize) : [ret] "={rax}" (-> usize)
: [number] "{rax}" (number) : [number] "{rax}" (number)
: "rcx", "r11") : "rcx", "r11");
} }
pub fn syscall1(number: usize, arg1: usize) -> usize { pub fn syscall1(number: usize, arg1: usize) -> usize {
asm volatile ("syscall" return asm volatile ("syscall"
: [ret] "={rax}" (-> usize) : [ret] "={rax}" (-> usize)
: [number] "{rax}" (number), : [number] "{rax}" (number),
[arg1] "{rdi}" (arg1) [arg1] "{rdi}" (arg1)
: "rcx", "r11") : "rcx", "r11");
} }
pub fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { pub fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize {
asm volatile ("syscall" return asm volatile ("syscall"
: [ret] "={rax}" (-> usize) : [ret] "={rax}" (-> usize)
: [number] "{rax}" (number), : [number] "{rax}" (number),
[arg1] "{rdi}" (arg1), [arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2) [arg2] "{rsi}" (arg2)
: "rcx", "r11") : "rcx", "r11");
} }
pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize {
asm volatile ("syscall" return asm volatile ("syscall"
: [ret] "={rax}" (-> usize) : [ret] "={rax}" (-> usize)
: [number] "{rax}" (number), : [number] "{rax}" (number),
[arg1] "{rdi}" (arg1), [arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2), [arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3) [arg3] "{rdx}" (arg3)
: "rcx", "r11") : "rcx", "r11");
} }
pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> usize { pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> usize {
asm volatile ("syscall" return asm volatile ("syscall"
: [ret] "={rax}" (-> usize) : [ret] "={rax}" (-> usize)
: [number] "{rax}" (number), : [number] "{rax}" (number),
[arg1] "{rdi}" (arg1), [arg1] "{rdi}" (arg1),
[arg2] "{rsi}" (arg2), [arg2] "{rsi}" (arg2),
[arg3] "{rdx}" (arg3), [arg3] "{rdx}" (arg3),
[arg4] "{r10}" (arg4) [arg4] "{r10}" (arg4)
: "rcx", "r11") : "rcx", "r11");
} }
pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> usize { pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> usize {
asm volatile ("syscall" return asm volatile ("syscall"
: [ret] "={rax}" (-> usize) : [ret] "={rax}" (-> usize)
: [number] "{rax}" (number), : [number] "{rax}" (number),
[arg1] "{rdi}" (arg1), [arg1] "{rdi}" (arg1),
@ -424,13 +424,13 @@ pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz
[arg3] "{rdx}" (arg3), [arg3] "{rdx}" (arg3),
[arg4] "{r10}" (arg4), [arg4] "{r10}" (arg4),
[arg5] "{r8}" (arg5) [arg5] "{r8}" (arg5)
: "rcx", "r11") : "rcx", "r11");
} }
pub fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, pub fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize,
arg5: usize, arg6: usize) -> usize arg5: usize, arg6: usize) -> usize
{ {
asm volatile ("syscall" return asm volatile ("syscall"
: [ret] "={rax}" (-> usize) : [ret] "={rax}" (-> usize)
: [number] "{rax}" (number), : [number] "{rax}" (number),
[arg1] "{rdi}" (arg1), [arg1] "{rdi}" (arg1),
@ -439,14 +439,14 @@ pub fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz
[arg4] "{r10}" (arg4), [arg4] "{r10}" (arg4),
[arg5] "{r8}" (arg5), [arg5] "{r8}" (arg5),
[arg6] "{r9}" (arg6) [arg6] "{r9}" (arg6)
: "rcx", "r11") : "rcx", "r11");
} }
pub nakedcc fn restore_rt() { pub nakedcc fn restore_rt() {
asm volatile ("syscall" return asm volatile ("syscall"
: :
: [number] "{rax}" (usize(SYS_rt_sigreturn)) : [number] "{rax}" (usize(SYS_rt_sigreturn))
: "rcx", "r11") : "rcx", "r11");
} }

View File

@ -749,21 +749,19 @@ pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8)
const resolved_to = %return resolveWindows(allocator, [][]const u8{to}); const resolved_to = %return resolveWindows(allocator, [][]const u8{to});
defer if (clean_up_resolved_to) allocator.free(resolved_to); defer if (clean_up_resolved_to) allocator.free(resolved_to);
const result_is_to = if (drive(resolved_to)) |to_drive| { const result_is_to = if (drive(resolved_to)) |to_drive|
if (drive(resolved_from)) |from_drive| { if (drive(resolved_from)) |from_drive|
asciiUpper(from_drive[0]) != asciiUpper(to_drive[0]) asciiUpper(from_drive[0]) != asciiUpper(to_drive[0])
} else { else
true true
} else if (networkShare(resolved_to)) |to_ns|
} else if (networkShare(resolved_to)) |to_ns| { if (networkShare(resolved_from)) |from_ns|
if (networkShare(resolved_from)) |from_ns| {
!networkShareServersEql(to_ns, from_ns) !networkShareServersEql(to_ns, from_ns)
} else { else
true true
} else
} else { unreachable;
unreachable
};
if (result_is_to) { if (result_is_to) {
clean_up_resolved_to = false; clean_up_resolved_to = false;
return resolved_to; return resolved_to;
@ -964,14 +962,16 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
// windows returns \\?\ prepended to the path // windows returns \\?\ prepended to the path
// we strip it because nobody wants \\?\ prepended to their path // we strip it because nobody wants \\?\ prepended to their path
const final_len = if (result > 4 and mem.startsWith(u8, buf, "\\\\?\\")) { const final_len = x: {
var i: usize = 4; if (result > 4 and mem.startsWith(u8, buf, "\\\\?\\")) {
while (i < result) : (i += 1) { var i: usize = 4;
buf[i - 4] = buf[i]; while (i < result) : (i += 1) {
buf[i - 4] = buf[i];
}
break :x result - 4;
} else {
break :x result;
} }
result - 4
} else {
result
}; };
return allocator.shrink(u8, buf, final_len); return allocator.shrink(u8, buf, final_len);

View File

@ -122,7 +122,7 @@ pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_m
/// Caller must free result. /// Caller must free result.
pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) -> %[]u8 { pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) -> %[]u8 {
// count bytes needed // count bytes needed
const bytes_needed = { const bytes_needed = x: {
var bytes_needed: usize = 1; // 1 for the final null byte var bytes_needed: usize = 1; // 1 for the final null byte
var it = env_map.iterator(); var it = env_map.iterator();
while (it.next()) |pair| { while (it.next()) |pair| {
@ -130,7 +130,7 @@ pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap)
// +1 for null byte // +1 for null byte
bytes_needed += pair.key.len + pair.value.len + 2; bytes_needed += pair.key.len + pair.value.len + 2;
} }
bytes_needed break :x bytes_needed;
}; };
const result = %return allocator.alloc(u8, bytes_needed); const result = %return allocator.alloc(u8, bytes_needed);
%defer allocator.free(result); %defer allocator.free(result);

View File

@ -28,9 +28,9 @@ pub const Rand = struct {
/// Initialize random state with the given seed. /// Initialize random state with the given seed.
pub fn init(seed: usize) -> Rand { pub fn init(seed: usize) -> Rand {
Rand { return Rand {
.rng = Rng.init(seed), .rng = Rng.init(seed),
} };
} }
/// Get an integer or boolean with random bits. /// Get an integer or boolean with random bits.
@ -78,13 +78,13 @@ pub const Rand = struct {
const end_uint = uint(end); const end_uint = uint(end);
const total_range = math.absCast(start) + end_uint; const total_range = math.absCast(start) + end_uint;
const value = r.range(uint, 0, total_range); const value = r.range(uint, 0, total_range);
const result = if (value < end_uint) { const result = if (value < end_uint) x: {
T(value) break :x T(value);
} else if (value == end_uint) { } else if (value == end_uint) x: {
start break :x start;
} else { } else x: {
// Can't overflow because the range is over signed ints // Can't overflow because the range is over signed ints
%%math.negateCast(value - end_uint) break :x %%math.negateCast(value - end_uint);
}; };
return result; return result;
} else { } else {
@ -114,13 +114,13 @@ pub const Rand = struct {
// const rand_bits = r.rng.scalar(int) & mask; // const rand_bits = r.rng.scalar(int) & mask;
// return @float_compose(T, false, 0, rand_bits) - 1.0 // return @float_compose(T, false, 0, rand_bits) - 1.0
const int_type = @IntType(false, @sizeOf(T) * 8); const int_type = @IntType(false, @sizeOf(T) * 8);
const precision = if (T == f32) { const precision = if (T == f32)
16777216 16777216
} else if (T == f64) { else if (T == f64)
9007199254740992 9007199254740992
} else { else
@compileError("unknown floating point type") @compileError("unknown floating point type")
}; ;
return T(r.range(int_type, 0, precision)) / T(precision); return T(r.range(int_type, 0, precision)) / T(precision);
} }
}; };
@ -133,7 +133,7 @@ fn MersenneTwister(
comptime t: math.Log2Int(int), comptime c: int, comptime t: math.Log2Int(int), comptime c: int,
comptime l: math.Log2Int(int), comptime f: int) -> type comptime l: math.Log2Int(int), comptime f: int) -> type
{ {
struct { return struct {
const Self = this; const Self = this;
array: [n]int, array: [n]int,
@ -189,7 +189,7 @@ fn MersenneTwister(
return x; return x;
} }
} };
} }
test "rand float 32" { test "rand float 32" {

View File

@ -355,7 +355,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
// these values will be pulled out to the start of A // these values will be pulled out to the start of A
last = A.start; last = A.start;
count = 1; count = 1;
while (count < find) : ({last = index; count += 1}) { while (count < find) : ({last = index; count += 1;}) {
index = findLastForward(T, items, items[last], Range.init(last + 1, A.end), lessThan, find - count); index = findLastForward(T, items, items[last], Range.init(last + 1, A.end), lessThan, find - count);
if (index == A.end) break; if (index == A.end) break;
} }
@ -410,7 +410,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
// these values will be pulled out to the end of B // these values will be pulled out to the end of B
last = B.end - 1; last = B.end - 1;
count = 1; count = 1;
while (count < find) : ({last = index - 1; count += 1}) { while (count < find) : ({last = index - 1; count += 1;}) {
index = findFirstBackward(T, items, items[last], Range.init(B.start, last), lessThan, find - count); index = findFirstBackward(T, items, items[last], Range.init(B.start, last), lessThan, find - count);
if (index == B.start) break; if (index == B.start) break;
} }
@ -547,7 +547,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
// swap the first value of each A block with the value in buffer1 // swap the first value of each A block with the value in buffer1
var indexA = buffer1.start; var indexA = buffer1.start;
index = firstA.end; index = firstA.end;
while (index < blockA.end) : ({indexA += 1; index += block_size}) { while (index < blockA.end) : ({indexA += 1; index += block_size;}) {
mem.swap(T, &items[indexA], &items[index]); mem.swap(T, &items[indexA], &items[index]);
} }
@ -1093,7 +1093,7 @@ test "another sort case" {
var arr = []i32{ 5, 3, 1, 2, 4 }; var arr = []i32{ 5, 3, 1, 2, 4 };
sort(i32, arr[0..], i32asc); sort(i32, arr[0..], i32asc);
assert(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 })) assert(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 }));
} }
test "sort fuzz testing" { test "sort fuzz testing" {

View File

@ -45,21 +45,17 @@ pub fn main() -> %void {
var stderr_file = io.getStdErr(); var stderr_file = io.getStdErr();
var stderr_file_stream: io.FileOutStream = undefined; var stderr_file_stream: io.FileOutStream = undefined;
var stderr_stream: %&io.OutStream = if (stderr_file) |*f| { var stderr_stream: %&io.OutStream = if (stderr_file) |*f| x: {
stderr_file_stream = io.FileOutStream.init(f); stderr_file_stream = io.FileOutStream.init(f);
&stderr_file_stream.stream break :x &stderr_file_stream.stream;
} else |err| { } else |err| err;
err
};
var stdout_file = io.getStdOut(); var stdout_file = io.getStdOut();
var stdout_file_stream: io.FileOutStream = undefined; var stdout_file_stream: io.FileOutStream = undefined;
var stdout_stream: %&io.OutStream = if (stdout_file) |*f| { var stdout_stream: %&io.OutStream = if (stdout_file) |*f| x: {
stdout_file_stream = io.FileOutStream.init(f); stdout_file_stream = io.FileOutStream.init(f);
&stdout_file_stream.stream break :x &stdout_file_stream.stream;
} else |err| { } else |err| err;
err
};
while (arg_it.next(allocator)) |err_or_arg| { while (arg_it.next(allocator)) |err_or_arg| {
const arg = %return unwrapArg(err_or_arg); const arg = %return unwrapArg(err_or_arg);

View File

@ -46,15 +46,15 @@ extern fn __stack_chk_fail() -> noreturn {
const math = @import("../math/index.zig"); const math = @import("../math/index.zig");
export fn fmodf(x: f32, y: f32) -> f32 { generic_fmod(f32, x, y) } export fn fmodf(x: f32, y: f32) -> f32 { return generic_fmod(f32, x, y); }
export fn fmod(x: f64, y: f64) -> f64 { generic_fmod(f64, x, y) } export fn fmod(x: f64, y: f64) -> f64 { return generic_fmod(f64, x, y); }
// TODO add intrinsics for these (and probably the double version too) // TODO add intrinsics for these (and probably the double version too)
// and have the math stuff use the intrinsic. same as @mod and @rem // and have the math stuff use the intrinsic. same as @mod and @rem
export fn floorf(x: f32) -> f32 { math.floor(x) } export fn floorf(x: f32) -> f32 { return math.floor(x); }
export fn ceilf(x: f32) -> f32 { math.ceil(x) } export fn ceilf(x: f32) -> f32 { return math.ceil(x); }
export fn floor(x: f64) -> f64 { math.floor(x) } export fn floor(x: f64) -> f64 { return math.floor(x); }
export fn ceil(x: f64) -> f64 { math.ceil(x) } export fn ceil(x: f64) -> f64 { return math.ceil(x); }
fn generic_fmod(comptime T: type, x: T, y: T) -> T { fn generic_fmod(comptime T: type, x: T, y: T) -> T {
@setDebugSafety(this, false); @setDebugSafety(this, false);
@ -84,7 +84,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) -> T {
// normalize x and y // normalize x and y
if (ex == 0) { if (ex == 0) {
i = ux << exp_bits; i = ux << exp_bits;
while (i >> bits_minus_1 == 0) : ({ex -= 1; i <<= 1}) {} while (i >> bits_minus_1 == 0) : (b: {ex -= 1; break :b i <<= 1;}) {}
ux <<= log2uint(@bitCast(u32, -ex + 1)); ux <<= log2uint(@bitCast(u32, -ex + 1));
} else { } else {
ux &= @maxValue(uint) >> exp_bits; ux &= @maxValue(uint) >> exp_bits;
@ -92,7 +92,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) -> T {
} }
if (ey == 0) { if (ey == 0) {
i = uy << exp_bits; i = uy << exp_bits;
while (i >> bits_minus_1 == 0) : ({ey -= 1; i <<= 1}) {} while (i >> bits_minus_1 == 0) : (b: {ey -= 1; break :b i <<= 1;}) {}
uy <<= log2uint(@bitCast(u32, -ey + 1)); uy <<= log2uint(@bitCast(u32, -ey + 1));
} else { } else {
uy &= @maxValue(uint) >> exp_bits; uy &= @maxValue(uint) >> exp_bits;
@ -115,7 +115,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) -> T {
return 0 * x; return 0 * x;
ux = i; ux = i;
} }
while (ux >> digits == 0) : ({ux <<= 1; ex -= 1}) {} while (ux >> digits == 0) : (b: {ux <<= 1; break :b ex -= 1;}) {}
// scale result up // scale result up
if (ex > 0) { if (ex > 0) {

View File

@ -38,27 +38,25 @@ pub extern fn __letf2(a: f128, b: f128) -> c_int {
// If at least one of a and b is positive, we get the same result comparing // If at least one of a and b is positive, we get the same result comparing
// a and b as signed integers as we would with a floating-point compare. // a and b as signed integers as we would with a floating-point compare.
return if ((aInt & bInt) >= 0) { return if ((aInt & bInt) >= 0)
if (aInt < bInt) { if (aInt < bInt)
LE_LESS LE_LESS
} else if (aInt == bInt) { else if (aInt == bInt)
LE_EQUAL LE_EQUAL
} else { else
LE_GREATER LE_GREATER
} else
} else {
// Otherwise, both are negative, so we need to flip the sense of the // Otherwise, both are negative, so we need to flip the sense of the
// comparison to get the correct result. (This assumes a twos- or ones- // comparison to get the correct result. (This assumes a twos- or ones-
// complement integer representation; if integers are represented in a // complement integer representation; if integers are represented in a
// sign-magnitude representation, then this flip is incorrect). // sign-magnitude representation, then this flip is incorrect).
if (aInt > bInt) { if (aInt > bInt)
LE_LESS LE_LESS
} else if (aInt == bInt) { else if (aInt == bInt)
LE_EQUAL LE_EQUAL
} else { else
LE_GREATER LE_GREATER
} ;
};
} }
// TODO https://github.com/zig-lang/zig/issues/305 // TODO https://github.com/zig-lang/zig/issues/305
@ -78,23 +76,21 @@ pub extern fn __getf2(a: f128, b: f128) -> c_int {
if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED; if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
if ((aAbs | bAbs) == 0) return GE_EQUAL; if ((aAbs | bAbs) == 0) return GE_EQUAL;
return if ((aInt & bInt) >= 0) { return if ((aInt & bInt) >= 0)
if (aInt < bInt) { if (aInt < bInt)
GE_LESS GE_LESS
} else if (aInt == bInt) { else if (aInt == bInt)
GE_EQUAL GE_EQUAL
} else { else
GE_GREATER GE_GREATER
} else
} else { if (aInt > bInt)
if (aInt > bInt) {
GE_LESS GE_LESS
} else if (aInt == bInt) { else if (aInt == bInt)
GE_EQUAL GE_EQUAL
} else { else
GE_GREATER GE_GREATER
} ;
};
} }
pub extern fn __unordtf2(a: f128, b: f128) -> c_int { pub extern fn __unordtf2(a: f128, b: f128) -> c_int {

View File

@ -10,7 +10,7 @@ test "global variable alignment" {
assert(@typeOf(slice) == []align(4) u8); assert(@typeOf(slice) == []align(4) u8);
} }
fn derp() align(@sizeOf(usize) * 2) -> i32 { 1234 } fn derp() align(@sizeOf(usize) * 2) -> i32 { return 1234; }
fn noop1() align(1) {} fn noop1() align(1) {}
fn noop4() align(4) {} fn noop4() align(4) {}
@ -53,14 +53,14 @@ test "implicitly decreasing pointer alignment" {
assert(addUnaligned(&a, &b) == 7); assert(addUnaligned(&a, &b) == 7);
} }
fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) -> u32 { *a + *b } fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) -> u32 { return *a + *b; }
test "implicitly decreasing slice alignment" { test "implicitly decreasing slice alignment" {
const a: u32 align(4) = 3; const a: u32 align(4) = 3;
const b: u32 align(8) = 4; const b: u32 align(8) = 4;
assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7); assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7);
} }
fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) -> u32 { a[0] + b[0] } fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) -> u32 { return a[0] + b[0]; }
test "specifying alignment allows pointer cast" { test "specifying alignment allows pointer cast" {
testBytesAlign(0x33); testBytesAlign(0x33);
@ -115,20 +115,20 @@ fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) -> i32, answer: i32) {
assert(ptr() == answer); assert(ptr() == answer);
} }
fn alignedSmall() align(8) -> i32 { 1234 } fn alignedSmall() align(8) -> i32 { return 1234; }
fn alignedBig() align(16) -> i32 { 5678 } fn alignedBig() align(16) -> i32 { return 5678; }
test "@alignCast functions" { test "@alignCast functions" {
assert(fnExpectsOnly1(simple4) == 0x19); assert(fnExpectsOnly1(simple4) == 0x19);
} }
fn fnExpectsOnly1(ptr: fn()align(1) -> i32) -> i32 { fn fnExpectsOnly1(ptr: fn()align(1) -> i32) -> i32 {
fnExpects4(@alignCast(4, ptr)) return fnExpects4(@alignCast(4, ptr));
} }
fn fnExpects4(ptr: fn()align(4) -> i32) -> i32 { fn fnExpects4(ptr: fn()align(4) -> i32) -> i32 {
ptr() return ptr();
} }
fn simple4() align(4) -> i32 { 0x19 } fn simple4() align(4) -> i32 { return 0x19; }
test "generic function with align param" { test "generic function with align param" {
@ -137,7 +137,7 @@ test "generic function with align param" {
assert(whyWouldYouEverDoThis(8) == 0x1); assert(whyWouldYouEverDoThis(8) == 0x1);
} }
fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) -> u8 { 0x1 } fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) -> u8 { return 0x1; }
test "@ptrCast preserves alignment of bigger source" { test "@ptrCast preserves alignment of bigger source" {

View File

@ -22,7 +22,7 @@ test "arrays" {
assert(getArrayLen(array) == 5); assert(getArrayLen(array) == 5);
} }
fn getArrayLen(a: []const u32) -> usize { fn getArrayLen(a: []const u32) -> usize {
a.len return a.len;
} }
test "void arrays" { test "void arrays" {
@ -41,7 +41,7 @@ test "array literal" {
} }
test "array dot len const expr" { test "array dot len const expr" {
assert(comptime {some_array.len == 4}); assert(comptime x: {break :x some_array.len == 4;});
} }
const ArrayDotLenConstExpr = struct { const ArrayDotLenConstExpr = struct {

View File

@ -10,5 +10,5 @@ fn testBitCast_i32_u32() {
assert(conv2(@maxValue(u32)) == -1); assert(conv2(@maxValue(u32)) == -1);
} }
fn conv(x: i32) -> u32 { @bitCast(u32, x) } fn conv(x: i32) -> u32 { return @bitCast(u32, x); }
fn conv2(x: u32) -> i32 { @bitCast(i32, x) } fn conv2(x: u32) -> i32 { return @bitCast(i32, x); }

View File

@ -22,7 +22,7 @@ test "bool cmp" {
assert(testBoolCmp(true, false) == false); assert(testBoolCmp(true, false) == false);
} }
fn testBoolCmp(a: bool, b: bool) -> bool { fn testBoolCmp(a: bool, b: bool) -> bool {
a == b return a == b;
} }
const global_f = false; const global_f = false;

View File

@ -50,7 +50,7 @@ test "peer resolve arrays of different size to const slice" {
comptime assert(mem.eql(u8, boolToStr(false), "false")); comptime assert(mem.eql(u8, boolToStr(false), "false"));
} }
fn boolToStr(b: bool) -> []const u8 { fn boolToStr(b: bool) -> []const u8 {
if (b) "true" else "false" return if (b) "true" else "false";
} }
@ -239,17 +239,17 @@ test "peer type resolution: error and [N]T" {
error BadValue; error BadValue;
fn testPeerErrorAndArray(x: u8) -> %[]const u8 { fn testPeerErrorAndArray(x: u8) -> %[]const u8 {
switch (x) { return switch (x) {
0x00 => "OK", 0x00 => "OK",
else => error.BadValue, else => error.BadValue,
} };
} }
fn testPeerErrorAndArray2(x: u8) -> %[]const u8 { fn testPeerErrorAndArray2(x: u8) -> %[]const u8 {
switch (x) { return switch (x) {
0x00 => "OK", 0x00 => "OK",
0x01 => "OKK", 0x01 => "OKK",
else => error.BadValue, else => error.BadValue,
} };
} }
test "explicit cast float number literal to integer if no fraction component" { test "explicit cast float number literal to integer if no fraction component" {
@ -269,11 +269,11 @@ fn testCast128() {
} }
fn cast128Int(x: f128) -> u128 { fn cast128Int(x: f128) -> u128 {
@bitCast(u128, x) return @bitCast(u128, x);
} }
fn cast128Float(x: u128) -> f128 { fn cast128Float(x: u128) -> f128 {
@bitCast(f128, x) return @bitCast(f128, x);
} }
test "const slice widen cast" { test "const slice widen cast" {

View File

@ -7,9 +7,9 @@ error FalseNotAllowed;
fn runSomeErrorDefers(x: bool) -> %bool { fn runSomeErrorDefers(x: bool) -> %bool {
index = 0; index = 0;
defer {result[index] = 'a'; index += 1;}; defer {result[index] = 'a'; index += 1;}
%defer {result[index] = 'b'; index += 1;}; %defer {result[index] = 'b'; index += 1;}
defer {result[index] = 'c'; index += 1;}; defer {result[index] = 'c'; index += 1;}
return if (x) x else error.FalseNotAllowed; return if (x) x else error.FalseNotAllowed;
} }
@ -18,9 +18,9 @@ test "mixing normal and error defers" {
assert(result[0] == 'c'); assert(result[0] == 'c');
assert(result[1] == 'a'); assert(result[1] == 'a');
const ok = runSomeErrorDefers(false) %% |err| { const ok = runSomeErrorDefers(false) %% |err| x: {
assert(err == error.FalseNotAllowed); assert(err == error.FalseNotAllowed);
true break :x true;
}; };
assert(ok); assert(ok);
assert(result[0] == 'c'); assert(result[0] == 'c');
@ -41,5 +41,5 @@ fn testBreakContInDefer(x: usize) {
if (i == 5) break; if (i == 5) break;
} }
assert(i == 5); assert(i == 5);
}; }
} }

View File

@ -41,7 +41,7 @@ const Bar = enum {
}; };
fn returnAnInt(x: i32) -> Foo { fn returnAnInt(x: i32) -> Foo {
Foo { .One = x } return Foo { .One = x };
} }

View File

@ -8,9 +8,9 @@ const ET = union(enum) {
pub fn print(a: &const ET, buf: []u8) -> %usize { pub fn print(a: &const ET, buf: []u8) -> %usize {
return switch (*a) { return switch (*a) {
ET.SINT => |x| { fmt.formatIntBuf(buf, x, 10, false, 0) }, ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
ET.UINT => |x| { fmt.formatIntBuf(buf, x, 10, false, 0) }, ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
} };
} }
}; };

View File

@ -3,7 +3,7 @@ const mem = @import("std").mem;
pub fn foo() -> %i32 { pub fn foo() -> %i32 {
const x = %return bar(); const x = %return bar();
return x + 1 return x + 1;
} }
pub fn bar() -> %i32 { pub fn bar() -> %i32 {
@ -21,7 +21,7 @@ test "error wrapping" {
error ItBroke; error ItBroke;
fn gimmeItBroke() -> []const u8 { fn gimmeItBroke() -> []const u8 {
@errorName(error.ItBroke) return @errorName(error.ItBroke);
} }
test "@errorName" { test "@errorName" {
@ -48,7 +48,7 @@ error AnError;
error AnError; error AnError;
error SecondError; error SecondError;
fn shouldBeNotEqual(a: error, b: error) { fn shouldBeNotEqual(a: error, b: error) {
if (a == b) unreachable if (a == b) unreachable;
} }
@ -60,11 +60,7 @@ test "error binary operator" {
} }
error ItBroke; error ItBroke;
fn errBinaryOperatorG(x: bool) -> %isize { fn errBinaryOperatorG(x: bool) -> %isize {
if (x) { return if (x) error.ItBroke else isize(10);
error.ItBroke
} else {
isize(10)
}
} }
@ -72,7 +68,7 @@ test "unwrap simple value from error" {
const i = %%unwrapSimpleValueFromErrorDo(); const i = %%unwrapSimpleValueFromErrorDo();
assert(i == 13); assert(i == 13);
} }
fn unwrapSimpleValueFromErrorDo() -> %isize { 13 } fn unwrapSimpleValueFromErrorDo() -> %isize { return 13; }
test "error return in assignment" { test "error return in assignment" {

View File

@ -44,7 +44,7 @@ test "static function evaluation" {
assert(statically_added_number == 3); assert(statically_added_number == 3);
} }
const statically_added_number = staticAdd(1, 2); const statically_added_number = staticAdd(1, 2);
fn staticAdd(a: i32, b: i32) -> i32 { a + b } fn staticAdd(a: i32, b: i32) -> i32 { return a + b; }
test "const expr eval on single expr blocks" { test "const expr eval on single expr blocks" {
@ -54,10 +54,10 @@ test "const expr eval on single expr blocks" {
fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) -> i32 { fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) -> i32 {
const literal = 3; const literal = 3;
const result = if (b) { const result = if (b) b: {
literal break :b literal;
} else { } else b: {
x break :b x;
}; };
return result; return result;
@ -94,9 +94,9 @@ pub const Vec3 = struct {
data: [3]f32, data: [3]f32,
}; };
pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 { pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
Vec3 { return Vec3 {
.data = []f32 { x, y, z, }, .data = []f32 { x, y, z, },
} };
} }
@ -176,7 +176,7 @@ fn max(comptime T: type, a: T, b: T) -> T {
} }
} }
fn letsTryToCompareBools(a: bool, b: bool) -> bool { fn letsTryToCompareBools(a: bool, b: bool) -> bool {
max(bool, a, b) return max(bool, a, b);
} }
test "inlined block and runtime block phi" { test "inlined block and runtime block phi" {
assert(letsTryToCompareBools(true, true)); assert(letsTryToCompareBools(true, true));
@ -202,9 +202,9 @@ const cmd_fns = []CmdFn{
CmdFn {.name = "two", .func = two}, CmdFn {.name = "two", .func = two},
CmdFn {.name = "three", .func = three}, CmdFn {.name = "three", .func = three},
}; };
fn one(value: i32) -> i32 { value + 1 } fn one(value: i32) -> i32 { return value + 1; }
fn two(value: i32) -> i32 { value + 2 } fn two(value: i32) -> i32 { return value + 2; }
fn three(value: i32) -> i32 { value + 3 } fn three(value: i32) -> i32 { return value + 3; }
fn performFn(comptime prefix_char: u8, start_value: i32) -> i32 { fn performFn(comptime prefix_char: u8, start_value: i32) -> i32 {
var result: i32 = start_value; var result: i32 = start_value;
@ -317,12 +317,12 @@ test "create global array with for loop" {
assert(global_array[9] == 9 * 9); assert(global_array[9] == 9 * 9);
} }
const global_array = { const global_array = x: {
var result: [10]usize = undefined; var result: [10]usize = undefined;
for (result) |*item, index| { for (result) |*item, index| {
*item = index * index; *item = index * index;
} }
result break :x result;
}; };
test "compile-time downcast when the bits fit" { test "compile-time downcast when the bits fit" {

View File

@ -4,7 +4,7 @@ test "params" {
assert(testParamsAdd(22, 11) == 33); assert(testParamsAdd(22, 11) == 33);
} }
fn testParamsAdd(a: i32, b: i32) -> i32 { fn testParamsAdd(a: i32, b: i32) -> i32 {
a + b return a + b;
} }
@ -22,7 +22,7 @@ test "void parameters" {
} }
fn voidFun(a: i32, b: void, c: i32, d: void) { fn voidFun(a: i32, b: void, c: i32, d: void) {
const v = b; const v = b;
const vv: void = if (a == 1) {v} else {}; const vv: void = if (a == 1) v else {};
assert(a + c == 3); assert(a + c == 3);
return vv; return vv;
} }
@ -45,9 +45,9 @@ test "separate block scopes" {
assert(no_conflict == 5); assert(no_conflict == 5);
} }
const c = { const c = x: {
const no_conflict = i32(10); const no_conflict = i32(10);
no_conflict break :x no_conflict;
}; };
assert(c == 10); assert(c == 10);
} }
@ -73,7 +73,7 @@ test "implicit cast function unreachable return" {
fn wantsFnWithVoid(f: fn()) { } fn wantsFnWithVoid(f: fn()) { }
fn fnWithUnreachable() -> noreturn { fn fnWithUnreachable() -> noreturn {
unreachable unreachable;
} }
@ -83,14 +83,14 @@ test "function pointers" {
assert(f() == u32(i) + 5); assert(f() == u32(i) + 5);
} }
} }
fn fn1() -> u32 {5} fn fn1() -> u32 {return 5;}
fn fn2() -> u32 {6} fn fn2() -> u32 {return 6;}
fn fn3() -> u32 {7} fn fn3() -> u32 {return 7;}
fn fn4() -> u32 {8} fn fn4() -> u32 {return 8;}
test "inline function call" { test "inline function call" {
assert(@inlineCall(add, 3, 9) == 12); assert(@inlineCall(add, 3, 9) == 12);
} }
fn add(a: i32, b: i32) -> i32 { a + b } fn add(a: i32, b: i32) -> i32 { return a + b; }

View File

@ -12,7 +12,7 @@ test "continue in for loop" {
} }
break; break;
} }
if (sum != 6) unreachable if (sum != 6) unreachable;
} }
test "for loop with pointer elem var" { test "for loop with pointer elem var" {

View File

@ -11,7 +11,7 @@ fn max(comptime T: type, a: T, b: T) -> T {
} }
fn add(comptime a: i32, b: i32) -> i32 { fn add(comptime a: i32, b: i32) -> i32 {
return (comptime {a}) + b; return (comptime a) + b;
} }
const the_max = max(u32, 1234, 5678); const the_max = max(u32, 1234, 5678);
@ -20,15 +20,15 @@ test "compile time generic eval" {
} }
fn gimmeTheBigOne(a: u32, b: u32) -> u32 { fn gimmeTheBigOne(a: u32, b: u32) -> u32 {
max(u32, a, b) return max(u32, a, b);
} }
fn shouldCallSameInstance(a: u32, b: u32) -> u32 { fn shouldCallSameInstance(a: u32, b: u32) -> u32 {
max(u32, a, b) return max(u32, a, b);
} }
fn sameButWithFloats(a: f64, b: f64) -> f64 { fn sameButWithFloats(a: f64, b: f64) -> f64 {
max(f64, a, b) return max(f64, a, b);
} }
test "fn with comptime args" { test "fn with comptime args" {
@ -49,28 +49,28 @@ comptime {
} }
fn max_var(a: var, b: var) -> @typeOf(a + b) { fn max_var(a: var, b: var) -> @typeOf(a + b) {
if (a > b) a else b return if (a > b) a else b;
} }
fn max_i32(a: i32, b: i32) -> i32 { fn max_i32(a: i32, b: i32) -> i32 {
max_var(a, b) return max_var(a, b);
} }
fn max_f64(a: f64, b: f64) -> f64 { fn max_f64(a: f64, b: f64) -> f64 {
max_var(a, b) return max_var(a, b);
} }
pub fn List(comptime T: type) -> type { pub fn List(comptime T: type) -> type {
SmallList(T, 8) return SmallList(T, 8);
} }
pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type { pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type {
struct { return struct {
items: []T, items: []T,
length: usize, length: usize,
prealloc_items: [STATIC_SIZE]T, prealloc_items: [STATIC_SIZE]T,
} };
} }
test "function with return type type" { test "function with return type type" {
@ -91,20 +91,20 @@ test "generic struct" {
assert(b1.getVal()); assert(b1.getVal());
} }
fn GenNode(comptime T: type) -> type { fn GenNode(comptime T: type) -> type {
struct { return struct {
value: T, value: T,
next: ?&GenNode(T), next: ?&GenNode(T),
fn getVal(n: &const GenNode(T)) -> T { n.value } fn getVal(n: &const GenNode(T)) -> T { return n.value; }
} };
} }
test "const decls in struct" { test "const decls in struct" {
assert(GenericDataThing(3).count_plus_one == 4); assert(GenericDataThing(3).count_plus_one == 4);
} }
fn GenericDataThing(comptime count: isize) -> type { fn GenericDataThing(comptime count: isize) -> type {
struct { return struct {
const count_plus_one = count + 1; const count_plus_one = count + 1;
} };
} }
@ -120,16 +120,16 @@ test "generic fn with implicit cast" {
assert(getFirstByte(u8, []u8 {13}) == 13); assert(getFirstByte(u8, []u8 {13}) == 13);
assert(getFirstByte(u16, []u16 {0, 13}) == 0); assert(getFirstByte(u16, []u16 {0, 13}) == 0);
} }
fn getByte(ptr: ?&const u8) -> u8 {*??ptr} fn getByte(ptr: ?&const u8) -> u8 {return *??ptr;}
fn getFirstByte(comptime T: type, mem: []const T) -> u8 { fn getFirstByte(comptime T: type, mem: []const T) -> u8 {
getByte(@ptrCast(&const u8, &mem[0])) return getByte(@ptrCast(&const u8, &mem[0]));
} }
const foos = []fn(var) -> bool { foo1, foo2 }; const foos = []fn(var) -> bool { foo1, foo2 };
fn foo1(arg: var) -> bool { arg } fn foo1(arg: var) -> bool { return arg; }
fn foo2(arg: var) -> bool { !arg } fn foo2(arg: var) -> bool { return !arg; }
test "array of generic fns" { test "array of generic fns" {
assert(foos[0](true)); assert(foos[0](true));

View File

@ -29,10 +29,10 @@ test "else if expression" {
} }
fn elseIfExpressionF(c: u8) -> u8 { fn elseIfExpressionF(c: u8) -> u8 {
if (c == 0) { if (c == 0) {
0 return 0;
} else if (c == 1) { } else if (c == 1) {
1 return 1;
} else { } else {
u8(2) return u8(2);
} }
} }

View File

@ -1 +1 @@
pub fn foo() -> i32 { 1234 } pub fn foo() -> i32 { return 1234; }

View File

@ -8,10 +8,10 @@ fn foo(id: u64) -> %i32 {
return %return getErrInt(); return %return getErrInt();
}, },
else => error.ItBroke, else => error.ItBroke,
} };
} }
fn getErrInt() -> %i32 { 0 } fn getErrInt() -> %i32 { return 0; }
error ItBroke; error ItBroke;

View File

@ -28,16 +28,16 @@ fn testDivision() {
assert(divTrunc(f32, -5.0, 3.0) == -1.0); assert(divTrunc(f32, -5.0, 3.0) == -1.0);
} }
fn div(comptime T: type, a: T, b: T) -> T { fn div(comptime T: type, a: T, b: T) -> T {
a / b return a / b;
} }
fn divExact(comptime T: type, a: T, b: T) -> T { fn divExact(comptime T: type, a: T, b: T) -> T {
@divExact(a, b) return @divExact(a, b);
} }
fn divFloor(comptime T: type, a: T, b: T) -> T { fn divFloor(comptime T: type, a: T, b: T) -> T {
@divFloor(a, b) return @divFloor(a, b);
} }
fn divTrunc(comptime T: type, a: T, b: T) -> T { fn divTrunc(comptime T: type, a: T, b: T) -> T {
@divTrunc(a, b) return @divTrunc(a, b);
} }
test "@addWithOverflow" { test "@addWithOverflow" {
@ -71,7 +71,7 @@ fn testClz() {
} }
fn clz(x: var) -> usize { fn clz(x: var) -> usize {
@clz(x) return @clz(x);
} }
test "@ctz" { test "@ctz" {
@ -86,7 +86,7 @@ fn testCtz() {
} }
fn ctz(x: var) -> usize { fn ctz(x: var) -> usize {
@ctz(x) return @ctz(x);
} }
test "assignment operators" { test "assignment operators" {
@ -180,10 +180,10 @@ fn test_u64_div() {
assert(result.remainder == 100663296); assert(result.remainder == 100663296);
} }
fn divWithResult(a: u64, b: u64) -> DivResult { fn divWithResult(a: u64, b: u64) -> DivResult {
DivResult { return DivResult {
.quotient = a / b, .quotient = a / b,
.remainder = a % b, .remainder = a % b,
} };
} }
const DivResult = struct { const DivResult = struct {
quotient: u64, quotient: u64,
@ -191,8 +191,8 @@ const DivResult = struct {
}; };
test "binary not" { test "binary not" {
assert(comptime {~u16(0b1010101010101010) == 0b0101010101010101}); assert(comptime x: {break :x ~u16(0b1010101010101010) == 0b0101010101010101;});
assert(comptime {~u64(2147483647) == 18446744071562067968}); assert(comptime x: {break :x ~u64(2147483647) == 18446744071562067968;});
testBinaryNot(0b1010101010101010); testBinaryNot(0b1010101010101010);
} }
@ -331,7 +331,7 @@ test "f128" {
comptime test_f128(); comptime test_f128();
} }
fn make_f128(x: f128) -> f128 { x } fn make_f128(x: f128) -> f128 { return x; }
fn test_f128() { fn test_f128() {
assert(@sizeOf(f128) == 16); assert(@sizeOf(f128) == 16);

View File

@ -110,17 +110,17 @@ fn testShortCircuit(f: bool, t: bool) {
var hit_3 = f; var hit_3 = f;
var hit_4 = f; var hit_4 = f;
if (t or {assert(f); f}) { if (t or x: {assert(f); break :x f;}) {
hit_1 = t; hit_1 = t;
} }
if (f or { hit_2 = t; f }) { if (f or x: { hit_2 = t; break :x f; }) {
assert(f); assert(f);
} }
if (t and { hit_3 = t; f }) { if (t and x: { hit_3 = t; break :x f; }) {
assert(f); assert(f);
} }
if (f and {assert(f); f}) { if (f and x: {assert(f); break :x f;}) {
assert(f); assert(f);
} else { } else {
hit_4 = t; hit_4 = t;
@ -135,11 +135,11 @@ test "truncate" {
assert(testTruncate(0x10fd) == 0xfd); assert(testTruncate(0x10fd) == 0xfd);
} }
fn testTruncate(x: u32) -> u8 { fn testTruncate(x: u32) -> u8 {
@truncate(u8, x) return @truncate(u8, x);
} }
fn first4KeysOfHomeRow() -> []const u8 { fn first4KeysOfHomeRow() -> []const u8 {
"aoeu" return "aoeu";
} }
test "return string from function" { test "return string from function" {
@ -167,7 +167,7 @@ test "memcpy and memset intrinsics" {
} }
test "builtin static eval" { test "builtin static eval" {
const x : i32 = comptime {1 + 2 + 3}; const x : i32 = comptime x: {break :x 1 + 2 + 3;};
assert(x == comptime 6); assert(x == comptime 6);
} }
@ -190,7 +190,7 @@ test "slicing" {
test "constant equal function pointers" { test "constant equal function pointers" {
const alias = emptyFn; const alias = emptyFn;
assert(comptime {emptyFn == alias}); assert(comptime x: {break :x emptyFn == alias;});
} }
fn emptyFn() {} fn emptyFn() {}
@ -280,14 +280,14 @@ test "cast small unsigned to larger signed" {
assert(castSmallUnsignedToLargerSigned1(200) == i16(200)); assert(castSmallUnsignedToLargerSigned1(200) == i16(200));
assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
} }
fn castSmallUnsignedToLargerSigned1(x: u8) -> i16 { x } fn castSmallUnsignedToLargerSigned1(x: u8) -> i16 { return x; }
fn castSmallUnsignedToLargerSigned2(x: u16) -> i64 { x } fn castSmallUnsignedToLargerSigned2(x: u16) -> i64 { return x; }
test "implicit cast after unreachable" { test "implicit cast after unreachable" {
assert(outer() == 1234); assert(outer() == 1234);
} }
fn inner() -> i32 { 1234 } fn inner() -> i32 { return 1234; }
fn outer() -> i64 { fn outer() -> i64 {
return inner(); return inner();
} }
@ -310,8 +310,8 @@ test "call result of if else expression" {
fn f2(x: bool) -> []const u8 { fn f2(x: bool) -> []const u8 {
return (if (x) fA else fB)(); return (if (x) fA else fB)();
} }
fn fA() -> []const u8 { "a" } fn fA() -> []const u8 { return "a"; }
fn fB() -> []const u8 { "b" } fn fB() -> []const u8 { return "b"; }
test "const expression eval handling of variables" { test "const expression eval handling of variables" {
@ -379,7 +379,7 @@ test "pointer comparison" {
assert(ptrEql(b, b)); assert(ptrEql(b, b));
} }
fn ptrEql(a: &const []const u8, b: &const []const u8) -> bool { fn ptrEql(a: &const []const u8, b: &const []const u8) -> bool {
a == b return a == b;
} }
@ -483,7 +483,7 @@ test "@typeId" {
assert(@typeId(AUnion) == Tid.Union); assert(@typeId(AUnion) == Tid.Union);
assert(@typeId(fn()) == Tid.Fn); assert(@typeId(fn()) == Tid.Fn);
assert(@typeId(@typeOf(builtin)) == Tid.Namespace); assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
assert(@typeId(@typeOf({this})) == Tid.Block); assert(@typeId(@typeOf(x: {break :x this;})) == Tid.Block);
// TODO bound fn // TODO bound fn
// TODO arg tuple // TODO arg tuple
// TODO opaque // TODO opaque

View File

@ -22,7 +22,7 @@ test "reflection: function return type, var args, and param types" {
} }
} }
fn dummy(a: bool, b: i32, c: f32) -> i32 { 1234 } fn dummy(a: bool, b: i32, c: f32) -> i32 { return 1234; }
fn dummy_varargs(args: ...) {} fn dummy_varargs(args: ...) {}
test "reflection: struct member types and names" { test "reflection: struct member types and names" {

Some files were not shown because too many files have changed in this diff Show More