tmail/amstd/environ.rb
#
# environ.rb
#
# Copyright (c) 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
#
require 'amstd/to_s'
class Environment
def initialize( name, parent, stack )
@name = name.dup
@parent = parent
@stack = stack
@values = {}
@parent = nil
@children = []
do_initialize
end
attr :name
attr :parent
attr :children
def warn( mes )
$stderr.print 'Warning: '
$stderr.puts mes
end
def set( name, val )
targ, nm = gettarg( name )
targ.in_set nm, val
end
alias s set
def get( name )
targ, nm = gettarg( name )
ret = targ.in_get( nm )
unless ret then
warn "#{_name2str(name)} is nil"
end
ret
end
alias g get
def g?( name )
targ, nm = gettarg( name )
ret = targ.in_get( nm )
ret ? true : false
end
def get_env( name )
@stack[ name ]
end
alias e get_env
private
def do_initialize
end
def gettarg( nm )
name = _name2str( nm )
a = name.split('.')
if a.size > 1 then
p a
unless env = @stack[ a[0] ] then
raise ArgumentError, "non exist environment '#{env}'"
end
a[0] = env
else
a.unshift self
end
a
end
protected
def in_set( n, v )
@values[n] = v
end
def in_get( n )
@values[n]
end
end
class EnvironmentError < StandardError ; end
class EnvironmentStack
def initialize
@vals = {}
@current = nil
@prev = nil
@stack = []
end
class << self
def item_type( arg = nil )
if arg then
@item_type = arg
else
@item_type
end
end
end
item_type Environment
attr :current
attr :prev
def []( name )
@vals[ _name2str( name ) ]
end
def enter( name )
name = _name2str( name )
if e = @vals[ name ] then
raise EnvironmentError, "environment name '#{name}' used twice"
end
paren = @current
@vals[ name ] = @current = type.item_type.new( name, paren, self )
if paren then
paren.children.push @current
end
@stack.push @current
@current
end
def leave( name = nil )
unless e = @stack.pop then
raise EnvironmentError, "too many leave than enter"
end
name = _name2str( name ) if name
if name and e.name != name then
puts "warning: leave from #{e.name}, but #{e.name} is required"
end
@prev = @current
@current = @stack[-1]
e
end
def environ( name, &block )
e = enter( name )
e.instance_eval &block
leave e.name
end
end