GOAL P1-1..1-3: 리터럴이 자기 타입에 안 맞으면 거부한다
그리고 그 자리를 파다가 더 나쁜 것이 나왔다. store 의 폭이 목적지가 아니라 값에서 왔다. 정수 리터럴은 더 좁은 것이 요구하기 전까지 i32 이므로 let b: u8 = 200; 은 4바이트가 1바이트 자리로 가는 것으로 도착하고, 4바이트를 쓰면 프레임이 그 옆에 놓은 것을 지운다. let a: i32 = 5; let b: u8 = 300; let d: u8 = 44; a 0 / b 0 / d 44 → a 5 / b 44 / d 44 폭 넓은 지역 하나만 있으면 드러나지 않아서 여태 살아 있었다. exec/narrow.fe 가 폭이 섞인 지역을 나란히 두어 고정한다. 규칙 자체는 SPEC §3 에 넣었다: 리터럴의 타입은 문맥이 요구하는 정수 타입이고, 없으면 i32 다. 범위를 벗어나면 잘리는 것이 아니라 거부된다. 앞의 단항 - 는 리터럴의 일부로 보아 i8 = -128 은 되고 u8 = -1 은 안 된다. 같이 넣은 문장 둘: - §9 미사용 타입 파라미터는 정상이다. typed handle 이 그 모양이고 구현은 이미 그렇게 동작했다. - §7.4 --no-checks 에서 오버플로는 랩어라운드로 정의된다. 타깃이 실제로 하는 일이고 미정의로 두지 않는다. 237/237, 35/35.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
// EXIT:0
|
||||
// OUTPUT:a 5 b 200 c 44 d 9
|
||||
// OUTPUT:e 5 f 1 g 65535
|
||||
// OUTPUT:sum 253
|
||||
unit narrow;
|
||||
|
||||
import std.io;
|
||||
|
||||
// How wide a store is belongs to the place, not to the value. An integer
|
||||
// literal is `i32` until something narrower asks for it, so `let b: u8 = 200;`
|
||||
// arrives at the store as four bytes going into one -- and writing four wipes
|
||||
// out whatever the frame put beside it.
|
||||
//
|
||||
// Several locals of mixed width, next to each other, is what it takes to see
|
||||
// it: each narrow store used to reach back over the one declared before it.
|
||||
|
||||
fn main() -> i32 {
|
||||
let a: i32 = 5;
|
||||
let b: u8 = 200;
|
||||
let c: u8 = 44;
|
||||
let d: i16 = 9;
|
||||
@print("a {} b {} c {} d {}\n", a, b, c, d);
|
||||
|
||||
let e = 5; // no annotation: i32 (SPEC 4.1)
|
||||
let f: i8 = 1;
|
||||
let g: u16 = 65535;
|
||||
@print("e {} f {} g {}\n", e, f as i32, g);
|
||||
|
||||
// And the values are still there after everything else was written.
|
||||
@print("sum {}\n", (b as i32) + (c as i32) + (d as i32) + e - (a as i32));
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user