add list implementation to standard library

master
Andrew Kelley 2016-05-08 01:34:00 -07:00
parent 18ed87c695
commit 0c32b0b4ad
7 changed files with 112 additions and 2 deletions

View File

@ -214,6 +214,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/math.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/index.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/linux_x86_64.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/mem.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/list.zig" DESTINATION "${ZIG_STD_DEST}")
add_executable(run_tests ${TEST_SOURCES})
target_link_libraries(run_tests)

View File

@ -2386,6 +2386,7 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
LLVMPositionBuilderAtEnd(g->builder, then_block);
LLVMValueRef then_expr_result = gen_expr(g, then_node);
if (then_endif_reachable) {
clear_debug_source_node(g);
LLVMBuildBr(g->builder, endif_block);
}
LLVMBasicBlockRef after_then_block = LLVMGetInsertBlock(g->builder);
@ -2393,6 +2394,7 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
LLVMPositionBuilderAtEnd(g->builder, else_block);
LLVMValueRef else_expr_result = gen_expr(g, else_node);
if (else_endif_reachable) {
clear_debug_source_node(g);
LLVMBuildBr(g->builder, endif_block);
}
LLVMBasicBlockRef after_else_block = LLVMGetInsertBlock(g->builder);
@ -2400,6 +2402,7 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
if (then_endif_reachable || else_endif_reachable) {
LLVMPositionBuilderAtEnd(g->builder, endif_block);
if (use_then_value && use_else_value) {
set_debug_source_node(g, source_node);
LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};

View File

@ -5,6 +5,8 @@ pub const math = @import("math.zig");
pub const str = @import("str.zig");
pub const cstr = @import("cstr.zig");
pub const net = @import("net.zig");
pub const list = @import("list.zig");
pub const mem = @import("mem.zig");
pub fn assert(b: bool) {
if (!b) unreachable{}

92
std/list.zig Normal file
View File

@ -0,0 +1,92 @@
const assert = @import("index.zig").assert;
const mem = @import("mem.zig");
const Allocator = mem.Allocator;
/*
fn List(T: type) -> type {
List(T, 8)
}
*/
pub struct SmallList(T: type, STATIC_SIZE: isize) {
items: []T,
length: isize,
prealloc_items: [STATIC_SIZE]T,
allocator: &Allocator,
pub fn init(l: &SmallList(T, STATIC_SIZE), allocator: &Allocator) {
l.items = l.prealloc_items[0...];
l.length = 0;
l.allocator = allocator;
}
pub fn deinit(l: &SmallList(T, STATIC_SIZE)) {
if (l.items.ptr == &l.prealloc_items[0]) {
l.allocator.free(l.allocator, ([]u8)(l.items));
}
}
pub fn append(l: &SmallList(T, STATIC_SIZE), item: T) -> %void {
const new_length = l.length + 1;
%return l.ensure_capacity(new_length);
l.items[l.length] = item;
l.length = new_length;
}
pub fn ensure_capacity(l: &SmallList(T, STATIC_SIZE), new_capacity: isize) -> %void {
const old_capacity = l.items.len;
var better_capacity = old_capacity;
while (better_capacity < new_capacity) {
better_capacity *= 2;
}
if (better_capacity != old_capacity) {
const alloc_bytes = better_capacity * @sizeof(T);
if (l.items.ptr == &l.prealloc_items[0]) {
l.items = ([]T)(%return l.allocator.alloc(l.allocator, alloc_bytes));
@memcpy(l.items.ptr, &l.prealloc_items[0], old_capacity * @sizeof(T));
} else {
l.items = ([]T)(%return l.allocator.realloc(l.allocator, ([]u8)(l.items), alloc_bytes));
}
}
}
}
var global_allocator = Allocator {
.alloc = global_alloc,
.realloc = global_realloc,
.free = global_free,
.context = null,
};
var some_mem: [200]u8 = undefined;
var some_mem_index: isize = 0;
fn global_alloc(self: &Allocator, n: isize) -> %[]u8 {
const result = some_mem[some_mem_index ... some_mem_index + n];
some_mem_index += n;
return result;
}
fn global_realloc(self: &Allocator, old_mem: []u8, new_size: isize) -> %[]u8 {
const result = %return global_alloc(self, new_size);
@memcpy(result.ptr, old_mem.ptr, old_mem.len);
return result;
}
fn global_free(self: &Allocator, old_mem: []u8) {
}
#attribute("test")
fn basic_list_test() {
var list: SmallList(i32, 4) = undefined;
list.init(&global_allocator);
defer list.deinit();
{var i: isize = 0; while (i < 10; i += 1) {
%%list.append(i32(i + 1));
}}
{var i: isize = 0; while (i < 10; i += 1) {
assert(list.items[i] == i32(i + 1));
}}
}

10
std/mem.zig Normal file
View File

@ -0,0 +1,10 @@
pub error NoMem;
pub type Context = u8;
pub struct Allocator {
alloc: fn (self: &Allocator, n: isize) -> %[]u8,
realloc: fn (self: &Allocator, old_mem: []u8, new_size: isize) -> %[]u8,
free: fn (self: &Allocator, mem: []u8),
context: ?&Context,
}

View File

@ -1666,7 +1666,7 @@ static void run_self_hosted_test(bool is_release_mode) {
Termination term;
os_exec_process(zig_exe, args, &term, &zig_stderr, &zig_stdout);
if (term.how != TerminationIdClean) {
if (term.how != TerminationIdClean || term.code != 0) {
printf("\nSelf-hosted tests failed:\n");
printf("./zig");
for (int i = 0; i < args.length; i += 1) {

View File

@ -1622,7 +1622,8 @@ fn div_exact(a: u32, b: u32) -> u32 {
#attribute("test")
fn null_literal_outside_function() {
assert(here_is_a_null_literal.context == null);
const is_null = if (const _ ?= here_is_a_null_literal.context) false else true;
assert(is_null);
}
struct SillyStruct {
context: ?i32,