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