پرش به مطلب اصلی

پوینتر

مدل نوع حافظه صریح Wave

طراحی پوینتر در Wave بر اساس مدل نوع حافظه صریح Wave است. این مدل هدفش تعریف اشاره‌گرها و آرایه‌ها به‌عنوان نوع حافظه صریح در سطح زبان است، نه ترفندهای دستوری یا انتزاع‌های کتابخانه‌ای.

با این طراحی، در 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
  • ptr + int: عملیات مشابه
  • int + ptr: عقب‌روی اشاره‌گر مبتنی بر 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 توصیه می‌شود.