' send'是什么意思? Ruby的关键字AST?

时间:2017-06-01 05:44:34

标签: ruby parsing abstract-syntax-tree s-expression ruby-ripper

我正在尝试学习Ruby词法分析器和解析器(whitequark parser)以了解有关从Ruby脚本进一步生成机器代码的过程的更多信息。

解析以下Ruby代码字符串。

def add(a, b)
    return a + b
end

puts add 1, 2

它产生以下S表达式表示法。

s(:begin,
    s(:def, :add,
        s(:args,
            s(:arg, :a),
            s(:arg, :b)),
        s(:return,
            s(:send,
                s(:lvar, :a), :+,
                s(:lvar, :b)))),
    s(:send, nil, :puts,
        s(:send, nil, :add,
            s(:int, 1),
            s(:int, 3))))

有人可以在结果S表达式表示法中向我解释:发送关键字的定义吗?

2 个答案:

答案 0 :(得分:5)

Ruby建立在“一切都是对象”范式的基础之上。也就是说,包括数字在内的所有内容都是一个对象。

运算符,正如我们在普通的ruby代码中看到的那样,对于各个对象的方法调用只是语法糖

getPromise(URL+'/olympic/2016/ranking/4')
  .then(function(data){
     console.log("Response "+JSON.parse(data).Country);

     /////////// here
     return getPromise(URL+'/iso/country/'+JSON.parse(data).Country);
  })
  .then(function(data){
    console.log("Data "+data)
  })
  .catch(function(err){
     console.log(err)
  });

以上就是Ruby如何处理3.14.+(42) #⇒ 45.14 简短符号。反过来,它可能使用通用Object#send

编写
3.14 + 42

后者应理解为:“将带有参数[s](3.14.send :+, 42 #⇒ 45.14 )的消息:+发送给接收方42。”

答案 1 :(得分:4)

Ruby是一种面向对象的语言。在面向对象的编程中,我们通过让对象向其他对象发送消息来做事。例如,

foo.bar(baz)

表示self将消息bar发送到通过解除引用本地变量foo获得的对象,将通过解除引用本地变量baz获得的对象作为参数传递。 (假设foobaz是局部变量。它们也可以是消息发送,因为如果它是self,Ruby允许你省略接收器,如果它是空的则允许你省略参数列表注意,此时解析器将静态地知道这一点,因为局部变量是在解析时静态创建的。)

在您的代码中,有几个消息发送:

a + b

将消息+发送给变量a中的对象,并在变量b中传递对象

puts add 1, 2

发送消息addself,将文字整数12作为参数发送,然后将消息puts发送到self传递上述消息的结果作为参数发送。

请注意,这与<{1}} / Object#send 无关。这两个是反射方法,允许您在源代码中动态地而不是静态地指定消息。它们通常通过委托AST解释器委托给的同一个私有内部运行时例程在内部实现。 不是反过来。解释器调用Object#public_send(否则,您可以通过猴子修补Object#send在Ruby中自定义方法查找规则,您可以轻松尝试不是这种情况),而是Object#send和解释器都调用相同的私有内部实现细节。