fOOrth 0.6.6 → 0.6.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/CODE_OF_CONDUCT.md +49 -0
  3. data/README.md +32 -1
  4. data/fOOrth.gemspec +3 -3
  5. data/integration/array_lib_tests.rb +10 -0
  6. data/integration/compile_lib_tests.rb +67 -1
  7. data/integration/exception_lib_tests.rb +4 -0
  8. data/integration/hash_lib_tests.rb +9 -0
  9. data/integration/numeric_lib_tests.rb +326 -321
  10. data/integration/procedure_lib_tests.rb +16 -0
  11. data/integration/queue_lib_tests.rb +2 -1
  12. data/integration/stack_lib_tests.rb +2 -1
  13. data/integration/stdio_lib_tests.rb +62 -0
  14. data/integration/string_lib_tests.rb +11 -0
  15. data/integration/thread_lib_tests.rb +19 -5
  16. data/lib/fOOrth.rb +0 -2
  17. data/lib/fOOrth/compiler/context.rb +64 -64
  18. data/lib/fOOrth/compiler/context/locals.rb +34 -34
  19. data/lib/fOOrth/compiler/context/map_name.rb +85 -74
  20. data/lib/fOOrth/compiler/context/tags.rb +60 -48
  21. data/lib/fOOrth/compiler/process/generate.rb +1 -1
  22. data/lib/fOOrth/compiler/process/procedure.rb +40 -0
  23. data/lib/fOOrth/compiler/word_specs.rb +3 -3
  24. data/lib/fOOrth/core/object.rb +1 -1
  25. data/lib/fOOrth/library.rb +3 -0
  26. data/lib/fOOrth/library/alias_library.rb +126 -0
  27. data/lib/fOOrth/library/array_library.rb +41 -21
  28. data/lib/fOOrth/library/command_library.rb +1 -1
  29. data/lib/fOOrth/library/compile_library.rb +266 -264
  30. data/lib/fOOrth/library/complex_library.rb +82 -80
  31. data/lib/fOOrth/library/float_library.rb +37 -0
  32. data/lib/fOOrth/library/formatting/array.rb +90 -0
  33. data/lib/fOOrth/library/formatting/bullets.rb +15 -79
  34. data/lib/fOOrth/library/formatting/columns.rb +20 -42
  35. data/lib/fOOrth/library/formatting/hash.rb +29 -0
  36. data/lib/fOOrth/library/formatting/nil.rb +13 -0
  37. data/lib/fOOrth/library/formatting/object.rb +18 -0
  38. data/lib/fOOrth/library/formatting/string.rb +46 -0
  39. data/lib/fOOrth/library/hash_library.rb +14 -6
  40. data/lib/fOOrth/library/introspection/class.rb +20 -18
  41. data/lib/fOOrth/library/introspection/context.rb +3 -2
  42. data/lib/fOOrth/library/introspection/object.rb +42 -20
  43. data/lib/fOOrth/library/introspection/string.rb +21 -5
  44. data/lib/fOOrth/library/introspection/vm.rb +17 -29
  45. data/lib/fOOrth/library/mutex_library.rb +8 -1
  46. data/lib/fOOrth/library/numeric_library.rb +359 -380
  47. data/lib/fOOrth/library/procedure_library.rb +69 -65
  48. data/lib/fOOrth/library/queue_library.rb +6 -1
  49. data/lib/fOOrth/library/rational_library.rb +89 -89
  50. data/lib/fOOrth/library/stack_library.rb +6 -1
  51. data/lib/fOOrth/library/stdio_library.rb +11 -8
  52. data/lib/fOOrth/library/string_library.rb +21 -6
  53. data/lib/fOOrth/library/stubs_library.rb +49 -0
  54. data/lib/fOOrth/monkey_patch/exceptions.rb +2 -6
  55. data/lib/fOOrth/monkey_patch/object.rb +7 -0
  56. data/lib/fOOrth/version.rb +1 -1
  57. data/reek.txt +1 -59
  58. data/sire.rb +0 -1
  59. data/tests/compiler/context_tests.rb +188 -177
  60. data/tests/compiler/file_source_tests.rb +130 -130
  61. data/tests/compiler/parser_tests.rb +4 -4
  62. data/tests/compiler/string_source_tests.rb +4 -4
  63. data/tests/core_tests.rb +138 -138
  64. data/tests/monkey_patch/complex_test.rb +24 -24
  65. data/tests/monkey_patch/object_test.rb +49 -49
  66. data/tests/monkey_patch/string_test.rb +61 -61
  67. metadata +20 -13
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+
3
+ #* library/formatting/hash.rb - Hash support for displaying data formatted neatly.
4
+ class Hash
5
+
6
+ # Bullets ========================================================
7
+
8
+ #Print out the array as bullet points.
9
+ def puts_foorth_bullets(page_width)
10
+ puts foorth_format_bullets(page_width)
11
+ end
12
+
13
+ #Convert the array to strings with bullet points.
14
+ #<br>Returns
15
+ #* A string.
16
+ def foorth_format_bullets(page_width)
17
+ return "" if empty?
18
+
19
+ builder = XfOOrth::BulletPoints.new(page_width)
20
+
21
+ self.each do |pair|
22
+ builder.add(*pair)
23
+ end
24
+
25
+ builder.render.join("\n").freeze
26
+ end
27
+
28
+ end
29
+
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+
3
+ #* library/formatting/nil.rb - Support for displaying nothing formatted neatly.
4
+ class NilClass
5
+
6
+ #Create a bullet point description from nothing.
7
+ def format_description(_max_width)
8
+ []
9
+ end
10
+
11
+ end
12
+
13
+
@@ -0,0 +1,18 @@
1
+ # coding: utf-8
2
+
3
+ #* library/formatting/object.rb - Support for displaying data formatted neatly.
4
+ class Object
5
+
6
+ #Create a bullet point description from this object.
7
+ def format_description(max_width)
8
+ self.to_s.format_description(max_width)
9
+ end
10
+
11
+ #Get data ready for being in a bullet point.
12
+ def prepare_bullet_data
13
+ ["*", self]
14
+ end
15
+
16
+ end
17
+
18
+
@@ -0,0 +1,46 @@
1
+ # coding: utf-8
2
+
3
+ #* library/formatting/string.rb - Support for displaying data formatted neatly.
4
+ class String
5
+
6
+ #Create a bullet point description from this string.
7
+ def format_description(max_width)
8
+ do_format_description(split(' ').each, max_width)
9
+ end
10
+
11
+ #Do the formatting legwork.
12
+ def do_format_description(input, max_width)
13
+ result, build = [], ""
14
+
15
+ loop do
16
+ build = build.split_if_over(input.next, max_width, result)
17
+ .split_if_huge(max_width, result)
18
+ end
19
+
20
+ result << build
21
+ end
22
+
23
+ #Split if adding a word goes over a little.
24
+ def split_if_over(word, max_width, buffer)
25
+ word.prepend(" ") unless self.empty?
26
+ word_len = word.length
27
+
28
+ if (length + word_len) >= max_width && word_len < max_width
29
+ buffer << self
30
+ word.lstrip
31
+ else
32
+ self + word
33
+ end
34
+
35
+ end
36
+
37
+ #Split up a overlong blob of text.
38
+ def split_if_huge(max_width, buffer)
39
+ while length >= max_width
40
+ buffer << slice!(0, max_width)
41
+ end
42
+
43
+ self
44
+ end
45
+ end
46
+
@@ -70,27 +70,35 @@ module XfOOrth
70
70
 
71
71
  # [i h] .[]@ [h[i]]
72
72
  Hash.create_shared_method('.[]@', TosSpec, [],
73
- &lambda {|vm| vm.poke(self[vm.peek]); })
73
+ &lambda {|vm| vm.poke(self[vm.peek]) })
74
74
 
75
75
  # [v i h] .[]! []; h[i]=v
76
76
  Hash.create_shared_method('.[]!', TosSpec, [],
77
- &lambda {|vm| value, index = vm.popm(2); self[index] = value; })
77
+ &lambda {|vm| value, index = vm.popm(2); self[index] = value })
78
78
 
79
79
  # [{"a"=>1, "b"=>2}] .length [2]]
80
80
  Hash.create_shared_method('.length', TosSpec, [],
81
- &lambda {|vm| vm.push(self.length); })
81
+ &lambda {|vm| vm.push(self.length) })
82
82
 
83
83
  # [a_hash] .empty? [a_boolean]]
84
84
  Hash.create_shared_method('.empty?', TosSpec, [],
85
- &lambda {|vm| vm.push(self.empty?); })
85
+ &lambda {|vm| vm.push(self.empty?) })
86
+
87
+ # [a_hash] .present? [a_boolean]]
88
+ Hash.create_shared_method('.present?', TosSpec, [],
89
+ &lambda {|vm| vm.push(!self.empty?) })
90
+
91
+ # [a_hash] .clear! []]
92
+ Hash.create_shared_method('.clear!', TosSpec, [],
93
+ &lambda {|vm| self.clear })
86
94
 
87
95
  # [h] .keys [[keys]]
88
96
  Hash.create_shared_method('.keys', TosSpec, [],
89
- &lambda {|vm| vm.push(self.keys); })
97
+ &lambda {|vm| vm.push(self.keys) })
90
98
 
91
99
  # [h] .values [[values]]
92
100
  Hash.create_shared_method('.values', TosSpec, [],
93
- &lambda {|vm| vm.push(self.values); })
101
+ &lambda {|vm| vm.push(self.values) })
94
102
 
95
103
  # [h] .strmax2 [widest_key widest_value]
96
104
  Hash.create_shared_method('.strmax2', TosSpec, [], &lambda {|vm|
@@ -30,17 +30,11 @@ class Class
30
30
  found = false
31
31
 
32
32
  if symbol
33
- spec, info = map_foorth_shared_info(symbol)
34
-
35
- if spec && !spec.has_tag?(:stub)
36
- (results << ["", ""]).concat(info).concat(spec.get_info)
33
+ if scrape_method_info(results, *map_foorth_shared_info(symbol))
37
34
  found = true
38
35
  end
39
36
 
40
- spec, info = map_foorth_exclusive_info(symbol)
41
-
42
- if spec && !spec.has_tag?(:stub)
43
- (results << ["", ""]).concat(info).concat(spec.get_info)
37
+ if scrape_method_info(results, *map_foorth_exclusive_info(symbol, "Class"))
44
38
  found = true
45
39
  end
46
40
 
@@ -54,18 +48,28 @@ class Class
54
48
  def get_info
55
49
  results = [["Lineage", lineage]]
56
50
 
57
- if foorth_has_exclusive?
58
- results.concat([["", ""], ["Methods", "Class"]])
51
+ get_exclusive_method_info(results, "Class")
52
+ get_shared_method_info(results)
59
53
 
60
- foorth_exclusive.extract_method_names(:all).sort.each do |name|
61
- symbol, info = XfOOrth::SymbolMap.map_info(name)
62
- (results << ["", ""]).concat(info)
54
+ results
55
+ end
63
56
 
64
- spec, info = map_foorth_exclusive_info(symbol, :shallow)
65
- results.concat(info).concat(spec.get_info)
66
- end
57
+ private
58
+
59
+ #Get method information
60
+ #<br>Endemic Code Smells
61
+ #* :reek:UtilityFunction
62
+ def scrape_method_info(results, spec, info)
63
+ if spec && !spec.has_tag?(:stub)
64
+ (results << ["", ""]).concat(info).concat(spec.get_info)
65
+ true
66
+ else
67
+ false
67
68
  end
69
+ end
68
70
 
71
+ #Get shared method info
72
+ def get_shared_method_info(results)
69
73
  unless foorth_shared.empty?
70
74
  results.concat([["", ""], ["Methods", "Shared"]])
71
75
 
@@ -77,8 +81,6 @@ class Class
77
81
  results.concat(info).concat(spec.get_info)
78
82
  end
79
83
  end
80
-
81
- results
82
84
  end
83
85
 
84
86
  end
@@ -7,6 +7,8 @@ module XfOOrth
7
7
  class Context
8
8
 
9
9
  #Get introspection info.
10
+ #<br>Endemic Code Smells
11
+ #* :reek:FeatureEnvy :reek:TooManyStatements
10
12
  def get_info
11
13
  results = [["Level", depth]]
12
14
 
@@ -25,8 +27,7 @@ module XfOOrth
25
27
  end
26
28
 
27
29
  if (prev = self.previous)
28
- results << ["", ""]
29
- results.concat(prev.get_info)
30
+ results.concat([["", ""]]).concat(prev.get_info)
30
31
  end
31
32
 
32
33
  results
@@ -17,31 +17,15 @@ class Object
17
17
  #Get introspection info.
18
18
  def get_info
19
19
  results = [["Type", foorth_name]]
20
-
21
- unless (vars = instance_variables).empty?
22
- results.concat([["", ""], ["Data", "Instance"], ["", ""]])
23
-
24
- vars.sort.each do |name|
25
- var_name = XfOOrth::SymbolMap.unmap(name[1..-1].to_sym) || name
26
- results << [var_name, instance_variable_get(name)]
27
- end
28
- end
29
-
30
- if foorth_has_exclusive?
31
- results.concat([["", ""], ["Methods", "Exclusive"]])
32
-
33
- foorth_exclusive.extract_method_names(:all).sort.each do |name|
34
- symbol, info = XfOOrth::SymbolMap.map_info(name)
35
- results.concat([["", ""], ["Name", name], info])
36
- spec, info = map_foorth_exclusive_info(symbol, :shallow)
37
- results.concat(info).concat(spec.get_info)
38
- end
39
- end
20
+ get_instance_variable_info(results)
21
+ get_exclusive_method_info(results, "Exclusive")
40
22
 
41
23
  results
42
24
  end
43
25
 
44
26
  #Investigate a method of this object.
27
+ #<br>Endemic Code Smells
28
+ #* :reek:FeatureEnvy
45
29
  def foorth_method_info(name)
46
30
  symbol, results = XfOOrth::SymbolMap.map_info(name)
47
31
  found = false
@@ -65,5 +49,43 @@ class Object
65
49
  foorth_name + " < " + self.class.lineage
66
50
  end
67
51
 
52
+ private
53
+
54
+ #Get information about instance variables
55
+ def get_instance_variable_info(results)
56
+ names = instance_variables.map do |sym|
57
+ if (name = XfOOrth::SymbolMap.unmap(sym.to_s[1..-1].to_sym))
58
+ [name, sym]
59
+ end
60
+ end
61
+ .compact
62
+ .sort {|first, second| first[0] <=> second[0] }
63
+
64
+ unless names.empty?
65
+ results.concat([["", ""], ["Data", "Instance"], ["", ""]])
66
+
67
+ names.each do |name, sym|
68
+ results << [name, instance_variable_get(sym)]
69
+ end
70
+ end
71
+ end
72
+
73
+
74
+ #Get exclusive method info
75
+ def get_exclusive_method_info(results, designation)
76
+ if foorth_has_exclusive?
77
+ results.concat([["", ""], ["Methods", designation]])
78
+
79
+ foorth_exclusive.extract_method_names(:all).sort.each do |name|
80
+ symbol, info = XfOOrth::SymbolMap.map_info(name)
81
+ (results << ["", ""]).concat(info)
82
+
83
+ spec, info = map_foorth_exclusive_info(symbol, :shallow)
84
+ results.concat(info).concat(spec.get_info)
85
+ end
86
+ end
87
+ end
88
+
89
+
68
90
 
69
91
  end
@@ -4,6 +4,8 @@
4
4
  class String
5
5
 
6
6
  #Scan all classes for information about a method.
7
+ #<br>Endemic Code Smells
8
+ #* :reek:DuplicateMethodCall :reek:FeatureEnvy :reek:TooManyStatements
7
9
  def foorth_method_scan
8
10
  symbol, results = XfOOrth::SymbolMap.map_info(self)
9
11
  found = false
@@ -11,13 +13,27 @@ class String
11
13
  symbol && $FOORTH_GLOBALS.values
12
14
  .select {|entry| entry.has_tag?(:class)}
13
15
  .collect {|spec| spec.new_class}
14
- .sort {|a,b| a.foorth_name <=> b.foorth_name}
16
+ .sort {|first, second| first.foorth_name <=> second.foorth_name}
15
17
  .each do |klass|
16
- spec, info = klass.map_foorth_shared_info(symbol, :shallow)
17
- found |= spec && (results << ["", ""]).concat(info).concat(spec.get_info)
18
+ shared_spec, shared_info = klass.map_foorth_shared_info(symbol, :shallow)
18
19
 
19
- spec, info = klass.map_foorth_exclusive_info(symbol, :shallow)
20
- found |= spec && (results << ["", ""]).concat(info).concat(spec.get_info)
20
+ if shared_spec
21
+ results
22
+ .concat([["", ""]])
23
+ .concat(shared_info)
24
+ .concat(shared_spec.get_info)
25
+ end
26
+
27
+ excl_spec, excl_info = klass.map_foorth_exclusive_info(symbol, :shallow)
28
+
29
+ if excl_spec
30
+ results
31
+ .concat([["", ""]])
32
+ .concat(excl_info)
33
+ .concat(excl_spec.get_info)
34
+ end
35
+
36
+ found ||= (shared_spec || excl_spec)
21
37
  end
22
38
 
23
39
  results << ["Scope", "not found in any class."] if symbol && !found
@@ -8,6 +8,18 @@ module XfOOrth
8
8
 
9
9
  #Get introspection info.
10
10
  def get_info
11
+ results = get_basic_vm_info
12
+ get_instance_variable_info(results)
13
+ get_vm_thread_data_info(results)
14
+ get_exclusive_method_info(results, "Exclusive")
15
+
16
+ results
17
+ end
18
+
19
+ private
20
+
21
+ #Get the vm basic stuff first.
22
+ def get_basic_vm_info
11
23
  results = [["Name", foorth_name],
12
24
  ["Ruby", self.to_s],
13
25
  ["Stack", @data_stack.inspect],
@@ -22,47 +34,23 @@ module XfOOrth
22
34
  results << ["Buffer", source.read_buffer.inspect]
23
35
  end
24
36
 
25
- names = instance_variables.map do |sym|
26
- if (name = XfOOrth::SymbolMap.unmap(sym.to_s[1..-1].to_sym))
27
- [name, sym]
28
- end
29
- end
30
-
31
- names.compact!
32
-
33
- unless names.empty?
34
- results.concat([["", ""], ["Data", "Instance"], ["", ""]])
35
-
36
- names.each do |name, sym|
37
- results << [name, instance_variable_get(sym)]
38
- end
39
- end
37
+ results
38
+ end
40
39
 
40
+ #Get the thread data info.
41
+ def get_vm_thread_data_info(results)
41
42
  unless @data.empty?
42
43
  results.concat([["", ""], ["Data", "Thread"], ["", ""]])
43
44
 
44
45
  @data
45
46
  .keys
46
47
  .map{|symbol| [SymbolMap.unmap(symbol), symbol]}
47
- .sort{|a,b| a[0] <=> b[0]}
48
+ .sort{|first, second| first[0] <=> second[0]}
48
49
  .map{|name, symbol| [name, @data[symbol]]}
49
50
  .each do |name, value|
50
51
  results << [name, value.inspect]
51
52
  end
52
53
  end
53
-
54
- if foorth_has_exclusive?
55
- results.concat([["", ""], ["Methods", "Exclusive"]])
56
-
57
- foorth_exclusive.extract_method_names(:all).sort.each do |name|
58
- symbol, info = SymbolMap.map_info(name)
59
- results.concat([["", ""], ["Name", name], info])
60
- spec, info = map_foorth_exclusive_info(symbol, :shallow)
61
- results.concat(info).concat(spec.get_info)
62
- end
63
- end
64
-
65
- results
66
54
  end
67
55
 
68
56
  end
@@ -9,7 +9,7 @@ module XfOOrth
9
9
  # [Mutex] .do{{ ... }} [] (Releases a lock on the mutex)
10
10
  Mutex.create_exclusive_method('.do{{', NosSpec, [], &lambda {|vm|
11
11
  block = vm.pop
12
- Thread.exclusive { block.call(vm, nil, nil) }
12
+ foorth_shared_mutex.synchronize { block.call(vm, nil, nil) }
13
13
  })
14
14
 
15
15
  # [a_mutex] .lock [] (Acquires a lock on the mutex)
@@ -29,3 +29,10 @@ module XfOOrth
29
29
  })
30
30
 
31
31
  end
32
+
33
+ # Create a shared mutex instance.
34
+ class Mutex
35
+ def self.foorth_shared_mutex
36
+ @foorth_shared_mutex ||= Mutex.new
37
+ end
38
+ end