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
@@ -1,81 +1,83 @@
1
- # coding: utf-8
2
-
3
- #* library/complex_library.rb - Numeric support for the fOOrth library.
4
- module XfOOrth
5
-
6
- #Connect the Complex class to the fOOrth class system.
7
- Complex.create_foorth_proxy
8
-
9
- #Some complex stubs.
10
- Complex.create_shared_method('mod', NosSpec, [:stub])
11
- Complex.create_shared_method('.ceil', TosSpec, [:stub])
12
- Complex.create_shared_method('.floor', TosSpec, [:stub])
13
- Complex.create_shared_method('.round', TosSpec, [:stub])
14
- Complex.create_shared_method('<', NosSpec, [:stub])
15
- Complex.create_shared_method('>', NosSpec, [:stub])
16
- Complex.create_shared_method('<=', NosSpec, [:stub])
17
- Complex.create_shared_method('>=', NosSpec, [:stub])
18
- Complex.create_shared_method('<=>', NosSpec, [:stub])
19
-
20
-
21
- #Some conversion words.
22
- # [a b] complex [a+bi]
23
- VirtualMachine.create_shared_method('complex', VmSpec, [], &lambda {|vm|
24
- real,imag = popm(2)
25
-
26
- begin
27
- push(Complex(real,imag));
28
- rescue
29
- error "F40: Cannot coerce a #{real.foorth_name}, #{imag.foorth_name} to a Complex"
30
- end
31
- })
32
-
33
- # [a+bi] .split [a b]
34
- Complex.create_shared_method('.split', TosSpec, [],
35
- &lambda {|vm| vm.push(self.real); vm.push(self.imaginary); })
36
-
37
- # [a] .to_x [compleX or nil]
38
- Object.create_shared_method('.to_x', TosSpec, [], &lambda {|vm|
39
- begin
40
- vm.push(Complex(self))
41
- rescue
42
- vm.push(nil)
43
- end
44
- })
45
-
46
- # [a] .to_x! [compleX]
47
- Object.create_shared_method('.to_x!', TosSpec, [], &lambda {|vm|
48
- begin
49
- vm.push(Complex(self))
50
- rescue
51
- error "F40: Cannot coerce a #{self.foorth_name} to a Complex"
52
- end
53
- })
54
-
55
- # [a+bi] .imaginary [b]
56
- Numeric.create_shared_method('.imaginary', TosSpec, [],
57
- &lambda {|vm| vm.push(self.imaginary); })
58
-
59
- # [a+bi] .real [a]
60
- Numeric.create_shared_method('.real', TosSpec, [],
61
- &lambda {|vm| vm.push(self.real); })
62
-
63
- # [a+bi] .angle [atan2(b,a) or 0]
64
- Numeric.create_shared_method('.angle', TosSpec, [],
65
- &lambda {|vm| vm.push(self.angle); })
66
-
67
- # [a+bi] .magnitude [sqrt(a**2 + b**2)]
68
- Numeric.create_shared_method('.magnitude', TosSpec, [],
69
- &lambda {|vm| vm.push(self.magnitude); })
70
-
71
- # [a+bi] .conjugate [a-bi]
72
- # Complex convicts that behave well are allowed .conjugate visits.
73
- Numeric.create_shared_method('.conjugate', TosSpec, [],
74
- &lambda {|vm| vm.push(self.conjugate); })
75
-
76
- # [a+bi] .polar [magnitude angle]
77
- # Convert a complex number to polar format
78
- Numeric.create_shared_method('.polar', TosSpec, [],
79
- &lambda {|vm| vm.pushm(self.polar); })
80
-
1
+ # coding: utf-8
2
+
3
+ #* library/complex_library.rb - Numeric support for the fOOrth library.
4
+ module XfOOrth
5
+
6
+ #Connect the Complex class to the fOOrth class system.
7
+ Complex.create_foorth_proxy
8
+
9
+ #Some complex stubs.
10
+ Complex.create_shared_method('mod', NosSpec, [:stub])
11
+ Complex.create_shared_method('.ceil', TosSpec, [:stub])
12
+ Complex.create_shared_method('.floor', TosSpec, [:stub])
13
+ Complex.create_shared_method('.round', TosSpec, [:stub])
14
+ Complex.create_shared_method('<', NosSpec, [:stub])
15
+ Complex.create_shared_method('>', NosSpec, [:stub])
16
+ Complex.create_shared_method('<=', NosSpec, [:stub])
17
+ Complex.create_shared_method('>=', NosSpec, [:stub])
18
+ Complex.create_shared_method('<=>', NosSpec, [:stub])
19
+ Complex.create_shared_method('.numerator', TosSpec, [:stub])
20
+ Complex.create_shared_method('.denominator', TosSpec, [:stub])
21
+
22
+
23
+ #Some conversion words.
24
+ # [a b] complex [a+bi]
25
+ VirtualMachine.create_shared_method('complex', VmSpec, [], &lambda {|vm|
26
+ real,imag = popm(2)
27
+
28
+ begin
29
+ push(Complex(real,imag));
30
+ rescue
31
+ error "F40: Cannot coerce a #{real.foorth_name}, #{imag.foorth_name} to a Complex"
32
+ end
33
+ })
34
+
35
+ # [a+bi] .split [a b]
36
+ Complex.create_shared_method('.split', TosSpec, [],
37
+ &lambda {|vm| vm.push(self.real); vm.push(self.imaginary); })
38
+
39
+ # [a] .to_x [compleX or nil]
40
+ Object.create_shared_method('.to_x', TosSpec, [], &lambda {|vm|
41
+ begin
42
+ vm.push(Complex(self))
43
+ rescue
44
+ vm.push(nil)
45
+ end
46
+ })
47
+
48
+ # [a] .to_x! [compleX]
49
+ Object.create_shared_method('.to_x!', TosSpec, [], &lambda {|vm|
50
+ begin
51
+ vm.push(Complex(self))
52
+ rescue
53
+ error "F40: Cannot coerce a #{self.foorth_name} to a Complex"
54
+ end
55
+ })
56
+
57
+ # [a+bi] .imaginary [b]
58
+ Numeric.create_shared_method('.imaginary', TosSpec, [],
59
+ &lambda {|vm| vm.push(self.imaginary); })
60
+
61
+ # [a+bi] .real [a]
62
+ Numeric.create_shared_method('.real', TosSpec, [],
63
+ &lambda {|vm| vm.push(self.real); })
64
+
65
+ # [a+bi] .angle [atan2(b,a) or 0]
66
+ Numeric.create_shared_method('.angle', TosSpec, [],
67
+ &lambda {|vm| vm.push(self.angle); })
68
+
69
+ # [a+bi] .magnitude [sqrt(a**2 + b**2)]
70
+ Numeric.create_shared_method('.magnitude', TosSpec, [],
71
+ &lambda {|vm| vm.push(self.magnitude); })
72
+
73
+ # [a+bi] .conjugate [a-bi]
74
+ # Complex convicts that behave well are allowed .conjugate visits.
75
+ Numeric.create_shared_method('.conjugate', TosSpec, [],
76
+ &lambda {|vm| vm.push(self.conjugate); })
77
+
78
+ # [a+bi] .polar [magnitude angle]
79
+ # Convert a complex number to polar format
80
+ Numeric.create_shared_method('.polar', TosSpec, [],
81
+ &lambda {|vm| vm.pushm(self.polar); })
82
+
81
83
  end
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+
3
+ #* library/float_library.rb - Float specific support for the fOOrth library.
4
+ module XfOOrth
5
+
6
+ #Connect the Float class to the fOOrth class system.
7
+ Float.create_foorth_proxy
8
+
9
+ # [a] .to_f [Float or nil]
10
+ Object.create_shared_method('.to_f', TosSpec, [], &lambda {|vm|
11
+ begin
12
+ vm.push(Float(self))
13
+ rescue
14
+ vm.push(nil)
15
+ end
16
+ })
17
+
18
+ # [a] .to_f! [Float]
19
+ Object.create_shared_method('.to_f!', TosSpec, [],
20
+ &lambda {|vm| vm.push(Float.foorth_coerce(self)) })
21
+
22
+ # [num_digits a_number] .round_to [a_float]
23
+ Numeric.create_shared_method('.round_to', TosSpec, [], &lambda {|vm|
24
+ value = Float.foorth_coerce(self)
25
+ digits = Integer.foorth_coerce(vm.pop)
26
+ vm.push(value.round(digits))
27
+ })
28
+
29
+ # [n/d] .numerator [n]
30
+ Float.create_shared_method('.numerator', TosSpec, [],
31
+ &lambda {|vm| vm.push(self.rationalize.numerator); })
32
+
33
+ # [n/d] .denominator [d]
34
+ Float.create_shared_method('.denominator', TosSpec, [],
35
+ &lambda {|vm| vm.push(self.rationalize.denominator); })
36
+
37
+ end
@@ -0,0 +1,90 @@
1
+ # coding: utf-8
2
+
3
+ #* library/formatting/array.rb - Array support for displaying data formatted neatly.
4
+ class Array
5
+
6
+ # Columns ========================================================
7
+
8
+ #Print out the array with efficient columns.
9
+ def puts_foorth_columns(page_length, page_width)
10
+ format_foorth_pages(page_length, page_width).each do |page|
11
+ puts page, ""
12
+ end
13
+ end
14
+
15
+ #Convert the array to strings with efficient columns.
16
+ #<br>Returns
17
+ #* A string.
18
+ def format_foorth_columns(page_length, page_width)
19
+ format_foorth_pages(page_length, page_width)
20
+ .map {|page| page << ""}
21
+ .flatten[0...-1]
22
+ .join("\n")
23
+ .freeze
24
+ end
25
+
26
+ #Get the widest element of an array.
27
+ #<br>Returns
28
+ #* The width of the widest string in the array.
29
+ def foorth_column_width
30
+ (self.max_by {|item| item.length}).length
31
+ end
32
+
33
+ private
34
+
35
+ #Convert the array to strings with efficient columns.
36
+ #<br>Returns
37
+ #* An array of pages (arrays of strings)
38
+ def format_foorth_pages(page_length, page_width)
39
+ index, pages, limit = 0, [], self.length
40
+ builder = XfOOrth::ColumnizedPage.new(page_length, page_width)
41
+
42
+ while index < limit
43
+ index += 1 - (left_over = builder.add(self[index]))
44
+ pages << builder.render if (left_over > 0) || (index == limit)
45
+ end
46
+
47
+ pages
48
+ end
49
+
50
+ # Bullets ========================================================
51
+
52
+ public
53
+
54
+ #Print out the array as bullet points.
55
+ def puts_foorth_bullets(page_width)
56
+ puts foorth_format_bullets(page_width)
57
+ end
58
+
59
+ #Convert the array to strings with bullet points.
60
+ #<br>Returns
61
+ #* A string
62
+ def foorth_format_bullets(page_width)
63
+ return "" if empty?
64
+
65
+ builder = XfOOrth::BulletPoints.new(page_width)
66
+
67
+ self.each do |pair|
68
+ builder.add(*pair.prepare_bullet_data)
69
+ end
70
+
71
+ builder.render.join("\n").freeze
72
+ end
73
+
74
+ #Convert the array to a bullet point description.
75
+ #<br>Returns
76
+ #* An array of strings.
77
+ def format_description(page_width)
78
+ format_foorth_pages(false, page_width)[0] || []
79
+ end
80
+
81
+ #Get data ready for being in a bullet point.
82
+ def prepare_bullet_data
83
+ if length < 2
84
+ ["*", self[0]]
85
+ else
86
+ self
87
+ end
88
+ end
89
+
90
+ end
@@ -5,30 +5,22 @@ module XfOOrth
5
5
 
6
6
  #A class to display data in bullet points.
7
7
  class BulletPoints
8
+
8
9
  #Prepare a blank slate.
9
10
  def initialize(page_width)
10
- @page_width, @bullet_data = page_width, []
11
+ @page_width = page_width
12
+ @bullet_data = []
11
13
  end
12
14
 
13
- #Add an item to this page.
14
- #<br>Returns
15
- #* The number if items that did not fit in the page.
16
- def add(raw_bullet = "*", *raw_item)
17
-
18
- if raw_item.empty?
19
- bullet = ["*"]
20
- items = raw_bullet.in_array
21
- else
22
- bullet = raw_bullet.in_array
23
- items = raw_item.in_array
24
- end
25
-
26
- items.each_index do |index|
27
- @bullet_data << [(bullet[index] || "").to_s, items[index].to_s]
15
+ #Add items to these bullet points.
16
+ def add(bullet, *items)
17
+ items.each do |item|
18
+ @bullet_data << [bullet.to_s, item]
19
+ bullet = ""
28
20
  end
29
21
  end
30
22
 
31
- #Render the page as an array of strings.
23
+ #Render the bullet points as an array of strings.
32
24
  def render
33
25
  @key_length, results = get_key_length, []
34
26
 
@@ -42,80 +34,24 @@ module XfOOrth
42
34
 
43
35
  private
44
36
 
45
- #How large is the largest bullet?
37
+ #Allowing for a trailing space, how large is the largest bullet?
46
38
  def get_key_length
47
- (@bullet_data.max_by {|line| line[0].length})[0].length
39
+ (@bullet_data.max_by {|line| line[0].length})[0].length + 1
48
40
  end
49
41
 
50
42
  #Render one bullet point.
51
43
  def render_bullet(key, item)
52
44
  result = []
53
- input = item.split(' ').each
54
- temp = key.ljust(len = @key_length)
55
- pass_one = true
56
-
57
- loop do
58
- word = ' ' + input.next
59
45
 
60
- while len >= @page_width
61
- result << temp.slice!(0, @page_width - 1)
62
- temp = (' ' * @key_length) + ' ' + temp
63
- len = temp.length
64
- end
65
-
66
- if ((len += word.length) >= @page_width) && !pass_one
67
- result << temp
68
- temp = (' ' * @key_length) + word
69
- len = temp.length
70
- else
71
- temp << word
72
- pass_one = false
73
- end
46
+ item.format_description(@page_width - @key_length - 1).each do |desc_line|
47
+ result << key.ljust(@key_length) + desc_line
48
+ key = ""
74
49
  end
75
50
 
76
- result << temp
51
+ result
77
52
  end
78
53
 
79
54
  end
80
55
 
81
56
  end
82
57
 
83
- class Array
84
- #Print out the array as bullet points.
85
- def puts_foorth_bullets(page_width)
86
- puts foorth_bulletize(page_width)
87
- end
88
-
89
- #Convert the array to strings with bullet points.
90
- #<br>
91
- #* An array of arrays of strings
92
- def foorth_bulletize(page_width)
93
- builder = XfOOrth::BulletPoints.new(page_width)
94
-
95
- self.each do |pair|
96
- builder.add(*pair)
97
- end
98
-
99
- builder.render
100
- end
101
- end
102
-
103
- class Hash
104
- #Print out the hash as bullet points.
105
- def puts_foorth_bullets(page_width)
106
- puts foorth_bulletize(page_width)
107
- end
108
-
109
- #Convert the hash to strings with bullet points.
110
- #<br>
111
- #* An array of arrays of strings
112
- def foorth_bulletize(page_width)
113
- builder = XfOOrth::BulletPoints.new(page_width)
114
-
115
- self.each do |key, value|
116
- builder.add(key, *value.in_array)
117
- end
118
-
119
- builder.render
120
- end
121
- end
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- #* library/formatting/columns.rb - Print out data in columns.
3
+ #* library/formatting/bullets.rb - Print out data in neat columns.
4
4
  module XfOOrth
5
5
 
6
6
  #A class to display data in columns.
@@ -18,8 +18,8 @@ module XfOOrth
18
18
  item = raw_item.to_s
19
19
  fail "Item too large to fit." unless item.length < @page_width
20
20
 
21
- if (slot = find_next_column)
22
- @page_data[slot] << item
21
+ if (column = find_next_column)
22
+ @page_data[column] << item
23
23
  else
24
24
  @page_data << [item]
25
25
  end
@@ -29,21 +29,28 @@ module XfOOrth
29
29
 
30
30
  #Render the page as an array of strings.
31
31
  def render
32
- results = []
33
- widths = @page_data.map {|column| column.foorth_column_width}
32
+ results, column_widths = [], get_column_widths
34
33
 
35
- (0...rows).each do |column_index|
36
- results << @page_data.each_with_index.map do |column, index|
37
- column[column_index].to_s.ljust(widths[index])
38
- end.join(" ").freeze
39
- end
34
+ rows.times { |row_index| results << render_row(row_index, column_widths)}
40
35
 
41
- @page_data = []
36
+ @page_data.clear
42
37
  results
43
38
  end
44
39
 
45
40
  private
46
41
 
42
+ #Get the widths of all columns
43
+ def get_column_widths
44
+ @page_data.map {|column| column.foorth_column_width}
45
+ end
46
+
47
+ #Render a single row of data.
48
+ def render_row(row_index, widths)
49
+ @page_data.each_with_index.map do |column, index|
50
+ column[row_index].to_s.ljust(widths[index])
51
+ end.join(" ")
52
+ end
53
+
47
54
  #Make sure the page fits within its boundaries.
48
55
  #<br>Returns
49
56
  #* The number if items that did not fit in the page.
@@ -74,6 +81,8 @@ module XfOOrth
74
81
  if empty?
75
82
  0
76
83
  else
84
+ #The starting point, @page_data.length-1, represents the spaces needed
85
+ #between the columns. So N columns means N-1 spaces.
77
86
  @page_data.inject(@page_data.length-1) do |sum, column|
78
87
  sum + column.foorth_column_width
79
88
  end
@@ -111,34 +120,3 @@ module XfOOrth
111
120
 
112
121
  end
113
122
 
114
- #Support for displaying an array in neat columns.
115
- class Array
116
- #Print out the array with efficient columns.
117
- def puts_foorth_columnized(page_length, page_width)
118
- foorth_columnize(page_length, page_width).each do |page|
119
- puts page
120
- puts
121
- end
122
- end
123
-
124
- #Convert the array to strings with efficient columns.
125
- #<br>
126
- #* An array of arrays of strings
127
- def foorth_columnize(page_length, page_width)
128
- index, pages, limit = 0, [], self.length
129
- builder = XfOOrth::ColumnizedPage.new(page_length, page_width)
130
-
131
- while index < limit
132
- index += 1 - (left_over = builder.add(self[index]))
133
- pages << builder.render if (left_over > 0) || (index == limit)
134
- end
135
-
136
- pages
137
- end
138
-
139
- #Get the widest element of an array.
140
- def foorth_column_width
141
- (self.max_by {|item| item.length}).length
142
- end
143
- end
144
-