Pointeur
Wave Explicit Memory Type Model
Wave의 포인터 설계는 Wave Explicit Memory Type Model을 기반으로 합니다. 이 모델은 포인터와 배열을 문법적 트릭이나 라이브러리 추상화가 아닌, 언어 차원의 명시적인 메모리 타입으로 정의하는 것을 목표로 합니다.
이러한 설계에 따라 Wave에서는 포인터를 ptr<T> 형태의 타입으로 표현하며,
이는 특정 타입 T의 값을 저장하고 있는 메모리 주소를 가리키는 타입임을 명확하게 드러냅니다.
이 접근 방식은 포인터를 연산자나 선언 문법이 아닌 타입 시스템의 일부로 다룸으로써,
메모리 구조를 더 직관적이고 일관되게 표현할 수 있게 합니다.
Wave에서 포인터는 ptr<T> 형태의 명시적 타입입니다.
주소 획득은 &, 역참조는 deref를 사용합니다.
선언과 초기화
var x: i32 = 10;
var p: ptr<i32> = &x;
포인터 타입은 중첩 가능합니다.
var p1: ptr<i32> = &x;
var p2: ptr<ptr<i32>> = &p1;
역참조
var x: i32 = 10;
var p: ptr<i32> = &x;
println("{}", deref p); // 10
deref p = 20;
println("{}", x); // 20
null 리터럴 규칙
null은 정식 리터럴입니다. 식별자가 아니며 변수명으로 사용할 수 없습니다.
핵심 규칙:
null은 오직ptr<T>대상에만 대입할 수 있습니다.i32,bool,array<...>같은 비포인터 타입에는 대입할 수 없습니다.- 정수 리터럴(
0,123,-1등)로 포인터를 초기화할 수 없습니다. 명시적으로null을 사용합니다.
var p: ptr<i32> = null;
var arrp: ptr<array<i32, 3>> = null;
// var n: i32 = null; // ERROR
// var b: bool = null; // ERROR
포인터 산술
Wave는 다음 포인터 산술을 지원합니다.
ptr + int: GEP 기반 포인터 전진int + ptr: 동일 동작ptr - int: GEP 기반 포인터 후진ptr - ptr:i64바이트 차이 계산
포인트:
ptr<T> +/- n은T의 크기(sizeof(T))를 기준으로 이동합니다.- 즉
ptr<i32> + 3은 바이트 기준으로+12이동입니다.
var base: ptr<i32> = 0x1000 as ptr<i32>;
var p1: ptr<i32> = base + 3; // 0x1000 + 12
var p2: ptr<i32> = 2 + base; // 0x1000 + 8
var p3: ptr<i32> = base - 1; // 0x1000 - 4
var diff: i64 = p1 - base; // 12 (byte diff)
포인터 비교
포인터는 비교에 사용할 수 있습니다.
if (p == null) { ... }
if (p != null) { ... }
if (p1 == p2) { ... }
배열과의 관계
포인터 배열:
var a: i32 = 10;
var b: i32 = 20;
var arr: array<ptr<i32>, 2> = [&a, &b];
println("{} {}", deref arr[0], deref arr[1]);
배열 포인터:
var p: ptr<array<i32, 3>> = &[1, 2, 3];
if (p != null) {
println("{}", deref p[1]);
}
안전성 노트
Wave는 현재 Rust 같은 소유권/수명 기반 포인터 안전 모델이 아닙니다.
따라서 null 역참조를 자동으로 막아주지 않습니다. deref 전에 명시적으로 null 체크를 넣는 패턴을 권장합니다.