fOOrth 0.6.6 → 0.6.11

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 (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