Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 133 lines (120 sloc) 3.678 kb
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 32 33 34 35 36 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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 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
require 'reg'
require 'regcompiler'
module Reg
  module Reg
    def xform!(datum,changed={})
      datum or fail
      Thread.current[:Reg_xform_session]=session={}
      changed.merge!(session) if self===datum
    ensure
      Thread.current[:Reg_xform_session]=nil
    end
  end

  class Bound
    def === other #this is a hack
      result= @reg===other
      session=Thread.current[:Reg_xform_session]
      if result and session and !session.has_key? @name
        session[@name]=other
      end
      return result
    end

    def formula_value other,session #another hack...
      result= @reg.formula_value other,session
      
      if session and !session.has_key? @name
        session[@name]=result
      end
      return result
    end
  end

  class BoundRef
    def inspect
      "~:#{name}"
    end
    def === other #this is a hack
      session=Thread.current[:Reg_xform_session]
      if session and session.has_key? @name
        session[@name]==other
      else raise NameNotBound #name not bound yet? that's an error
      end
    end

    def formula_value(other,session)
      session.fetch(name,session["final"] ? nil : self)
    end
  end

  module Formula #more hackery
    def % other
      if Symbol===other
        Reg::Bound.new(self,other)
      else
        super
      end
    end
  end

  class NameNotBound<RuntimeError; end
  class ReplacingNilError<RuntimeError; end

  class Transform
    def inspect
      from.inspect+" >> "+to.inspect
    end
    def === other #this is a hack
      result= from===other
      session=Thread.current[:Reg_xform_session]
      if result and session
        raise ReplacingNilError,"replaces of nil or false are not allowed" unless other
        locals={:self=>other}
        if $&
          locals[:$&]=$&
          locals[:$`]=$`
          locals[:$']=$'
          $&.to_a.each_with_index{|br,i| locals[:"$#{i}"]=br }
        end
        session[other.__id__]=
          case to
          when Replace::Form; to.fill_out_simple(locals,other) #should handle Literals as well...
          when BoundRef; to.formula_value(other,locals) #must be eval'd early...?
          when Formula; WithBoundRefValues.new(to,locals)
          else to
          end
      end
      return result
    end
  end

 
  class And
    def === other #hack around bugs in AndMachine
      @regs.each{|reg| return unless reg===other }
      return other||true
    end
    def multiple_infection(*args) end #hacky, never do anything for Reg::And
  end

  class Or
    def multiple_infection(*args) end #hacky, never do anything for Reg::Or
  end
  class Hash
    def multiple_infection(*args) end #hacky, never do anything for Reg::Hash
  end
  class Object
    def multiple_infection(*args) end #hacky, never do anything for Reg::Object
  end
  class Trace
    def multiple_infection(*args) end #hacky, never do anything for Reg::Trace
  end
  class BP
    def multiple_infection(*args) end #hacky, never do anything for Reg::BreakPoint
  end
end

tests=proc{
  require 'test/unit'
  class XformTests<Test::Unit::TestCase
    alias assert_op assert_operator
    def test_and_with_bound_and_replace
      assert_op String>>"bop", :===, "sdfsdf"
      assert String>>"bop" === "sdfsdf"
      assert_op +{ :body=>String >> 'bop' }, :===, {:body => "23423"}
      assert_op (/sdfgdf/ | Hash )%:top & +{ :body=>String >> 'bop' }, :===, {:body => "23423"}
      assert_op( (((/7869/ | Hash )%:top) & +{ :body=>String >> 'sdf' }) | Symbol, :===, Hash[:body, "4564563"] )
      assert_op( ((((/7869/ | Hash )%:top) & +{ :body=>String >> 'sdf' }) | Symbol).trace, :===, Hash[:body, "4564563"] )
    end
  end
}
tests[] if __FILE__==$0
Something went wrong with that request. Please try again.