Making Ruby?

subtitle

ゆるふわRuby生活

author

Nobuyoshi Nakada / 中田伸悦

institution

Salseforce.com / Heroku

theme

lightning-rabbit

allotted-time

60m

Self-introduction

{:.center} Fulltime Ruby Committer @ Salesforce.com / Heroku {::note}(2011~){:/note}

So called Matz team

日常/Daily

About Ruby development

Repository

Why not Git?

Not enough advantage

Issues

Developers' meeting

How to build Ruby (from tarball)

{:.center} Similar to other OSS

configure

{:.center} +

make

Out-of-Place build

Various configure options

Many build directories by combination

How to Build Ruby {::note}(from repo){:/note}

To build Ruby, you need Ruby

Ruby

pre-installed ruby

ruby made during the build

BASERUBY

Ruby (maybe old) to generate source files

MINIRUBY

To generate Makefiles for extension libraries, and others

MINIRUBY's feature

{:.center} No dynamic loading ↓ Runnable alone

MINIRUBY's limitation

{:.center} Feature can be also a limitation

Building encodings

To generate Makefile by erb

{::note}no details{:/note}

Similar to exts but bit simpler

Building extension libraries

ruby Dir.glob("{ext,gems}/**/extconf.rb") do |file| load(file) end

Parallel build (~2.4)

Parallel build (2.5)

Problem

No headers and libraries are installed at build

Solution

Mimic global variables used in mkmf.rb by trace_var

trace_var

Hook changes of a global variable

trace_var(symbol, cmd )             -> nil
  trace_var(symbol) {|val| block }    -> nil

Controls tracing of assignments to global variables. The parameter symbol
identifies the variable (as either a string name or a symbol identifier).
cmd (which may be a string or a Proc object) or block is executed
whenever the variable is assigned. The block or Proc object receives the
variable's new value as a parameter. Also see Kernel::untrace_var.

  trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
  $_ = "hello"
  $_ = ' there'

produces:

  $_ is now 'hello'
  $_ is now ' there'

$extmk

Flag to handle bundled exts in mkmf.rb

$ruby

Path to ruby to run

?

Bug Report

[ruby-list:50578]

w/o local variable

# p = 2
p (-1.3).abs #=> 1.3

w/ local variable

p = 2
p (-1.3).abs #=> -1.3

Exactly Not-A-Bug

{:.center} {::tag name=“x-large”}__Ancient Spec__{:/tag} at least 1.1

Just-size bug

NOT SO HARD?

-w option

$ ruby -w -e 'p=2; p (-1.3).abs'
-e:1: warning: don't put space
 before argument parentheses

parser_yylex()

the lexical analysis

case '(':
    // ...
    else if (lex_state == (EXPR_END|EXPR_LABEL) && space_seen) {
        rb_warning0("don't put space before argument parentheses");
    }
    // ...
    SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);

What's space_seen?

a space was seen just before the current token?

p (-1.3).abs
 ^------------!Here!

lex_state

state of lexer

(EXPR_END|EXPR_LABEL)

What's EXPR_END?

Able to end an expression

What's EXPR_LABEL?

Able to place a label

In parse_ident()

parse an identifier starts with a lower letter (local variable / method)

ident = tokenize_ident(parser, last_state);
if (!IS_lex_state_for(last_state, EXPR_DOT|EXPR_FNAME) &&
    (result == tIDENTIFIER) && /* not EXPR_FNAME, not attrasgn */
    lvar_defined(ident)) {
    SET_LEX_STATE(EXPR_END|EXPR_LABEL);
}

What's lvar_defined(ident)?

Prediction to tell “whether the name referred as ident (p here) is defined as a local variable in the current scope”

Rules

W/o variable

primary         : tLPAREN_ARG

W/ variable

paren_args      : '(' opt_call_args rparen

How to Fix?

Remove the condition by lvar_defined

{::wait/}I consider it a bug, but…

?

literal symbol by intern

literal symbol by intern

:"#{foo}"

[Feature #13812]

Refinements can't affect string interpolation

Difference

Conversion is explicitly visible or not

New Features

No eye-catcher in 2.5

Such as &. in 2.3

“Unicode case” in 2.4

Approved

Rejected

Under Discussion

Write Ruby

Wouldn't you write New Ruby?