برنامه نویسی

یک مثال عملی از RakuAST

چندی پیش شخصی در #raku پرسید که آیا امکان ایجاد کلاس کاراکتر Raku با کاراکترهای معتبر توسط یک رشته وجود دارد یا خیر. این هست نه در حال حاضر در راکو امکان پذیر است. اما آن است با استفاده از RakuAST امکان پذیر است!

بیایید ابتدا ببینیم که چگونه می توان با استفاده از RakuAST کلاس های کاراکتر ایجاد کرد .AST روش به یک مثال

به هر حال، همه این مثال ها فرض می کنند که الف use experimental :rakuast; یا use v6.e.PREVIEW فعال است.

say 'my token {<[abc]>}'.AST.statements.head.expression;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کاری که این می کند این است

  • ایجاد AST (.AST) برای یک ناشناس token با یک charclas برای حروف “a”، “b” و “c”
  • سپس به عبارت اول می‌رود (.statements.head)
  • سپس به آن می‌پرد .expression

زیرا .AST یک لیست عبارت را برمی گرداند، و ما فقط به بیان عبارت اول علاقه مند هستیم.

نتیجه این است:

RakuAST::TokenDeclaration.new(
  body => RakuAST::Regex::Assertion::CharClass.new(
    RakuAST::Regex::CharClassElement::Enumeration.new(
      elements => (
        RakuAST::Regex::CharClassEnumerationElement::Character.new("a"),
        RakuAST::Regex::CharClassEnumerationElement::Character.new("b"),
        RakuAST::Regex::CharClassEnumerationElement::Character.new("c"),
      )
    )
  )
);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بنابراین به نظر می رسد که هر شخصیت در charclass جداگانه است RakuAST::Regex::CharClassEnumerationElement::Character هدف – شی. با این دانش، ساختن سفارشی بسیار آسان است token برای کاراکترهای یک رشته داده شده بیایید یک زیر روال “chars-matcher” ایجاد کنیم که یک توکن با یک charclas از کاراکترها برای یک رشته معین ایجاد می کند:

sub chars-matcher($string) {
    my @elements = $string.comb.unique.map: {
        RakuAST::Regex::CharClassEnumerationElement::Character.new($_)
    }
    RakuAST::TokenDeclaration.new(
      body => RakuAST::Regex::Assertion::CharClass.new(
        RakuAST::Regex::CharClassElement::Enumeration.new(:@elements)
      )
    ).EVAL
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ابتدا یک آرایه “@elements” ایجاد می کنیم و آن را با یک شیء شمارش برای هر کاراکتر منحصر به فرد در رشته داده شده پر می کنیم ($string.comb.unique). و سپس شی TokenDeclaration را مانند مثال ایجاد می کنیم، اما با @elements آرایه به عنوان مشخصات کاراکترها. و سپس آن را به یک قابل استفاده واقعی تبدیل می کنیم token با دویدن .EVAL بر روی آن.

نمونه ای از کاربرد آن:

my $matcher = chars-matcher("Anna Mae Bullock");
say "Tina Turner" ~~ $matcher;       # 「n」
say "Tina Turner" ~~ / $matcher+ /;  # 「na 」
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همانطور که می بینید، می توانید از تولید شده استفاده کنید token مستقیم در یک مسابقه هوشمند یا می توانید از آن به عنوان بخشی از یک regex پیچیده تر استفاده کنید.

اگر آماده هستید تا با RakuAST بیشتر آشنا شوید، احتمالاً ایده خوبی است که کمی از نحوه اجرای آن در حال حاضر بدانید. پس بیایید کمی به آن بپردازیم تا برخی از خطاهایی را که ممکن است هنگام نوشتن کد زبان برنامه نویسی Raku برای ایجاد AST با آنها مواجه شوید، بهتر درک کنیم.

پیش نیازهای RakuAST

هدف این است که تمام کد منبع Raku در آینده توسط دستور زبان Raku (و اقدامات مرتبط) (جدید) تجزیه شود، درست همانطور که اکنون در گرامر قدیمی انجام می شود. از آنجایی که تنظیمات هسته Raku (که شامل کد Raku برای اکثر پیاده سازی زبان برنامه نویسی Raku است) نیز باید توسط این تجزیه و تحلیل شود، به این معنی است که کلاس های RakuAST باید وجود داشته باشند. قبل از هر زبان برنامه نویسی Raku وجود دارد.

این یک مشکل مرغ و تخم مرغ است که در راکودو با اصطلاح “بوت استرپ” حل می شود. این بخش کاملاً قابل توجهی از کد NQP است که “به صورت دستی” عملکرد کافی را ایجاد می کند تا به تنظیمات هسته Raku اجازه دهد تا خود را به یک پیاده سازی کاملاً کاربردی از زبان برنامه نویسی Raku بسازد.

چه زمانی جاناتان ورتینگتون پروژه RakuAST را شروع کردند، آن‌ها نمی‌خواستند دوباره همه این قابلیت‌ها را در NQP پیاده‌سازی کنند. بنابراین آنها با ایجاد یک تجزیه کننده نسبتاً ساده که کدهای Raku مانند را می خواند و آن را به کد منبع NQP تبدیل می کرد که همه کدها را ایجاد می کرد، یک هک دقیق ابداع کردند. 360+ کلاس های RakuAST هنگام اجرا. البته، آن کد شبیه به راکو هنوز قابلیت‌های کامل راکو را ندارد، اما کار پیاده‌سازی را بسیار ساده‌تر از آنچه که اگر همه آن‌ها در NQP نوشته می‌شد، آسان‌تر می‌کند.

نمونه ای از داخلی های کلاس RakuAST

بیایید یک مثال ساده از چنین کلاس RakuAST را بررسی کنیم. به عنوان مثال، RakuAST::StrLiteral کلاسی که قبلاً در قسمت اول دیده بودیم.

class RakuAST::StrLiteral is RakuAST::Literal {
    has Str $.value;

    method new(Str $value) {
        my $obj := nqp::create(self);
        nqp::bindattr($obj, RakuAST::StrLiteral, '$!value', $value);
        $obj
    }

    # other methods

    method IMPL-EXPR-QAST(RakuAST::IMPL::QASTContext $context) {
        my $value := $!value;
        $context.ensure-sc($value);
        my $wval := QAST::WVal.new( :$value );
        QAST::Want.new($wval,'Ss', QAST::SVal.new(:value(nqp::unbox_s($value))))
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برای سادگی، تنها دو روش نشان داده شده است. این new روش، گرفتن یک موقعیت واحد Str $value. که به مقداری NQP برای ایجاد شی و پیوند دادن مقدار به آن نیاز دارد $!value صفت.

و ما یک IMPL-EXPR-QAST روش. هر زمان که آن شی RakuAST نیاز به تولید QAST (پیش ساز بایت کد واقعی) داشته باشد، این روش فراخوانی می شود.

اگر به نظر شما این بسیار جالب است، احتمالاً می خواهید RakuAST README را بخوانید. و کد منبع واقعی کلاس های RakuAST را می توان در همان دایرکتوری یافت. و اگر واقعاً احساس ماجراجویی می‌کنید و مخزن Rakudo را بررسی کرده‌اید، می‌توانید به کد NQP تولید شده نگاهی بیندازید. gen/moar/ast.nqp.

چه فایده ای دارد؟

پس چرا من این را ذکر می کنم؟ از آنجا که RakuAST کلاس ها نگاه کن مثل کلاس‌های Raku واقعی هستند، اما واقعاً زیرروال‌های NQP هستند که شبیه کلاس‌های Raku به نظر می‌رسند. که در صورت بروز خطا در تماس‌های شما، منجر به حالت‌های شکست غیرمنتظره می‌شود RakuAST کلاس ها. به عبارت دیگر: لبه‌ها با کلاس‌های RakuAST کمی واضح‌تر هستند و پیام‌های خطای LTA می‌توانند اتفاق بیفتند. این یکی از “مزایای” زندگی در حاشیه است!

البته، به عنوان کاربر کلاس های RakuAST، فقط باید به آن علاقه مند باشید new روش، و هر روش غیر داخلی دیگر. متاسفانه راهش هست خیلی زود در بوت استرپ برای علامت گذاری متدهای داخلی با علامت is implementation-detail ویژگی، بنابراین اکتشافی دیگری مورد نیاز است. و این چنین خواهد بود: “هر روش ALL-CAPS را غیرمجاز در نظر بگیرید”.

نتیجه

این قسط یک مثال واقعی از نحوه استفاده از RakuAST در کد امروز ارائه می دهد. و برخی پیش زمینه های فنی در مورد اجرای کلاس های RakuAST ارائه می دهد که هنوز در لبه ها کمی واضح است.

مخاطبان مورد نظر آن دسته از افرادی هستند که مایلند اولین پذیرندگان این ویژگی های جدید هیجان انگیز در زبان برنامه نویسی Raku باشند.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا