Hatena::Grouprubyist

たばさの RSSフィード

12/15(土) 2007

最強の

最強の - たばさの を含むブックマーク はてなブックマーク - 最強の - たばさの

golf言語ならおらもちょっと考えた。あまりおもしろくないけど。

1でhello,world,2でecho,3で99hamaji...

というふうに問題にあわせて作る。

というのはあんまりなので、すべての言語を呼び出せて、一文字目で言語指定、二文字目からその言語でのソース。すべての問題でトップ+1バイト。*1

自動的に自分以外のトップの言語に決まるというのもいいかな。

どう?つまらないでしょ。

電卓 続き ファイル実行モード

| 電卓 続き ファイル実行モード - たばさの を含むブックマーク はてなブックマーク - 電卓 続き ファイル実行モード - たばさの

対話モードでなくてもいいようにした。

実行モードで終了時に余分に改行してしまうのはなぜだ。んー。

あとは複数行プリント文の調整などをした。

つぎはファイルopen,readか。クラス、インスタンスは難しそうだな。


# koneko.rb  ver.0.4.5


$os="win"

require 'Win32API' if $os=="win"

$mode=""
$stack=[""]

$prompt=">"
$lprompt=">>"
$prprompt=":"
$repprompt="|>"
$show=false
$debug=false
$editor=""
$IOI="STDIN."

def edit txt,editor=$editor
  if editor=="type"
    system("type #{txt}")
  elsif editor!=""
    `#{editor} #{txt}` 
  else
    browse txt
  end
end

def browse ur
  return if $os!="win"
  shellexecute = Win32API.new('shell32.dll','ShellExecuteA',%w(p p p p p i),'i')
  shellexecute.call(0, 'open', ur, 0, 0, 1)
end

class Env
 attr_accessor(:hlist,:assign,:mem,:his)
 def reset
   @mem=[]
   @hlist=[]
   @assign={}
   @his=[]
 end
end

$base = Env.new
$envs=["base"]
$base.reset
$current=$base
$currentname="base"
$hisfile="hensu-his.txt"

def showprompt
  print $currentname+$prompt
end

class Fv
 attr_accessor(:hlist,:assign,:name,:argv,:body)
end


def exist x,env
 env.hlist.member?(x)
end


def existusing x
 /(.*):(.*)/ =~ x
 return [false,nil,nil]if !$&
 $envs.each{|en|
   next if en!=$1
   env=eval("$"+en)
   return [true,env,$2] if exist($2,env)
   return [false,nil,nil]
 }
 [false,nil,nil]
end


def existf x,env
 /\(.*\)/ =~x
 return false if !$`
 name=$`
 env.hlist.each{|i|
  /\(.*\)/ =~i
  n=$`
 # p"exf",x,n,name,"$$"
  if $&
    if n==name
      return true
    end
  end
 }
 false
end

def getfunc x,env
 /\(([^\)]*)\)/ =~x
 vals=$1
 name=$`
 env.hlist.each{|i|
  /\(([^\)]*)\)/ =~i
  n=$`
  if $&
    if n==name
      arg =$1
      return [i,arg.split(','),vals.split(',')]
    end
  end
 }
 false
end

def set x,env
 n=0
 while 1
  (env.assign[x]=n ;env.mem[n]=""; break) if env.mem[n]==nil
  n+=1
 end
end

def argcalc arg,vals,a
  tmp=a.dup
  arg.length.times{|i|
    v=mainloop(vals[i])
    tmp.gsub!(arg[i],v)
  }
  mainloop(tmp)
end

# uhenchi
def calc d,env
 /^\"([^\"]*)\"/ =~d
 str=$&
 mae=$`
 usr=$'
 if str
   tmp =$1.gsub("\\n","\n")
   /\#\{([^\}]*)\}/ =~ tmp
   if $&
     return calc(mae+"\""+$`+calc($1,env)+$'+"\""+usr,env)
   end
   return mae+tmp+usr if !$&
 end
 /- *-[0-9]+/=~d
 d.gsub!(/- *-/,'+') if $&
 # func(..)
 /([a-zA-Z_][a-zA-Z_0-9]*\([^\)]+\))/ =~ d
 mae=$`
 usr=$'
 if $1
  if existf($1,env)
   f,arg,vals =getfunc($1,env)
   a = env.mem[env.assign[f]]
   a = argcalc(arg,vals,a)
   # p a,f,arg,vals,"$!$"
   return calc(mae+a.to_s+usr,env)
  else
   return calc(mae+usr,env)
  end
 end
 return calc($`+calc($1,env)+$',env) if $1
 # (...)
 /(.*)\(([^\)]+)\)(.*)/ =~ d
 return calc($1+calc($2,env)+$3,env) if $2
 # array
 /([a-zA-Z_0-9]+)\[([^\.])\.\.([^\.])\]/ =~d
 return calc($`+calc($1,env)[$2.to_i..$3.to_i]+$',env) if $&
 # ..*/..
 /([a-zA-Z_0-9\.\[\]]+ *[\*\/] *[a-zA-Z_0-9\.\[\]]+) *([+\/\*\-].+)/ =~ d
 return calc($`+calc($1,env)+$2,env) if $2
 # ..*/..
 /(.+[+\/\*\-]) *([a-zA-Z_0-9\.\[\]]+ *[\*\/] *[a-zA-Z_0-9\.\[\]]+)/ =~ d
 return calc($1+calc($2,env)+$',env) if $2
 # ..+-..
 /([a-zA-Z_0-9\.\[\]]+ *[+\-] *[a-zA-Z_0-9\.\[\]]+) *([+-].+)/ =~ d
 return calc($`+calc($1,env)+$2,env) if $2
 # p d
 /([a-zA-Z_0-9\.\[\]]+) *([+\*\-\/%]) *([a-zA-Z_0-9\.\[\]]+)/=~d
 a=$1
 si=$2
 c=$3
 if !a
  f,en,a = existusing(d)
  if f
   a =en.mem[en.assign[a]]
   return a.to_s
  elsif exist(d,env)
   a = env.mem[env.assign[d]]
   return a.to_s
  else 
   system(d[1..-1]) if d.class==String && d.length>0 && d[0,1]=="$"
   return d 
  end
 end
 if exist($1,env)
  a=env.mem[env.assign[$1]] 
 else
  a=$1
 end
 if exist($3,env)
  c=env.mem[env.assign[$3]] 
 else
  c=$3
 end
 /[^0-9e+\-\. ]/ =~ a.to_s
 f1=$&
 /[^0-9e+\-\. ]/ =~ c.to_s
 f2=$&
 return calc(a,env).to_s + calc(c,env).to_s if f2!=nil || f1!=nil
 return calc(eval(calc(a,env).to_s + si + calc(c,env).to_s ).to_s,env)
end

def getfname da
 / *(.+)/ =~ da
 file =$1
 if !$1
   file ="mylog.txt" 
 else
   /\./ =~file
   file =file+".ko" if !$&
 end
 file
end

def getstr da
 / *(.+)/ =~ da
 file =$1
 file ="" if !$1
 file
end

def memo env
 open($hisfile,'a'){|f|
  f.puts env.his
 }
end

def funccalc a,b,c
  fn=Fv.new
  fn.name=a
  fn.argv=b.split(',')
  fn.body=c
  fn
end

def setval a,b,env
  (env.hlist<<a) if !exist a,env
  set a,env if env.assign[a]==nil 
  envfrom=env
  f,en,v =existusing(b)
  (envfrom=en;b=v) if f
  env.mem[env.assign[a]] =calc(b,envfrom)
  return env.mem[env.assign[a]]
end

def geteditor env
  return "" if !env.hlist.member?("editor")
  env.mem[env.assign["editor"]]
end

def mainloop da,env=$base
 env.his<<da
 p "m:"+da if $debug
 # comment
 # p
 / *p  *(.*)/ =~ da
 if $&
   p mainloop($1,env)
   return $` 
 end
 # regexp
 /\/[^\/]+\/ *=~.*/ =~ da
 eval($&) if $&
# p $&,$1
 setval("$1",$1,env) if $1
 setval("$&",$&,env) if $1
 # function
 /([a-zA-Z_][a-zA-Z_0-9]*\((.*)\)) *=(.+)/ =~ da
 if $&
   a=funccalc $1,$2,$3
   # p a
   env.hlist<<a.name if !exist a.name,env
   set a.name,env if env.assign[a.name]==nil 
   env.mem[env.assign[a.name]]=$3 #calc($3,env)
   return a.name
 end
 # while
 /while  *([^><=]+)(!?[=><]+)(.+)  *\{([^\}]+)\}/ =~ da
 mae,usr,m1,m2,m3,body =$`,$',$1,$2,$3,$4
 if $1
  ans =calc($1,env)+$2+calc($3,env)
  if eval(ans)
    / *break */=~ mainloop(body,env)
    if $&
      return mainloop(mae+usr,env)
    end
    return mainloop(mae+"while "+m1+m2+m3+" {"+body+"}"+usr,env)
  else
    return mainloop(mae+usr,env)
  end
 end
 /while  *([^\{]+)  *\{([^\}]+)\}/ =~ da
 mae,usr,cond,body =$`,$',$1,$2
 if cond
  ans =mainloop(cond,env)
  if ans
    / *break */=~ mainloop(body,env)
    if $&
      return mainloop(mae+usr,env)
    end
    return mainloop(mae+"while "+cond+" {"+body+"}"+usr,env)
  else
    return mainloop(mae+usr,env)
  end
 end
 # num.times
 /([a-zA-Z_0-9]+)\.times *\{ *([^\}]+) *\}/ =~ da
 body=$2
 if $&
  return calc($1,env).to_i.times{ |it|
    a=body.gsub("it", it.to_s)
    print "(#{a})",$repprompt if $debug
    / *break */=~ mainloop(a,env)
    break if $&
  }
 end
 # gets
 /gets(\([^\)]*\))?/ =~ da
 if $&
   inp=$IOI+$&
   a=eval(inp)
   setval("$_",$_,env)
   return a if $`=="" && $'==""
   a="" if a==nil
   return mainloop($`+a+$',env)
 end
 # multi
 /([^;]*);(.*)/ =~ da
 m1=$1
 m2=$2
 if $1
   ans =mainloop $1,env
   / *break */ =~ ans
   return "break" if $&
   return mainloop(m2,env)
 end
 /if  *(.+)([!=]=)(.+)  *then *(.+)/ =~ da
 mae,usr,m1,m2,m3,mtrue =$`,$',$1,$2,$3,$4
 if $1
  p $& if $debug
  /else  *(.*)/ =~ mtrue
  mfalse =$1
  mtrue =$` if $&
  p $& if $debug
  if m2=="=="
   if calc(m1,env)==calc(m3,env)
    return mainloop(mae +mtrue +usr,env) 
   else
    if mfalse
      return mainloop(mae+mfalse+usr,env)
    else
      return mainloop(mae+usr,env)
    end
   end
  else
   if calc(m1,env)!=calc(m3,env)
    return mainloop(mae+mtrue+usr,env)
   else
    if mfalse
      return mainloop(mae+mfalse+usr,env)
    else
      return mainloop(mae+usr,env)
    end
   end
  end
 end
 /if  *(.+)<(.+)  *then (.+)  *else  *(.+)/ =~ da
 if $1
  if calc($1,env)<calc($2,env)
    return mainloop($`+$3+$',env)
  else
    return mainloop($`+$4+$',env)
  end
 end
 /if  *(.+)>(.+)  *then (.+)  *else  *(.+)/ =~ da
 if $1
  if calc($1,env)>calc($2,env)
    return mainloop($`+$3+$',env)
  else
    return mainloop($`+$4+$',env)
  end
 end
 # print
 /print  *((.|\n)+)/ =~ da
 strs=$1
 if strs
   /(".*"),(".*")/ =~ strs
   return (mainloop("print #{$1}");mainloop("print #{$2}")) if $&
 end
 ( a= calc(strs,env)
   print a
   return $`.to_s+a+$'.to_s ) if strs
 # puts
 /puts  *((.|\n)+)/ =~ da
 strs=$1
 if strs
   /(".*"),(".*")/ =~ strs
   return (mainloop("puts #{$1}");mainloop("puts #{$2}")) if $&
 end
 ( a= calc(strs,env)
   puts a
   return $`.to_s+a+$'.to_s ) if strs
 # browse
 /^http.*/ =~ da
 browse($&) if $&
 # browse
 /.*\.txt/ =~ da
 editor=""
 editor=geteditor(env) if exist("editor",env)
 edit($&,editor) if $&
 # simple equation
 /([a-zA-Z_][a-zA-Z_0-9]*(\[[0-9]+\])?) *= *(.+)/ =~ da
 a=$1
 b=$3
 if a
   return setval(a,b,env)
 else
   if da=="??"
     env.hlist.each{|i| 
       puts $prprompt+i+" = "+env.mem[env.assign[i]].to_s
     }
     return""
   elsif da=="?"
     puts env.hlist*","
     return ""
   elsif da=="???"
     p env.mem,env.hlist,env.assign
     return ""
   elsif da=="his"
     p env.his
     return ""
   elsif da=="hiss"
     return memo(env)
   elsif da=="hisl"
     return mainloop("!load #{$hisfile}",env)
   elsif exist(da,env) 
     a=env.mem[env.assign[da]]
     system(a[1..-1]) if a.class==String && a[0..0]=="$"
     return a
   elsif da=="????"
     print "hensuu:\t"
     p env.hlist
     print "assign:\t"
     p env.assign
     print "memory:\t"
     p env.mem
     print "env:\t"
     p $envs
     puts
     return ""
   elsif da=="?????"
     $envs.each{|e|
       puts "env::"+":"*30+"("+e+")"
       mainloop("?",eval("$"+e))
     }
     puts
     return ""
   elsif da=="??????"
     $envs.each{|e|
       puts "env:"+"."*30+" ("+e+")"
       mainloop("????",eval("$"+e))
     }
     return ""
   elsif da=='$'
     exit
   elsif da=='exit'
     memo env
     exit
   elsif da[0..9]=='@namespace'
     envname=getstr da[10..-1]
     (p $envs;return"") if envname==""
     if ! $envs.member?(envname)
       name="$#{envname}"
       eval(name+"=Env.new")
       $envs<<envname
       eval("$current="+name)
       $current.reset
     else
       eval("$current=$"+envname)
     end
     $currentname=envname
     mainloop("?",$current)
     return""
   elsif da=='help'
     help
     return ""
   elsif da=='show'
     $show=!$show
     return ""
   elsif da=='debug'
     $show=true
     $debug=true
     return ""
   elsif da=='undebug'
     $show=false
     $debug=false
     return ""
   elsif da=='reset'
     env.reset
     return ""
   elsif da[0,6]=='$eopen'
     file =getfname da[6..-1]
     edit(file,geteditor(env))
     return ""
   elsif da[0,1]=='$'
     puts da[1..-1]
     system(da[1..-1])
     return ""
   elsif da[0,5]=="!load"
     loadf da[5..-1]
     return ""
     # puts "loaded \'#{file}\'."
   elsif da[0,2]=="!l"
     loadf da[2..-1]
     return ""
   elsif da[0,5]=="!save"
     file =getfname da[5..-1]
     open(file,"a"){|f| 
       env.hlist.each{|i| 
         f.puts i.to_s+"="+env.mem[env.assign[i]].to_s
       }
     }
     return "saved as \'#{file}\'."
   else
     a=calc(da,env)
     return a
   end
 end
end

def help
 puts "example: 'x=1','y=text','?'(list),'z=x*2+(5-x)','!save [file]'(file save),'!load [file]', '???'(internal hensu dump),'$dir'(exec system.command) etc."
end

# check whether this block is a single line
def blockok d
  flag = false
  a=d.gsub(/[^\{\}]/,'')
  a=a.gsub(/\{\}/,'')
  while $& ;a=a.gsub(/\{\}/,'') end
  #p "a=",a
  return false if a!="" 
  /puts *"((.|\n)*)/ =~ d
  if $&
    #p "qst:"+$1+".m:"+$&
    /"/ =~$1
    if !$&
      return false
    end
  end
  /print *"[^"]*$/ =~ d
  return false if $&
  true
end

def commentoff da
  /[ \t]*#.*/ =~da
  flag =false
  a =$&
  b =$`
  if a
    flag =true
    /^\{[^\}]+\}/ =~a
    flag =false if $&
    /\"/ =~a
    flag =false if $&
  end
  return b if flag
  da
end


def main da, env=$current
  line=$stack.pop 
  data=commentoff(da.chomp)
  ($stack.push(""); return "") if data=="" && line==""
  if line!=""
    /[^\\]\"[^\"]*$/ =~ line 
    if $&
      line = line +"\n" + da.chomp
    else
      line = line+";"+ data
    end
  else
    line = data
  end
  p "l:"+line if $debug
  $stack.push(line) 
  if blockok(line)
    p"blk:"+line if $debug
    an=mainloop(line,env)
    puts an if $show
    mainloop("??",env) if $debug
    showprompt if $mode!="load" || $show
    $stack.pop
    line=""
    $stack.push(line)
  else
    print $repprompt if $mode!="load" || $show
  end
end


def loadf fname
 $mode="load"
 file =getfname fname
 open(file,"r"){|f|
   n=0
   $stack.push("")
   f.each{|dat|
     n+=1
     #p dat
     puts n.to_s+":"+dat+"("+fname +")" if $show
     main(dat)
   }
   $stack.pop
 }
 $mode=""
end


### start ###

if ARGV==[]
  # dialog mode
  showprompt
  while gets
    main $_, $current
  end
else
  # file load mode
  loadf ARGV[0]
end

# hello.ko
print "Hello, world!"
# echo.ko
while gets {puts $_}
# kaigyo.ko

puts "test1
test2
test3

test4 after blank line.
end.
"

puts "ok?"
# apri.ko

http://d.hatena.ne.jp/hatecha/

電卓、historyはここにしようか

| 電卓、historyはここにしようか - たばさの を含むブックマーク はてなブックマーク - 電卓、historyはここにしようか - たばさの

# koneko-his
script language? koneko 
history

2007/12/01  v.0.0
       whirl かなにかやってて、メモリシミュレーション用に始める。
       なので割り当ての部分で無駄な処理をしている
2007/12/11  v.0.4
2007/12/12 v.0.41
            array[1..3] 。>文字列の判定しないと。
            /asd(fg)/=~data => set $&,$1。
            testhen.txt(テスト用読み込みファイル)。
            
            [コマンドなど現状]
            だいたいrubyに準じて。節操なく。
            ?,??,???,???? => 状態表示。
            $ =>終了。
            exit => his保存、終了。
            debug => 行実行ごとに変数状態表示。
            undebug
            show => 行実行ごとに戻り値表示、on-off。
            reset => 全状態の初期化(変数消去)。
            $dir など => $を取り除いてシステムコマンドとして実行。
            !load [file] => ファイル読み込み実行。
            !save [file] => 変数状態をファイルに保存。
            文字列は""括りなしで(多分変える)。
            変数は宣言要らず。代入時になければ作られる。
             それ以外では現状は文字列として扱われる。
            
            @namespace name => 名前空間というのか、丸ごと入れ替え。
             まだ単独(継承なし)。
            name:hensu で名前空間名付きで変数呼び出し。 
            (行頭)http... =>ブラウザで開く
            (行頭)...txt  =>エディタで開く,
              editor=...で設定してあればそれで。editor=typeならtypeする。
            # のあとはコメント
            $eopen [file] =>エディタで開く、など。
            名前はnekoにしようか。koneko nuko?
            なんでもありの柔軟性というか雑食性。
            特殊命令は$,@で始めようかと思ったが入力面倒なので途中でやめた。
            
            break 導入
            
            
2007/12/15 v.0.4.5
            複数行読み込み、調整中。
            引数にファイル名で実行モード、なければ対話モード(今までのもの)。
            puts "..",".." (コンマ区切り。)
            全部evalで出来るような。でもそれだとおもしろくなかったり。
            
            n.timesループのなかでit,ti。(xtal参照)
            a=file(name) => a[0],a[1]...に、行ごとに読み込む。
            
2007/12/17 v.0.4.7
            ファイル操作。まずテキスト。配列<=>行
             file(name)=a => a[0],a[1]... をファイルに書き込む。
             a=file(name) => a[0],a[1]... にファイルから読み込む。
             file(name)<<a => a[0],a[1]... をファイルに追加モードで書き込む。
             a<<file(name) => a[max],a[max+1]... にファイルから読み込む(追加)。
             =はいいだろうか。>だと比較みたいだし。
            配列は現在はそれっぽい変数名にしてあるだけで型を作っているわけではない。
            正規表現、$9 までセット。
            
            puts a,b,c... => puts a;puts b;puts c...
            とやったら、puts "... , ..."がおかしくなった。なるほどー。
            
            a[9]<<file(name) => 読み込む配列の開始位置を指定できるように。
            a=reval(...) => ruby eval
            a=keval(...[,$env]) => koneko.env eval then reval
              i=4 を koneko script で定義してある場合
              reval("1+2") => 3
              reval("1+2+i") => error
              keval("1+2+i") => 7
              これである程度のことは無理やりできるようになっただろうか。
              あとエラーですぐ落ちるのをなんとかすれば。
              
            ネストの類は多分うまくいかない。
             「 , " ; ( ) 」 での分割処理が適当なため。
            file(..., rb) =>binary mode など。モード指定。
            
2007/12/19
            todo> label->jump (goto) 入れたい。なんとなく。<done
             program counter? 。ロードの仕方変えないとかな。
            todo> alias別名。多重代入。
            @ns => @namespace。
            ''囲いの文字列( '...' )を追加。
            正規表現の結果、$~ をとりあえず 内部変数 $match に入れてみる。
             a=reval("$match[11]") などとやって使える。( =>$~[11] )
             当面文字列しか変数に入れられないため、とりあえず。
             ファイルも同様、openじゃなくて文字列にすぐにいれた。どうなんでしょう。
              nuko,あるいはkoneko2では型も増えるでしょう。?
            puts ".. , ..." は、文字列を変数に入れればいいようだ、
            現状ほかで「,」をチェックしてないから。それもどうなんだか。
            正規表現とevalで結構出来るもんだなあと、しかしそのせいで
             クラスなどを作る気が起きない。
             
             
2007/12/20 v 0.4.83
            goto label  と
            label: 追加。
             ファイルロードの場合のみ行頭のみ単文で。
              (のみじゃなかった、同じの使ってた)
             ラベル名はアルファベットか数字の文字列。
             実装のためファイルを最初にすべて読み込むようにしたら速くなった。
             そうなんだ。知らなかった。
             テストしたら300行おきに軽く止まる、なぜだろう。
             読み込んだからやろうと思えば自己書換えもできるかな。
            if .. goto .. 追加。現状ではラベルは空白以外。
            
            a=reval("$last") => 直前の代入の値を参照。$lastは内部変数。
              ちょっと変わったことをやってみたかった。使い道は特に思いつかないけど。
              

2007/12/21 v 0.4.93
            case .. { 
             .. : .. ;;
             .. : .. ;;
              .... 
             }
             => bash 風の case。
            case .. {
             /regex/: .. ;;
             /regex/: .. ;;
              .... 
             }
             => おなじく、正規表現も使える。
             改行処理は不完全。
            loop{...} ループ。
            _1_ => 1行目をコピー、マクロ。
            alias .. ....... => 読み込み時に置換。
            a,b,c=1,2,3 => a=1;b=2;c=3;  単純な多重代入。
            __END__ => 以降はコメント扱い。
            keval(a==y) => y=>aのときtrueを返すようにした。
              aが変数で定義されていなくても文字列として。
            browse http://... , http://.. , http://...
            browse { .. [ 改行 .. 改行 .. ] } 
            koneko -e '...' => '...' をtmp.koに保存して実行。
            $l => 実行中のスクリプトファイル名。
            exit => 終了。
            $ => メモして終了。 (逆にした)
            
            現在一部(kevalなど)の置き換えは単語チェックなどしてないので
              i=9 のあと keval( ...times )  => ...t9mes  などとなってしまう。

2007/12/23 0.4.93.1+
            if文書き換えで行き詰まり。判定を一ヶ所にまとめようとして。
            rb 3.times{|i|
               p i
               }
            rb
               => rubyコード。行頭にrbで挟む。
               
            forget a => 変数 a を未定義にする。


*1:当然すべての言語のトップレベルのマスターが必要。

トラックバック - http://rubyist.g.hatena.ne.jp/hatecha/20071215
カレンダー
<< 2007/12 >>
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
archive Error : RSSが取得できませんでした。