$30 off During Our Annual Pro Sale. View Details »

Implementing "++" operator, stepping into parse.y

Implementing "++" operator, stepping into parse.y

More Decks by Misaki Shioi(塩井美咲/しおい)

Other Decks in Programming

Transcript

  1. *NQMFNFOUJOHPQFSBUPS
    TUFQQJOHJOUPQBSTFZ
    .JTBLJ4IJPJ !TIJPJNN!DPF@

    .BZ
    3VCZ,BJHJ

    View Slide

  2. "CPVUNF
    (JU)VC!TIJPJNN
    5XJUUFS!DPF@
    8FCBQQMJDBUJPOEFWFMPQFSBU4.4$P -UE
    .FNCFSPG"TBLVTBSC'VLVPLBSC
    "NJOUFSFTUFEJOOFUXPSLJOHBOEQBSTJOH

    View Slide

  3. )BWFZPVFWFSXJTIFE
    3VCZIBEJODSFNFOUEFDSFNFOUPQFSBUPST
    i = 0
    while i < 100
    i++
    puts "FizzBuzz" if i % 15 == 0
    puts "Fizz" if i % 3 == 0
    puts "Buzz" if i % 5 == 0
    end
    'PSFYBNQMF

    View Slide

  4. 8IZEPFTOU3VCZIBWFBOJODSFNFOUPQFSBUPS
    .PTUQFPQMFIBWFQSPCBCMZXPOEFSFEBCPVUUIJT
    BUMFBTUPODF

    View Slide

  5. .BU[TUBUFTUIFSFBTPOGPSUIJT
    :PVDBOUEF
    fi
    OFPCKFDUPSJFOUFETFNBOUJDT
    GPSJODSFNFOUEFDSFNFOUPQFSBUJPOT
    SFGIUUQTCVHTSVCZMBOHPSHJTTVFT

    View Slide

  6. 4PXJUIUIFDVSSFOU.3*
    JGXFUSZUPFYFDVUFBTDSJQUMJLFAJA

    # test.rb
    i = 0
    i++

    View Slide

  7. ʜJUDBVTFTBTZOUBYFSSPSBUQBSTJOH
    # test.rb
    i = 0
    i++
    SVCZUFTUSC
    J
    J
    UFTUSCTZOUBYFSSPS VOFYQFDUFEFOEPGJOQVU 4ZOUBY&SSPS

    View Slide

  8. 8IZJTUIJTIBQQFOJOH
    5IFQBSTJOHMPHTIPXTUIFSFBTPO

    View Slide

  9. SVCZZFJJ
    5IFQBSTJOHMPHTIPXTXIZ
    1BSTJOHMPHTDBOCFFBTJMZPCUBJOFECZSVOOJOH
    UIFTDSJQUXJUIAZAPQUJPOUPUIFASVCZADPNNBOE
    TPMFUTHJWFJUBUSZXJUIBTDSJQUAJJA
    3VOUIFTDSJQU
    JJ
    XJUIASVCZZADPNNBOE
    ˞5IJTJTSVOOJOHPO3VCZ

    View Slide

  10. SVCZZFJJ
    BEE@EFMBZFE@UPLFO cc

    4UBSUJOHQBSTF
    ʜ
    &OUFSJOHTUBUF
    4UBDLOPX
    3FEVDJOHTUBDLCZSVMF MJOF

    OUFSNMIT /0%&@-"4(/

    UPLFO

    OUFSNMFY@DUYU

    OUFSNBSH@SIT /0%&@-*5

    OUFSNBSH /0%&@-"4(/

    ʜ
    5IFQBSTJOHMPHTIPXTXIZ
    "DDPSEJOHUPJU JUXPSLT
    fi
    OFVQUPAJA
    AJATFFNTUPCFQBSTFEKVTU
    fi
    OF

    View Slide

  11. SVCZZFJJ
    ʜ
    &OUFSJOHTUBUF
    4UBDLOPX
    /FYUUPLFOJTUPLFO

    4IJGUJOHUPLFO

    &OUFSJOHTUBUF
    4UBDLOPX
    3FEVDJOHTUBDLCZSVMF MJOF

    UPLFO

    OUFSNUFSN

    &OUFSJOHTUBUF
    4UBDLOPX
    3FEVDJOHTUBDLCZSVMF MJOF

    OUFSNUFSN

    OUFSNUFSNT

    5IFQBSTJOHMPHTIPXTXIZ
    5IFOUIF
    fi
    STUFYQSFTTJPOJTQSPQFSMZFOEFEXJUIAA
    5IJTFYQSFTTJPOJTTVDDFTTGVMMZFOEFE
    AABMTPTFFNTUPCFQBSTFEDPSSFDUMZ

    View Slide

  12. SVCZZFJJ
    ʜ
    &OUFSJOHTUBUF
    4UBDLOPX
    3FBEJOHBUPLFO
    QBSTFS@EJTQBUDI@TDBO@FWFOU cc

    MFY@TUBUF#&($.%"3(BUMJOF
    MFY@TUBUF$.%"3(&/%c-"#&-BUMJOF
    QBSTFS@EJTQBUDI@TDBO@FWFOU cc

    /FYUUPLFOJTUPLFOMPDBMWBSJBCMFPSNFUIPE J

    4IJGUJOHUPLFOMPDBMWBSJBCMFPSNFUIPE J

    5IFQBSTJOHMPHTIPXTXIZ
    *OUIFMBUFSQBSU UIFWBSJBCMFAJAJT
    fi
    STUSFBE
    5IFWBSJBCMFAJAJTSFBE

    View Slide

  13. SVCZZFJJ
    ʜ
    &OUFSJOHTUBUF
    4UBDLOPX
    /FYUUPLFOJTUPLFO

    4IJGUJOHUPLFO

    &OUFSJOHTUBUF
    4UBDLOPX
    3FBEJOHBUPLFO
    MFY@TUBUF#&(#&(BUMJOF
    QBSTFS@EJTQBUDI@TDBO@FWFOU cc

    /FYUUPLFOJTUPLFOVOBSZ

    4IJGUJOHUPLFOVOBSZ

    5IFQBSTJOHMPHTIPXTXIZ
    5XPAATBSFUIFOSFBE5IJT TFDPOEAAJT
    EFUFSNJOFEBTUIFAAPGBVOBSZPQFSBUPS
    'JSTUAA
    4FDPOEAA
    *UTEFUFSNJOFEUIBUBVOBSZPQFSBUPS

    View Slide

  14. SVCZZFJJ
    ʜ
    &OUFSJOHTUBUF
    4UBDLOPX
    3FBEJOHBUPLFO
    QBSTFS@EJTQBUDI@TDBO@FWFOU cc

    /PXBUFOEPGJOQVU
    FTZOUBYFSSPS VOFYQFDUFEFOEPGJOQVU
    JJ
    5IFQBSTJOHMPHTIPXTXIZ
    .3*FYQFDUTTPNFOVNFSJDUPCFSFBEBGUFS
    BVOBSZPQFSBUPSJOUIJTDPOUFYU
    )PXFWFS JOSFBMJUZ UIFMJOFFOETBCSVQUMZIFSF
    5IJTJTBOVOFYQFDUFEFOEPGJOQVU
    "TZOUBYFSSPSIBTPDDVSSFE
    5IFMJOFFOEFEVOFYQFDUFEMZ

    View Slide

  15. 5IJTJTXIZXFHFUBTZOUBYFSSPS
    XIFOXFUSZUPVTFAAJOUIFDVSSFOU.3*

    View Slide

  16. #VUUIFO JGXFSFBMMZ SFBMMZXBOUPQFSBUPS
    IPXEPXFEPʜ

    View Slide

  17. 5BLFPOUIFDIBMMFOHFPGBEEJOH
    OFXTZOUBYJO3VCZ

    View Slide

  18. 4P JOUIJTUBML
    *XPVMEMJLFUPTIBSFXJUIQSPHSBNNFSTMJLFNF
    XIPJTOPUBQBSTFSFYQFSU
    XIBUJUUBLFTUPBEEOFXTZOUBYUP.3*
    CBTFEPONZEPDVNFOUBSZ

    View Slide

  19. *OBEEJUJPO
    .3*TQBSTFSIBTCFFOBDUJWFMZEFWFMPQFEBOE
    TFWFSBMUBMLTXJMMCFHJWFOBUUIJTZFBST3VCZ,BJHJ
    5IJTUBMLXJMMCFCBTFEPOUIFTPVSDFDPEFPG
    .3*XBTSFMFBTFEUIJT.BSDI

    View Slide

  20. 5PVSJOH.3*`TQBSTFS

    View Slide

  21. /PX -FUTUBLFBRVJDLMPPL
    BUIPX.3*QBSTFT3VCZTDSJQUT
    CFGPSFXFUSZUPBEEBOFXTZOUBYUP3VCZ

    View Slide

  22. "3VCZTDSJQUDPOTJTUTPGBTFRVFODFPGUPLFOT
    UIBUBSFWBMJEBT3VCZTZOUBY
    5PLFOTDPOTUJUVUFB3VCZTDSJQU
    5IJTTDSJQUDPOTJTUTPG QVUT )FMMP

    puts "Hello"

    View Slide

  23. .3*SFBETUIFTFUPLFOTPOFCZPOF GSPNMFGUUPSJHIU
    VTJOHBGVODUJPODBMMFETDBOOFS
    )PXTDBOOFSXPSLT
    SFBETUIFUPLFOJT
    puts "Hello"
    QVUT
    4DBOOFS
    /PUF4DBOOFSJTBMTPDBMMFEMFYJDBMBOBMZ[FSPSMFYFS
    CVUKVTUDBMMJUTDBOOFSJOUIJTTMJEF

    View Slide

  24. 5IFTDBOOFSUIFOEFUFSNJOFTUIFLJOEPGUPLFOJUSFBET
    5IFLJOEPGUPLFOJTDBMMFEBTZNCPM
    )PXTDBOOFSXPSLT
    EFUFSNJOFTUIFUPLFOQVUTJT U*%&/5*'*&3
    puts "Hello"
    QVUT
    5PLFO
    4DBOOFS

    View Slide

  25. 5IFTDBOOFSTFUTUIFWBMVFPGUIFUPLFOUPBTZNCPM
    5IJTWBMVFDBOCFBOJE BO3/PEF PSTPNFUIJOHFMTF
    )PXTDBOOFSXPSLT
    TFUTU*%&/5*'*&3UPBNFUIPEJE QVUT
    puts "Hello"
    U*%&/5*'*&3
    QVUT
    4ZNCPM
    5PLFO
    /PUF4PNFUPLFOTIBWFOPWBMVF

    /PUF7BMVFJTDBMMFETFNBOUJDWBMVF CVUKVTUDBMMJUWBMVFJOUIJTTMJEF

    4DBOOFS

    View Slide

  26. 'JOBMMZ UIFTDBOOFSSFUVSOTUIJTTZNCPMXJUIUIFWBMVF
    UPBGVODUJPODBMMFEBQBSTFS
    )PXTDBOOFSXPSLT
    puts "Hello"
    SFUVSOTUIFTZNCPMXJUIUIFWBMVFUPBQBSTFS
    U*%&/5*'*&3
    QVUT
    QVUT
    7BMVF
    4ZNCPM
    5PLFO
    4DBOOFS

    View Slide

  27. )PXQBSTFSXPSLT
    5IFQBSTFSJTBGVODUJPOUIBUSFDFJWFTBTZNCPMGSPNUIF
    TDBOOFS DIFDLTTZOUBY DSFBUFT3/PEFT BOETPPO
    5IFSFBSFNBOZHSBNNBSSVMFTEF
    fi
    OFEJOUIFQBSTFS
    QBSTFS
    U*%&/5*'*&3
    QVUT
    7BMVF
    4ZNCPM 3/PEF
    7$"-- QVUT

    SFDFJWF DSFBUF
    .BOZHSBNNBSSVMFT

    View Slide

  28. )PXQBSTFSXPSLT
    5IFTZOUBYSVMFTMPPLMJLFUIJT
    )FSFUIFSJHIUBOEMFGUIBOETJEFTBSFEF
    fi
    OFE
    // An example of a grammar rule
    operation : tIDENTIFIER
    | tCONSTANT
    | tFID
    ;
    5IFMFGUIBOETJEF 5IFSJHIUIBOETJEF
    5IFMFGUIBOETJEFEF
    fi
    OFTTZNCPMTUIBUNBLFTZNCPMTNPSFBCTUSBDU
    5IFSJHIUIBOETJEFEF
    fi
    OFTUIFPSJHJOBMTZNCPMT

    View Slide

  29. )PXQBSTFSXPSLT
    4ZNCPMTBSFUVSOFEJOUPNPSFBCTUSBDUTZNCPM
    XIFOUIFZNBUDIUIFSJHIUIBOETJEFPGUIFTZOUBYSVMFT
    5IJTDIBOHFJTDBMMFESFEVDUJPO
    // An example of a grammar rule
    operation : tIDENTIFIER
    | tCONSTANT
    | tFID
    ;
    .PSFBCTUSBDUTZNCPM
    0SJHJOBMTZNCPMTBSFUVSOFEJOUP
    NPSFBCTUSBDUTZNCPM

    View Slide

  30. )PXQBSTFSXPSLT
    5IFWBMVFTFUGPSUIFTZNCPMCFGPSFSFEVDUJPOXJMMCF
    DBSSJFEPWFSUPUIFTZNCPMBGUFSSFEVDUJPO
    6OMFTTBOBDUJPOUIBUXJMMCFEJTDVTTFEMBUFSJTEF
    fi
    OFE

    // An example of a grammar rule
    operation : tIDENTIFIER
    | tCONSTANT
    | tFID
    ;
    5IFNFUIPEJEQVUT UIFWBMVFPGU*%&/5*'*&3
    JT
    TFUUPPQFSBUJPOBGUFSSFEVDUJPO

    View Slide

  31. )PXQBSTFSXPSLT
    "MUIPVHIPQUJPOBM XIBUUPCFQFSGPSNFEXIFOB
    SFEVDUJPOIBTPDDVSSFEDBOCFEF
    fi
    OFEJOBHSBNNBSSVMF
    5IJTJTDBMMFEBTFNBOUJDBDUJPO
    /PUF4JNQMZDBMMJUBOBDUJPOJOUIJTTMJEF

    // An example of a grammar rule
    fcall : operation
    {
    $$ = NEW_FCALL($1, 0, &@$);
    nd_set_line($$, p->tokline);
    }
    5IJTBDUJPOJTFYFDVUFE
    XIFOPQFSBUJPOJTSFEVDFEUPGDBMM

    View Slide

  32. )PXBQBSTFSXPSLT
    8JUIJOUIFBDUJPO
    FBDIWBMVFPGTZNCPMTDBOCFBDDFTTFE
    "WBSJBCMF5IFOVNCFSPGUIFPSEFSPGUIFTZNCPMTCFGPSFSFEVDUJPO
    TUPSFTFBDIWBMVF
    "WBSJBCMFNFBOTUIFTZNCPMTWBMVFBGUFSSFEVDUJPO
    // An example of a grammar rule
    fcall : operation
    {
    // $1
    // $$
    }
    5IFWBMVFPGPQFSBUJPO5IFNFUIPEJEQVUT
    5IFWBMVFPGGDBMM

    View Slide

  33. )PXQBSTFSXPSLT
    *ONBOZDBTFT UIFBDUJPOEF
    fi
    OFTBQSPDFTTUPDSFBUFBO
    3/PEFGSPNUIFWBMVFTFUJOUIFTZNCPMCFGPSFSFEVDUJPO
    5IF3/PEFDSFBUFEJOUIJTXBZJTTFUUPUIFTZNCPMBGUFS
    SFEVDUJPO
    // An example of a grammar rule
    fcall : operation
    {
    $$ = NEW_FCALL($1, 0, &@$);
    nd_set_line($$, p->tokline);
    }
    $SFBUFBO3/PEFGSPN
    BOETFUJUUP

    View Slide

  34. )PXQBSTFSXPSLT
    4PNFUJNFTUXPPSNPSFTZNCPMTBSFSFEVDFEBUPODF
    *OTVDIDBTFT HSBNNBSSVMFTWFSJGZUIBUUIFTFRVFODFPG
    TZNCPMTJTDPSSFDU
    *GUIFTFRVFODFPGTZNCPMTJTJODPSSFDU UIFSFEVDUJPOXJMM
    OPUCFFYFDVUFE BOEBTZOUBYFSSPSXJMMPDDVS
    // An example of a grammar rule
    command : fcall command_args
    // ...
    7FSJGZJOHGDBMMBOEDPNNBOE@BSHTBSF
    JOBSPXBOEPSEFSGSPNMFGUUPSJHIU

    View Slide

  35. "MMPGUIFTZNCPMT HSBNNBSSVMFT BOEUIFTDBOOFSBSF
    EF
    fi
    OFEJOUIF
    fi
    MFQBSTFZJOUIF.3*TPVSDF
    SVCZQBSTFZ

    View Slide

  36. /PX CBTFEPOUIJT
    -FUT
    fi
    HVSFPVUIPXUPJNQMFNFOUAAJO.3*

    View Slide

  37. $BMMJOHBNFUIPEXJUIAA

    View Slide

  38. 5IF
    fi
    STUJEFBJT3FQMBDFAAXJUI*OUFHFSTVDD
    XIFOAAJTSFBEGSPNUIFTPVSDFDPEF
    i = 0
    i++ # => Call Integer#succ and return 1
    *OUFHFSTVDDSFUVSOTUIFWBMVFPGUIFSFTVMU
    XIJDIJTJODSFNFOUFECZUIFSFDFJWFS*OUFHFSPCKFDU
    i = 0
    i.succ # => 1
    $BMMJOHBNFUIPEXJUIAA
    AABDUTMJLFBOBMJBTGPS*OUFHFSTVDDJOUIJTJEFB

    View Slide

  39. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT
    $BMMJOHBNFUIPEXJUIAA

    View Slide

  40. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT
    "OFXTZNCPMGPS
    4ZNCPM
    i++
    $BMMJOHBNFUIPEXJUIAA

    5PLFO
    %F
    fi
    OFBOFXTZNCPMGPSUIFUPLFO BOENBLFUIF
    TDBOOFSSFUVSOTUIFTZNCPMXIFOJUJTSFBEUPLFO

    View Slide

  41. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT
    "EEHSBNNBSSVMFTUPQBSTFBTDSJQUMJLFAJA
    BOEDBMM*OUFHFSTVDDJOTJEFPGUIFBDUJPO
    -FUTHFUUPJU
    ⬇︎
    i = 0
    i++ # Call Integer#succ internally
    $BMMJOHBNFUIPEXJUIAA
    %F
    fi
    OFBOFXTZNCPMGPSUIFUPLFO BOENBLFUIF
    TDBOOFSSFUVSOTUIFTZNCPMXIFOJUJTSFBEUPLFO

    View Slide

  42. // ruby/parse.y
    // ...
    %token tIDENTIFIER "local variable or method"
    %token tFID "method"
    %token tGVAR "global variable"
    %token tIVAR "instance variable"
    %token tCONSTANT "constant"
    %token tCVAR "class variable"
    %token tLABEL "label"
    %token tINTEGER "integer literal"
    %token tFLOAT "float literal"
    %token tRATIONAL "rational literal"
    // ...
    %F
    fi
    OFBOFXTZNCPM
    *OQBSTFZ TZNCPMTBSFEF
    fi
    OFEMJLFUIJT

    View Slide

  43. // ruby/parse.y
    // ...
    %token tINCOP "increment operator"
    %token tIDENTIFIER "local variable or method"
    %token tFID "method"
    %token tGVAR "global variable"
    %token tIVAR "instance variable"
    %token tCONSTANT "constant"
    %token tCVAR "class variable"
    %token tLABEL "label"
    %token tINTEGER "integer literal"
    %token tFLOAT "float literal"
    %token tRATIONAL "rational literal"
    // ...
    /PXMFU`TBEEBOFXTZNCPMU*/$01IFSF
    GPSUIFUPLFO
    %F
    fi
    OFBOFXTZNCPM
    %F
    fi
    OFBOFXTZNCPM

    View Slide

  44. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    .BLFUIFTDBOOFSSFUVSOU*/$01
    5IFO NPEJGZUIFTDBOOFSUPSFUVSOU*/$01
    XIFOJTSFBE
    *O.3* BGVODUJPOQBSTFS@ZZMFY
    EPFTNBOZPGXIBU
    BTDBOOFSEPFTGPSMFYJDBMBOBMZTJT

    View Slide

  45. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    .BLFUIFTDBOOFSSFUVSOU*/$01
    5IFSFJTBIVHFTXJUDITUBUFNFOUJOJU
    5IJTJTUPSFBEUIFDIBSBDUFSTJOUIFTDSJQUPOFBUB
    UJNFBOEEPTPNFUIJOHEFQFOEJOH
    POUIFDIBSBDUFSSFBE
    %PTPNFUIJOHEFQFOEJOHPOUIFDIBSBDUFSTSFBE

    View Slide

  46. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    // ...
    .BLFUIFTDBOOFSSFUVSOU*/$01
    *OUIJTTXJUDITUBUFNFOU JUJTBMSFBEZEF
    fi
    OFE
    XIBUUPEPJGUIFDIBSBDUFSSFBEJT
    *GUIFDIBSBDUFSSFBEJT

    View Slide

  47. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    c = nextc(p);
    if (IS_AFTER_OPERATOR()) // ...
    if (c == '=') // ...
    .BLFUIFTDBOOFSSFUVSOU*/$01
    *OJU BOBQQSPQSJBUFTZNCPMJTSFUVSOFEEFQFOEJOHPO
    UIFDIBSBDUFSCFGPSFBOEBGUFSUIF
    3FBEUIFOFYUDIBSBDUFSPGUIF
    3FUVSOTPNFUPLFOJGUIFQSFWJPVTDIBSBDUFSJT
    3FUVSOTPNFUPLFOJGUIFOFYUDIBSBDUFSJT
    "OEPUIFS

    View Slide

  48. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    c = nextc(p);
    if (c == '+')
    .BLFUIFTDBOOFSSFUVSOU*/$01
    -FUTBEEBOFXDPOEJUJPOIFSF
    *GUIFOFYUDIBSBDUFSBGUFSJTBHBJO
    3FBEUIFOFYUDIBSBDUFSPGUIF
    *GUIFOFYUDIBSBDUFSJTBHBJO

    View Slide

  49. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    c = nextc(p);
    if (c == '+') {
    return tINCOP;
    }
    // ...
    .BLFUIFTDBOOFSSFUVSOU*/$01
    SFUVSOU*/$01 UIFOFXTZNCPMEF
    fi
    OFEFBSMJFS
    5IFTDBOOFSNPEJ
    fi
    DBUJPOJTOPXDPNQMFUF
    3FBEUIFOFYUDIBSBDUFSPGUIF
    *GUIFOFYUDIBSBDUFSJTBHBJO
    3FUVSOU*/$01

    View Slide

  50. // ruby/parse.y
    method_call : fcall paren_args
    // ...
    | primary_value call_op operation2 opt_paren_args
    // ...
    | primary_value tCOLON2 operation2 paren_args
    // ...
    | primary_value tCOLON2 operation3
    // ...
    | primary_value call_op paren_args
    // ...
    %F
    fi
    OFBOFXHSBNNBSSVMF
    /FYU MFU`TEF
    fi
    OFBOFXHSBNNBSSVMFUPUIFQBSTFS
    GPSUIFTZOUBYMJLFAJA
    QBSTFZEF
    fi
    OFTNBOZHSBNNBSSVMFTMJLFUIJTUP
    TVQQPSUWBSJPVTQBUUFSOTPGNFUIPEDBMMT

    View Slide

  51. // ruby/parse.y
    method_call : fcall paren_args
    // ...
    | primary_value call_op operation2 opt_paren_args
    // ...
    | primary_value tCOLON2 operation2 paren_args
    // ...
    | primary_value tCOLON2 operation3
    // ...
    | primary_value call_op paren_args
    // ...
    | ????
    %F
    fi
    OFBOFXHSBNNBSSVMF
    *UTFFNTBHPPEJEFBUPEF
    fi
    OFBOFXHSBNNBSSVMF
    IFSFGPSBNFUIPEDBMM
    %F
    fi
    OFBOFXHSBNNBSSVMF

    View Slide

  52. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    %F
    fi
    OFBOFXHSBNNBSSVMF
    )FSFJTUIFHSBNNBSSVMFUPCFBEEFE
    5IFOFXHSBNNBSSVMFDIFDLTUIBUUIFTZNCPMT
    QSJNBSZ@WBMVFBOEU*/$01BSFJOBSPX
    %F
    fi
    OFBOFXHSBNNBSSVMF

    View Slide

  53. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    QSJNBSZ@WBMVFJTUIFTZNCPMGPSUIFSFDFJWFSPGUIJT
    FYQSFTTJPO BOEU*/$01JTGPSAA
    5IJTNBLFTFYQSFTTJPOTMJLFAJAWBMJEBTBTZOUBY

    5IFTFTZNCPMTNFBOTʜ J
    # In a Ruby script
    i++
    %F
    fi
    OFBOFXHSBNNBSSVMF

    View Slide

  54. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    // ...
    %F
    fi
    OFBOFXBDUJPOUPDBMM*OUFHFSTVDD
    /FYU EF
    fi
    OFBOBDUJPO XIJDIDBMMT*OUFHFSTVDD
    XIFOSFEVDUJPOIBTPDDVSSFEGPSUIJTHSBNNBSSVMF

    View Slide

  55. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    %F
    fi
    OFBOFXBDUJPOUPDBMM*OUFHFSTVDD
    5IF
    fi
    STUXFOFFEUPEPJTUPUFMMUIFTDBOOFSUIBUUIJT
    FYQSFTTJPOFOETXIFOJTSFBE
    5IJTJTOFFEFEUPQSFWFOUUIFTDBOOFSSFBETUIFOFYU
    UPLFOBGUFSBOEDBVTJOHBTZOUBYFSSPS5PEPTP
    DBMMUIFNBDSP4&5@-&9@45"5&XJUI&913@&/%
    5FSNJOBUFUIJTFYQSFTTJPO
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  56. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ???
    %F
    fi
    OFBOFXBDUJPOUPDBMM*OUFHFSTVDD
    /FYU MFUT
    fi
    OBMMZDBMM*OUFHFSTVDD
    )PXDBOXFEPUIBU
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  57. // ruby/parse.y
    static NODE *
    new_qcall(struct parser_params* p,
    ID atype,
    NODE *recv,
    ID mid,
    NODE *args,
    const YYLTYPE *op_loc,
    const YYLTYPE *loc)
    OFX@RDBMM

    .3*QSPWJEFTOFX@RDBMM
    UPDSFBUFBO3/PEF
    UPDBMMBNFUIPE
    -FUTVTFUIJTGVODUJPOUPEPXIBUJTUIFTBNF
    BTUIFNFUIPEDBMMJOUIFBDUJPO

    View Slide

  58. // ruby/parse.y
    static NODE *
    new_qcall(struct parser_params* p,
    ID atype,
    NODE *recv,
    ID mid,
    NODE *args,
    const YYLTYPE *op_loc,
    const YYLTYPE *loc)
    OFX@RDBMM

    4PNFBSHVNFOUTBSFSFRVJSFEUPDBMMUIJTGVODUJPO
    "O3/PEFUIBUJTUIFSFDFJWFSPGUIFNFUIPE
    5IFNFUIPEJE
    "O3/PEFUIBUJTUIFBSHVNFOUTPGUIFNFUIPE

    View Slide

  59. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    new_qcall(p, $2, ???, ???, ???, &@2, &@$);
    $BMMOFX@RDBMM
    UPDBMM*OUFHFSTVDD
    4PMFUTQSFQBSFUIFBSHVNFOUTUPDBMMOFX@RDBMM

    OFX@RDBMM
    OFFETBSHVNFOUT
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  60. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    new_qcall(p, $2, ???, ???, ???, &@2, &@$);
    $BMMOFX@RDBMM
    UPDBMM*OUFHFSTVDD
    'JSTU OFX@RDBMM
    OFFETBO3/PEFUIBUJTUIFSFDFJWFS
    BTUIFUIJSEBSHVNFOU
    "O3/PEFUIBUJTUIFSFDFJWFS
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  61. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    $BMMOFX@RDBMM
    UPDBMM*OUFHFSTVDD
    "TNFOUJPOFEFBSMJFS QSJNBSZ@WBMVFJTUIFTZNCPM
    UIBUJTUIFSFDFJWFSPGUIJTFYQSFTTJPO
    5IJTTZNCPMIBTBO3/PEFPGUIFSFDFJWFSBTJUTWBMVF
    QSJNBSZ@WBMVF ʹUIFSFDFJWFS
    IBT
    BO3/PEFPGUIFSFDFJWFSPCKFDUBTJUTWBMVF
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  62. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    // ...
    $1;
    $BMMOFX@RDBMM
    UPDBMM*OUFHFSTVDD
    3FNFNCFS XFDBOHFUUIFTZNCPMTWBMVFXJUI
    BOVNCFSPGUIFPSEFSPGUIFTZNCPMT
    JOBOBDUJPO
    5IFWBMVFPGQSJNBSZ@WBMVF JF UIF3/PEFUIBUJT
    UIFSFDFJWFSJTTUPSFEGPS
    5IFWBMVFPGQSJNBSZ@WBMVF

    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  63. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    new_qcall(p, $2, $1, ???, ???, &@2, &@$);
    $BMMOFX@RDBMM
    UPDBMM*OUFHFSTVDD
    4PDBOCFQBTTFEBTJTBTUIFUIJSEBSHVNFOUPG
    OFX@RDBMM

    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    5IFWBMVFPGQSJNBSZ@WBMVF
    5IF3/PEFUIBUJTUIFSFDFJWFS

    View Slide

  64. $BMMOFX@RDBMM
    UPDBMM*OUFHFSTVDD
    // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    new_qcall(p, $2, $1, ???, ???, &@2, &@$);
    /FYU UIFGPVSUIBSHVNFOUPGOFX@RDBMM
    JT
    BNFUIPEJEPGUIFDBMMJOHNFUIPE
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    5IFNFUIPEJE

    View Slide

  65. $BMMOFX@RDBMM
    UPDBMM*OUFHFSTVDD
    // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ID succ = rb_intern("succ");
    new_qcall(p, $2, $1, succ, ???, &@2, &@$);
    (FUUIFNFUIPEJEPG*OUFHFSTVDDBOEQBTTJU
    UPOFX@RDBMM

    (FUUIFNFUIPEJEPG*OUFHFSTVDD
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    1BTTUIFNFUIPEJE

    View Slide

  66. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ID succ = rb_intern("succ");
    new_qcall(p, $2, $1, succ, ???, &@2, &@$);
    // ...
    }
    $BMMOFX@RDBMM
    UPDBMM*OUFHFSTVDD
    5IF
    fi
    GUIBSHVNFOUJTBO3/PEFXIJDIJT
    UIFDBMMJOHNFUIPEBSHVNFOU
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    5IFBSHVNFOUTPGUIFDBMMJOHNFUIPE

    View Slide

  67. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ID succ = rb_intern("succ");
    new_qcall(p, $2, $1, succ, Qnull, &@2, &@$);
    // ...
    }
    $BMMOFX@RDBMM
    UPDBMM*OUFHFSTVDD
    )PXFWFS *OUFHFSTVDDOPBSHVNFOU
    -FUTQBTTOJMIFSF
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    1BTTOJM

    View Slide

  68. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ID succ = rb_intern("succ");
    $$ = new_qcall(p, $2, $1, succ, Qnull, &@2, &@$);
    $BMMOFX@RDBMM
    UPDBMM*OUFHFSTVDD
    'JOBMMZ TFUUIF3/PEFPGUIFNFUIPEDBMM UIFSFUVSO
    WBMVFPGOFX@RDBMM
    UPUIFTZNCPMBGUFSSFEVDUJPO
    5IJTDPNQMFUFTUIFWJUBMQBSUPGUIFJNQMFNFOUBUJPO
    "TTJHOUIFSFUVSOWBMVFUPUIFTZNCPMBGUFSSFEVDUJPO
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  69. *TJUXPSLJOH
    NBLFSVO
    3VOUIFDPNQJMFDPNNBOE
    # ruby/test.rb
    i = 0
    i++
    8JUIUIJTJNQMFNFOUBUJPO XSJUFBTDSJQUDPOUBJOJOH
    AA UIFOSVOUIFDPNQJMFDPNNBOE

    View Slide

  70. *UMPPLTXPSLJOH
    NBLFSVO
    HFOFSBUJOHQBSTFD
    DPNQJMJOHQBSTFD
    MJOLJOHNJOJSVCZ
    NJOJSVCZ*SVCZMJC*a
    *FYUDPNNPOa
    SBSNEBSXJOGBLF
    SVCZUFTUSC

    # ruby/test.rb
    i = 0
    i++
    *USFUVSOTBOJODSFNFOUFEWBMVFXJUIPVUBOZ
    TZOUBYFSSPS
    5IFJNQMFNFOUBUJPOPGJTTVDDFTTGVM
    *USFUVSOTJODSFNFOUFEWBMVF

    View Slide

  71. )PXFWFSʜ

    View Slide

  72. *GPVOEBQSPCMFNXJUIUIJTJNQMFNFOUBUJPO
    i = 0
    i++ # => It returns 1
    i # => But i is still 0...
    *UJTUIBU*OUFHFSTVDDEPFTOPUBTTJHOJUTSFUVSOWBMVF
    UPUIFSFDFJWFSWBSJBCMF

    View Slide

  73. 0, MFU`TUIJOLPGBOPUIFSXBZ

    View Slide

  74. $BMMJOHBNFUIPEXJUIAA SFWJTFE

    View Slide

  75. *OUIFQSFWJPVTJNQMFNFOUBUJPO
    UIFSFJTBQSPCMFNUIBU*OUFHFSTVDDEJEOPUBTTJHO
    UIFSFUVSOWBMVFUPUIFSFDFJWFS
    i = 0
    i++ # => Call Integer#succ, then i is still 0
    4P JOTUFBEPG*OUFHFSTVDD MFUTDBMMTPNFPUIFS
    UIBUDBOBTTJHOUIFJODSFNFOUFEWBMVFUPUIFSFDFJWFS
    i = 0
    i++ # => Call some other method, then i becomes 1
    $BMMJOHBNFUIPEXJUIAA SFWJTFE

    NFUIPE

    View Slide

  76. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT
    $BMMJOHBNFUIPEXJUIAA SFWJTFE

    View Slide

  77. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT
    "EEBOFXNFUIPE*OUFHFS@@QMVTQMVT@@UPBTTJHO
    BOJODSFNFOUFEWBMVFUPUIFSFDFJWFS
    i = 0
    i.__plusplus__
    p i # => 1
    $BMMJOHBNFUIPEXJUIAA SFWJTFE

    View Slide

  78. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT
    "EEBOFXNFUIPE*OUFHFS@@QMVTQMVT@@UPBTTJHO
    BOJODSFNFOUFEWBMVFUPUIFSFDFJWFS

    $BMM*OUFHFS@@QMVTQMVT@@JOTUFBEPG*OUFHFSTVDD
    JOUIFBDUJPO
    -FUTHFUUPJU
    ⬇︎
    i = 0
    i++ # Call i.__plusplus__ internally
    $BMMJOHBNFUIPEXJUIAA SFWJTFE

    View Slide

  79. # ruby/numeric.rb
    class Integer
    def __plusplus__(name, b)
    b.local_variable_set(name, self.succ)
    end
    # ...
    %F
    fi
    OF*OUFHFS@@QMVTQMVT@@
    ,FSOFMMPDBM@WBSJBCMF@TFUPSTPNFUIJOH
    %FUFSNJOFUIFUZQFPGUIFWBSJBCMFGSPNUIFWBSJBCMFOBNF

    1BTTUIFBSHVNFOUT
    ɾWBSJBCMFOBNF
    ɾB#JOEJOHPCKFDU
    'JSTU MFU`TEF
    fi
    OF*OUFHFS@@QMVTQMVT@@
    *UJODSFNFOUTTFMGBOETFUTJUTWBMVFUPBWBSJBCMF
    JOJUTFOWJSPONFOUVTJOHUIFBSHVNFOUT

    View Slide

  80. # ruby/numeric.rb
    class Integer
    def __plusplus__(name, b)
    b.local_variable_set(name, self.succ)
    end
    # ...
    %F
    fi
    OF*OUFHFS@@QMVTQMVT@@
    *OUFHFS@@QMVTQMVT@@DBOCFDBMMFEMJLFUIJT
    JOB3VCZTDSJQU
    *UBTTJHOTBOJODSFNFOUFEWBMVFUPUIFSFDFJWFS
    # In a Ruby script
    i = 0
    i.__plusplus__("i", binding)
    i # => 1
    1BTTUIFBSHVNFOUT
    ɾWBSJBCMFOBNF
    ɾ,FSOFMCJOEJOH

    View Slide

  81. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ID succ = rb_intern("succ");
    $$ = new_qcall(p, $2, $1, succ, Qnull, &@2, &@$);
    // ...
    }
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    /FYU MFU`TNPEJGZUIFBDUJPOUPDBMM
    *OUFHFS@@QMVTQMVT@@JOTUFBEPG*OUFHFSTVDD
    *OUFHFSTVDDJTDBMMFEJOUIFQSFWJPVTJNQMFNFOUBUJPO
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  82. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    // ...
    $$ = new_qcall(p, $2, $1, ???, ???, &@3, &@$);
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    'JSTU JOUIFTBNFXBZBTCFGPSF
    DBMMUIF4&5@-&9@45"5&NBDSPBOEQBTT
    BTUIFUIJSEBSHVNFOUUPOFX@RDBMM

    5FSNJOBUFUIJTFYQSFTTJPO
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    1BTTUIFWBMVFPGUIFSFDFJWFS

    View Slide

  83. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ID plusplus = rb_intern("__plusplus__");
    $$ = new_qcall(p, $2, $1, plusplus, ???, &@3, &@$);
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    1BTTUIFNFUIPEJEPG*OUFHFS@@QMVTQMVT@@
    BTUIFGPVSUIBSHVNFOU
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    1BTTUIFNFUIPEJE
    (FUUIFNFUIPEJEPG*OUFHFS@@QMVTQMVT@@

    View Slide

  84. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ID plusplus = rb_intern("__plusplus__");
    $$ = new_qcall(p, $2, $1, plusplus, ???, &@3, &@$);
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    /PX *OUFHFS@@QMVTQMVT@@SFRVJSFTUXPBSHVNFOUT
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    # In a Ruby script
    i = 0
    i.__plusplus__("i", binding)

    View Slide

  85. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ID plusplus = rb_intern("__plusplus__");
    $$ = new_qcall(p, $2, $1, plusplus, ???, &@3, &@$);
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    5IF
    fi
    STUJTBTUSJOHMJUFSBMPGUIFWBSJBCMFOBNF
    BOEUIFTFDPOEJTBNFUIPEDBMMPG,FSOFMCJOEJOH
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    # In a Ruby script
    i = 0
    i.__plusplus__("i", binding)
    1BTTUIFBSHVNFOUT
    ɾWBSJBCMFOBNF
    ɾ,FSOFMCJOEJOH

    View Slide

  86. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ID plusplus = rb_intern("__plusplus__");
    $$ = new_qcall(p, $2, $1, plusplus, ???, &@3, &@$);
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    5IFTFBSHVNFOUTNVTUCFQSFQBSFEBTBO3/PEF
    UIBUJTBOBSSBZBOEUIFOQBTTFEUPUIF
    fi
    GUIBSHVNFOU
    PGOFX@RDBMM

    1BTTUIFBSHVNFOUTIFSF
    BTBO3/PEFUIBUJTBOBSSBZ
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  87. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    // $1;
    // $1->u1.id;
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    4P MFUTDSFBUFUIFTUSJOHMJUFSBMPGUIFSFDFJWFS`T
    WBSJBCMFOBNF
    8FDBOHFUUIF3/PEFPGUIFSFDFJWFSGSPN
    5IFWBSJBCMFJEJTTUPSFEJOBNFNCFSPGUIJT3/PEF
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    5IFWBMVFPGQSJNBSZ@WBMVF
    5IF3/PEFPGUIFSFDFJWFSPCKFDU
    5IFWBSJBCMFJEPGUIFSFDFJWFS

    View Slide

  88. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    // ...
    VALUE v = QUOTE_ID($1->u1.id);
    NODE *receiver = NEW_LIT(v, &NULL_LOC);
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    $SFBUFB7"-6&PG4USJOHGSPNUIFWBSJBCMFJE
    BOEDSFBUFBO3/PEFPGBMJUFSBMGSPNUIJTWBMVF
    *UDBOCFUIF
    fi
    STUBSHVNFOUPG*OUFHFS@@QMVTQMVT@@
    "O3/PEFUIBUJTBTUSJOHMJUFSBMGSPNUIF7"-6&
    7"-6&PGUIFTUSJOHGSPNUIFWBSJBCMFJE
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  89. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    // ...
    VALUE v = QUOTE_ID($1->u1.id);
    NODE *receiver = NEW_LIT(v, &NULL_LOC);
    NODE *binding = NEW_VCALL(rb_intern("binding"), &@$);
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    /FYU DSFBUFBO3/PEFUIBUDBMMT,FSOFCJOEJOH
    BTUIFTFDPOEBSHVNFOUPG*OUFHFS@@QMVTQMVT@@
    "O3/PEFUIBUDBMMT,FSOFMCJOEJOH
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  90. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    // ...
    VALUE v = QUOTE_ID($1->u1.id);
    NODE *receiver = NEW_LIT(v, &NULL_LOC);
    NODE *binding = NEW_VCALL(rb_intern("binding"), &@$);
    NODE *args = NEW_LIST(receiver, &NULL_LOC);
    args = list_append(p, args, binding);
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    $SFBUFBO3/PEFUIBUJTBOBSSBZGSPNBO3/PEF
    PGUIFMJUFSBMBOEBO3/PEFPGUIFNFUIPEDBMM
    "O3/PEFUIBUJTBOBSSBZPGUIFBSHVNFOUT
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  91. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    // ...
    VALUE v = QUOTE_ID($1->u1.id);
    NODE *receiver = NEW_LIT(v, &NULL_LOC);
    NODE *binding = NEW_VCALL(rb_intern("binding"), &@$);
    NODE *args = NEW_LIST(receiver, &NULL_LOC);
    args = list_append(p, args, binding);
    ID plusplus = rb_intern("__plusplus__");
    $$ = new_qcall(p, $2, $1, plusplus, args, &@2, &@$);
    .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@
    5IFOQBTTJUUPOFX@RDBMM
    BTJUT
    fi
    GUIBSHVNFOU
    5IJTDPNQMFUFTUIFWJUBMQBSUPGUIFJNQMFNFOUBUJPO
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  92. *TJUXPSLJOH
    8JUIUIJTJNQMFNFOUBUJPO XSJUFBTDSJQUDPOUBJOJOH
    AABOEDIFDLJOHUIFWBMVFPGUIFSFDFJWFS
    UIFOFYFDVUFTUIFDPNQJMFDPNNBOE
    NBLFSVO
    3VOUIFDPNQJMFDPNNBOE
    # ruby/test.rb
    i = 0
    i++
    p i

    View Slide

  93. *UMPPLTXPSLJOH
    NBLFSVO
    HFOFSBUJOHQBSTFD
    DPNQJMJOHQBSTFD
    MJOLJOHNJOJSVCZ
    NJOJSVCZ*SVCZMJC*a
    *FYUDPNNPOa
    SBSNEBSXJOGBLF
    SVCZUFTUSC

    # ruby/test.rb
    i = 0
    i++
    p i
    JJTOPXJODSFNFOUFE
    5IFOUIFDPNQJMBUJPOTVDDFFEFE BOEUIFWBSJBCMFXBT
    BTTJHOFEBOJODSFNFOUFEWBMVF
    5IFJNQMFNFOUBUJPOPGJTTVDDFTTGVM

    View Slide

  94. )PXFWFSʜ

    View Slide

  95. *GPVOEBQSPCMFNJOUIJTJNQMFNFOUBUJPOBHBJO
    1++ # => ???
    *OUIJTJNQMFNFOUBUJPO
    AABDUTMJLFBOBMJBTGPS*OUFHFS@@QMVTQMVT@@
    *UNBLFTVTXBOUUPDBMMAAFWFOJGUIFSFDFJWFSJTOPU
    BWBSJBCMFCVUBO*OUFHFSMJUFSBM
    )PXFWFS EPJOHTPXPVME

    View Slide

  96. DBVTFBTFHNFOUBUJPOGBVMU

    View Slide

  97. 5IFSFDFJWFSJTOPUBMXBZTBWBSJBCMF
    // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    // ...
    SET_LEX_STATE(EXPR_END);
    VALUE v = QUOTE_ID($1->u1.id);
    5IFSFBTPOJTUIBUUIJTJNQMFNFOUBUJPOOFFET
    UIFWBSJBCMFJEPGUIFSFDFJWFS
    8FUSZUPHFUUIFWBSJBCMFJEVOEFSUIFBTTVNQUJPO
    UIBUUIF3/PEFPGUIFSFDFJWFSPCKFDUIBTJU
    &YQFDUJOHJTBO3/PEF
    UIBUIBTUIFWBSJBCMFJE
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF

    View Slide

  98. // ruby/parse.y
    method_call : // ...
    | primary_value tINCOP
    {
    // ...
    SET_LEX_STATE(EXPR_END);
    VALUE v = QUOTE_ID($1->u1.id);
    )PXFWFS JGUIFSFDFJWFSJTBMJUFSBM UIJT3/PEFEPFTOU
    IBWFUIFWBSJBCMFJE
    *OUIBUDBTF BOVOJOUFOEFENFNPSZBSFBJTBDDFTTFE
    BOEBTFHNFOUBUJPOGBVMUPDDVST
    6OMFTTUIFSFDFJWFSJTBWBSJBCMF
    XFDBO`UBDDFTTWBSJBCMFJE
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    5IFSFDFJWFSJTOPUBMXBZTBWBSJBCMF

    View Slide

  99. 3VCZIBTOPWBSJBCMFPCKFDU
    *UNFBOTUIBUXFJNQMJDJUMZFYQFDUUIFSFDFJWFSUPCFBWBSJBCMF
    XIFOXFXPVMEMJLFUPVTFAA
    "OEUIJTTFFNTUPCFXIBU.BU[TBZTUIBUDBO`UEFGJOFPCKFDU
    PSJFOUFETFNBOUJDTGPSJODSFNFOUEFDSFNFOUPQFSBUPST
    8IJMFAAJTGPSNBOJQVMBUJOHWBSJBCMFT UIFSFBSFOPWBSJBCMF
    PCKFDUTJO3VCZUIBUDBOCFNBOJQVMBUFECZNFUIPET

    View Slide

  100. 4P MFUTTUPQDBMMJOHTPNFNFUIPEXJUIAA
    BOEUIJOLPGBOPUIFSXBZ

    View Slide

  101. 5VSOAAJOUPAA

    View Slide

  102. 4PGBS XFIBWFUSJFEUPDPOTJEFSAABTBOBMJBTPG
    NFUIPEDBMM
    i++
    )PXFWFS JOUIBUXBZ XFIBWFUPDPOTJEFSXIFUIFSUIF
    SFDFJWFSJTBWBSJBCMFPSBMJUFSBM BOEJUJTEJ
    ff
    i
    DVMUUPCF
    DPOTJTUFOUXJUIJO3VCZTTFNBOUJDT
    5VSOAAJOUPAA
    "NFUIPEDBMM

    View Slide

  103. -FU`TGPSHFUBCPVUQSFWJPVTJEFBTBOE
    UIJOLNPSFTJNQMZ
    8IBUXFXBOUUPEPJTAA
    5VSOAAJOUPAA

    View Slide

  104. 4P XIZOPUKVTUDSFBUFUIFTBNF"45XJUIAA
    $ ruby -e "pp RubyVM::AbstractSyntaxTree.parse('i+= 1')"
    (SCOPE@1:0-1:5
    tbl: [:i]
    args: nil
    body: (LASGN@1:0-1:5 :i
    (CALL@1:0-1:5
    (LVAR@1:0-1:1 :i)
    :+
    (LIST@1:4-1:5
    (LIT@1:4-1:5 1)
    nil))))
    5VSOAAJOUPAA
    5IF"45PGAJA

    View Slide

  105. *OQBSTFZ BHSBNNBSSVMFJTEF
    fi
    OFEUPQBSTFTDSJQUT
    TVDIBTAJA
    i++
    i += 1
    4PJGXFDBOEPFYBDUMZUIFTBNFUIJOHBTAJA
    XIFOUIFTDBOOFSSFBEBTDSJQUMJLFAJA
    XF`MMCFBCMFUPQBSTFJUBTAJA MJLFBTZOUBYTVHBS

    5VSOAAJOUPAA
    ⬇︎

    View Slide

  106. 8IFOUIFTDBOOFSSFBETAA JUSFUVSOTUIFTZNCPM
    U01@"4(/GPSAABOEU*/5&(&3GPSAA
    i += 1 i++
    3FUVSOUIFTBNFTZNCPMTBTAA
    U01@"4(/

    U01@"4(/

    U*/5&(&3
    3/PEF

    4ZNCPM
    7BMVF
    U*/5&(&3
    3/PEF

    4PJUXPVMECFOJDFJGUIFTDBOOFSDPVMESFUVSOCPUIU01@"4(/
    BOEU*/5&(&3BUPODFXIFOJUSFBETAA
    CVUVOGPSUVOBUFMZ UIFTDBOOFSPOMZSFUVSOTPOFTZNCPMQFSSFBE

    View Slide

  107. 4PIPXBCPVUNPEJGZJOHUIFTDBOOFSMJLFUIJT
    i += 1 i++
    3FUVSOUIFTBNFTZNCPMTBTAA
    U01@"4(/

    U01@"4(/

    U*/5&(&3
    3/PEF

    4ZNCPM
    7BMVF
    U*/5&(&3
    3/PEF

    'PSUIF
    fi
    STUAA SFUVSOUIFTZNCPMBOEWBMVFPGAA
    'PSUIFTFDPOEAA SFUVSOUIFTZNCPMBOEWBMVFPGJOUFHFS

    View Slide

  108. 5IBOLGVMMZ .3*TDBOOFSIBTMPDBUJPOBMJOGPSNBUJPOJOUIF
    SFBEJOHMJOF5IFZDPVMECFIFMQGVMJOUIJTUJNF
    // ruby/parse.y
    /*
    Structure of Lexer Buffer:
    lex.pbeg lex.ptok lex.pcur lex.pend
    | | | |
    |------------+------------+------------|
    |<---------->|
    token
    */
    5PQQPTJUJPOPGUIFMJOFSFBE &OEQPTJUJPOPGUIFMJOFSFBE
    $VSSFOUQPTJUJPOPGDVSTPS
    5IFTDBOOFSIBTMPDBUJPOBMJOGPSNBUJPO

    View Slide

  109. )FSFJTIPXUIFTDBOOFSTIPVMEXPSLXJUIUIJTJEFB
    i++
    8IFOUIFSFJTBTDSJQUMJLFAJA
    UIFTDBOOFS
    fi
    STUSFBETJBTBWBSJBCMFAJABOE
    SFUVSOTUIFTZNCPMPGJU
    5IFDVSTPSPGUIFTDBOOFSJTIFSF
    8IBUUIFNPEJ
    fi
    FETDBOOFSEPFT
    3FBEBOESFUVSOUIFTZNCPMPGUIFWBSJBCMFJ

    View Slide

  110. i++
    5IFOUIFDVSTPSNPWFTPOFDIBSBDUFSBOEUIFTDBOOFS
    UIFOSFBETUIFOFYUDIBSBDUFS
    4PGBS UIJTJTUIFDPOWFOUJPOBMCFIBWJPS
    5IFDVSTPSJTIFSF
    8IBUUIFNPEJ
    fi
    FETDBOOFSEPFT

    View Slide

  111. i++
    5IFOFYUDIBSBDUFSJTUIF
    fi
    STU
    8IFOUIFTDBOOFSSFBET EPOPUSFUVSOUIFTZNCPM
    JNNFEJBUFMZ CVUQFFLOFYUDIBSBDUFS LFFQJOHUIFDVSTPS
    QPTJUJPO

    8IBUUIFNPEJ
    fi
    FETDBOOFSEPFT
    5IFDVSTPSJTIFSF
    5IJTJT

    View Slide

  112. i++
    *GUIFOFYUDIBSBDUFSJTBMTP
    UIFTDBOOFSDBOTFFUIBUUIJTJTQBSUPGAA
    5IFDVSTPSJTIFSF 5IJTJTBMTP
    5IJTJT
    8IBUUIFNPEJ
    fi
    FETDBOOFSEPFT

    View Slide

  113. i++
    5IFTDBOOFSTIPVMEOPXSFUVSOU01@"4(/
    UIFTZNCPMGPSUIFUPLFOAA
    3FUVSOTU01@"4(/
    5IFDVSTPSJTIFSF
    8IBUUIFNPEJ
    fi
    FETDBOOFSEPFT

    View Slide

  114. i++
    5IFDVSTPSNPWFTPOFDIBSBDUFS UIFOUIFTDBOOFSSFBET
    UIFMBTUDIBSBDUFS
    5IFMBTUDIBSBDUFSJTUIFTFDPOE
    5IFDVSTPSJTIFSF
    5IJTJTBHBJO
    8IBUUIFNPEJ
    fi
    FETDBOOFSEPFT

    View Slide

  115. i++
    8IFOUIFTDBOOFSSFBETUIFTFDPOE
    QFFLBUUIFDIBSBDUFSJOUIFPOFQPTJUJPOCFGPSFJU
    LFFQJOHUIFDVSTPSQPTJUJPO
    5IFDVSTPSJTIFSF

    5IJTJTBHBJO
    8IBUUIFNPEJ
    fi
    FETDBOOFSEPFT

    View Slide

  116. i++
    *GUIFQSFWJPVTDIBSBDUFSJTBMTP
    UIFTDBOOFSDBOTFFUIBUUIJTJTQBSUPGAABHBJO
    5IJTJTBHBJO
    5IFDVSTPSJTIFSF
    5IJTJTBMTP
    8IBUUIFNPEJ
    fi
    FETDBOOFSEPFT

    View Slide

  117. i++
    5IFOUIFTDBOOFSSFUVSOTU*/5&(&3
    UIFTZNCPMPGBOJOUFHFS XJUIUIFWBMVFJOUFHFSTFU
    )PXDBOXFEP
    3FUVSOUIFJOUFHFS
    8IBUUIFNPEJ
    fi
    FETDBOOFSEPFT

    View Slide

  118. // ruby/parse.y
    static eunm yytokentype
    set_integer_literal(struct parser_params *p,
    VALUE v,
    int suffix)
    TFU@JOUFHFS@MJUFSBM

    .3*QSPWJEFTTFU@JOUFHFS@MJUFSBM

    *UDSFBUFTBO3/PEFUIBUJTBOJOUFHFSMJUFSBMBOE
    SFUVSOTUIFTZNCPMU*/5&(&3TFUXJUIJU

    View Slide

  119. i++
    $BMMJOHUIJTGVODUJPOXIFOUIFTFDPOEJTSFBEXJMM
    SFUVSOBTZNCPMXJUIBWBMVFPGJOUFHFS
    5IJTXJMMDBVTFUIFTDBOOFSUPCFIBWFUIFTBNF
    BTXIFOJUSFBETAA-FUTHFUUPJU
    $BMMTFU@JOUFHFS@MJUFSBM

    $BMMTFU@JOUFHFS@MJUFSBM
    UPSFUVSOU*/5&(&3

    View Slide

  120. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    // ...
    .BLFUIFTDBOOFSSFUVSOU01@"4(/GPSUIF
    fi
    STU
    "TXFTBXFBSMJFS QBSTFS@ZZMFY
    UIBUFYFDVUFTMFYJDBM
    BOBMZTJTIBTBTXJUDITUBUFNFOUUPCFEF
    fi
    OFEBT
    XIBUUPEPJGUIFSFBEDIBSBDUFSJT
    -FUTNPEJGZJU
    *GUIFDIBSBDUFSSFBEJT
    i++

    View Slide

  121. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    peekc(p);
    .BLFUIFTDBOOFSSFUVSOU01@"4(/GPSUIF
    fi
    STU
    'JSTU XIFOUIFTDBOOFSSFBET LFFQUIFDVSTPS
    QPTJUJPOBOEQFFLUIFOFYUDIBSBDUFSBGUFSJU
    5IFSFJTBGVODUJPOQFFLD
    GPSJUJO.3*
    1FFLUIFOFYUDIBSBDUFSPG
    i++

    View Slide

  122. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    if (peekc(p) == '+') {
    set_yylval_id('+');
    SET_LEX_STATE(EXPR_BEG);
    return tOP_ASGN;
    }
    .BLFUIFTDBOOFSSFUVSOU01@"4(/GPSUIF
    fi
    STU
    *GUIFOFYUDIBSBDUFSJT SFUVSOUIFTZNCPM
    U01@"4(/XIJDINFBOTAA
    3FUVSOU01@"4(/
    *GUIFOFYUDIBSBDUFSJT
    i++
    U01@"4(/

    View Slide

  123. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    if (peekc(p) == '+') {
    set_yylval_id('+');
    SET_LEX_STATE(EXPR_BEG);
    return tOP_ASGN;
    }
    .BLFUIFTDBOOFSSFUVSOU01@"4(/GPSUIF
    fi
    STU
    5IFOUIFDVSTPSNPWFTBIFBEUPPOFDIBSBDUFSBOE
    QBSTFS@ZZMFY
    BUUFNQUTUPSFBEUIFOFYUDIBSBDUFS
    5IFDVSTPSNPWFTBIFBE
    i++

    View Slide

  124. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    if (peekc(p) == '+') {
    // ...
    }
    peekc_n(p, -2)
    .BLFUIFTDBOOFSSFUVSOU*/5&(&3GPSUIFTFDPOE
    /FYU XIFOUIFTDBOOFSSFBETUIFTFDPOE LFFQUIF
    DVSTPSQPTJUJPOBOEDIFDLUIFDIBSBDUFSPOFCFGPSFJU
    QFFLD@O
    QSPWJEFECZ.3*DBOCFVTFEGPSUIJT
    1FFLUIFQSFWJPVTDIBSBDUFSPG
    *GUIFDIBSBDUFSSFBEJT
    i++

    View Slide

  125. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    if (peekc(p) == '+') {
    // ...
    }
    if (peekc_n(p, -2) == '+') {
    VALUE i = rb_cstr_to_inum("1", 16, FALSE);
    .BLFUIFTDBOOFSSFUVSOU*/5&(&3GPSUIFTFDPOE
    *GUIFQSFWJPVTDIBSBDUFSXBTBMTPB
    UIFODSFBUFB7"-6&UIBUJTBOJOUFHFS
    $SFBUFB7"-6&UIBUJTBJOUFHFS
    *GUIFQSFWJPVTDIBSBDUFSJT

    View Slide

  126. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    if (peekc(p) == '+') {
    set_yylval_id('+');
    SET_LEX_STATE(EXPR_BEG);
    return tOP_ASGN;
    }
    if (peekc_n(p, -2) == '+') {
    VALUE i = rb_cstr_to_inum("1", 16, FALSE);
    return set_integer_literal(p, i, 0);
    }
    // ...
    .BLFUIFTDBOOFSSFUVSOU*/5&(&3GPSUIFTFDPOE
    3FUVSOUIFSFTVMUPGTFU@JOUFHFS@MJUFSBM

    i++
    U*/5&(&3
    1BTTJUBTBOBSHVNFOUUPDBMMTFU@JOUFHFS@MJUFSBM

    BOESFUVSOUIFSFTVMUGSPNUIFTDBOOFS

    View Slide

  127. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    if (peekc(p) == '+') {
    set_yylval_id('+');
    SET_LEX_STATE(EXPR_BEG);
    return tOP_ASGN;
    }
    if (peekc_n(p, -2) == '+') {
    VALUE i = rb_cstr_to_inum("1", 16, FALSE);
    return set_integer_literal(p, i, 0);
    }
    // ...
    .BLFUIFTDBOOFSSFUVSOU*/5&(&3GPSUIFTFDPOE
    5IJTTIPVMESFUVSOUIFTBNFSFTVMUBTJGAA
    IBECFFOSFBE"OEUIJTJNQMFNFOUBUJPOJTDPNQMFUF
    U01@"4(/ U*/5&(&3
    i++

    View Slide

  128. *TJUXPSLJOH
    NBLFSVO # ruby/test.rb
    i = 0
    i++
    p i
    3VOUIFDPNQJMFDPNNBOE
    8JUIUIJTJNQMFNFOUBUJPO XSJUFBTDSJQUDPOUBJOJOH
    AABOEDIFDLJOHUIFWBMVFPGUIFSFDFJWFS
    UIFOFYFDVUFTUIFDPNQJMFDPNNBOE

    View Slide

  129. *UMPPLTXPSLJOH
    NBLFSVO
    HFOFSBUJOHQBSTFD
    DPNQJMJOHQBSTFD
    MJOLJOHNJOJSVCZ
    NJOJSVCZ*SVCZMJC*a
    *FYUDPNNPOa
    SBSNEBSXJOGBLF
    SVCZUFTUSC

    # ruby/test.rb
    i = 0
    i++
    p i
    JJTOPXJODSFNFOUFE
    5IFOUIFDPNQJMBUJPOTVDDFFEFE BOEUIFWBSJBCMFXBT
    BTTJHOFEBOJODSFNFOUFEWBMVF

    View Slide

  130. NBLFSVO
    NJOJSVCZ*SVCZMJC*a
    *FYUDPNNPOa
    SBSNEBSXJOGBLF
    SVCZUFTUSCSVCZUFTUSC
    TZOUBYFSSPS
    VOFYQFDUFEPQFSBUPSBTTJHONFOU
    FYQFDUJOHFOEPGJOQVU 4ZOUBY&SSPS

    NBLF&SSPS
    *UMPPLTXPSLJOH
    # ruby/test.rb
    1++
    "OTZOUBYFSSPSIBTPDDVSSFE
    $BMMJOHAAXJUIBOJOUFHFSMJUFSBMEPFTOPUDBVTF
    BTFHNFOUBUJPOGBVMU CVUBTZOUBYFSSPSBTTBNFBT
    AA5IJTJTUIFJOUFOEFECFIBWJPS
    5IFJNQMFNFOUBUJPOPGJTTVDDFTTGVM

    View Slide

  131. )PXFWFSʜ

    View Slide

  132. *GPVOEBQSPCMFNJOUIJTJNQMFNFOUBUJPOBHBJO
    i = 0
    i++ * 2 # => 2
    p i # => ?
    8IFOFYFDVUJOHBTDSJQUMJLFUIJT
    XIBUXPVMECFBOBQQSPQSJBUFWBMVFGPSUIFWBSJBCMFAJA

    View Slide

  133. 5IJTJTBLJOEPGMBOHVBHFEFTJHONBUUFS BOEUIFSFBSF
    NBOZXBZTUPUIJOLBCPVUJU1FSTPOBMMZ *UIJOLJUJT
    BQQSPQSJBUFGPSUIFWBSJBCMFAJAUPCFBTTJHOFE
    i = 0
    i++ * 2 # => Expect: (i += 1) * 2
    p i # => Expect: 1
    *FYQFDUUIFWBSJBCMFAJAUPCFBTTJHOFE
    fi
    STUBOE
    NVMUJQMJFECZOFYU

    View Slide

  134. )PXFWFS UIJTAAJTFRVJWBMFOUUPAA5IFSFGPSF
    UIFSFTVMUJTBTTJHOFEUPUIFWBSJBCMFAJABGUFSUIF
    NVMUJQMJDBUJPOPGJTDPNQVUFE
    fi
    STUCZQSFDFEFODF
    i = 0
    i++ * 2 # => Actual: i += (1 * 2)
    p i # => Actual: 2
    5IFOUIFWBSJBCMFAJAJTBTTJHOFE
    *GFFMUIJTJTBOBUVSBMCFIBWJPSGPSAA CVUBCJU
    TUSBOHFGPSAA

    View Slide

  135. 4JODFUIFQSFDFEFODFPGPQFSBUPSTJTEF
    fi
    OFEJOQBSTFZ
    JUJTQPTTJCMFUPBWPJEUIJTQSPCMFNCZNBLJOHUIF
    QSFDFEFODFPGAAIJHIFSUIBOAA
    // ruby/parse.y
    // ...
    %right '=' tOP_ASGN
    %left modifier_rescue
    %right '?' ':'
    // ...
    %left '&'
    %left tLSHFT tRSHFT
    %left '+' '-'
    %left '*' '/' ‘%'
    // ...
    5IFQSFDFEFODF
    )JHIFS
    -PXFS

    View Slide

  136. )PXFWFS UIFQSPCMFNUIJTUJNFJTPOMZGPSUIFDBTFPG
    SFBEJOHAA*EPOUXBOUUPDIBOHFUIFQSFDFEFODFGPS
    UIFDBTFPGSFBEJOHAAVTVBMMZ
    x = 0
    x += 1 ** 2
    p x # => Intend: 2 (Keeping current behavior)
    y = 0
    y++ ** 2
    p y # => Intend: 1 (Changing current behavior)

    View Slide

  137. "MUFSOBUJWFMZ JUNJHIUCFQPTTJCMFUPDSFBUFBTZOUBYUSFF
    UIBUXSBQTUIFMFGUIBOETJEFBOEAAJOA
    AUPDPOUSPM
    UIFQSFDFEFODFPGFYQSFTTJPOT
    i = 0
    i++ * 2 # => i += (1 * 2)
    )PXFWFS UIJTXPVMENBLFUIFCFIBWJPSPGUIFTDBOOFS
    UPPDPNQMJDBUFE

    View Slide

  138. 0, MFU`TUIJOLPGBOPUIFSXBZ

    View Slide

  139. 5VSOAAJOUPAA 3FWJTFE



    View Slide

  140. *OUIFQSFWJPVTJNQMFNFOUBUJPO XFUSJFEUPNBLFUIF
    TBNF"45XJUIAACZUIFTDBOOFS
    i = 0
    i++ * 2 # => i += (1 * 2)
    p i # => 2
    #VUXFGPVOEUIBUJGAAJTGPMMPXFECZBOFYQSFTTJPO
    XFDBOOPUIBOEMFJU
    5VSOAAJOUPAA 3FWJTFE

    View Slide

  141. 5PBWPJEUIJT IPXBCPVUDPOTJEFSJOHUIFTFRVFODFPG
    UIFMFGUIBOETJEFPGUIFFYQSFTTJPOBOEBTBTJOHMF
    TZOUBYBOEEPJOHUIFTBNFUIJOHUPAACZUIFQBSTFS
    i++
    1BSTFBOENBLFBTBNF"45BT
    5VSOAAJOUPAA 3FWJTFE

    View Slide

  142. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT
    5VSOAAJOUPAA 3FWJTFE

    View Slide

  143. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT
    "EETZNCPMTBOEHSBNNBSSVMFTUPBMMPX
    TZOUBYMJLFAJA
    5VSOAAJOUPAA 3FWJTFE

    View Slide

  144. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT
    "EETZNCPMTBOEHSBNNBSSVMFTUPBMMPX
    TZOUBYMJLFAJA
    %F
    fi
    OFBOBDUJPOUIBUEPFTUIFTBNFUIJOH
    XIFOBTZOUBYMJLFAJAJTQBSTFE
    BTXIFOBTZOUBYMJLFAJAJTEPOF
    5VSOAAJOUPAA 3FWJTFE

    -FUTHFUUPJU
    i = 0
    i++ # Do the same thing as `i+=1` internally

    View Slide

  145. // ruby/parse.y
    %token tCOLON2 RUBY_TOKEN(COLON2) "::"
    %token tCOLON3 ":: at EXPR_BEG"
    %token tOP_ASGN "operator-assignment" /* +=, -= etc. */
    %token tINCOP "increment-operator"
    %token tASSOC "=>"
    %token tLPAREN "("
    %token tLPAREN_ARG "( arg"
    %token tRPAREN ")"
    %token tLBRACK "["
    %token tLBRACE “{"
    %token tSTAR "*"
    %token tDSTAR "**arg"
    %token tAMPER "&"
    // ...
    %F
    fi
    OFTZNCPMU*/$01
    'JSTU EF
    fi
    OFU*/$01BTUIFTZNCPM
    GPSUIFUPLFO
    %F
    fi
    OFBOFXTZNCPMGPS

    View Slide

  146. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    c = nextc(p);
    // ...
    if (c == '+')
    .BLFUIFTDBOOFSSFUVSOU*/$01
    5IFONPEJGZQBSTFS@ZZMFY

    *GJTSFBEUXJDFJOBSPX
    *GUIFOFYUDIBSBDUFSJTBMTP
    3FBEOFYUDIBSBDUFSPGUIF
    8IFOUIFDIBSBDUFSSFBEJT

    View Slide

  147. // ruby/parse.y
    static enum yytokentype
    parser_yylex(struct parser_params *p)
    {
    // ...
    switch (c = nextc(p)) {
    // ...
    case '+':
    c = nextc(p);
    // ...
    if (c == '+') {
    SET_LEX_STATE(EXPR_BEG);
    return tINCOP;
    }
    // ...
    .BLFUIFTDBOOFSSFUVSOU*/$01
    SFUVSOU*/$01
    5IFTDBOOFSNPEJ
    fi
    DBUJPOJTOPXDPNQMFUF
    3FUVSOU*/$01

    View Slide

  148. // ruby/parse.y
    arg : lhs '=' lex_ctxt arg_rhs
    // ...
    | var_lhs tOP_ASGN lex_ctxt arg_rhs
    // ...
    | ????
    %F
    fi
    OFBOFXHSBNNBSSVMF
    /FYU EF
    fi
    OFBOFXHSBNNBSSVMFGPSAA
    4JODFBHSBNNBSSVMFGPSBTDSJQUTVDIBTAJAJT
    EF
    fi
    OFEJOQBSTFZ MFUTEF
    fi
    OFUIFOFXPOFOFBSIFSF
    %F
    fi
    OFUIFOFXHSBNNBSSVMF
    "HSBNNBSSVMFGPS
    3VCZTDSJQUTMJLFAJA

    View Slide

  149. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    %F
    fi
    OFBOFXHSBNNBSSVMF
    )FSFJTUIFHSBNNBSSVMFUPCFBEEFE
    5IFOFXHSBNNBSSVMFDIFDLTUIBUUIFTZNCPMT
    WBS@MIT MFY@DUYU BOEU*/$01BSFJOBSPX
    %F
    fi
    OFBOFXHSBNNBSSVMF

    View Slide

  150. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    5IFNJEEMFPOF MFY@DUYU JTOPUTPSFMFWBOUUIJTUJNF TPTLJQJU

    WBS@MITJTUIFMFGUTJEFPGAA BOEU*/$01JTAA
    MFY@DUYUJTOPUTPSFMFWBOU TPXFTLJQJU

    5IJTNBLFTFYQSFTTJPOTMJLFAJAWBMJEBTBTZOUBY

    5IFTFTZNCPMTNFBOTʜ J
    # In a Ruby script
    i++
    OPOF

    %F
    fi
    OFBOFXHSBNNBSSVMF

    View Slide

  151. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    {
    // ...
    %F
    fi
    OFBOFXBDUJPOUPEPUIFTBNFUIJOHAAEPFT
    -FUTOPXEF
    fi
    OFUIFBDUJPOUPCFFYFDVUFEVQPO
    SFEVDJOHUIJTHSBNNBSSVMF

    View Slide

  152. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    'JSTU DBMM4&5@-&9@45"5&XJUI&913@&/%UPUFMM
    UIFTDBOOFSUPFOEUIJTFYQSFTTJPO
    /PUF5IFEF
    fi
    OJUJPOTPGBDUJPOTGPS3JQQFSBSFTLJQQFEJOUIJTTMJEF
    5FSNJOBUFUIJTFYQSFTTJPO
    %F
    fi
    OFBOFXBDUJPOUPEPUIFTBNFUIJOHAAEPFT

    View Slide

  153. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    ???
    /FYU MFUTEPUIFTBNFUIJOHBTAA
    )PXDBOXFEPUIBU
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    %F
    fi
    OFBOFXBDUJPOUPEPUIFTBNFUIJOHAAEPFT

    View Slide

  154. // ruby/parse.y
    static NODE *
    new_op_assign(struct parser_params *p,
    NODE *lhs,
    ID op,
    NODE *rhs,
    struct lex_context ctxt,
    const YYLTYPE *loc);
    OFX@PQ@BTTJHO

    .3*QSPWJEFTOFX@PQ@BTTJHO
    UPDSFBUFBO3/PEF
    UIBUJTBOFYQSFTTJPOXJUIAAPSAA
    -FUTVTFUIJTGVODUJPOUPEPXIBUJTUIFTBNF
    BTAA

    View Slide

  155. // ruby/parse.y
    static NODE *
    new_op_assign(struct parser_params *p,
    NODE *lhs,
    ID op,
    NODE *rhs,
    struct lex_context ctxt,
    const YYLTYPE *loc);
    OFX@PQ@BTTJHO

    4PNFBSHVNFOUTBSFSFRVJSFEUPDBMMUIJTGVODUJPO
    "O3/PEFUIBUJTUIFWBMVFPOUIFMFGUTJEFPGUIFFYQSFTTJPO
    "OPQFSBUPS AAPSAA
    "O3/PEFUIBUJTUIFWBMVFPOUIFSJHIUTJEFPGUIFFYQSFTTJPO

    View Slide

  156. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    // ...
    new_op_assign(p, ???, ???, ???, $2, &@$);
    }
    $BMMOFX@PQ@BTTJHO

    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    4PMFUTQSFQBSFUIFBSHVNFOUT
    UPDBMMOFX@PQ@BTTJHO

    OFX@PQ@BTTJHO
    SFRVJSFTBSHVNFOUT

    View Slide

  157. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    // ...
    new_op_assign(p, $1, '+', ???, $2, &@$);
    }
    1BTTUIFMFGUIBOETJEFPGAABTUIFTFDPOE
    BSHVNFOUBOEAABTUIFUIJSEBSHVNFOU
    -FGUIBOETJEF
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    $BMMOFX@PQ@BTTJHO

    View Slide

  158. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    // ...
    new_op_assign(p, $1, '+', ???, $2, &@$);
    }
    5IFGPVSUIBSHVNFOUJTUIFWBMVFPGUIFSJHIUTJEFPG
    AA*OUIFDBTFPGAA UIFSJHIUTJEFJTBMXBZTBO
    JOUFHFS TPXFOFFEUPDSFBUFBWBMVFPGUIJT
    3FRVJSFTBOJOUFHFSWBMVFAA
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    $BMMOFX@PQ@BTTJHO

    View Slide

  159. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    // ...
    new_op_assign(p, $1, '+', ???, $2, &@$);
    }
    TFU@JOUFHFS@MJUFSBM
    VTFEJOPOFQSFWJPVT
    JNQMFNFOUBUJPODBOOPUCFVTFEIFSF
    BTJUJTBGVODUJPOUPTFUBWBMVFUPBTZNCPM
    8FOFFEUPDSFBUFBO3/PEFUIBUJTBOJOUFHFS
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    $BMMOFX@PQ@BTTJHO

    View Slide

  160. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    VALUE v = rb_cstr_to_inum("1", 16, FALSE);
    NODE *one = NEW_LIT(v, &NULL_LOC);
    5PEPUIJT DSFBUFB7"-6&PGJOUFHFS BOEUIFO
    DSFBUFBO3/PEFUIBUJTMJUFSBMGSPNUIJT7"-6&
    "7"-6&PGBOJOUFHFS
    "O3/PFPGBMJUFSBM
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    $BMMOFX@PQ@BTTJHO

    View Slide

  161. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    VALUE v = rb_cstr_to_inum("1", 16, FALSE);
    NODE *one = NEW_LIT(v, &NULL_LOC);
    RB_OBJ_WRITTEN(p->ast, Qnil, x);
    new_op_assign(p, $1, '+', one, $2, &@$);
    }
    5IFOQBTTJUUPUIFGPVSUIBSHVNFOUPG
    OFX@PQ@BTTJHO

    1BTTUIF3/PEFUIBUJTBJOUFHFSMJUFSBM
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    $BMMOFX@PQ@BTTJHO

    View Slide

  162. // ruby/parse.y
    arg : // ...
    | var_lhs lex_ctxt tINCOP
    {
    SET_LEX_STATE(EXPR_END);
    VALUE v = rb_cstr_to_inum("1", 16, FALSE);
    NODE *one = NEW_LIT(v, &NULL_LOC);
    RB_OBJ_WRITTEN(p->ast, Qnil, x);
    $$ = new_op_assign(p, $1, '+', one, $2, &@$);
    }
    'JOBMMZ TFUUIF3/PEF UIFSFUVSOWBMVFPG
    OFX@PQ@BTTJHO
    UPUIFTZNCPMBGUFSSFEVDUJPO
    /PUFUIFEF
    fi
    OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ
    fi
    FEJOUIJTTMJEF
    "TTJHOUIFSFUVSOWBMVFUPUIFTZNCPMBGUFSSFEVDUJPO
    $BMMOFX@PQ@BTTJHO

    View Slide

  163. 5IFJNQMFNFOUBUJPOPGAAJT
    OPXDPNQMFUF

    View Slide

  164. %FNP

    View Slide

  165. 3VOUIFEFNP

    View Slide

  166. "MMTXFMMUIBUFOETXFMMʜ

    View Slide

  167. 6OGPSUVOBUFMZ UIFBOTXFSJTOP
    5IFBEEJUJPOPGUIFAAPQFSBUPSJTCSFBLJOH
    POFFYJTUJOHTZOUBY

    View Slide

  168. *OPSEJOBSZ3VCZ XFDBOVTFBOZOVNCFSPGJO
    TVDDFTTJPOXJUIPVUDBVTJOHTZOUBYFSSPST
    # Normal Ruby
    i = 0
    i + 1 # => 1
    i ++ 1 # => 1
    i +++ 1 # => 1
    i ++++ 1 # => 1
    i +++++ 1 # => 1
    5IJTJTCFDBVTFJGUIFSFBSFUXPPSNPSFT
    UIFTFDPOEBOETVCTFRVFOUTBSFDPOTJEFSFE
    VOBSZPQFSBUPST
    "MM`T/05XFMMUIBUFOETXFMM
    "MMTZOUBY0,

    View Slide

  169. #VUJO3VCZXJUIPQFSBUPS
    XFHFUBTZOUBYFSSPSXJUIVOFYQFDUFEJOUFHFSMJUFSBM
    JGXFUSZUPQVUBOJOUFHFSBGUFSAA
    # Ruby with "++" operator
    # ruby/test.rb
    i = 0
    i + 1 # => 1
    i ++ 1 # => SyntaxError
    i = 0
    i + (+1) # => 1
    i ++ +1 # => 3
    "MM`T/05XFMMUIBUFOETXFMM
    SVCZSVCZUFTUSC
    SVCZUFTUSCSVCZUFTUSC
    TZOUBYFSSPS VOFYQFDUFEJOUFHFSMJUFSBM
    FYQFDUJOHFOEPGJOQVU 4ZOUBY&SSPS

    J
    J?
    5IFZBSFTZOUBY0,
    ɾ5PVTFBVOBSZPQFSBUPSXJUIQBSFOUIFTFT
    ɾ5PVTFAABOEBVOBSZPQFSBUPSBUUIFTBNFUJNF

    View Slide

  170. *TUIJTBWBMJETQFDJ
    fi
    DBUJPO
    )PXTIPVMEUIFPQFSBUPSBOEVOBSZPQFSBUPST
    DPPQFSBUFXJUIFBDIPUIFS
    5IFTFBSFRVFTUJPOTUIBUTIPVMECFDPOTJEFSFEJO3VCZ
    UIBUBEEFEUIFOFXTZOUBYXJUIUIFPQFSBUPS
    5IJTJTBOJTTVFPGMBOHVBHFEFTJHO
    'PSUIFNPNFOU UIJTJTUIFTQFDJ
    fi
    DBUJPOPGUIF
    JNQMFNFOUBUJPOTPGBS
    5IFMBOHVBHFEFTJHOBGUFSBEEJOHBOFXTZOUBY

    View Slide

  171. 8FDBOOPMPOHFSDBMMUIJT3VCZ
    CFDBVTF*IBWFDIBOHFEUIFFYJTUJOHTZOUBY
    5IJTOFXMBOHVBHFOFFETBOFXOBNF
    TPNFUIJOHBQQSPQSJBUFGPSJU

    View Slide

  172. 3VCZ3VCZ

    View Slide

  173. 3VCZ3VCZ
    IUUQTHJUIVCDPNTIJPJNNSVCZQMVTQMVT

    View Slide

  174. &QJMPHVF

    View Slide

  175. !TQJLFPMBGUPMENFʜ
    SFGIUUQTUXJUUFSDPNTQJLFPMBG

    View Slide


  176. 5IFSFBSFUXPUZQFTPGQFPQMF
    0OFJTXIPOFFETBOFXHSBNNBSSVMF
    UPBEEBOFXTZOUBYJOUP.3*
    BOEPUIFSTXIPEPO`U

    View Slide


  177. 5IFSFBSFUXPUZQFTPGQFPQMF
    0OFJTXIPOFFETBOFXHSBNNBSSVMF
    UPBEEBOFXTZOUBYJOUP.3*
    BOEPUIFSTXIPEPO`U
    "EEJOHOFXTZOUBYPOMZCZMFYJDBMBOBMZTJT

    View Slide

  178. 8IBUUIJTNFBOTJTUIBUBMUIPVHI*FWFOUVBMMZBEEFE
    BOFXTZOUBYSVMFGPSPQFSBUPSUIJTUJNF
    UIFSFBSFQSPCBCMZPUIFSXBZTUPEPJUUIBU*IBWFOPU
    EJTDPWFSFEJOQSBDUJDF

    View Slide

  179. "OEOPUKVTUPQFSBUPS
    UIFSFXJMMCFBTNBOZXBZTUPBEEOFXTZOUBYUP
    .3*BTJNQMFNFOUPSTDBODPNFVQXJUI

    View Slide

  180. "OEBT*IBWFTIPXO .3*IBTNBOZVTFGVMUPPMLJUTGPS
    SFBMJ[JOHUIFTFJEFBT
    7BSJPVTUPPMLJUTUPTVQQPSUZPVSJEFB
    'PSFYBNQMF
    )PXUPNPEJGZUIFTDBOOFS QBSTFS@ZZMFY


    )PXUPEF
    fi
    OFOFXTZOUBYSVMFTBOEBDUJPOTXJUITFNBOUJDWBMVFT
    8IBUJTUIFPCKFDUPSJFOUFETFNBOUJDT
    "NBDSPUPDIBOHFUIFTUBUFPGUIFTDBOOFS 4&5@-&9@45"5&

    4PNFVTFGVMGVODUJPOTUPDSFBUF3/PEFT FHOFX@RDBMM
    OFX@PQ@BTHO


    4PNFVTFGVMNBDSPTUPDSFBUF3/PEFT FH/&8@-*5 /&8@7$"-- /&8@-*45

    5IFMPDBUJPOBMJOGPSNBUJPOPGUIFTDBOOFSBOETPNFVTFGVMGVODUJPOT
    UPQFFLBUUIFDIBSBDUFSPOBTPVSDFDPEF FHQFFLD
    QFFLD@O


    View Slide

  181. #ZNBLJOHGVMMVTFPGUIFN XIPBEET
    BOFXTZOUBYUP.3*OFYUJOPUIFSXBZT
    ʜJUNBZCFZPV

    View Slide

  182. 5IBOLZPVGPSZPVSBUUFOUJPO
    4QFDJBMUIBOLTUP
    !TQJLFPMBG
    !NJOFSPBPLJ
    !PLVSBNBTBGVNJ
    3FGFSFODFUP
    3VCZ)BDLJOH(VJEF
    1BSU4ZOUBYBOBMZTJT
    IUUQTSVCZIBDLJOHHVJEFHJUIVCJP

    3VCZ6OEFSB.JDSPTDPQF"O*MMVTUSBUFE(VJEFUP3VCZ*OUFSOBMT
    $IBQUFS5PLFOJ[BUJPOBOE1BSTJOH
    IUUQTQBUTIBVHIOFTTZOFUSVCZVOEFSBNJDSPTDPQF

    View Slide

  183. 'PSXIFOUIFEFNPEPFTOUXPSL

    View Slide

  184. 3VOXJUIDPNQJMFE3VCZ

    View Slide