virtual_keywords 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. data/lib/parsetree/History.txt +477 -0
  2. data/lib/parsetree/Manifest.txt +19 -0
  3. data/lib/parsetree/README.txt +97 -0
  4. data/lib/parsetree/Rakefile +37 -0
  5. data/lib/parsetree/bin/parse_tree_abc +89 -0
  6. data/lib/parsetree/bin/parse_tree_audit +28 -0
  7. data/lib/parsetree/bin/parse_tree_deps +62 -0
  8. data/lib/parsetree/bin/parse_tree_show +63 -0
  9. data/lib/parsetree/demo/printer.rb +20 -0
  10. data/lib/parsetree/lib/gauntlet_parsetree.rb +121 -0
  11. data/lib/parsetree/lib/parse_tree.rb +1202 -0
  12. data/lib/parsetree/lib/parse_tree_extensions.rb +59 -0
  13. data/lib/parsetree/lib/unified_ruby.rb +421 -0
  14. data/lib/parsetree/test/something.rb +53 -0
  15. data/lib/parsetree/test/test_parse_tree.rb +2567 -0
  16. data/lib/parsetree/test/test_parse_tree_extensions.rb +107 -0
  17. data/lib/parsetree/test/test_unified_ruby.rb +57 -0
  18. data/lib/parsetree/validate.sh +31 -0
  19. data/lib/sexps/{count_to_ten_sexp.txt → count_to_ten_sexp.rb} +0 -0
  20. data/lib/sexps/{sexps_and.txt → sexps_and.rb} +0 -0
  21. data/lib/sexps/{sexps_case_when.txt → sexps_case_when.rb} +0 -0
  22. data/lib/sexps/{sexps_greet.txt → sexps_greet.rb} +0 -0
  23. data/lib/sexps/sexps_not.rb +24 -0
  24. data/lib/sexps/{sexps_rewritten_keywords.txt → sexps_rewritten_keywords.rb} +0 -0
  25. data/lib/sexps/{sexps_symbolic_and.txt → sexps_symbolic_and.rb} +0 -0
  26. data/lib/sexps/sexps_until.rb +60 -0
  27. data/lib/sexps/{sexps_while.txt → sexps_while.rb} +0 -0
  28. data/lib/spec/class_reflection_spec.rb +64 -0
  29. data/lib/spec/keyword_rewriter_spec.rb +7 -54
  30. data/lib/spec/not_rewriter_spec.rb +25 -0
  31. data/lib/spec/parser_strategy_spec.rb +23 -0
  32. data/lib/spec/sexp_stringifier_spec.rb +19 -0
  33. data/lib/spec/spec_helper.rb +61 -307
  34. data/lib/spec/until_rewriter_spec.rb +26 -0
  35. data/lib/spec/virtualizees/and_user.rb +17 -0
  36. data/lib/spec/virtualizees/case_when_user.rb +20 -0
  37. data/lib/spec/virtualizees/fizzbuzzer.rb +15 -0
  38. data/lib/spec/virtualizees/greeter.rb +127 -0
  39. data/lib/spec/virtualizees/not_user.rb +9 -0
  40. data/lib/spec/virtualizees/operator_user.rb +15 -0
  41. data/lib/spec/virtualizees/or_user.rb +17 -0
  42. data/lib/spec/virtualizees/parents.rb +8 -0
  43. data/lib/spec/virtualizees/until_user.rb +16 -0
  44. data/lib/spec/virtualizees/while_user.rb +16 -0
  45. data/lib/spec/virtualizer_spec.rb +46 -83
  46. data/lib/virtual_keywords/class_reflection.rb +88 -0
  47. data/lib/virtual_keywords/deep_copy_array.rb +12 -0
  48. data/lib/virtual_keywords/keyword_rewriter.rb +54 -0
  49. data/lib/virtual_keywords/parser_strategy.rb +40 -0
  50. data/lib/virtual_keywords/rewritten_keywords.rb +15 -0
  51. data/lib/virtual_keywords/sexp_stringifier.rb +1 -5
  52. data/lib/virtual_keywords/version.rb +1 -1
  53. data/lib/virtual_keywords/virtualizer.rb +30 -115
  54. data/lib/virtual_keywords.rb +31 -5
  55. metadata +117 -90
  56. data/lib/spec/class_mirrorer_spec.rb +0 -18
  57. data/lib/virtual_keywords/class_mirrorer.rb +0 -39
@@ -0,0 +1,89 @@
1
+ #!/usr/local/bin/ruby -ws
2
+
3
+ # ABC metric
4
+ #
5
+ # Assignments, Branches, and Calls
6
+ #
7
+ # A simple way to measure the complexity of a function or method.
8
+
9
+ if defined? $I and String === $I then
10
+ $I.split(/:/).each do |dir|
11
+ $: << dir
12
+ end
13
+ end
14
+
15
+ PARSE_TREE_ABC=true
16
+
17
+ begin; require 'rubygems'; rescue LoadError; end
18
+ require 'sexp'
19
+ require 'parse_tree'
20
+ require 'sexp_processor'
21
+
22
+ old_classes = []
23
+ ObjectSpace.each_object(Module) do |klass|
24
+ old_classes << klass
25
+ end
26
+
27
+ ARGV.each do |name|
28
+ begin
29
+ require name
30
+ rescue NameError => err
31
+ $stderr.puts "ERROR requiring #{name}. Perhaps you need to add some -I's?\n\n#{err}"
32
+ end
33
+ end
34
+
35
+ new_classes = []
36
+ ObjectSpace.each_object(Module) do |klass|
37
+ new_classes << klass
38
+ end
39
+
40
+ score = {}
41
+
42
+ new_classes -= old_classes
43
+
44
+ klasses = Sexp.from_array(ParseTree.new.parse_tree(*new_classes))
45
+ klasses.each do |klass|
46
+ klass.shift # :class
47
+ klassname = klass.shift
48
+ klass.shift # superclass
49
+ methods = klass
50
+
51
+ methods.each do |defn|
52
+ a=b=c=0
53
+ defn.shift
54
+ methodname = defn.shift
55
+ tokens = defn.structure.flatten
56
+ tokens.each do |token|
57
+ case token
58
+ when :attrasgn, :attrset, :dasgn_curr, :iasgn, :lasgn, :masgn then
59
+ a += 1
60
+ when :and, :case, :else, :if, :iter, :or, :rescue, :until, :when, :while then
61
+ b += 1
62
+ when :call, :fcall, :super, :vcall, :yield then
63
+ c += 1
64
+ when :args, :argscat, :array, :begin, :block, :block_arg, :block_pass, :bool, :cfunc, :colon2, :const, :cvar, :defined, :defn, :dregx, :dstr, :dvar, :dxstr, :ensure, :false, :fbody, :gvar, :hash, :ivar, :lit, :long, :lvar, :match2, :match3, :nil, :not, :nth_ref, :return, :scope, :self, :splat, :str, :to_ary, :true, :unknown, :value, :void, :zarray, :zarray, :zclass, :zsuper then
65
+ # ignore
66
+ else
67
+ puts "unhandled token #{token.inspect}" if $VERBOSE
68
+ end
69
+ end
70
+ key = ["#{klassname}.#{methodname}", a, b, c]
71
+ val = Math.sqrt(a*a+b*b+c*c)
72
+ score[key] = val
73
+ end
74
+ end
75
+
76
+ puts "|ABC| = Math.sqrt(assignments^2 + branches^2 + calls^2)"
77
+ puts
78
+ count = 1
79
+ ta = tb = tc = tval = 0
80
+ score.sort_by { |k,v| v }.reverse.each do |key,val|
81
+ name, a, b, c = *key
82
+ ta += a
83
+ tb += b
84
+ tc += c
85
+ tval += val
86
+ printf "%3d) %-50s = %2d + %2d + %2d = %6.2f\n", count, name, a, b, c, val
87
+ count += 1
88
+ end rescue nil
89
+ printf "%3d) %-50s = %2d + %2d + %2d = %6.2f\n", count, "Total", ta, tb, tc, tval
@@ -0,0 +1,28 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ require 'parse_tree'
4
+
5
+ all_nodes = ParseTree::NODE_NAMES
6
+
7
+ ARGV.each do |processor|
8
+ require processor
9
+ end
10
+
11
+ ObjectSpace.each_object(Class) do |klass|
12
+ if klass < SexpProcessor then
13
+
14
+ processor = klass.new
15
+ processors = klass.public_instance_methods(true).grep(/process_/)
16
+
17
+ if processor.strict then
18
+ puts "#{klass.name}:"
19
+ puts
20
+
21
+ # TODO: check unsupported against supported
22
+ processors = processors.map { |m| m[8..-1].intern } + processor.unsupported
23
+ unsupported = all_nodes - processors
24
+ p unsupported.sort_by { |sym| sym.to_s }
25
+ puts
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,62 @@
1
+ #!/usr/local/bin/ruby -ws
2
+
3
+ old_classes = []; new_classes = []
4
+
5
+ ObjectSpace.each_object(Module) { |klass| old_classes << klass } if defined? $a
6
+
7
+ require 'pp'
8
+
9
+ begin; require 'rubygems'; rescue LoadError; end
10
+ require 'parse_tree'
11
+ require 'sexp_processor'
12
+
13
+ ObjectSpace.each_object(Module) { |klass| old_classes << klass } unless defined? $a
14
+
15
+ class DependencyAnalyzer < SexpProcessor
16
+
17
+ attr_reader :dependencies
18
+ attr_accessor :current_class
19
+
20
+ def initialize
21
+ super
22
+ self.auto_shift_type = true
23
+ @dependencies = Hash.new { |h,k| h[k] = [] }
24
+ @current_method = nil
25
+ @current_class = nil
26
+ end
27
+
28
+ def self.process(*klasses)
29
+ analyzer = self.new
30
+ klasses.each do |start_klass|
31
+ analyzer.current_class = start_klass
32
+ analyzer.process(ParseTree.new.parse_tree(start_klass))
33
+ end
34
+
35
+ deps = analyzer.dependencies
36
+ deps.keys.sort_by {|k| k.to_s}.each do |dep_to|
37
+ dep_from = deps[dep_to]
38
+ puts "#{dep_to}: #{dep_from.uniq.sort.join(", ")}"
39
+ end
40
+ end
41
+
42
+ def process_defn(exp)
43
+ name = exp.shift
44
+ @current_method = name
45
+ return s(:defn, name, process(exp.shift), process(exp.shift))
46
+ end
47
+
48
+ def process_const(exp)
49
+ name = exp.shift
50
+ const = (defined?($c) ? @current_class.name : "#{@current_class}.#{@current_method}")
51
+ is_class = ! (Object.const_get(name) rescue nil).nil?
52
+ @dependencies[name] << const if is_class
53
+ return s(:const, name)
54
+ end
55
+ end
56
+
57
+ if __FILE__ == $0 then
58
+ ARGV.each { |name| require name }
59
+ ObjectSpace.each_object(Module) { |klass| new_classes << klass }
60
+ new_classes.delete DependencyAnalyzer unless defined? $a
61
+ DependencyAnalyzer.process(*(new_classes - old_classes))
62
+ end
@@ -0,0 +1,63 @@
1
+ #!/usr/local/bin/ruby -ws
2
+
3
+ require 'pp'
4
+ begin; require 'rubygems'; rescue LoadError; end
5
+ require 'parse_tree'
6
+ require 'sexp'
7
+
8
+ $a ||= false
9
+ $h ||= false
10
+ $n ||= false
11
+ $r ||= false
12
+ $s ||= false
13
+ $U ||= false
14
+ $n = $n.intern if $n
15
+
16
+ $u ||= ! ($U || $r)
17
+
18
+ if $h then
19
+ puts "usage: #{File.basename $0} [options] [file...]"
20
+ puts "options:"
21
+ puts "-h : display usage"
22
+ puts "-a : all nodes, including newline"
23
+ puts "-n=node : only display matching nodes"
24
+ puts "-r : raw arrays, no sexps"
25
+ puts "-s : structural sexps, strip all content and show bare tree"
26
+ puts "-u : unified sexps (now the default)"
27
+ puts "-U : UNunified sexps"
28
+
29
+ exit 1
30
+ end
31
+
32
+ ARGV.push "-" if ARGV.empty?
33
+
34
+ if $u then
35
+ require 'sexp_processor'
36
+ require 'unified_ruby'
37
+
38
+ class Unifier
39
+ include UnifiedRuby
40
+ end
41
+ end
42
+
43
+ parse_tree = ParseTree.new($a)
44
+ unifier = Unifier.new if $u
45
+
46
+ ARGV.each do |file|
47
+ ruby = file == "-" ? $stdin.read : File.read(file)
48
+
49
+ sexp = parse_tree.parse_tree_for_string(ruby, file).first
50
+ sexp = Sexp.from_array sexp unless $r
51
+ sexp = unifier.process(sexp) if $u
52
+ sexp = sexp.structure if $s
53
+
54
+ if $n then
55
+ sexp.each_of_type $n do |node|
56
+ p node
57
+ end
58
+ elsif defined? $q then
59
+ p sexp
60
+ else
61
+ pp sexp
62
+ end
63
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/local/bin/ruby -w
2
+ require 'rubygems'
3
+ require 'sexp_processor'
4
+
5
+ class QuickPrinter < SexpProcessor
6
+ def initialize
7
+ super
8
+ self.strict = false
9
+ self.auto_shift_type = true
10
+ end
11
+ def process_defn(exp)
12
+ name = exp.shift
13
+ args = process exp.shift
14
+ body = process exp.shift
15
+ puts " def #{name}"
16
+ return s(:defn, name, args, body)
17
+ end
18
+ end
19
+
20
+ QuickPrinter.new.process(*ParseTree.new.parse_tree(QuickPrinter))
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/ruby -ws
2
+
3
+ $f ||= false
4
+
5
+ $:.unshift "../../ruby_parser/dev/lib"
6
+ $:.unshift "../../ParseTree/dev/lib"
7
+
8
+ require 'rubygems'
9
+ require 'parse_tree'
10
+ require 'ruby_parser'
11
+
12
+ require 'gauntlet'
13
+
14
+ class ParseTreeGauntlet < Gauntlet
15
+ def initialize
16
+ super
17
+
18
+ self.data = Hash.new { |h,k| h[k] = {} }
19
+ old_data = load_yaml data_file
20
+ self.data.merge! old_data
21
+ end
22
+
23
+ def should_skip? name
24
+ if $f then
25
+ if Hash === data[name] then
26
+ ! data[name].empty?
27
+ else
28
+ data[name]
29
+ end
30
+ else
31
+ data[name] == true # yes, == true on purpose
32
+ end
33
+ end
34
+
35
+ def diff_pp o1, o2
36
+ require 'pp'
37
+
38
+ File.open("/tmp/a.#{$$}", "w") do |f|
39
+ PP.pp o1, f
40
+ end
41
+
42
+ File.open("/tmp/b.#{$$}", "w") do |f|
43
+ PP.pp o2, f
44
+ end
45
+
46
+ `diff -u /tmp/a.#{$$} /tmp/b.#{$$}`
47
+ ensure
48
+ File.unlink "/tmp/a.#{$$}" rescue nil
49
+ File.unlink "/tmp/b.#{$$}" rescue nil
50
+ end
51
+
52
+ def broke name, file, msg
53
+ warn "bad"
54
+ self.data[name][file] = msg
55
+ self.dirty = true
56
+ end
57
+
58
+ def process path, name
59
+ begin
60
+ $stderr.print " #{path}: "
61
+ rp = RubyParser.new
62
+ pt = ParseTree.new
63
+
64
+ old_ruby = File.read(path)
65
+
66
+ begin
67
+ pt_sexp = pt.process old_ruby
68
+ rescue SyntaxError => e
69
+ warn "unparsable pt"
70
+ self.data[name][path] = :unparsable_pt
71
+ self.dirty = true
72
+ return
73
+ end
74
+
75
+ begin
76
+ rp_sexp = rp.process old_ruby
77
+ rescue Racc::ParseError => e
78
+ broke name, path, e.message
79
+ return
80
+ end
81
+
82
+ if rp_sexp != pt_sexp then
83
+ broke name, path, diff_pp(rp_sexp, pt_sexp)
84
+ return
85
+ end
86
+
87
+ self.data[name][path] = true
88
+ self.dirty = true
89
+
90
+ warn "good"
91
+ rescue Interrupt
92
+ puts "User cancelled"
93
+ exit 1
94
+ rescue Exception => e
95
+ broke name, path, " UNKNOWN ERROR: #{e}: #{e.message.strip}"
96
+ end
97
+ end
98
+
99
+ def run name
100
+ warn name
101
+ Dir["**/*.rb"].sort.each do |path|
102
+ next if path =~ /gemspec.rb/ # HACK
103
+ result = data[name][path]
104
+ next if result == true || Symbol === result
105
+ process path, name
106
+ end
107
+
108
+ if (self.data[name].empty? or
109
+ self.data[name].values.all? { |v| v == true }) then
110
+ warn " ALL GOOD!"
111
+ self.data[name] = true
112
+ self.dirty = true
113
+ end
114
+ end
115
+ end
116
+
117
+ filter = ARGV.shift
118
+ filter = Regexp.new filter if filter
119
+
120
+ gauntlet = ParseTreeGauntlet.new
121
+ gauntlet.run_the_gauntlet filter