どくぴーの備忘録

真面目なことを書こうとするクソメガネのブログ。いつ投げ捨てられるのかは不明

でなlangに見る手を抜いてつくる3文字言語

この記事は denari01 Advent Calendar 2016 - Adventar 5日目の記事です

諸注意

特に何もしてないのでご注意

動機

誰かが「Grassのトークンさえ入れ替えたら任意の3トークンを用いた言語ができるゾ」とか言ってた

まずGrassって何さ

ちょっと草植えときますね型言語 Grass

要は「W」「w」「v」だけで書く言語です.型無しラムダ計算がベースの関数型プログラミング言語ですが特にこれ以降このことに絡んだお話はしません.

やったこと

github.com

まずこちらのyagi.rbを拝借します.こちらを改変するだけです.基本的には「W」「w」「v」のトークンを使いたい任意の3トークンに入れ替えてあげましょう.今回は「で」「な」「り」なので
W -> でw -> なv -> り
ですね.

# W -> で
# w -> な
# v -> り

App = Struct.new(:m, :n)
L = Struct.new(:src)
src = File.read(ARGV[0])
src = src.gsub(/[^でなり]/, "")
# vで区切る,vなし区切りのために更に次で区切る
src = src[/.*\z/m].split(//).map.with_index do |sub, i|
  sub = sub.scan(/+|+/)
  arg_num = sub.first[0] == "" ? sub.shift.size : 0
  sub = sub.each_slice(2).map { |n, m| App[n.size - 1, m.size - 1 ] }
  arg_num.times { sub = [L[sub]] }
  sub
end.flatten(1)

# eval
eval = ->(src, env) do
  ctrue = ->(arg) { eval[[L[[App[2, 1]]]], [arg, ->(arg) { eval[[], [arg]] }]] }
  cfalse = ->(arg) { eval[[L[[]]], [arg]] }
  src.inject(env) do |env, insn|
    val = case insn
    when App
      clos, arg = env[insn.m], env[insn.n]
      case clos
      when Proc then clos[arg]
      when Fixnum then clos == arg ? ctrue : cfalse
      when :out then putc(arg); arg
      when :in then ch = $stdin.getc; ch ? ch.ord : arg
      when :succ then arg.succ & 0xff
      end
    when L
      ->(arg) { eval[insn.src, [arg] + env]}
    end
    [val] + env
  end.first
end

puts "-- denalang source code --"
puts File.read(ARGV[0])
puts "-- result --"
# プリミティブ
eval[[], [eval[[App[0,0]], [eval[src, [:out, :succ, "w".ord, :in]]]]]]
puts "\n"

できた

本当に何もしてないですが,これだけです,早速見てみましょう.じゃあHello World.

$ cat hello.dn
なりななででなでででなりでななななででなでででなででででなでででででなででででででなでででででででなでななななななななななななででででなでででででででなででででででででででででででなでででででででででででななででででででででででななででででででででででででなででででででででででななででででででででででななななななでででででででででででででででなでででででででででででででででででででででなででででででででででででででででででななでででででででででででででででででななでででででででででででででででででなななななででででででででででででででででででででななででででででででででででででででででででででなでででででででででででででででででででででででででななななななななななななななななななななななななななでななななななななななででなななななななでででなななななななででででなでででででななななななななででででででななななななななななななななななでででででででななななななななななななななななななななででででででででななななななななななななななななななななななななななななななななななななでででででででででななななででででででででででなななななななななななでででででででででででなななななななででででででででででででななななななななななななななななななでででででででででででででななななななななななななななななななななななななな
$ ruby denalang_interpreter.rb hello.dn
-- denalang source code --
なりななででなでででなりでななななででなでででなででででなでででででなででででででなでででででででなでななななななななななななででででなでででででででなででででででででででででででなでででででででででででななででででででででででななででででででででででででなででででででででででななででででででででででななななななでででででででででででででででなでででででででででででででででででででででなででででででででででででででででででななでででででででででででででででででななでででででででででででででででででなななななででででででででででででででででででででななででででででででででででででででででででででなでででででででででででででででででででででででででななななななななななななななななななななななななななでななななななななななででなななななななでででなななななななででででなでででででななななななななででででででななななななななななななななななでででででででななななななななななななななななななななででででででででななななななななななななななななななななななななななななななななななななでででででででででななななででででででででででなななななななななななでででででででででででなななななななででででででででででででななななななななななななななななななでででででででででででででななななななななななななななななななななななななな
-- result --
Hello, world!

できました(?)

おわび

Q: え?トークン入れ替えただけだよね?
A: はい,それだけなのに記事書いて申し訳ありませんでした.時間がないけどとりあえず書いた結果がこれです.クソ記事に付き合っていただきありがとうございました