compiler: Select parameter names in checked code
b4557190c4e4a7bf0d88410fa9abc4fc26a8fb7d556329f7ca7158e9d528b4e6
1 parent
2707105e
lib/std/lang/lower.rad
+14 -16
| 3211 | 3211 | newArgs.append(il::Val::Undef, alloc::arenaAllocator(self.arena)); |
|
| 3212 | 3212 | } |
|
| 3213 | 3213 | return (&mut newArgs[..]) as *unsafe mut [il::Val]; |
|
| 3214 | 3214 | } |
|
| 3215 | 3215 | ||
| 3216 | - | /// Extract the parameter name from an [`FnParam`] AST node value. |
|
| 3217 | - | fn paramName(value: *ast::NodeValue) -> *[u8] throws (LowerError) { |
|
| 3218 | - | let case ast::NodeValue::FnParam(param) = *value else { |
|
| 3216 | + | /// Select a receiver or explicit parameter name from its AST declaration. |
|
| 3217 | + | fn paramName(params: &[*ast::Node], receiver: ?*ast::Node, index: u32) -> *[u8] throws (LowerError) { |
|
| 3218 | + | let mut position = index; |
|
| 3219 | + | if let node = receiver { |
|
| 3220 | + | if index == 0 { |
|
| 3221 | + | let case ast::NodeValue::Ident(name) = node.value else { |
|
| 3222 | + | throw LowerError::ExpectedIdentifier; |
|
| 3223 | + | }; |
|
| 3224 | + | return name; |
|
| 3225 | + | } |
|
| 3226 | + | set position -= 1; |
|
| 3227 | + | } |
|
| 3228 | + | let case ast::NodeValue::FnParam(param) = params[position].value else { |
|
| 3219 | 3229 | throw LowerError::ExpectedFunctionParam; |
|
| 3220 | 3230 | }; |
|
| 3221 | 3231 | let case ast::NodeValue::Ident(name) = param.name.value else { |
|
| 3222 | 3232 | throw LowerError::ExpectedIdentifier; |
|
| 3223 | 3233 | }; |
| 3251 | 3261 | params.append(il::Param { value: reg, type }, alloc::arenaAllocator(self.arena)); |
|
| 3252 | 3262 | ||
| 3253 | 3263 | // Declare the parameter variable. For the receiver, the name comes |
|
| 3254 | 3264 | // from the receiver node. |
|
| 3255 | 3265 | // For all other parameters, the name comes from the AST params. |
|
| 3256 | - | let mut name: *[u8] = undefined; |
|
| 3257 | - | if let recNode = receiverName { |
|
| 3258 | - | if i == 0 { |
|
| 3259 | - | let case ast::NodeValue::Ident(recName) = recNode.value else { |
|
| 3260 | - | throw LowerError::ExpectedIdentifier; |
|
| 3261 | - | }; |
|
| 3262 | - | set name = recName; |
|
| 3263 | - | } else { |
|
| 3264 | - | set name = try paramName(&astParams[i - 1].value); |
|
| 3265 | - | } |
|
| 3266 | - | } else { |
|
| 3267 | - | set name = try paramName(&astParams[i].value); |
|
| 3268 | - | } |
|
| 3266 | + | let name = try paramName(&astParams[..], receiverName, i); |
|
| 3269 | 3267 | let v = newVar(self, name, type, false, il::Val::Undef); |
|
| 3270 | 3268 | ||
| 3271 | 3269 | set self.params[i] = FnParamBinding { var: v, reg }; |
|
| 3272 | 3270 | set self.paramsLen += 1; |
|
| 3273 | 3271 | } |
test/tests/parameter.receiver.names.rad
added
+43 -0
| 1 | + | //! returns: 0 |
|
| 2 | + | ||
| 3 | + | /// Receiver with a value distinct from every explicit argument. |
|
| 4 | + | record Counter: Copy { |
|
| 5 | + | /// Receiver contribution. |
|
| 6 | + | value: u32, |
|
| 7 | + | } |
|
| 8 | + | ||
| 9 | + | /// Check a standalone receiver without explicit parameters. |
|
| 10 | + | fn (counter: &Counter) read() -> u32 { |
|
| 11 | + | return counter.value; |
|
| 12 | + | } |
|
| 13 | + | ||
| 14 | + | /// Check standalone receiver and parameter-name indexing. |
|
| 15 | + | fn (counter: &Counter) add(amount: u32) -> u32 { |
|
| 16 | + | return counter.value + amount; |
|
| 17 | + | } |
|
| 18 | + | ||
| 19 | + | /// Dynamic dispatch with the maximum register-only argument count. |
|
| 20 | + | trait Weighted { |
|
| 21 | + | /// Include all seven explicit arguments in order. |
|
| 22 | + | fn (&Weighted) sum(a: u32, b: u32, c: u32, d: u32, e: u32, f: u32, g: u32) -> u32; |
|
| 23 | + | } |
|
| 24 | + | ||
| 25 | + | instance Weighted for Counter { |
|
| 26 | + | /// Include the receiver and every named parameter in the result. |
|
| 27 | + | fn (counter: &Counter) sum(a: u32, b: u32, c: u32, d: u32, e: u32, f: u32, g: u32) -> u32 { |
|
| 28 | + | return counter.value + a + 2*b + 3*c + 4*d + 5*e + 6*f + 7*g; |
|
| 29 | + | } |
|
| 30 | + | } |
|
| 31 | + | ||
| 32 | + | /// Check receiver names and explicit names over repeated dispatches. |
|
| 33 | + | @default unsafe fn main() -> u32 { |
|
| 34 | + | for value in 0..8 { |
|
| 35 | + | let counter = Counter { value }; |
|
| 36 | + | assert counter.read() == value; |
|
| 37 | + | assert counter.add(17) == value + 17; |
|
| 38 | + | let weighted: *unsafe opaque Weighted = &counter; |
|
| 39 | + | assert weighted.sum(1, 2, 3, 4, 5, 6, 7) == value + 140; |
|
| 40 | + | assert weighted.sum(7, 6, 5, 4, 3, 2, 1) == value + 84; |
|
| 41 | + | } |
|
| 42 | + | return 0; |
|
| 43 | + | } |