Commit 273cebdf4d

Andrew Kelley <superjoe30@gmail.com>
2017-04-07 00:07:38
peer resolve types [N]T, [M]T as []const T
closes #125
1 parent 47f58d6
Changed files (3)
src
std
test
cases
src/ir.cpp
@@ -5857,6 +5857,10 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
     return ImplicitCastMatchResultNo;
 }
 
+static bool is_slice(TypeTableEntry *type) {
+    return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
+}
+
 static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, IrInstruction **instructions, size_t instruction_count) {
     assert(instruction_count >= 1);
     IrInstruction *prev_inst = instructions[0];
@@ -5865,6 +5869,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
     }
     bool any_are_pure_error = (prev_inst->value.type->id == TypeTableEntryIdPureError);
     bool any_are_null = (prev_inst->value.type->id == TypeTableEntryIdNullLit);
+    bool convert_to_const_slice = false;
     for (size_t i = 1; i < instruction_count; i += 1) {
         IrInstruction *cur_inst = instructions[i];
         TypeTableEntry *cur_type = cur_inst->value.type;
@@ -5932,6 +5937,34 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
             } else {
                 return ira->codegen->builtin_types.entry_invalid;
             }
+        } else if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
+                cur_type->data.array.len != prev_type->data.array.len &&
+                types_match_const_cast_only(cur_type->data.array.child_type, prev_type->data.array.child_type))
+        {
+            convert_to_const_slice = true;
+            prev_inst = cur_inst;
+            continue;
+        } else if (cur_type->id == TypeTableEntryIdArray && prev_type->id == TypeTableEntryIdArray &&
+                cur_type->data.array.len != prev_type->data.array.len &&
+                types_match_const_cast_only(prev_type->data.array.child_type, cur_type->data.array.child_type))
+        {
+            convert_to_const_slice = true;
+            continue;
+        } else if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&
+                prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const &&
+                types_match_const_cast_only(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
+                    cur_type->data.array.child_type))
+        {
+            convert_to_const_slice = false;
+            continue;
+        } else if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&
+                cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const &&
+                types_match_const_cast_only(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
+                    prev_type->data.array.child_type))
+        {
+            prev_inst = cur_inst;
+            convert_to_const_slice = false;
+            continue;
         } else {
             ErrorMsg *msg = ir_add_error_node(ira, source_node,
                 buf_sprintf("incompatible types: '%s' and '%s'",
@@ -5944,7 +5977,10 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
             return ira->codegen->builtin_types.entry_invalid;
         }
     }
-    if (any_are_pure_error && prev_inst->value.type->id != TypeTableEntryIdPureError) {
+    if (convert_to_const_slice) {
+        assert(prev_inst->value.type->id == TypeTableEntryIdArray);
+        return get_slice_type(ira->codegen, prev_inst->value.type->data.array.child_type, true);
+    } else if (any_are_pure_error && prev_inst->value.type->id != TypeTableEntryIdPureError) {
         if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt ||
             prev_inst->value.type->id == TypeTableEntryIdNumLitFloat)
         {
@@ -6038,10 +6074,6 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
     }
 }
 
-static bool is_slice(TypeTableEntry *type) {
-    return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
-}
-
 static bool is_container(TypeTableEntry *type) {
     return type->id == TypeTableEntryIdStruct ||
         type->id == TypeTableEntryIdEnum ||
std/build.zig
@@ -360,11 +360,11 @@ pub const Builder = struct {
 
     pub fn typeIdName(id: TypeId) -> []const u8 {
         return switch (id) {
-            TypeId.Bool => ([]const u8)("bool"), // TODO issue #125
-            TypeId.Int => ([]const u8)("int"), // TODO issue #125
-            TypeId.Float => ([]const u8)("float"), // TODO issue #125
-            TypeId.String => ([]const u8)("string"), // TODO issue #125
-            TypeId.List => ([]const u8)("list"), // TODO issue #125
+            TypeId.Bool => "bool",
+            TypeId.Int => "int",
+            TypeId.Float => "float",
+            TypeId.String => "string",
+            TypeId.List => "list",
         };
     }
 
@@ -462,127 +462,127 @@ fn printInvocation(exe_name: []const u8, args: &const List([]const u8)) {
 // TODO issue #299
 fn targetOsName(target_os: Os) -> []const u8 {
     return switch (target_os) {
-        Os.freestanding => ([]const u8)("freestanding"),
-        Os.cloudabi => ([]const u8)("cloudabi"),
-        Os.darwin => ([]const u8)("darwin"),
-        Os.dragonfly => ([]const u8)("dragonfly"),
-        Os.freebsd => ([]const u8)("freebsd"),
-        Os.ios => ([]const u8)("ios"),
-        Os.kfreebsd => ([]const u8)("kfreebsd"),
-        Os.linux => ([]const u8)("linux"),
-        Os.lv2 => ([]const u8)("lv2"),
-        Os.macosx => ([]const u8)("macosx"),
-        Os.netbsd => ([]const u8)("netbsd"),
-        Os.openbsd => ([]const u8)("openbsd"),
-        Os.solaris => ([]const u8)("solaris"),
-        Os.windows => ([]const u8)("windows"),
-        Os.haiku => ([]const u8)("haiku"),
-        Os.minix => ([]const u8)("minix"),
-        Os.rtems => ([]const u8)("rtems"),
-        Os.nacl => ([]const u8)("nacl"),
-        Os.cnk => ([]const u8)("cnk"),
-        Os.bitrig => ([]const u8)("bitrig"),
-        Os.aix => ([]const u8)("aix"),
-        Os.cuda => ([]const u8)("cuda"),
-        Os.nvcl => ([]const u8)("nvcl"),
-        Os.amdhsa => ([]const u8)("amdhsa"),
-        Os.ps4 => ([]const u8)("ps4"),
-        Os.elfiamcu => ([]const u8)("elfiamcu"),
-        Os.tvos => ([]const u8)("tvos"),
-        Os.watchos => ([]const u8)("watchos"),
-        Os.mesa3d => ([]const u8)("mesa3d"),
+        Os.freestanding => "freestanding",
+        Os.cloudabi => "cloudabi",
+        Os.darwin => "darwin",
+        Os.dragonfly => "dragonfly",
+        Os.freebsd => "freebsd",
+        Os.ios => "ios",
+        Os.kfreebsd => "kfreebsd",
+        Os.linux => "linux",
+        Os.lv2 => "lv2",
+        Os.macosx => "macosx",
+        Os.netbsd => "netbsd",
+        Os.openbsd => "openbsd",
+        Os.solaris => "solaris",
+        Os.windows => "windows",
+        Os.haiku => "haiku",
+        Os.minix => "minix",
+        Os.rtems => "rtems",
+        Os.nacl => "nacl",
+        Os.cnk => "cnk",
+        Os.bitrig => "bitrig",
+        Os.aix => "aix",
+        Os.cuda => "cuda",
+        Os.nvcl => "nvcl",
+        Os.amdhsa => "amdhsa",
+        Os.ps4 => "ps4",
+        Os.elfiamcu => "elfiamcu",
+        Os.tvos => "tvos",
+        Os.watchos => "watchos",
+        Os.mesa3d => "mesa3d",
     };
 }
 
 // TODO issue #299
 fn targetArchName(target_arch: Arch) -> []const u8 {
     return switch (target_arch) {
-        Arch.armv8_2a => ([]const u8)("armv8_2a"),
-        Arch.armv8_1a => ([]const u8)("armv8_1a"),
-        Arch.armv8 => ([]const u8)("armv8"),
-        Arch.armv8m_baseline => ([]const u8)("armv8m_baseline"),
-        Arch.armv8m_mainline => ([]const u8)("armv8m_mainline"),
-        Arch.armv7 => ([]const u8)("armv7"),
-        Arch.armv7em => ([]const u8)("armv7em"),
-        Arch.armv7m => ([]const u8)("armv7m"),
-        Arch.armv7s => ([]const u8)("armv7s"),
-        Arch.armv7k => ([]const u8)("armv7k"),
-        Arch.armv6 => ([]const u8)("armv6"),
-        Arch.armv6m => ([]const u8)("armv6m"),
-        Arch.armv6k => ([]const u8)("armv6k"),
-        Arch.armv6t2 => ([]const u8)("armv6t2"),
-        Arch.armv5 => ([]const u8)("armv5"),
-        Arch.armv5te => ([]const u8)("armv5te"),
-        Arch.armv4t => ([]const u8)("armv4t"),
-        Arch.armeb => ([]const u8)("armeb"),
-        Arch.aarch64 => ([]const u8)("aarch64"),
-        Arch.aarch64_be => ([]const u8)("aarch64_be"),
-        Arch.avr => ([]const u8)("avr"),
-        Arch.bpfel => ([]const u8)("bpfel"),
-        Arch.bpfeb => ([]const u8)("bpfeb"),
-        Arch.hexagon => ([]const u8)("hexagon"),
-        Arch.mips => ([]const u8)("mips"),
-        Arch.mipsel => ([]const u8)("mipsel"),
-        Arch.mips64 => ([]const u8)("mips64"),
-        Arch.mips64el => ([]const u8)("mips64el"),
-        Arch.msp430 => ([]const u8)("msp430"),
-        Arch.powerpc => ([]const u8)("powerpc"),
-        Arch.powerpc64 => ([]const u8)("powerpc64"),
-        Arch.powerpc64le => ([]const u8)("powerpc64le"),
-        Arch.r600 => ([]const u8)("r600"),
-        Arch.amdgcn => ([]const u8)("amdgcn"),
-        Arch.sparc => ([]const u8)("sparc"),
-        Arch.sparcv9 => ([]const u8)("sparcv9"),
-        Arch.sparcel => ([]const u8)("sparcel"),
-        Arch.s390x => ([]const u8)("s390x"),
-        Arch.tce => ([]const u8)("tce"),
-        Arch.thumb => ([]const u8)("thumb"),
-        Arch.thumbeb => ([]const u8)("thumbeb"),
-        Arch.i386 => ([]const u8)("i386"),
-        Arch.x86_64 => ([]const u8)("x86_64"),
-        Arch.xcore => ([]const u8)("xcore"),
-        Arch.nvptx => ([]const u8)("nvptx"),
-        Arch.nvptx64 => ([]const u8)("nvptx64"),
-        Arch.le32 => ([]const u8)("le32"),
-        Arch.le64 => ([]const u8)("le64"),
-        Arch.amdil => ([]const u8)("amdil"),
-        Arch.amdil64 => ([]const u8)("amdil64"),
-        Arch.hsail => ([]const u8)("hsail"),
-        Arch.hsail64 => ([]const u8)("hsail64"),
-        Arch.spir => ([]const u8)("spir"),
-        Arch.spir64 => ([]const u8)("spir64"),
-        Arch.kalimbav3 => ([]const u8)("kalimbav3"),
-        Arch.kalimbav4 => ([]const u8)("kalimbav4"),
-        Arch.kalimbav5 => ([]const u8)("kalimbav5"),
-        Arch.shave => ([]const u8)("shave"),
-        Arch.lanai => ([]const u8)("lanai"),
-        Arch.wasm32 => ([]const u8)("wasm32"),
-        Arch.wasm64 => ([]const u8)("wasm64"),
-        Arch.renderscript32 => ([]const u8)("renderscript32"),
-        Arch.renderscript64 => ([]const u8)("renderscript64"),
+        Arch.armv8_2a => "armv8_2a",
+        Arch.armv8_1a => "armv8_1a",
+        Arch.armv8 => "armv8",
+        Arch.armv8m_baseline => "armv8m_baseline",
+        Arch.armv8m_mainline => "armv8m_mainline",
+        Arch.armv7 => "armv7",
+        Arch.armv7em => "armv7em",
+        Arch.armv7m => "armv7m",
+        Arch.armv7s => "armv7s",
+        Arch.armv7k => "armv7k",
+        Arch.armv6 => "armv6",
+        Arch.armv6m => "armv6m",
+        Arch.armv6k => "armv6k",
+        Arch.armv6t2 => "armv6t2",
+        Arch.armv5 => "armv5",
+        Arch.armv5te => "armv5te",
+        Arch.armv4t => "armv4t",
+        Arch.armeb => "armeb",
+        Arch.aarch64 => "aarch64",
+        Arch.aarch64_be => "aarch64_be",
+        Arch.avr => "avr",
+        Arch.bpfel => "bpfel",
+        Arch.bpfeb => "bpfeb",
+        Arch.hexagon => "hexagon",
+        Arch.mips => "mips",
+        Arch.mipsel => "mipsel",
+        Arch.mips64 => "mips64",
+        Arch.mips64el => "mips64el",
+        Arch.msp430 => "msp430",
+        Arch.powerpc => "powerpc",
+        Arch.powerpc64 => "powerpc64",
+        Arch.powerpc64le => "powerpc64le",
+        Arch.r600 => "r600",
+        Arch.amdgcn => "amdgcn",
+        Arch.sparc => "sparc",
+        Arch.sparcv9 => "sparcv9",
+        Arch.sparcel => "sparcel",
+        Arch.s390x => "s390x",
+        Arch.tce => "tce",
+        Arch.thumb => "thumb",
+        Arch.thumbeb => "thumbeb",
+        Arch.i386 => "i386",
+        Arch.x86_64 => "x86_64",
+        Arch.xcore => "xcore",
+        Arch.nvptx => "nvptx",
+        Arch.nvptx64 => "nvptx64",
+        Arch.le32 => "le32",
+        Arch.le64 => "le64",
+        Arch.amdil => "amdil",
+        Arch.amdil64 => "amdil64",
+        Arch.hsail => "hsail",
+        Arch.hsail64 => "hsail64",
+        Arch.spir => "spir",
+        Arch.spir64 => "spir64",
+        Arch.kalimbav3 => "kalimbav3",
+        Arch.kalimbav4 => "kalimbav4",
+        Arch.kalimbav5 => "kalimbav5",
+        Arch.shave => "shave",
+        Arch.lanai => "lanai",
+        Arch.wasm32 => "wasm32",
+        Arch.wasm64 => "wasm64",
+        Arch.renderscript32 => "renderscript32",
+        Arch.renderscript64 => "renderscript64",
     };
 }
 
 // TODO issue #299
 fn targetEnvironName(target_environ: Environ) -> []const u8 {
     return switch (target_environ) {
-        Environ.gnu => ([]const u8)("gnu"),
-        Environ.gnuabi64 => ([]const u8)("gnuabi64"),
-        Environ.gnueabi => ([]const u8)("gnueabi"),
-        Environ.gnueabihf => ([]const u8)("gnueabihf"),
-        Environ.gnux32 => ([]const u8)("gnux32"),
-        Environ.code16 => ([]const u8)("code16"),
-        Environ.eabi => ([]const u8)("eabi"),
-        Environ.eabihf => ([]const u8)("eabihf"),
-        Environ.android => ([]const u8)("android"),
-        Environ.musl => ([]const u8)("musl"),
-        Environ.musleabi => ([]const u8)("musleabi"),
-        Environ.musleabihf => ([]const u8)("musleabihf"),
-        Environ.msvc => ([]const u8)("msvc"),
-        Environ.itanium => ([]const u8)("itanium"),
-        Environ.cygnus => ([]const u8)("cygnus"),
-        Environ.amdopencl => ([]const u8)("amdopencl"),
-        Environ.coreclr => ([]const u8)("coreclr"),
+        Environ.gnu => "gnu",
+        Environ.gnuabi64 => "gnuabi64",
+        Environ.gnueabi => "gnueabi",
+        Environ.gnueabihf => "gnueabihf",
+        Environ.gnux32 => "gnux32",
+        Environ.code16 => "code16",
+        Environ.eabi => "eabi",
+        Environ.eabihf => "eabihf",
+        Environ.android => "android",
+        Environ.musl => "musl",
+        Environ.musleabi => "musleabi",
+        Environ.musleabihf => "musleabihf",
+        Environ.msvc => "msvc",
+        Environ.itanium => "itanium",
+        Environ.cygnus => "cygnus",
+        Environ.amdopencl => "amdopencl",
+        Environ.coreclr => "coreclr",
     };
 }
 
test/cases/cast.zig
@@ -1,4 +1,5 @@
 const assert = @import("std").debug.assert;
+const mem = @import("std").mem;
 
 test "intToPtrCast" {
     const x = isize(13);
@@ -41,3 +42,25 @@ fn testCastIntToErr(err: error) {
     const y = error(x);
     assert(error.ItBroke == y);
 }
+
+test "peer resolve arrays of different size to const slice" {
+    assert(mem.eql(u8, boolToStr(true), "true"));
+    assert(mem.eql(u8, boolToStr(false), "false"));
+    comptime assert(mem.eql(u8, boolToStr(true), "true"));
+    comptime assert(mem.eql(u8, boolToStr(false), "false"));
+}
+fn boolToStr(b: bool) -> []const u8 {
+    if (b) "true" else "false"
+}
+
+
+test "peer resolve array and const slice" {
+    testPeerResolveArrayConstSlice(true);
+    comptime testPeerResolveArrayConstSlice(true);
+}
+fn testPeerResolveArrayConstSlice(b: bool) {
+    const value1 = if (b) "aoeu" else ([]const u8)("zz");
+    const value2 = if (b) ([]const u8)("zz") else "aoeu";
+    assert(mem.eql(u8, value1, "aoeu"));
+    assert(mem.eql(u8, value2, "zz"));
+}