compiler: Share checked method and v-table name assembly
54994768e04274fa96c84baef10b385e86205697b98dca86a8109aebeec3ecba
1 parent
72388a52
lib/std/lang/lower.rad
+8 -24
| 1135 | 1135 | } |
|
| 1136 | 1136 | } |
|
| 1137 | 1137 | ||
| 1138 | 1138 | /// Build a qualified name of the form "Type::method". |
|
| 1139 | 1139 | unsafe fn instanceMethodName 'arena 'phase (self: &mut Lowerer 'arena 'phase, modId: ?u16, typeName: *[u8], methodName: *[u8]) -> *[u8] where 'arena: 'phase { |
|
| 1140 | - | let sepLen: u32 = 2; // "::" |
|
| 1141 | - | let totalLen = typeName.len + sepLen + methodName.len; |
|
| 1142 | - | let buf = try! alloc::allocSlice(self.arena, 1, 1, totalLen) as *mut [u8]; |
|
| 1143 | - | let mut pos: u32 = 0; |
|
| 1144 | - | ||
| 1145 | - | set pos += try! mem::copy(&mut buf[pos..], typeName); |
|
| 1146 | - | set pos += try! mem::copy(&mut buf[pos..], "::"); |
|
| 1147 | - | set pos += try! mem::copy(&mut buf[pos..], methodName); |
|
| 1148 | - | assert pos == totalLen; |
|
| 1149 | - | ||
| 1150 | - | return qualifyName(self, modId, &buf[..totalLen]); |
|
| 1140 | + | // "::" separates the type and method names. |
|
| 1141 | + | let path = [typeName]; |
|
| 1142 | + | let name = il::formatQualifiedName(self.arena, &path[..], methodName); |
|
| 1143 | + | return qualifyName(self, modId, name); |
|
| 1151 | 1144 | } |
|
| 1152 | 1145 | ||
| 1153 | 1146 | /// Build a v-table data name of the form "vtable::Type::Trait". |
|
| 1154 | 1147 | unsafe fn vtableName 'arena 'phase (self: &mut Lowerer 'arena 'phase, modId: ?u16, typeName: *[u8], traitName: *[u8]) -> *[u8] where 'arena: 'phase { |
|
| 1155 | - | let prefix = "vtable::"; |
|
| 1156 | - | let sepLen: u32 = 2; // "::" |
|
| 1157 | - | let totalLen = prefix.len + typeName.len + sepLen + traitName.len; |
|
| 1158 | - | let buf = try! alloc::allocSlice(self.arena, 1, 1, totalLen) as *mut [u8]; |
|
| 1159 | - | let mut pos: u32 = 0; |
|
| 1160 | - | ||
| 1161 | - | set pos += try! mem::copy(&mut buf[pos..], prefix); |
|
| 1162 | - | set pos += try! mem::copy(&mut buf[pos..], typeName); |
|
| 1163 | - | set pos += try! mem::copy(&mut buf[pos..], "::"); |
|
| 1164 | - | set pos += try! mem::copy(&mut buf[pos..], traitName); |
|
| 1165 | - | assert pos == totalLen; |
|
| 1166 | - | ||
| 1167 | - | return qualifyName(self, modId, &buf[..totalLen]); |
|
| 1148 | + | // "::" separates the namespace, type, and trait names. |
|
| 1149 | + | let path = ["vtable", typeName]; |
|
| 1150 | + | let name = il::formatQualifiedName(self.arena, &path[..], traitName); |
|
| 1151 | + | return qualifyName(self, modId, name); |
|
| 1168 | 1152 | } |
|
| 1169 | 1153 | ||
| 1170 | 1154 | /// Lower an instance declaration (`instance Trait for Type { ... }`). |
|
| 1171 | 1155 | /// |
|
| 1172 | 1156 | /// Each method in the instance block is lowered as a standalone function |
test/tests/method.with.trait.rad
+18 -0
| 20 | 20 | unsafe fn (w: *unsafe Widget) code() -> i32 { |
|
| 21 | 21 | return w.x + w.y; |
|
| 22 | 22 | } |
|
| 23 | 23 | } |
|
| 24 | 24 | ||
| 25 | + | /// A second implementation with a distinct method symbol and v-table. |
|
| 26 | + | record Counter: Copy { |
|
| 27 | + | /// Value returned through dynamic dispatch. |
|
| 28 | + | value: i32, |
|
| 29 | + | } |
|
| 30 | + | ||
| 31 | + | /// Preserve type-qualified method names for a shared trait. |
|
| 32 | + | instance Printable for Counter { |
|
| 33 | + | /// Read the counter through its trait receiver. |
|
| 34 | + | unsafe fn (counter: *unsafe Counter) code() -> i32 { |
|
| 35 | + | return counter.value; |
|
| 36 | + | } |
|
| 37 | + | } |
|
| 38 | + | ||
| 25 | 39 | @default unsafe fn main() -> i32 { |
|
| 26 | 40 | let w = Widget { x: 3, y: 5 }; |
|
| 27 | 41 | ||
| 28 | 42 | // Standalone method call. |
|
| 29 | 43 | assert w.area() == 15; |
|
| 30 | 44 | ||
| 31 | 45 | // Trait method call via trait object. |
|
| 32 | 46 | let p: *unsafe opaque Printable = &w; |
|
| 33 | 47 | assert p.code() == 8; |
|
| 48 | + | let counter = Counter { value: 37 }; |
|
| 49 | + | let other: *unsafe opaque Printable = &counter; |
|
| 50 | + | assert other.code() == 37; |
|
| 51 | + | assert p.code() == 8; |
|
| 34 | 52 | ||
| 35 | 53 | return 0; |
|
| 36 | 54 | } |