Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby as a Frontend for Programming Language Imp...

Avatar for White-Green White-Green
April 17, 2025
42

Ruby as a Frontend for Programming Language Implementations (RubyKaigi 2025 LT)

Avatar for White-Green

White-Green

April 17, 2025
Tweet

Transcript

  1. RubyKaigi 2025 LT Ruby as a Frontend for Programming Language

    Implementations @White-Green (GitHub) @White_Green2525 (𝕏) 2025/04/17 STORES, Inc.
  2. What I’ll Talk About • My Own Programming Language ‣

    https://github.com/White-Green/equivoc ‣ Forget this exists • One of the idea that came out of developing this • Make a Programming Language effortless 2
  3. Programming Language Implementation p 2 + 2 parse ⇒ AST

    translate ⇒ IR1 … IRn translate ⇒ Bytecode Machine Code execute ⇒ 4 6
  4. Programming Language Implementation p 2 + 2 parse ⇒ Prism

    AST translate ⇒ IR1 … IRn translate ⇒ YJIT Bytecode Machine Code execute ⇒ 4 7
  5. Programming Language Implementation p 2 + 2 ↑ String parse

    ⇒ AST translate ⇒ IR1 … IRn translate ⇒ Bytecode Machine Code execute ⇒ 4 8
  6. Programming Language Implementation p 2 + 2 parse ⇒ AST

    ↑ { tag: "Expr", expr: { tag: "Call", fn: "p", args: [ { tag: "Add", lhs: { tag: "Const", value: 2, }, rhs: { tag: "Const", value: 2, translate ⇒ IR1 … IRn translate ⇒ Bytecode Machine Code execute ⇒ 4 9
  7. Programming Language Implementation p 2 + 2 parse ⇒ AST

    translate ⇒ IR1 … IRn ↑ Easy to Optimize & Translate SSA Form [ { tag: "Const", out: "v0", value: 2 }, { tag: "Const", out: "v1", value: 2 }, { tag: "Add", out: "v2", lhs: "v0", rhs: "v1" }, { tag: "Call", out: "v3", fn: "p", args: ["v2"] }, ] translate ⇒ Bytecode Machine Code execute ⇒ 4 10
  8. Programming Language Implementation p 2 + 2 parse ⇒ AST

    translate ⇒ IR1 … IRn translate ⇒ Bytecode Machine Code execute ⇒ 4 ← Frontend Backend → 11
  9. Programming Language Implementation p 2 + 2 parse ⇒ AST

    translate ⇒ IR1 … IRn translate ⇒ Bytecode Machine Code execute ⇒ 4 ← Frontend Complicated (even if in PoC) Backend → Simple 12
  10. Programming Language Implementation p 2 + 2 parse ⇒ AST

    translate ⇒ IR1 … IRn translate ⇒ Bytecode Machine Code execute ⇒ 4 • I want to make a New Programming Language 13
  11. Programming Language Implementation p 2 + 2 parse ⇒ AST

    translate ⇒ IR1 … IRn translate ⇒ Bytecode Machine Code execute ⇒ 4 • I want to make a New Programming Language ‣ → Develop these ALL! (so hard…) 14
  12. My Idea: Use Ruby as a Frontend Ruby ⇒ IR1

    … IRn translate ⇒ Bytecode Machine Code execute ⇒ 4 15
  13. My Idea: Use Ruby as a Frontend Example of My

    Own Programming Language require "./equivoc" # import something def fma(a, b, c) = a * b + c v = fma(1, 2, 3) e_if v < 0 do # custom if statement v = 0 end 16
  14. My Idea: Use Ruby as a Frontend Example of My

    Own Programming Language require "./equivoc" def fma(a, b, c) = a * b + c v = fma(1, 2, 3) e_if v < 0 do v = 0 end Run $ ruby ./entry.rb ↓ # easy to create a backend to process this INSTRUCTIONS = [ {tag:"Call",out:"v0",fn:"fma",args:[1, 2, 3]}, {tag:"Le",out:"v1",lhs:"v0",rhs:0}, {tag:"If",cond:"v1", updates:[{"v3","v2","v0"}], then_instr:[ {tag:"Const",out:"v2",value:0}, ],else_instr:[]}, ] 17
  15. internal equivoc.rb: Variable INSTRUCTIONS = [] class Variable def +(rhs)

    out = Variable.new instr = { tag: "Add", out:, lhs: self, rhs: } INSTRUCTIONS << instr out end end 22
  16. internal equivoc.rb: if def e_if(cond, &block) INSTRUCTIONS, buffer = [],

    INSTRUCTIONS # Save INSTRUCTIONS block.call INSTRUCTIONS, result = buffer, INSTRUCTIONS # Restore INSTRUCTIONS end 24
  17. internal equivoc.rb: if def e_if(cond, &block) INSTRUCTIONS, buffer = [],

    INSTRUCTIONS block.call INSTRUCTIONS, result = buffer, INSTRUCTIONS instr = { tag: "If", cond:, updates: [], then_instr: result, else_instr: [] } INSTRUCTIONS << instr end 25
  18. internal equivoc.rb: if def e_if(cond, &block) INSTRUCTIONS, buffer = [],

    INSTRUCTIONS before_variables = block.binding.#(snip) # Save local variables in block block.call after_variables = block.binding.#(snip) INSTRUCTIONS, result = buffer, INSTRUCTIONS updates = # variable updates from before_variables, after_variables instr = { tag: "If", cond:, updates:, then_instr: result, else_instr: [] } INSTRUCTIONS << instr end 26
  19. internal equivoc.rb: function class Object def self.method_added(name) # Called on

    `def` # Since, top-level function is private method of Object end end 27
  20. internal equivoc.rb: function class Object def self.method_added(name) # override method

    # (collect INSTRUCTIONS in the method before overwriting) define_method name do |*args| end end end 28
  21. internal equivoc.rb: function class Object def self.method_added(name) # override method

    define_method name do |*args| out = Variable.new instr = { tag: "Call", out:, fn: name, args: } INSTRUCTIONS << instr out end end end 29
  22. internal equivoc.rb: call backend process at exit # in equivoc.rb

    Kernel.at_exit do # Called when the program exits # We can use INSTRUCTIONS # INSTRUCTIONS = [ # {tag:"Call",out:"v0",fn:"fma",args:[1, 2, 3]}, # {tag:"Le",out:"v1",lhs:"v0",rhs:0}, # {tag:"If",cond:"v1", # updates:[{"v3","v2","v0"}], # then_instr:[ # {tag:"Const",out:"v2",value:0}, # ],else_instr:[]}, # ] end 32
  23. internal equivoc.rb: call backend process at exit # in equivoc.rb

    Kernel.at_exit do # We can process INSTRUCTIONS as we want # e.g. Dump INSTRUCTIONS into filesystem # Spawn backend process and pass INSTRUCTIONS # Process INSTRUCTIONS in Ruby end 33
  24. My Idea: Use Ruby as a Frontend Example of My

    Own Programming Language require "./equivoc" # the trick is only this! # ...snip... $ ruby entry.rb • collect INSTRUCTIONS like SSA-Form • call backend process (Optimize, Translate and Execute) 34
  25. My Idea: Use Ruby as a Frontend Example of My

    Own Programming Language require "./equivoc" # the trick is only this! # ...snip... $ ruby entry.rb • collect INSTRUCTIONS like SSA-Form • call backend process (Optimize, Translate and Execute) • Here is Exactly a Programming Language Implementation! ‣ Without parser ‣ Without tree-traversal algorithm • It is enough for testing • Let’s make Programming Language Implementation effortless with Ruby! 35