audit: 프런트엔드 빈틈 열하나와 진법 리터럴
전부 구현 쪽이었다. SPEC 은 §6.2(체이닝·단항 뒤 as), §5 R9(asm), §6.1·§7.3
(extern, 빈 enum/error)을 이미 옳게 적고 있었고 구현만 따라가지 않았다.
const A: i32 = r(); 전역 초기값에 호출. lowering 이 조용히 버리고 0
static A: i32 = r(); 같은 것을 저장소 0 으로
true == false == true 비교 체이닝
-x as u32 괄호 없이 단항 뒤 as
asm { } unsafe 밖에서
extern fn f(); ABI 문자열 없이
extern "stdcall" fn f(); c 아닌 ABI
extern "c" fn f() { } extern 에 본문
fn f() -> i32; extern 아닌데 본문 없음
enum E { } error E { } 빈 선언
FRONT-01/02 는 SPEC 에도 규칙이 없었다. §7.1 에 넣었다 -- 전역의 바이트는
이미지에 들어가므로 초기값이 실행될 순간이 없다. 리터럴과 다른 const, 배리언트,
error.Name, 그리고 그것들에 대한 연산까지가 허용된다.
-x as T 와 비교 체이닝을 잡으려면 괄호가 트리에 남아야 해서 FE_NODE_PAREN 을
두었다. 파싱 뒤에는 -x as T 와 -(x as T) 가 같은 트리다.
그리고 0b1010 이 0, 0o17 이 0 이었다. 10진으로 읽다가 b 에서 멈춰 0 을 내는데
0 도 숫자라 아무도 눈치채지 못한다. 값 계산 두 군데를 고쳤다.
262/262, 40/40.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
// EXIT:0
|
||||
// OUTPUT:bin 10 255 0
|
||||
// OUTPUT:oct 15 511 8
|
||||
// OUTPUT:hex 255 4095 16
|
||||
// OUTPUT:dec 1000 1000000
|
||||
// OUTPUT:same yes yes
|
||||
unit radix;
|
||||
|
||||
import std.io;
|
||||
|
||||
// SPEC §3 spells four radices. Reading `0b1010` as decimal stops at the `b`
|
||||
// and answers zero -- which is a number, so nothing looks wrong until the
|
||||
// program does the wrong thing.
|
||||
|
||||
fn main() -> i32 {
|
||||
@print("bin {} {} {}\n", 0b1010, 0b11111111, 0b0);
|
||||
@print("oct {} {} {}\n", 0o17, 0o777, 0o10);
|
||||
@print("hex {} {} {}\n", 0xFF, 0xfff, 0x10);
|
||||
@print("dec {} {}\n", 1_000, 1_000_000);
|
||||
|
||||
// The same number four ways.
|
||||
@print("same {} {}\n", yesno(0b1111 == 0o17), yesno(0o17 == 0xF));
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn yesno(b: bool) -> []u8 {
|
||||
if b { return "yes"; }
|
||||
return "no";
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// ERROR:3:at least one variant
|
||||
unit bademen;
|
||||
enum E { }
|
||||
@@ -0,0 +1,3 @@
|
||||
// ERROR:3:at least one member
|
||||
unit bademer;
|
||||
error E { }
|
||||
@@ -0,0 +1,3 @@
|
||||
// ERROR:3:unsafe block
|
||||
unit badasm;
|
||||
fn f() -> void { asm { "nop" } return; }
|
||||
@@ -0,0 +1,3 @@
|
||||
// ERROR:3:do not chain
|
||||
unit badchain;
|
||||
fn f() -> bool { return true == false == true; }
|
||||
@@ -0,0 +1,4 @@
|
||||
// ERROR:4:known at compile time
|
||||
unit badcini;
|
||||
fn r() -> i32 { return 1; }
|
||||
const A: i32 = r();
|
||||
@@ -0,0 +1,3 @@
|
||||
// ERROR:3:only ABI
|
||||
unit badexab;
|
||||
extern "stdcall" fn f();
|
||||
@@ -0,0 +1,3 @@
|
||||
// ERROR:3:no body
|
||||
unit badexbd;
|
||||
extern "c" fn f() -> i32 { return 1; }
|
||||
@@ -0,0 +1,3 @@
|
||||
// ERROR:3:ABI string
|
||||
unit badexns;
|
||||
extern fn f();
|
||||
@@ -0,0 +1,3 @@
|
||||
// ERROR:4:must be extern
|
||||
unit badfnsm;
|
||||
fn f() -> i32;
|
||||
@@ -0,0 +1,4 @@
|
||||
// ERROR:4:known at compile time
|
||||
unit badsini;
|
||||
fn r() -> i32 { return 1; }
|
||||
static A: i32 = r();
|
||||
@@ -0,0 +1,3 @@
|
||||
// ERROR:3:parenthesise
|
||||
unit badunas;
|
||||
fn f(x: i32) -> u32 { return -x as u32; }
|
||||
@@ -0,0 +1,23 @@
|
||||
unit okglobin;
|
||||
|
||||
// 거부되는 것들의 짝. 전역 초기값은 컴파일 시점에 알 수 있어야 하고,
|
||||
// extern 은 ABI 를 대고 본문이 없으며, 비교는 괄호로 묶으면 이어 쓸 수 있고,
|
||||
// 단항 뒤의 as 는 괄호가 어느 쪽인지 말해주면 되고, asm 은 unsafe 안이면 된다.
|
||||
import std.sys;
|
||||
|
||||
const A: i32 = 1;
|
||||
const B: i32 = A + 2;
|
||||
const S: str = "hi";
|
||||
static C: i32 = -A;
|
||||
var D: u32 = 0xFF;
|
||||
|
||||
enum E { One, Two, }
|
||||
error Er { Bad = 1, }
|
||||
|
||||
extern "c" fn fe_rt_allocs() -> i32;
|
||||
|
||||
fn f(x: i32) -> u32 { return (-x) as u32; }
|
||||
fn g(x: i32) -> u32 { return -(x as u32); }
|
||||
fn h(a: i32, b: i32, c: i32) -> bool { return a < b and b < c; }
|
||||
fn i(a: i32, b: i32) -> bool { return (a == b) == true; }
|
||||
fn j() -> void { unsafe { asm { "nop" } } return; }
|
||||
Reference in New Issue
Block a user