Class: Macro::FormNode

Inherits:
ValueNode
  • Object
show all
Defined in:
lib/macro/form.rb,
lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_9.rb,
lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_8.rb,
lib/macro.rb

Overview

postpone macro expansion (and definition) in forms until they are evaled (or returned from a macro) but not in form parameters

Defined Under Namespace

Modules: InlineList

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(colon, text) ⇒ FormNode

Create a new form node. The user should normally not call this function. Form nodes are created by the parser.

colon

A colon token

text

A ParenedNode or VarLikeNode



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/macro/form.rb', line 37

def initialize(colon,text)
  @startline=@endline=nil

  # Certain node types need to be quoted
  # (or rather, not unquoted)
  if RedParse::VarLikeNode===text
    #this code is dead now, I believe
    @transform=HashLiteralNode[]
    @stars_transform=HashLiteralNode[]
    text.startline=text.endline=0
    super text
    return
  end


  # Sanity check - make sure this is a valid ParenedNode
  if ParenedNode===text && text.size==1 
    text=text.body #unquote the form
  elsif text.size==0
    @transform=HashLiteralNode[]
    @stars_transform=HashLiteralNode[]
    super SequenceNode[]
    return
  end

  super text
  rebuild_transform
end

Class Method Details

._load(str) ⇒ Object



82
83
84
85
86
# File 'lib/macro/form.rb', line 82

def self._load str
  result=allocate
  result.replace [Marshal.load(str)]
  result.rebuild_transform
end

Instance Method Details

#_dump(depth) ⇒ Object



78
79
80
# File 'lib/macro/form.rb', line 78

def _dump depth
  Marshal.dump text,depth
end

#deep_copy(transform = {}) ⇒ Object

Make a deep copy of this form

transform

TODO



162
163
164
# File 'lib/macro/form.rb', line 162

def deep_copy transform={}
  super(transform).rebuild_transform
end

#each_parameter(&block) ⇒ Object

Iterate over all the parameters in this form

block

the block to call for each parameter



154
155
156
# File 'lib/macro/form.rb', line 154

def each_parameter(&block)
  @parameters.each(&block) if defined? @parameters
end

#formnameObject

Lazily evaluate the name of the form and return it



265
266
267
268
269
270
271
# File 'lib/macro/form.rb', line 265

def formname
  startline=@startline if defined? @startline
  endline=@endline if defined? @endline
  ivars={:@startline=>startline, :@endline=>endline}

  @formname ||= ConstantNode[nil,"Macro","Names",::Macro::Names.request(self), ivars]
end

#initialize_copy(other) ⇒ Object



70
71
72
73
74
75
76
# File 'lib/macro/form.rb', line 70

def initialize_copy other
  replace other
  other.instance_variables{|v|
    instance_variable_set v, other.instance_variable_get(v)
  }
  rebuild_transform
end

#initialize_ivarsObject

def _dump depth

  "foobarbaz"
end

def self._load str
  result=allocate
end


98
99
100
101
# File 'lib/macro/form.rb', line 98

def initialize_ivars
  rebuild_transform
  super
end

#macro_expand(macros, session) ⇒ Object



680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
# File 'lib/macro.rb', line 680

def macro_expand(macros,session)
  #return text.to_sexp({})
   

  #maybe this doesn't allow expansion of parameters themselves... only within params?
  each_parameter{|param| Macro.expand(param,macros,session) }


  #replace (text for) form itself with a reference which will be 
  #looked up at runtime (and have parameters expanded at that point too)
  
  


  return parses_like,false #halt further recursion: already done where necessary
end

#noinspect_instance_variablesObject



66
67
68
# File 'lib/macro/form.rb', line 66

def noinspect_instance_variables
  %w[@stars_transform @transform]
end

#parses_likeObject

Turn the form into something that is legal ruby (since :(..) is not legal ruby syntax). Thus the form is changed from the syntax:

:(code)

to:

RedParse::SomeNodeType[ some transform of code ]


253
254
255
256
257
258
259
260
261
262
# File 'lib/macro/form.rb', line 253

def parses_like
  startline=@startline if defined? @startline
  endline=@endline if defined? @endline
  ivars={:@startline=>startline, :@endline=>endline}
  CallSiteNode[
    CallSiteNode[formname, "reify", [@transform,@stars_transform], ivars], 
    "text", ivars
  ]
  #:(^(formname).reify(^@transform,^@stars_transform).text)
end

#parsetreeObject

Transform this node into a ParseTree parse tree



221
222
223
# File 'lib/macro/form.rb', line 221

def parsetree
  parses_like.parsetree
end

#rebuild_transformObject

Initialize the transform and create all the form escapes that are used in this form



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/macro/form.rb', line 105

def rebuild_transform
  # TODO: this method needs to be better documented/refactored
  @transform=HashLiteralNode[]
  @stars_transform=HashLiteralNode[]
  @parameters=[]
  @parameters.extend RedParse::ListInNode

  walkers=proc{|rcvr,wraplayers| #curry
    rcvr.walk{|parent,i,j,node| 
     node.startline=node.endline=0 if node.respond_to? :startline
     case node
     when FormEscapeNode
       target=node.wraplevel
       #fail if wraplayers > target
       if wraplayers==target #skip this parameter if it doesn't have enough wrappers
         @parameters << node #remember parameter (and implicitly, location)

         nil# and stop further recursion
       else 
         true
       end
     when FormNode
       #walk form with same walker we're using now, except an extra layer of form parameters
       #must be present for them to be considered 'our' parameters
       walkers[node.text,wraplayers+1]
       nil #don't recurse in this node again, we just did it
     else true
     end
    } if rcvr.respond_to? :walk
  }
  walkers[text,1]

  @parameters.each{|orig_escd| 
    escd=orig_escd
    escd=escd.val while FormEscapeNode===escd
    if UnaryStarNode===escd
      @stars_transform.push LiteralNode[orig_escd.__id__], escd.val
    else
      @transform.push LiteralNode[orig_escd.__id__], escd
    end
  }

  return self
end

#reducer_identObject



19083
19084
19085
# File 'lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_9.rb', line 19083

def reducer_ident
  :FormNode
end

#reify(transform, stars_transform) ⇒ Object

Called when the form is evaluated to convert the abstract form of the parse tree into a concrete form that can be modified (makes a copy of the form).

transform

the transform to use in the deep copy



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/macro/form.rb', line 181

def reify transform, stars_transform
  transform&&=transform.dup
  stars_transform&&=stars_transform.dup
  transform.each_pair{|k,v|
    case v
    when Node; next
    when Symbol; v=CallNode[nil,v.to_s]
    else v=Macro.quote v
    end
    transform[k]=v
  }
  stars_transform.each_pair{|k,v|
    case v
    when Symbol; v=CallNode[nil,v.to_s]
    else v=Macro.quote v
    end
    stars_transform[k]=v.extend InlineList
  }
  result=deep_copy(transform.merge( stars_transform ))
  #expand InlineLists somehow
  result.walk{|parent,i,j,node|
    if InlineList===node
      if j
        parent[i][j,1]=*node
      else
        parent[i,1]=*node
      end
      nil #halt further recursion
    else
      true
    end
  } unless stars_transform.empty?
  
  return result
end

#to_sexp(session) ⇒ Object

Convert this node to an S-expression

session

the context in which this macro is being processed



701
702
703
704
705
706
707
708
709
710
711
712
713
# File 'lib/macro.rb', line 701

def to_sexp session
  nest=session[:form_nest_level]
  session[:form_nest_level]=nest ? nest+1 : 2

  result=super

  if nest
    session[:form_nest_level]-=1
  else
    session.delete :form_nest_level
  end
  return result
end

#unparse(o = default_unparse_options) ⇒ Object

Performs the reverse of a parse operation (turns the node into a string)

o

a list of options for unparse



171
172
173
# File 'lib/macro/form.rb', line 171

def unparse o=default_unparse_options
  ":("+text.unparse(o)+")"
end