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.
- data/lib/parsetree/History.txt +477 -0
- data/lib/parsetree/Manifest.txt +19 -0
- data/lib/parsetree/README.txt +97 -0
- data/lib/parsetree/Rakefile +37 -0
- data/lib/parsetree/bin/parse_tree_abc +89 -0
- data/lib/parsetree/bin/parse_tree_audit +28 -0
- data/lib/parsetree/bin/parse_tree_deps +62 -0
- data/lib/parsetree/bin/parse_tree_show +63 -0
- data/lib/parsetree/demo/printer.rb +20 -0
- data/lib/parsetree/lib/gauntlet_parsetree.rb +121 -0
- data/lib/parsetree/lib/parse_tree.rb +1202 -0
- data/lib/parsetree/lib/parse_tree_extensions.rb +59 -0
- data/lib/parsetree/lib/unified_ruby.rb +421 -0
- data/lib/parsetree/test/something.rb +53 -0
- data/lib/parsetree/test/test_parse_tree.rb +2567 -0
- data/lib/parsetree/test/test_parse_tree_extensions.rb +107 -0
- data/lib/parsetree/test/test_unified_ruby.rb +57 -0
- data/lib/parsetree/validate.sh +31 -0
- data/lib/sexps/{count_to_ten_sexp.txt → count_to_ten_sexp.rb} +0 -0
- data/lib/sexps/{sexps_and.txt → sexps_and.rb} +0 -0
- data/lib/sexps/{sexps_case_when.txt → sexps_case_when.rb} +0 -0
- data/lib/sexps/{sexps_greet.txt → sexps_greet.rb} +0 -0
- data/lib/sexps/sexps_not.rb +24 -0
- data/lib/sexps/{sexps_rewritten_keywords.txt → sexps_rewritten_keywords.rb} +0 -0
- data/lib/sexps/{sexps_symbolic_and.txt → sexps_symbolic_and.rb} +0 -0
- data/lib/sexps/sexps_until.rb +60 -0
- data/lib/sexps/{sexps_while.txt → sexps_while.rb} +0 -0
- data/lib/spec/class_reflection_spec.rb +64 -0
- data/lib/spec/keyword_rewriter_spec.rb +7 -54
- data/lib/spec/not_rewriter_spec.rb +25 -0
- data/lib/spec/parser_strategy_spec.rb +23 -0
- data/lib/spec/sexp_stringifier_spec.rb +19 -0
- data/lib/spec/spec_helper.rb +61 -307
- data/lib/spec/until_rewriter_spec.rb +26 -0
- data/lib/spec/virtualizees/and_user.rb +17 -0
- data/lib/spec/virtualizees/case_when_user.rb +20 -0
- data/lib/spec/virtualizees/fizzbuzzer.rb +15 -0
- data/lib/spec/virtualizees/greeter.rb +127 -0
- data/lib/spec/virtualizees/not_user.rb +9 -0
- data/lib/spec/virtualizees/operator_user.rb +15 -0
- data/lib/spec/virtualizees/or_user.rb +17 -0
- data/lib/spec/virtualizees/parents.rb +8 -0
- data/lib/spec/virtualizees/until_user.rb +16 -0
- data/lib/spec/virtualizees/while_user.rb +16 -0
- data/lib/spec/virtualizer_spec.rb +46 -83
- data/lib/virtual_keywords/class_reflection.rb +88 -0
- data/lib/virtual_keywords/deep_copy_array.rb +12 -0
- data/lib/virtual_keywords/keyword_rewriter.rb +54 -0
- data/lib/virtual_keywords/parser_strategy.rb +40 -0
- data/lib/virtual_keywords/rewritten_keywords.rb +15 -0
- data/lib/virtual_keywords/sexp_stringifier.rb +1 -5
- data/lib/virtual_keywords/version.rb +1 -1
- data/lib/virtual_keywords/virtualizer.rb +30 -115
- data/lib/virtual_keywords.rb +31 -5
- metadata +117 -90
- data/lib/spec/class_mirrorer_spec.rb +0 -18
- 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
|