توابع داخلی

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

    اشکال توابع داخلی

    توابع داخلی در کوروش می‌توانند به دو شکل مجزا استفاده شوند:

    شکل تابع (شکل عبارت)

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

    مثال‌ها:

    const size = @sizeof(int32);
    const line_num = @line();
    const value = @cast(uint32, -1);
    

    شکل بلوک (شکل دستور)

    توابع داخلی که به صورت دستورات بلوکی برای کنترل جریان و کامپایل شرطی ظاهر می‌شوند. این‌ها می‌توانند شامل چندین دستور و تعریف در محدوده خود باشند.

    مثال‌ها:

    @debug() {
        // کدی که فقط در حالت اشکال‌زدایی کامپایل می‌شود
        const x = 10;
        printf("حالت اشکال‌زدایی\n");
    }
    
    @release() printf("نماد اختصاری حالت انتشار");
    

    خانواده‌های توابع داخلی

    خانواده ConstEval (ارزیابی در زمان کامپایل)

    این توابع داخلی کاملاً در زمان کامپایل ارزیابی می‌شوند و مقادیر ثابتی تولید می‌کنند که می‌توانند در عبارات ثابت استفاده شوند.

    // همگی در زمان کامپایل ارزیابی می‌شوند
    const type_size = @sizeof(int32);    // مقدار ۴ را برمی‌گرداند
    const alignment = @alignof(float64); // مقدار ۸ را برمی‌گرداند
    const current_line = @line();        // شماره خط را برمی‌گرداند
    const current_file = @file_name();   // نام فایل را به صورت رشته برمی‌گرداند
    

    خانواده Intrinsic (عملیات کامپایلر)

    این توابع داخلی عملیات‌های سطح پایینی هستند که مستقیماً توسط کامپایلر پیاده‌سازی شده و به کد ماشین کارآمد کامپایل می‌شوند.

    // عملیات سطح پایین
    @memcpy(&dest, &src, @sizeof(Data)); // کپی حافظه
    @memset(&buffer, 0x00, 100);         // تنظیم حافظه
    const x = @cast(uint32, y);          // تبدیل نوع
    

    مرجع توابع داخلی

    توابع داخلی اطلاعات منبع

    @func_name()

    نام تابع فعلی را به صورت یک رشته literal برمی‌گرداند.

    import std::libc{printf};
    
    pub fn main() {
        printf("%s\n", @func_name()); // خروجی: main
    }
    

    @method_name()

    زمانی که در داخل یک متد ساختار فراخوانی شود، نام متد فعلی را برمی‌گرداند.

    struct Object {
        pub fn my_method() {
            printf("%s\n", @method_name()); // خروجی: my_method
        }
    }
    

    @module_name()

    نام ماژول فعلی را به صورت یک رشته literal برمی‌گرداند.

    printf("%s\n", @module_name()); // خروجی: my_module_name
    

    @file_name()

    نام فایل منبع فعلی را به صورت یک رشته literal برمی‌گرداند.

    printf("%s\n", @file_name()); // خروجی: main.cyrus
    

    @line()

    شماره خط فعلی را به صورت یک ثابت عدد صحیح برمی‌گرداند.

    printf("خطا در خط %d\n", @line()); // خروجی: خطا در خط ۵
    

    @column()

    شماره ستون فعلی را به صورت یک ثابت عدد صحیح برمی‌گرداند.

    printf("خطا در ستون %d\n", @column()); // خروجی: خطا در ستون ۱۰
    

    توابع داخلی اطلاعات نوع

    @sizeof(type)

    اندازه بر حسب بایت از نوع داده شده را به عنوان یک ثابت زمان کامپایل برمی‌گرداند.

    printf("%d ", @sizeof(int32));   // ۴
    printf("%d ", @sizeof(int64));   // ۸
    printf("%d ", @sizeof(float64)); // ۸
    printf("%d ", @sizeof(bool));    // ۱
    
    // با انواع تعریف شده توسط کاربر نیز کار می‌کند
    struct MyStruct { a: int32, b: int32 }
    printf("%d\n", @sizeof(MyStruct)); // ۸
    

    @alignof(type)

    نیازمندی ترازبندی بر حسب بایت از نوع داده شده را برمی‌گرداند.

    printf("%d ", @alignof(int32));                         // ۴
    printf("%d ", @alignof(float64));                       // ۸
    printf("%d ", @alignof(struct { a: int32* }));          // ۸
    printf("%d\n", @alignof(struct { a: int32, b: int8 })); // ۴
    

    @offsetof(type, field_name)

    آفست بایت یک فیلد را در داخل یک نوع ساختار برمی‌گرداند.

    struct Foo {
        a: int32,
        b: int32*
    }
    
    printf("%d ", @offsetof(Foo, "a"));  // ۰
    printf("%d\n", @offsetof(Foo, "b")); // ۸
    

    @typeof(expression)

    نوع عبارت داده شده را در زمان کامپایل برمی‌گرداند.

    var x: @typeof('a'); // x از نوع char است
    x = 'b';
    printf("%c\n", x);   // خروجی: b
    
    var y: @typeof(42);  // y از نوع int32 است
    

    عملیات ذاتی

    @cast(target_type, value)

    تبدیل نوع را بین انواع سازگار انجام می‌دهد.

    // تبدیل بین انواع عددی
    var i8_val: int8 = 100;
    var i32_val = @cast(int32, i8_val);  // ۱۰۰
    
    // تبدیل بین علامت‌دار و بدون علامت
    var u32_val: uint32 = 4294967295;
    var i64_val = @cast(int64, u32_val); // ۴۲۹۴۹۶۷۲۹۵
    
    // تبدیل کاراکتر به rune
    type rune = uint32;
    const x = @cast(rune, 'x'); // ۱۲۰
    

    @memcpy(dest, src, size)

    یک بلوک حافظه را از مبدأ به مقصد کپی می‌کند.

    struct Data {
        id: int32,
        score: float64,
        flag: bool
    }
    
    var src = Data { id: 99, score: 99.5, flag: true };
    var dst: Data;
    
    @memcpy(&dst, &src, @sizeof(Data));
    // اکنون dst شامل یک کپی از src است
    

    @memset(dest, value, size)

    یک بلوک حافظه را با مقدار مشخص شده پر می‌کند.

    var x: int32 = 0;
    @memset(&x, 0xAAAA, @sizeof(int32));
    // x اکنون برابر ۰xAAAAAAAA است
    

    توابع داخلی کنترل جریان

    @assert(condition, message?)

    تأیید می‌کند که یک شرط در زمان اجرا درست است، در صورت نادرست بودن با یک پیام اختیاری باعث وحشت (panic) می‌شود.

    const x = 20;
    @assert(x == 2, "x برابر ۲ نیست"); // با پیام باعث وحشت می‌شود
    

    @panic(message?)

    برنامه را با یک پیام اختیاری متوقف می‌کند.

    @panic("خطای فatal رخ داد"); // با پیام خاتمه می‌یابد
    

    @todo(message?)

    کد را به عنوان کار انجام‌نشده علامت‌گذاری می‌کند و باعث وحشت در زمان کامپایل یا اجرا می‌شود.

    @todo("این تابع را پیاده‌سازی کنید"); // با پیام TODO باعث وحشت می‌شود
    

    @unimplemented(message?)

    کد را به عنوان پیاده‌سازی‌نشده علامت‌گذاری می‌کند و باعث وحشت در زمان کامپایل یا اجرا می‌شود.

    @unimplemented("هنوز پیاده‌سازی نشده است");
    

    @unreachable(message?)

    کد را به عنوان غیرقابل دسترس علامت‌گذاری می‌کند و در صورت رسیدن به آن، باعث وحشت در زمان کامپایل یا اجرا می‌شود.

    if (x) {
        // کاری انجام بده
    } else {
        @unreachable("این شاخه هرگز نباید اجرا شود");
    }
    

    توابع داخلی کامپایل شرطی

    @debug() { ... }

    بلوک کد را فقط در ساخت‌های اشکال‌زدایی اجرا می‌کند. هم به صورت بلوک و هم به صورت دستور نماد اختصاری کار می‌کند.

    // شکل بلوک
    @debug() {
        const x = 10;
        printf("حالت اشکال‌زدایی: %d\n", x);
    }
    
    // شکل دستور نماد اختصاری
    @debug() printf("خروجی فقط در حالت اشکال‌زدایی\n");
    
    // متغیرهای تعریف شده در داخل بلوک اشکال‌زدایی فقط در حالت اشکال‌زدایی در دسترس هستند
    @debug() {
        const debug_var = 100;  // فقط در ساخت‌های اشکال‌زدایی وجود دارد
    }
    printf("%d\n", debug_var);  // در ساخت‌های انتشار خطا می‌دهد
    

    @release() { ... }

    بلوک کد را فقط در ساخت‌های انتشار اجرا می‌کند. هم به صورت بلوک و هم به صورت دستور نماد اختصاری کار می‌کند.

    // شکل بلوک
    @release() {
        const x = 10;
        printf("حالت انتشار: %d\n", x);
    }
    
    // شکل دستور نماد اختصاری
    @release() printf("خروجی فقط در حالت انتشار\n");