Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रूबी कैसे आपके प्रोग्राम की व्याख्या और संचालन करती है

जितना अधिक आप अपने टूल के बारे में जानेंगे, एक डेवलपर के रूप में आप उतने ही बेहतर निर्णय लेंगे। यह अक्सर उपयोगी होता है - विशेष रूप से प्रदर्शन समस्याओं को डीबग करते समय - यह समझने के लिए कि रूबी वास्तव में क्या कर रही है जब यह आपका प्रोग्राम चलाता है।

इस पोस्ट में हम एक साधारण प्रोग्राम की यात्रा का अनुसरण करेंगे क्योंकि यह लेक्सेड, पार्स और बायटेकोड में संकलित है। हम हर कदम पर दुभाषिए की जासूसी करने के लिए रूबी द्वारा दिए गए टूल का उपयोग करेंगे।

चिंता न करें - भले ही आप विशेषज्ञ न हों, इस पोस्ट का अनुसरण करना बहुत आसान होना चाहिए। यह एक तकनीकी मैनुअल की तुलना में अधिक निर्देशित टूर है।

हमारे नमूना कार्यक्रम से मिलें

उदाहरण के तौर पर, मैं एक if/else स्टेटमेंट का उपयोग करने जा रहा हूं। जगह बचाने के लिए, मैं इसे टर्नरी ऑपरेटर का उपयोग करके लिखूंगा। लेकिन मूर्ख मत बनो, यह सिर्फ एक if/else है।

x > 100 ? 'foo' : 'bar'

जैसा कि आप देखेंगे, यहां तक ​​कि इस तरह का एक साधारण प्रोग्राम भी संसाधित होने पर बहुत अधिक डेटा में अनुवादित हो जाता है।

नोट:इस पोस्ट के सभी उदाहरण रूबी (एमआरआई) 2.2 में लिखे गए थे। यदि आप रूबी के अन्य कार्यान्वयन का उपयोग कर रहे हैं, तो वे शायद काम नहीं करेंगे।

टोकन करना

इससे पहले कि रूबी दुभाषिया आपके प्रोग्राम को चला सके, उसे इसे कुछ हद तक फ्री-फॉर्म प्रोग्रामिंग भाषा से अधिक संरचित डेटा में बदलना होगा।

कार्यक्रम को टुकड़ों में तोड़ने के लिए पहला कदम हो सकता है। इन टुकड़ों को टोकन कहा जाता है।

# This is a string
"x > 1"

# These are tokens
["x", ">", "1"]

रूबी मानक पुस्तकालय रिपर नामक एक मॉड्यूल प्रदान करता है जो हमें रूबी कोड को रूबी दुभाषिया की तरह ही संसाधित करने देता है।

नीचे दिए गए उदाहरण में हम अपने रूबी कोड पर टोकन विधि का उपयोग कर रहे हैं। जैसा कि आप देख सकते हैं, यह टोकन की एक सरणी देता है।

require 'ripper'
Ripper.tokenize("x > 1 ? 'foo' : 'bar'")
# => ["x", " ", ">", " ", "1", " ", "?", " ", "'", "foo", "'", " ", ":", " ", "'", "bar", "'"]

टोकननाइज़र बहुत बेवकूफ है। आप इसे पूरी तरह से अमान्य रूबी खिला सकते हैं और यह अभी भी इसे टोकन करेगा।

# bad code
Ripper.tokenize("1var @= \/foobar`")
# => ["1", "var"]

लेक्सिंग

लेक्सिंग टोकनाइजेशन से एक कदम आगे है। स्ट्रिंग अभी भी टोकन में विभाजित है, लेकिन टोकन में अतिरिक्त डेटा जोड़ा जाता है।

नीचे दिए गए उदाहरण में हम अपने छोटे से प्रोग्राम के लिए रिपर टू लेक्स का उपयोग कर रहे हैं। जैसा कि आप देख सकते हैं, यह अब प्रत्येक टोकन को एक पहचानकर्ता के रूप में टैग कर रहा है :on_ident , एक ऑपरेटर :on_op , एक पूर्णांक :on_int , आदि.

require 'ripper'
require 'pp'

pp Ripper.lex("x > 100 ? 'foo' : 'bar'")

# [[[1, 0], :on_ident, "x"],
#  [[1, 1], :on_sp, " "],
#  [[1, 2], :on_op, ">"],
#  [[1, 3], :on_sp, " "],
#  [[1, 4], :on_int, "100"],
#  [[1, 5], :on_sp, " "],
#  [[1, 6], :on_op, "?"],
#  [[1, 7], :on_sp, " "],
#  [[1, 8], :on_tstring_beg, "'"],
#  [[1, 9], :on_tstring_content, "foo"],
#  [[1, 12], :on_tstring_end, "'"],
#  [[1, 13], :on_sp, " "],
#  [[1, 14], :on_op, ":"],
#  [[1, 15], :on_sp, " "],
#  [[1, 16], :on_tstring_beg, "'"],
#  [[1, 17], :on_tstring_content, "bar"],
#  [[1, 20], :on_tstring_end, "'"]]

इस बिंदु पर अभी भी कोई वास्तविक वाक्यविन्यास जांच नहीं चल रही है। लेक्सर खुशी-खुशी अमान्य कोड को प्रोसेस करेगा।

पार्सिंग

अब जबकि रूबी ने कोड को अधिक प्रबंधनीय भागों में विभाजित कर दिया है, यह विश्लेषण शुरू करने का समय है।

पार्सिंग चरण के दौरान, रूबी टेक्स्ट को एब्सट्रैक्ट सिंटैक्स ट्री या एएसटी नामक किसी चीज़ में बदल देती है। एब्सट्रैक्ट सिंटैक्स ट्री मेमोरी में आपके प्रोग्राम का प्रतिनिधित्व करता है।

आप कह सकते हैं कि सामान्य रूप से प्रोग्रामिंग भाषाएं अमूर्त सिंटैक्स ट्री का वर्णन करने के लिए अधिक उपयोगकर्ता के अनुकूल तरीके हैं।

require 'ripper'
require 'pp'

pp Ripper.sexp("x > 100 ? 'foo' : 'bar'")

# [:program,
#  [[:ifop,
#    [:binary, [:vcall, [:@ident, "x", [1, 0]]], :>, [:@int, "100", [1, 4]]],
#    [:string_literal, [:string_content, [:@tstring_content, "foo", [1, 11]]]],
#    [:string_literal, [:string_content, [:@tstring_content, "foobar", [1, 19]]]]]]]

हो सकता है कि इस आउटपुट को पढ़ना आसान न हो, लेकिन अगर आप इसे काफी देर तक देखते हैं तो आप देख सकते हैं कि यह मूल प्रोग्राम से कैसे मेल खाता है।

# Define a progam
[:program,
 # Do an "if" operation
 [[:ifop,
   # Check the conditional (x > 100)
   [:binary, [:vcall, [:@ident, "x", [1, 0]]], :>, [:@int, "100", [1, 4]]],
   # If true, return "foo"
   [:string_literal, [:string_content, [:@tstring_content, "foo", [1, 11]]]],
   # If false, return "bar"
   [:string_literal, [:string_content, [:@tstring_content, "foobar", [1, 19]]]]]]]

इस बिंदु पर, रूबी दुभाषिया जानता है कि आप इसे क्या करना चाहते हैं। यह अभी आपका प्रोग्राम चला सकता है। और रूबी 1.9 से पहले, यह होगा। लेकिन अब, एक और कदम है।

बाइटकोड में संकलित करना

अमूर्त सिंटैक्स ट्री को सीधे ट्रैवर्स करने के बजाय, आजकल रूबी एब्सट्रैक्ट सिंटैक्स ट्री को निचले स्तर के बाइट कोड में संकलित करता है।

यह बाइट कोड तब रूबी वर्चुअल मशीन द्वारा चलाया जाता है।

हम RubyVM::InstructionSequence के माध्यम से वर्चुअल मशीन की आंतरिक कार्यप्रणाली पर एक नज़र डाल सकते हैं कक्षा। नीचे दिए गए उदाहरण में, हम अपने नमूना कार्यक्रम को संकलित करते हैं और फिर मानव को पढ़ने योग्य बनाने के लिए इसे अलग करते हैं।

puts RubyVM::InstructionSequence.compile("x > 100 ? 'foo' : 'bar'").disassemble
# == disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
# 0000 trace            1                                               (   1)
# 0002 putself
# 0003 opt_send_without_block <callinfo!mid:x, argc:0, FCALL|VCALL|ARGS_SIMPLE>
# 0005 putobject        100
# 0007 opt_gt           <callinfo!mid:>, argc:1, ARGS_SIMPLE>
# 0009 branchunless     15
# 0011 putstring        "foo"
# 0013 leave
# 0014 pop
# 0015 putstring        "bar"
# 0017 leave

वाह! यह अचानक रूबी की तुलना में असेंबली भाषा की तरह बहुत अधिक दिखता है। आइए इसके माध्यम से कदम उठाएं और देखें कि क्या हम इसका अर्थ समझ सकते हैं।

# Call the method `x` on self and save the result on the stack
0002 putself
0003 opt_send_without_block <callinfo!mid:x, argc:0, FCALL|VCALL|ARGS_SIMPLE>

# Put the number 100 on the stack
0005 putobject        100

# Do the comparison (x > 100)
0007 opt_gt           <callinfo!mid:>, argc:1, ARGS_SIMPLE>

# If the comparison was false, go to line 15
0009 branchunless     15

# If the comparison was true, return "foo"
0011 putstring        "foo"
0013 leave
0014 pop

# Here's line 15. We jumped here if comparison was false. Return "bar"
0015 putstring        "bar"
0017 leave

रूबी वर्चुअल मशीन (YARV) फिर इन निर्देशों के माध्यम से कदम उठाती है और उन्हें निष्पादित करती है। बस!

निष्कर्ष

यह रूबी दुभाषिया के हमारे बहुत सरल, कार्टोनी दौरे को समाप्त करता है। मैंने आपको यहां जो उपकरण दिखाए हैं, उनके साथ रूबी आपके कार्यक्रमों की व्याख्या कैसे कर रही है, इसका बहुत अनुमान लगाना संभव है। मेरा मतलब है, यह एएसटी से ज्यादा ठोस नहीं है। और अगली बार जब आप कुछ अजीब प्रदर्शन समस्या से फंस गए हों, तो बाइटकोड को देखने का प्रयास करें। यह शायद आपकी समस्या का समाधान नहीं करेगा, लेकिन यह आपके दिमाग को इससे हटा सकता है। :)

  1. अपने रूबी कार्यक्रमों को कैसे डिबग और ठीक करें

    आपका प्रोग्राम कितनी बार ठीक वही करता है जो आप पहली बार चाहते हैं? कई बार हमारे प्रोग्राम हमारी अपेक्षा के अनुरूप काम नहीं करते हैं, इसलिए हमें रूबी को डीबग करना की कला का उपयोग करना पड़ता है। क्यों पता लगाने में हमारी मदद करने के लिए। आप निम्न त्रुटि संदेश से परिचित हो सकते हैं: undefined method

  1. कीलॉगर का पता कैसे लगाएं और निकालें

    कीलॉगर क्या है? एक कीलॉगर एक प्रकार का स्पाइवेयर है जो कीबोर्ड इनपुट को रिकॉर्ड करता है और उस जानकारी को इसे नियंत्रित करने वाले व्यक्ति को वापस भेजता है। आपके द्वारा टाइप की जाने वाली हर चीज़ को ट्रैक किया जाता है, जिसमें पासवर्ड, खाता जानकारी, ईमेल, खोज और व्यक्तिगत जानकारी शामिल है। Keyloggers

  1. अपने पीसी पर अवांछित प्रोग्राम कैसे अनइंस्टॉल करें

    एक साफ और व्यवस्थित पीसी हमेशा एक अव्यवस्थित पीसी से बेहतर होता है। बेहतर प्रदर्शन और इसके प्रदर्शन और सुरक्षा को बनाए रखने के लिए इसे हमेशा अनुकूलित रखना चाहिए। अवांछित प्रोग्रामों का समूह मशीन को सुस्त बना देता है और हार्ड डिस्क स्थान को अवरुद्ध कर देता है। इसलिए सफाई जरूरी है लेकिन यह आसान काम