Hatena::Grouprubyist

たばさの RSSフィード

12/17(月) 2007

電卓 続き ファイル読み書き

| 電卓 続き ファイル読み書き - たばさの を含むブックマーク はてなブックマーク - 電卓 続き ファイル読み書き - たばさの

file(...)<<array
array<<file(...)

など。

履歴

いじってたらプリント文が一部おかしくなったけど。



# koneko-0.4.7.rb


$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 indmax ar,env
  i=0
  while exist(ar+"["+i.to_s+"]",env)
    i+=1
  end
  i
end

def existarray ar,env
  i=0
  exist(ar+"["+i.to_s+"]",env)
end

def arreset(ar,env)
  i=0
  while exist(ar+"["+i.to_s+"]",env)
    setvalstr(ar+"["+i.to_s+"]","",env)
    i+=1
  end
  i
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,eva=false
  (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
  if eva
    v=b
  else
    v=calc(b,envfrom)
    v="nul" if v==nil
  end
  env.mem[env.assign[a]] =v
  return env.mem[env.assign[a]]
end

def setvalstr a,b,env
  setval a,b,env,true
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 $&
 if $1
   9.times{|i|
     p eval("$#{i+1}") if $debug
     eval("setval(\"$#{i+1}\",$#{i+1},env)") 
   }
   setval("$&",$&,env)
   setval("$`",$`,env)
   setval("$'",$',env)
 end
 # file :write array
 /file\(([^\)]+)\) *(=|<<) *(.*)/ =~ da
 f=$1
 op=$2
 a=$3
 if f
   mode='w' if op=='='
   mode='a' if op=='<<'
   open(f,mode){|fo|
     if existarray(a,env)
       imax=ii=indmax(a,env)
       while ii>0
         line=calc(a+"["+(imax-ii).to_s+"]",env)
         fo.puts(line)
         ii-=1
       end
     elsif !exist(a,env)
       fo.puts(calc(a,env))
     else
       fo.puts(a)
     end
   }
   return ""
 end
 # 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 $&
  num=calc($1,env).to_i
  return num.times{ |it|
    a=body.gsub("it", it.to_s)
    a=a.gsub("ti", (num-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 $&
 # file to Array
 /([a-zA-Z_][a-zA-Z_0-9]*(\[[0-9]+\])?) *(=|<<) *file\((.+)\)/ =~ da
 a=$1
 op=$3
 f=$4
 if a
   tmp=[]
   /^"(.*)"$/ =~ f
   f=$1 if $&
   open(f){|fi|
     tmp=fi.readlines
   }
   #p tmp
   start=indmax(a,env)
   (arreset(a,env) ; start=0) if op=='='
   tmp.length.times{|i|
     puts a+"[#{i+start}]",tmp[i] if $debug
     setval(a+"[#{i+start}]",tmp[i],env,true)
   }
   return ""
 end
 # 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

トラックバック - http://rubyist.g.hatena.ne.jp/hatecha/20071217
カレンダー
<< 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が取得できませんでした。