From 0c32b0b4ad32549193b46d33026d72b5e4a17bd9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 8 May 2016 01:34:00 -0700 Subject: [PATCH] add list implementation to standard library --- CMakeLists.txt | 2 + src/codegen.cpp | 3 ++ std/index.zig | 2 + std/list.zig | 92 ++++++++++++++++++++++++++++++++++++++++++++ std/mem.zig | 10 +++++ test/run_tests.cpp | 2 +- test/self_hosted.zig | 3 +- 7 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 std/list.zig create mode 100644 std/mem.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index 545725b384..bf89535b97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/src/codegen.cpp b/src/codegen.cpp index 4f3b9e930e..8163cf9fc9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -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}; diff --git a/std/index.zig b/std/index.zig index 16005faf14..2eeba590fb 100644 --- a/std/index.zig +++ b/std/index.zig @@ -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{} diff --git a/std/list.zig b/std/list.zig new file mode 100644 index 0000000000..c651655561 --- /dev/null +++ b/std/list.zig @@ -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)); + }} +} diff --git a/std/mem.zig b/std/mem.zig new file mode 100644 index 0000000000..a21706b921 --- /dev/null +++ b/std/mem.zig @@ -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, +} + diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 576b424ca0..f4f958b911 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -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) { diff --git a/test/self_hosted.zig b/test/self_hosted.zig index aee8e91420..99ae4800de 100644 --- a/test/self_hosted.zig +++ b/test/self_hosted.zig @@ -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,