1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#!/usr/bin/ruby
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverrequire 'erb'
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverrequire 'antlr3'
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodule ANTLR3
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodule Template
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodule Builder
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  extend ClassMacros
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  module ClassMethods
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    attr_writer :template_library
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def template_library
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @template_library ||= ANTLR3::Template::Group.new
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def return_scope_members
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      super.push( :template )
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def load_templates( group_file )
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @template_library = 
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        ANTLR3::Template::Group.load( group_file )
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def define_template( name, source, &block )
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      template_library.define_template( name, source, &block )
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def self.included( klass )
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Class === klass and klass.extend( ClassMethods )
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def initialize( input, options = {} )
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    templates = @templates || options.fetch( :templates ) do
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      self.class.template_library or ANTLR3::Template::Group.new
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super( input, options )
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    self.templates = templates
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  shared_attribute( :templates )
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def create_template( source, values = {} )
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @templates.new( source, values )
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def fetch_template( name, values = {} )
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @templates.fetch( name, values )
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodule RewriteBuilder
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  include Builder
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def self.included( klass )
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Class === klass and klass.extend( Builder::ClassMethods )
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverprivate
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def cast_input( input, options )
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    case input
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    when TokenSource then TokenRewriteStream.new( input, options )
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    when IO, String
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      if lexer_class = self.class.associated_lexer
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        TokenRewriteStream.new( lexer_class.new( input, options ), options )
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      else
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        raise ArgumentError, Util.tidy( <<-END, true )
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        | unable to automatically convert input #{ input.inspect }
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        | to a ANTLR3::TokenStream object as #{ self.class }
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        | does not appear to have an associated lexer class
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        END
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    else
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      super
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverautoload :GroupFile, 'antlr3/template/group-file'
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass Group < Module
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  autoload :Lexer, 'antlr3/template/group-file'
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  autoload :Parser, 'antlr3/template/group-file'
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def self.parse( source, options = {} )
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    namespace = options.fetch( :namespace, ::Object )
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    lexer  = Lexer.new( source, options )
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    parser = Parser.new( lexer, options )
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return( parser.group( namespace ) )
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def self.load( group_file, options = {} )
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    unless( File.file?( group_file ) )
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      dir = $LOAD_PATH.find do | d |
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        File.file?( File.join( dir, group_file ) )
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end or raise( LoadError, "no such template group file to load %s" % group_file )
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      group_file = File.join( dir, group_file )
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    namespace = options.fetch( :namespace, ::Object )
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    input = ANTLR3::FileStream.new( group_file, options )
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    lexer = Lexer.new( input, options )
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    parser = Parser.new( lexer, options )
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return( parser.group( namespace ) )
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def self.new( &block )
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super do
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      const_set( :TEMPLATES, {} )
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      block_given? and module_eval( &block )
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def new( source, values = {} )
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    erb = ERB.new( source, nil, '%' )
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    template = Context.new( values )
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    template.extend( self )
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    sclass = class << template; self; end
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    erb.def_method( sclass, 'to_s' )
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return( template )
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def fetch( name, values = {} )
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    self::TEMPLATES.fetch( name.to_s ).new( values )
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def templates
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    self::TEMPLATES
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def template_defined?( name )
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    self::TEMPLATES.has_key?( name.to_s )
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def define_template( name, source, parameters = nil, &block )
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    name = name.to_s.dup.freeze
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Context.define( self, name, parameters ) do | tclass |
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      self::TEMPLATES[ name ] = tclass
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      ERB.new( source, nil, '%' ).def_method( tclass, 'to_s' )
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      define_template_methods( tclass )
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return( self )
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def alias_template( new_name, old_name )
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    new_name, old_name = new_name.to_s.dup.freeze, old_name.to_s
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    context = self::TEMPLATES.fetch( old_name.to_s ) do
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      raise( NameError,
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        "undefined template `%s' for template group %p" % [ old_name, self ]
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      )
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    context.define_alias( new_name ) do | tclass |
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      self::TEMPLATES[ new_name ] = tclass
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      define_template_methods( tclass )
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return( self )
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverprivate
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def define_template_methods( context )
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    name = context.name
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if params = context.parameters
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      init = params.names.map do | param |
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        "___[ #{ param.inspect } ] = #{ param }"
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end.join( "\n" )
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      module_eval( <<-END )
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        module_function
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        def #{ name }( #{ params } )
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          TEMPLATES[ #{ name.inspect } ].new do | ___ |
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            #{ init }
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          end
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        def #{ name }!( #{ params } )
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          TEMPLATES[ #{ name.inspect } ].new do | ___ |
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            #{ init }
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          end.to_s
190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      END
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    else
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      module_eval( <<-END )
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        module_function
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        def #{ name }( values = {} )
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          TEMPLATES[ #{ name.inspect } ].new( values )
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        def #{ name }!( values = {} )
203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          TEMPLATES[ #{ name.inspect } ].new( values ).to_s
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      END
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass Context
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  VARIABLE_FORM = /^(@)?[a-z_\x80-\xff][\w\x80-\xff]*$/
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  SETTER_FORM = /^([a-z_\x80-\xff][\w\x80-\xff]*)=$/
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  ATTR_FORM = /^[a-z_\x80-\xff][\w\x80-\xff]*$/
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  class << self
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    attr_accessor :group, :name, :parameters
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    protected :group=, :name=
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def define_alias( name )
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      new = clone
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      new.name = name
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      new.group = @group
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      block_given? and yield( new )
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      return( new )
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def define( group, name, parameters )
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      Class.new( self ) do
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        include( group )
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        @group = group
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        @name  = name
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        @parameters = parameters
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        block_given? and yield( self )
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def method_missing( method, *args )
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    case name = method.to_s
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    when SETTER_FORM then return( self[ $1 ] = args.first )
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    when ATTR_FORM
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      args.empty? and has_ivar?( name ) and return( self[ name ] )
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    super
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def []=( name, value )
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    instance_variable_set( make_ivar( name ), value )
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def []( name )
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    name = make_ivar( name )
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    instance_variable_defined?( name ) ? instance_variable_get( name ) : nil
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def <<( variable_map )
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    variable_map.each_pair do | name, value |
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      self[ name ] = value
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return( self )
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def initialize( variable_map = nil )
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    variable_map and self << variable_map
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    block_given? and yield( self )
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverprivate
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def has_ivar?( name )
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    instance_variable_defined?( make_ivar( name ) )
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def make_ivar( name )
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    name = name.to_s
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    VARIABLE_FORM =~ name or
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      raise ArgumentError, "cannot convert %p to an instance variable name" % name
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    $1 ? name : "@#{ name }"
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
286324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverParameter = Struct.new( :name, :default )
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass Parameter
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def to_s
289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    default ? "#{ name } = #{ default }" : "#{ name }"
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass ParameterList < ::Array
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  attr_accessor :splat, :block
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def self.default
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    new.add( :values ) do | p |
298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      p.default = '{}'
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def names
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    names = map { | param | param.name.to_s }
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @splat and names << @splat.to_s
305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @block and names << @block.to_s
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return( names )
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def add( name, options = nil )
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    param =
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      case name
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      when Parameter then name
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      else Parameter.new( name.to_s )
314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if options
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      default = options[ :default ] and param.default = default
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      param.splat = options.fetch( :splat, false )
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      param.block = options.fetch( :block, false )
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    block_given? and yield( param )
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    push( param )
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return( self )
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def to_s
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    signature = join( ', ' )
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @splat and signature << ", *" << @splat.to_s
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @block and signature << ", &" << @block.to_s
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return( signature )
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
334