module Delorean class SNode < Treetop::Runtime::SyntaxNode end class Line < SNode def check(context, *a) f.check(context, *a) end def rewrite(context) f.rewrite(context) end end class Parameter < SNode def check(context, *) context.parse_define_param(i.text_value, []) end def rewrite(context) # Adds a parameter to the current node. Parameters are # implemented as functions (just like attrs). The environment # arg (_e) is a Hash. To find a param (aname) in node (cname), # we first check to see if cname.aname has already been computed # in _e. If not, to compute it we check for the value in _e # (i.e. check for aname). Otherwise, we use the default value # if any. aname, cname = i.text_value, context.last_node not_found = defined?(e) ? e.rewrite(context) : "raise UndefinedParamError, 'undefined parameter #{aname}'" < #{v}"} + args.reverse.each_with_index.map {|v, i| "#{i} => #{v}"}).join(',') "_node_call(#{node_name}, _e, {#{kw_str}})" end end ###################################################################### class ExpGetAttr < SNode def check(context, *) v.check(context) end def rewrite(context) attrs = ga.text_value.split('.') # If ga.text_value is not "", then we need to drop the 1st # element since it'll be "". attrs.shift attrs.inject(v.rewrite(context)) {|x, y| "_get_attr(#{x}, '#{y}', _e)"} end end class FnArgs < SNode def check(context, *) arg0.check(context) + (defined?(args_rest.args) && !args_rest.args.text_value.empty? ? args_rest.args.check(context) : []) end def rewrite(context) arg0.rewrite(context) + (defined?(args_rest.args) && !args_rest.args.text_value.empty? ? ", " + args_rest.args.rewrite(context) : "") end def arg_count defined?(args_rest.args) ? 1 + args_rest.args.arg_count : 1 end end class IfElse < SNode def check(context, *) vc, e1c, e2c = v.check(context), e1.check(context), e2.check(context) vc + e1c + e2c end def rewrite(context) "(" + v.rewrite(context) + ") ? (" + e1.rewrite(context) + ") : (" + e2.rewrite(context) + ")" end end class ListExpr < SNode def check(context, *) defined?(args) ? args.check(context) : [] end def rewrite(context) "[" + (defined?(args) ? args.rewrite(context) : "") + "]" end end class UnpackArgs < SNode def check(context, *) [arg0.text_value] + (defined?(args_rest.args) && !args_rest.args.text_value.empty? ? args_rest.args.check(context) : []) end def rewrite(context) arg0.rewrite(context) + (defined?(args_rest.args) && !args_rest.args.text_value.empty? ? ", " + args_rest.args.rewrite(context) : "") end end class ListComprehension < SNode def check(context, *) unpack_vars = args.check(context) e1c = e1.check(context) unpack_vars.each {|vname| context.parse_define_var(vname)} # need to check e2/e3 in a context where the comprehension var # is defined. e2c = e2.check(context) e3c = defined?(ifexp.e3) ? ifexp.e3.check(context) : [] unpack_vars.each { |vname| context.parse_undef_var(vname) e2c.delete(vname) e3c.delete(vname) } e1c + e2c + e3c end def rewrite(context) res = "(#{e1.rewrite(context)})" unpack_vars = args.check(context) unpack_vars.each {|vname| context.parse_define_var(vname)} args_str = args.rewrite(context) res += ".select{|#{args_str}|(#{ifexp.e3.rewrite(context)})}" if defined?(ifexp.e3) res += ".map{|#{args_str}| (#{e2.rewrite(context)}) }" unpack_vars.each {|vname| context.parse_undef_var(vname)} res end end class SetExpr < ListExpr def rewrite(context) "Set#{super}" end end class SetComprehension < ListComprehension def rewrite(context) "Set[*#{super}]" end end class HashComprehension < SNode # used in generating unique hash names @@comp_count = 0 def check(context, *) unpack_vars = args.check(context) e1c = e1.check(context) unpack_vars.each {|vname| context.parse_define_var(vname)} # need to check el/er/ei in a context where the comprehension var # is defined. elc = el.check(context) erc = er.check(context) eic = defined?(ifexp.ei) ? ifexp.ei.check(context) : [] unpack_vars.each { |vname| context.parse_undef_var(vname) elc.delete(vname) erc.delete(vname) eic.delete(vname) } e1c + elc + erc + eic end def rewrite(context) res = "(#{e1.rewrite(context)})" unpack_vars = args.check(context) unpack_vars.each {|vname| context.parse_define_var(vname)} args_str = args.rewrite(context) hid = @@comp_count += 1 res += ".select{|#{args_str}| (#{ifexp.ei.rewrite(context)}) }" if defined?(ifexp.ei) unpack_str = unpack_vars.count > 1 ? "(#{args_str})" : args_str res += ".each_with_object({}){|#{unpack_str}, _h#{hid}| " + "_h#{hid}[#{el.rewrite(context)}]=(#{er.rewrite(context)})}" unpack_vars.each {|vname| context.parse_undef_var(vname)} res end end class HashExpr < SNode def check(context, *) defined?(args) ? args.check(context) : [] end def rewrite(context) "{#{args.rewrite(context) if defined?(args)}}" end end class KwArgs < SNode def check(context, *) arg0.check(context) + (defined?(args_rest.args) ? args_rest.args.check(context) : []) end def rewrite(context) arg0_rw = arg0.rewrite(context) if defined?(args_rest.al) && !args_rest.al.text_value.empty? args, kw = args_rest.al.rewrite(context) else args, kw = [], {} end if defined?(k.i) kw[k.i.text_value] = arg0_rw else args << arg0_rw end [args, kw] end end class HashArgs < SNode def check(context, *) e0.check(context) + e1.check(context) + (defined?(args_rest.args) ? args_rest.args.check(context) : []) end def rewrite(context) e0.rewrite(context) + " => " + e1.rewrite(context) + (defined?(args_rest.al) && !args_rest.al.text_value.empty? ? ", " + args_rest.al.rewrite(context) : "") end end end