Kentaro Kuribayashi
November 20, 2021
930

# Elixirでプログラミング言語を作ろう #tokyoex / Let's Make Your Own Language in Elixir

## Kentaro Kuribayashi

November 20, 2021

## Transcript

1. ElixirͰϓϩάϥϛϯάݴޠΛ࡞Ζ͏
܀ྛ ݈ଠ࿠ / GMO Pepabo, Inc.
2021.11.20 tokyo.ex Reboot
1

2. 2
ࣗݾ঺հ
GMOϖύϘגࣜձࣾ
ιϑτ΢ΣΞΤϯδχΞ
܀ྛ ݈ଠ࿠ a.k.a. ͋ΜͪΆ
● GMOϖύϘऔక໾CTO
● JAISTത࢜લظ՝ఔ
ElixirConf US 2021Ͱൃදͨ͠Γ͠·ͨ͠ɻ

3. ͜ͷτʔΫʹࢸ͖͔͚ͬͨͬ
3
● ͖͔͚ͬ͸ɺWEB+DB PRESS Vol.125
ʢӈਤʣͷಛूΛಡΜͩ͜ͱ
● पғʢࣾ಺ʣͰ΋ಠࣗݴޠΛ࡞ΔࢼΈ͕
੝Γ্͕͍ͬͯΔ
ɹˠ RBSʢԾʣʢby @udzuraʣ
ɹˠ EVMͰಈ͘εϚʔτίϯτϥΫτهड़ݴޠΛ
࡞Γ͍ͨʢby @akht_ikdʣ
ࣗ࡞ݴޠͷ੝Γ্͕Γ
ӈਤͷग़ॴɿWEB+DB PRESS Vol.125ʛٕज़ධ࿦ࣾ

4. 4
ElixirͰϓϩάϥϛϯάݴޠͷࣗ࡞Λ࢝Ί·ͨ͠
ग़ॴɿkentaro/rorty: Yet Another Language Implementation using Elixir.
Elixir 100%ʂ

5. 5
ͲΜͳݴޠ͔ʁʢ۩৅ߏจ͔Βʣ
def factorial(n) {
if (n < 2) {
1
} else {
n * factorial(n - 1)
}
}
puts(factorial(5))
ࣜϕʔεɺ৚݅෼ذɾ܁Γฦ͠ɺؔ਺ݺͼग़͠ɺσʔλ͸੔਺ͱจࣈྻ
for (i in 1 to 100) {
if (i % 15 == 0) {
puts("FizzBuzz")
} else {
if (i % 5 == 0) {
puts("Buzz")
} else {
if (i % 3 == 0) {
puts("Fizz")
} else {
puts(i)
}
}
}
}
※ ্ه͸ߨԋऀ͕࡞ͬͨݴޠʹΑΔίʔυྫͰ͋ΓɺWEB+DB PRESS Vol.125ͷಛूهࣄͰղઆ͞Ε͍ͯΔݴޠʢToysʣͱ͸΍΍ҟͳΔɻ

6. 6
WEB+DB PRESSಛूͷըظతͳͱ͜Ζ
۩৅ߏจ͔ΒͰ͸ͳ͘ந৅ߏจ͔Βݴޠ࣮૷Λ࢝ΊΔ
۩৅ߏจ
ந৅ߏจ
ҙຯ࿦
Α͋͘Δઆ໌ͷྲྀΕ
ந৅ߏจ
۩৅ߏจ
ҙຯ࿦
ຊಛूͷઆ໌ͷྲྀΕ ͜ͷྲྀΕͷϝϦοτ

ʮΠϯλϓϦλͷຊ࣭͸ந
৅ߏจ໦ʯʢp.21ʣ

۩৅ߏจ͔ΒೖΔͷ͸ɺ΍
Δ΂͖͜ͱ͕ෳࡶͰɺ࠳ં
͠΍͍͢ɻ

ந৅ߏจ͔ΒೖΔํ͕ɺී
ஈͷϓϩάϥϛϯάʹۙ͘
ͯͱ͖ͬͭ΍͍͢ʢͱࢥ͏ʣ
ग़ॴɿWEB+DB PRESS Vol.125 p.21Λݩʹ࡞ਤͨ͠ɻ

7. 7
·ͣ࡞Γ࢝ΊΔՕॴ
1.࢛ଇԋࢉΛදݱ͠ಘΔந৅ߏจ໦Λɺ
Structͱͯ͠ఆٛ͢Δ
2.ந৅ߏจ໦Λड͚औͬͯɺ࠶ىతʹղ
ऍɾ࣮ߦ͢Δʢӈਤͷinterpretؔ
਺ʣ
3.ࣜʹؚ·ΕΔૢ࡞ͷछผʹԠͯ͡ॲཧ
͠Θ͚Δ
4.ͦͷૢ࡞ʹରԠ͢ΔElixirͷૢ࡞Λ࣮ߦ
͢Δ
ந৅ߏจ໦ͷσʔλߏ଄ͱɺͦΕΛ࣮ߦ͢ΔΠϯλϓϦλ͔Β࡞Γ࢝ΊΔ
def interpret(%Rorty.Ast.Expression.Binary{} = expr) do
case expr.operator do
interpret(expr.left) + interpret(expr.right)
Rorty.Operator.Divide ->
interpret(expr.left) / interpret(expr.right)
Rorty.Operator.Multiply ->
interpret(expr.left) * interpret(expr.right)
Rorty.Operator.Subtract ->
interpret(expr.left) - interpret(expr.right)
end
end
࠶ؼ࣮ߦ

8. 8
ந৅ߏจͷछྨΛ૿΍͍ͯ͘͠
1.લड़ͷ௨Γɺinterpretؔ਺͸࠶
ىతʹந৅ߏจ໦Λղऍɾ࣮ߦ͢
Δ
ɹʢӈਤͷ࠷্෦ͷinterpretؔ਺Λࢀরʣ
1.ifจͷཏྻͰ͸ͳ͘ɺύλϯϚο
νΛ࢖ͬͯɺࣜͷछผʹԠͨ͡ॲ
ཧΛɺએݴతʹهड़͍ͯ͘͠ͱ
ElixirͬΆ͍
૿͑ଓ͚Δந৅ߏจͷछྨʹରͯ͠ElixirΒ͘͠ύλϯϚονͰରԠ

9. 9
۩৅ߏจΛ࡞͍ͬͯ͘
● ந৅ߏจΛ࡞͍ͬͯ͘ͱɺͦΕΛ࢖ͬͨϓϩάϥϜͦͷ΋ͷΛಈ͔͍ͨ͠ؾ࣋ͪʹͳͬͯ͘
ΔͷͰɺ͋Δఔ౓ͷͱ͜ΖͰ۩৅ߏจʹͱΓ͔͔Δ
○ ࣮ࡍʹ͸ɺ࢛ଇԋࢉͷந৅ߏจΛ࡞ͬͨΒɺରԠ͢Δ۩৅ߏจΛఆٛ͠·ͨ͠
● ۩৅ߏจͷهड़ʹ͸PEGΛར༻ʢଞͷબ୒ࢶ͸BNFͱYeccɺNimbleParsec౳ʣɻ
● ͦͷར఺͸ҎԼͷ௨Γ
͋Δఔ౓ந৅ߏจ͕Ͱ͖ͨΒɺύʔαδΣωϨʔλͰ۩৅ߏจΛ࡞Δ
ग़ॴɿWEB+DB PRESS Vol.125 p.30
1. ߏจղੳͱࣈ۟ղੳΛ۠ผ͠ͳ͍ʢ͠ͳͯ͘Α͍ʣ
2. BNF͔Β୯७ʹߏจղੳثΛ࡞ͬͨ৔߹ͷ໘౗͍͘͞໰୊ʹ൥Θ͞Εͳ͍
3. PEG͔ΒߏจղੳثΛ࡞Δͷ͸؆୯Ͱ͋Δ

10. 10
PEGΛElixirͰ࢖͏ʹ͸
PEGͷElixirʹΑΔ࣮૷͕͋Δʢ΍΍ݹ͍͚Ͳʣ
ग़ॴɿjtmoulia/neotomex: A PEG parser/transformer with a pleasant Elixir DSL.

11. 11
Neotomexೖ໳
PEGʹΑΔจ๏هड़ΛElixirͷDSLͰॻ͚Δʂʢ਺ࣈΛύʔε͢Δྫʣ
defmodule Number do
use Neotomex.ExGrammar
@root true
define :number, "digit+" do
digits -> digits |> Enum.join |> String.to_integer
end
define :digit, "[0-9]"
end
42 = Number.parse! "42"
ग़ॴɿjtmoulia/neotomex: A PEG parser/transformer with a pleasant Elixir DSL.

12. 12
DSLʹΑΔจ๏ఆ͔ٛΒAST΁
1.PEGͷจ๏͕DSLԽ͞Ε͍ͯΔͷ
ͰɺͦΕʹԊͬͯݴޠͷจ๏ͱϚο
νͨ࣌͠ͷૢ࡞Λॻ͍͍ͯ͘
2.طʹ࡞ͬͨந৅ߏจʹϚον͢ΔΑ
͏จ๏Λఆٛͯ͠ɺ۩৅ߏจΛந৅
ߏจʹม׵͍ͯ͘͠
PEG-LikeͳDSLͰจ๏Λهड़͠ɺ۩৅ߏจΛந৅ߏจʹม׵͍ͯ͘͠
@root true
int when is_struct(int, Rorty.Ast.Expr.IntegerLiteral) -
> int
end
# ʢলུʣ
define :decimal, "[0-9]+" do
digits ->
Enum.join(digits)
|> String.to_integer()
|> Rorty.Ast.integer()
end
۩৅ߏจΛந৅ߏจ
ʹม׵͢Δ

13. 13
ग़དྷ্͕ͬͨ΋ͷΛ૊Έ߹ΘͤΔ
۩৅ߏจʹΑΓهड़͞ΕͨιʔείʔυΛந৅ߏจʹม׵ͯ͠ɺղऍɾ࣮ߦ
def run(src) do
{result, _} =
src
|> parse()
|> Rorty.Interpreter.interpret(%Rorty.Env{})
result
end
def parse(src) do
try do
src |> String.trim() |> Rorty.Grammar.parse!()
rescue
e in Neotomex.Grammar.ParseError ->
e |> handle_exception()
end
end

14. 14
What's Next?
● Erlang VMʢBEAMʣ্Ͱಈ͘ݴޠ͸BEAM Languagesͱݺ͹ΕΔ
● ୅දతͳBEAM Languages͸Erlang/OTP΍Elixir
● ଞɺLispʹӨڹΛड͚ͨ΋ͷ΍੩తܕ෇͚ͷ΋ͷͳͲɺগͳ͘ͱ΋33Ҏ্͕͋Δ
͜͜Ͱ঺հͨࣗ͠࡞ݴޠ΋ɺElixirͰ࣮ߦ͍ͯ͠ΔͷͰBEAM্Ͱಈ͍ͯ͸͍ΔͷͰɺ
BEAM Languagesͱ͍͑͹͍͑Δ͚Ͳ……ɻ
→ ͡Ό͋ɺͪΌΜͱͨ͠BEAM Languagesͱ΍ΒΛ࡞ͬͯΈΑ͏͡Όͳ͍͔
؆қͳΠϯλϓϦλݴޠ͔ΒYet Another BEAM Language΁
ग़ॴɿllaisdy/beam_languages: Languages, and about languages, on the BEAM

15. 15
BEAM Languagesͷ࣮૷ํࣜ͋Ε͜Ε
ҰޱʹBEAM Languagesͱ͍ͬͯ΋͍ΖΜͳ΍Γํ͕͋Δ
ग़ॴɿImplementing languages on the BEAM by Robert Virding & Mariano Guerra | #OpenErlang webinar

16. 16
BEAM Languages΁޲͚ͯ
1.ࣗ࡞ݴޠͷASTΛElixirͷAST΁τϥϯε
ύΠϧ͢Δʢӈ্ʣ
2.τϥϯεύΠϧͨ݁͠ՌΛɺ
Code.eval_quoted/3Ͱ࣮ߦ
ElixirͷASTΛ࢖͏ͱɺࣗ࡞ݴޠͷந৅ߏจΛElixir
ʹௐ੔͠ͳ͚Ε͹ͳΒͳ͍͠ɺElixirͷҙຯ࿦ʹറΒ
Εͯɺ݁ہElixirͷαϒηοτΛ࡞Δ͜ͱʹͳͬͯ͠
·͏ɻ
→ ࠓޙͲ͏͢Δ͔͸໎ͬͯΔͱ͜Ζ
·ͣ͸ࣗ࡞ݴޠͷASTΛElixirͷAST΁τϥϯεύΠϧͯ͠Έͨ
defmodule Rorty.Transpiler do
def transpile(exprs) do
exprs |> Enum.map(fn expr ->
Rorty.Protocol.ElixirAst.to_elixir_ast(expr)
end)
end
end
def run(src, transpile: true) do
{result, _} =
src
|> parse()
|> transpile()
|> Code.eval_quoted([], __ENV__)
result
end

17. 17
·ͱΊ
● ϓϩάϥϛϯάݴޠͷ࡞Γํʹ͍ͭͯઆ໌͍ͯ͠Δॻ੶΍هࣄ͸ͨ͘͞Μ͋Δ͕ɺ
WEB+DB PRESS Vol.125ͷಛू͸ɺͦͷઆ໌ͷελΠϧʹ͓͍ͯग़৭
○ ந৅ߏจˠ۩৅ߏจͱ͍͏આ໌ͷྲྀΕ
○ ࣈ۟ղੳͱ͔BNFͱ͔ͦ͏͍͏࿩Λ͠ͳ͍
● جຊతʹɺͦ͜Ͱॻ͔Ε͍ͯΔ͜ͱΛຊτʔΫͰઆ໌ͨ͠Α͏ʹElixirతʹಡΈସ͑ͯ
࣮૷͍ͯ͘͠ͱɺϓϩάϥϛϯάݴޠͬΆ͍΋ͷ͕Ͱ͖Δ
● ͜ͷઌ͸ɺૉ๿ͳΠϯλϓϦλ͔ΒBEAM Languages΁ঢ՚͍͖͍ͤͯͨ͞ͱ͜Ζ
ElixirͰϓϩάϥϛϯάݴޠΛ࡞Ζ͏ʂ

18. 18
ϓϩάϥϛϯάݴޠͷࣗ࡞͸ָ͍͠