fOOrth 0.6.4 → 0.6.5

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/integration/compile_lib_tests.rb +41 -0
  3. data/irbt.rb +0 -2
  4. data/lib/fOOrth/compiler.rb +4 -8
  5. data/lib/fOOrth/compiler/cast.rb +39 -0
  6. data/lib/fOOrth/compiler/context/map_name.rb +12 -31
  7. data/lib/fOOrth/compiler/process.rb +5 -3
  8. data/lib/fOOrth/core/class.rb +1 -1
  9. data/lib/fOOrth/debug.rb +0 -2
  10. data/lib/fOOrth/debug/display_abort.rb +0 -6
  11. data/lib/fOOrth/library.rb +1 -0
  12. data/lib/fOOrth/library/array_library.rb +1 -47
  13. data/lib/fOOrth/library/command_library.rb +35 -60
  14. data/lib/fOOrth/library/compile_library.rb +27 -7
  15. data/lib/fOOrth/library/formatting/bullets.rb +121 -0
  16. data/lib/fOOrth/library/formatting/columns.rb +144 -0
  17. data/lib/fOOrth/library/hash_library.rb +2 -1
  18. data/lib/fOOrth/library/introspection/class.rb +84 -0
  19. data/lib/fOOrth/library/introspection/context.rb +36 -0
  20. data/lib/fOOrth/library/introspection/object.rb +69 -0
  21. data/lib/fOOrth/library/introspection/string.rb +28 -0
  22. data/lib/fOOrth/library/introspection/symbol_map.rb +19 -0
  23. data/lib/fOOrth/library/introspection/vm.rb +70 -0
  24. data/lib/fOOrth/library/introspection/word_specs.rb +18 -0
  25. data/lib/fOOrth/library/introspection_library.rb +78 -0
  26. data/lib/fOOrth/library/stack_library.rb +2 -4
  27. data/lib/fOOrth/library/stdio_library.rb +68 -0
  28. data/lib/fOOrth/library/stubs.rb +11 -7
  29. data/lib/fOOrth/library/vm_library.rb +1 -5
  30. data/lib/fOOrth/version.rb +1 -1
  31. data/tests/core_tests.rb +1 -1
  32. metadata +13 -4
  33. data/lib/fOOrth/debug/context_dump.rb +0 -31
  34. data/lib/fOOrth/debug/vm_dump.rb +0 -27
@@ -3,12 +3,27 @@
3
3
  #* library/compile_library.rb - The compile support fOOrth library.
4
4
  module XfOOrth
5
5
 
6
+ # METHOD CASTING ==============================
7
+
8
+ #TosSpec method cast.
9
+ VirtualMachine.create_shared_method("'.", VmSpec, [],
10
+ &lambda {|vm| vm.set_cast(TosSpec) })
11
+
12
+ #NosSpec method cast.
13
+ VirtualMachine.create_shared_method("'*", VmSpec, [],
14
+ &lambda {|vm| vm.set_cast(NosSpec) })
15
+
16
+ #SelfSpec method cast.
17
+ VirtualMachine.create_shared_method("'~", VmSpec, [],
18
+ &lambda {|vm| vm.set_cast(SelfSpec) })
19
+
6
20
  # COLON =======================================
7
21
 
8
22
  #The classic colon definition that creates a word in the Virtual Machine class.
9
23
  # [] : <name> <stuff omitted> ; []; creates <name> on the VirtualMachine
10
24
  VirtualMachine.create_shared_method(':', VmSpec, [:immediate], &lambda {|vm|
11
25
  if execute_mode?
26
+ verify_cast([VmSpec])
12
27
  target = VirtualMachine
13
28
  name = vm.parser.get_word()
14
29
  type = VmSpec
@@ -32,6 +47,7 @@ module XfOOrth
32
47
  # [] !: <name> <stuff omitted> ; []; creates <name> on the VirtualMachine
33
48
  VirtualMachine.create_shared_method('!:', VmSpec, [:immediate], &lambda {|vm|
34
49
  if execute_mode?
50
+ verify_cast([VmSpec])
35
51
  target = VirtualMachine
36
52
  name = vm.parser.get_word()
37
53
  type = VmSpec
@@ -58,7 +74,7 @@ module XfOOrth
58
74
  error "F13: The target of .: must be a class" unless target.is_a?(Class)
59
75
 
60
76
  name = vm.parser.get_word()
61
- type = XfOOrth.name_to_type(name)
77
+ type = XfOOrth.name_to_type(name, get_cast)
62
78
  XfOOrth.validate_type(vm, type, name)
63
79
  XfOOrth.validate_string_method(type, target, name)
64
80
 
@@ -116,7 +132,7 @@ module XfOOrth
116
132
  if execute_mode?
117
133
  target = vm.pop
118
134
  name = vm.parser.get_word()
119
- type = XfOOrth.name_to_type(name)
135
+ type = XfOOrth.name_to_type(name, get_cast)
120
136
  XfOOrth.validate_type(vm, type, name)
121
137
  XfOOrth.validate_string_method(type, target.class, name)
122
138
 
@@ -184,8 +200,10 @@ module XfOOrth
184
200
  &lambda {|vm| vm << 'super(vm); ' })
185
201
 
186
202
  #The standard end-compile adapter word: ';' semi-colon.
187
- context.create_local_method(';', LocalSpec, [:immediate],
188
- &lambda {|vm| vm.end_compile_mode([ctrl]) })
203
+ context.create_local_method(';', LocalSpec, [:immediate], &lambda {|vm|
204
+ vm.clear_cast
205
+ vm.end_compile_mode([ctrl])
206
+ })
189
207
  end
190
208
 
191
209
  #Determine the type of method being created. This only applies to non-vm
@@ -194,8 +212,8 @@ module XfOOrth
194
212
  #*name - The name of the method to be created.
195
213
  #<Returns>
196
214
  #* The class of the spec to be used for this method.
197
- def self.name_to_type(name)
198
- case name[0]
215
+ def self.name_to_type(name, cast_spec=nil)
216
+ normal_spec = case name[0]
199
217
  when '.'
200
218
  TosSpec
201
219
 
@@ -208,6 +226,8 @@ module XfOOrth
208
226
  else
209
227
  NosSpec
210
228
  end
229
+
230
+ cast_spec || normal_spec
211
231
  end
212
232
 
213
233
  #Compare the new method's spec against the specs of other methods of the
@@ -218,7 +238,7 @@ module XfOOrth
218
238
  #*type - The class of the method to be created.
219
239
  #*name - The name of the method to be created.
220
240
  def self.validate_type(vm, type, name)
221
- if (spec = vm.context.map(name))
241
+ if (spec = vm.context.map(name, false))
222
242
  if spec.class != type
223
243
  error "F90: Spec type mismatch #{spec.foorth_name} vs #{type.foorth_name}"
224
244
  end
@@ -0,0 +1,121 @@
1
+ # coding: utf-8
2
+
3
+ #* library/formatting/bullets.rb - Print out bullet points.
4
+ module XfOOrth
5
+
6
+ #A class to display data in bullet points.
7
+ class BulletPoints
8
+ #Prepare a blank slate.
9
+ def initialize(page_width)
10
+ @page_width, @bullet_data = page_width, []
11
+ end
12
+
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]
28
+ end
29
+ end
30
+
31
+ #Render the page as an array of strings.
32
+ def render
33
+ @key_length, results = get_key_length, []
34
+
35
+ @bullet_data.each do |key, item|
36
+ results.concat(render_bullet(key, item))
37
+ end
38
+
39
+ @bullet_data = []
40
+ results
41
+ end
42
+
43
+ private
44
+
45
+ #How large is the largest bullet?
46
+ def get_key_length
47
+ (@bullet_data.max_by {|line| line[0].length})[0].length
48
+ end
49
+
50
+ #Render one bullet point.
51
+ def render_bullet(key, item)
52
+ 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
+
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
74
+ end
75
+
76
+ result << temp
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
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
@@ -0,0 +1,144 @@
1
+ # coding: utf-8
2
+
3
+ #* library/formatting/columns.rb - Print out data in columns.
4
+ module XfOOrth
5
+
6
+ #A class to display data in columns.
7
+ class ColumnizedPage
8
+ #Prepare a blank page.
9
+ def initialize(page_length, page_width)
10
+ @page_length, @page_width = page_length, page_width
11
+ @page_data = []
12
+ end
13
+
14
+ #Add an item to this page.
15
+ #<br>Returns
16
+ #* The number if items that did not fit in the page.
17
+ def add(raw_item)
18
+ item = raw_item.to_s
19
+ fail "Item too large to fit." unless item.length < @page_width
20
+
21
+ if (slot = find_next_column)
22
+ @page_data[slot] << item
23
+ else
24
+ @page_data << [item]
25
+ end
26
+
27
+ adjust_configuration
28
+ end
29
+
30
+ #Render the page as an array of strings.
31
+ def render
32
+ results = []
33
+ widths = @page_data.map {|column| column.foorth_column_width}
34
+
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
40
+
41
+ @page_data = []
42
+ results
43
+ end
44
+
45
+ private
46
+
47
+ #Make sure the page fits within its boundaries.
48
+ #<br>Returns
49
+ #* The number if items that did not fit in the page.
50
+ def adjust_configuration
51
+ while total_width >= @page_width
52
+ return @page_data.pop.length if rows == @page_length
53
+ add_a_row
54
+ end
55
+
56
+ 0
57
+ end
58
+
59
+ #Add a row to the page, moving items as needed.
60
+ def add_a_row
61
+ target = rows + 1
62
+ pool, @page_data = @page_data.flatten, []
63
+
64
+ until pool.empty?
65
+ @page_data << pool.shift(target)
66
+ end
67
+ end
68
+
69
+ #Compute the total width of all of the columns.
70
+ #<br>Returns
71
+ #* The sum of the widths of the widest items of each column plus a space
72
+ # between each of those columns.
73
+ def total_width
74
+ if empty?
75
+ 0
76
+ else
77
+ @page_data.inject(@page_data.length-1) do |sum, column|
78
+ sum + column.foorth_column_width
79
+ end
80
+ end
81
+ end
82
+
83
+ #Does the data fit on the page?
84
+ def fits?
85
+ total_width < @page_width
86
+ end
87
+
88
+ #How many rows are currently in this page?
89
+ def rows
90
+ empty? ? 0 : @page_data[0].length
91
+ end
92
+
93
+ #Is this page empty?
94
+ def empty?
95
+ @page_data.empty?
96
+ end
97
+
98
+ #Which column will receive the next item?
99
+ #<br>Returns
100
+ #* The index of the first non-filled column or nil if none found.
101
+ def find_next_column
102
+ (1...(@page_data.length)).each do |index|
103
+ if @page_data[index].length < @page_data[index-1].length
104
+ return index
105
+ end
106
+ end
107
+
108
+ nil
109
+ end
110
+ end
111
+
112
+ end
113
+
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
+
@@ -197,7 +197,8 @@ class Hash
197
197
  #A helper method to extract non-stub method names from a method hash.
198
198
  def extract_method_names(search_type = :no_stubs)
199
199
  search_value = (search_type == :stubs)
200
- mkeys = self.keys.select {|key| search_value == self[key].has_tag?(:stub) }
200
+ get_all = (search_type == :all)
201
+ mkeys = self.keys.select {|key| get_all || search_value == self[key].has_tag?(:stub) }
201
202
  mkeys.collect {|key| XfOOrth::SymbolMap.unmap(key) || '?error?' }
202
203
  end
203
204
  end
@@ -0,0 +1,84 @@
1
+ # coding: utf-8
2
+
3
+ #* library/introspection/class.rb - Class support for introspection.
4
+ class Class
5
+
6
+ #Get information about the mapping of the symbol.
7
+ def map_foorth_shared_info(symbol, shallow=nil)
8
+ if (spec = foorth_shared[symbol])
9
+ [spec, [["Class", foorth_class_name], ["Scope", "Shared"]]]
10
+ elsif (sc = superclass) && !shallow
11
+ sc.map_foorth_shared_info(symbol)
12
+ else
13
+ [nil, nil]
14
+ end
15
+ end
16
+
17
+ #Get the lineage of this class.
18
+ def lineage
19
+ #Ugly hack, sorry!
20
+ if [Object, Module].include?(self)
21
+ "Object"
22
+ else
23
+ foorth_class_name + " < " + superclass.lineage
24
+ end
25
+ end
26
+
27
+ #Investigate a method of this class.
28
+ def foorth_method_info(name)
29
+ symbol, results = XfOOrth::SymbolMap.map_info(name)
30
+ found = false
31
+
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)
37
+ found = true
38
+ end
39
+
40
+ spec, info = map_foorth_exclusive_info(symbol)
41
+
42
+ if spec && !spec.has_tag?(:stub)
43
+ (results << ["", ""]).concat(info).concat(spec.get_info)
44
+ found = true
45
+ end
46
+
47
+ results << ["Scope", "not found."] unless found
48
+ end
49
+
50
+ results
51
+ end
52
+
53
+ #Get introspection info.
54
+ def get_info
55
+ results = [["Lineage", lineage]]
56
+
57
+ if foorth_has_exclusive?
58
+ results.concat([["", ""], ["Methods", "Class"]])
59
+
60
+ foorth_exclusive.extract_method_names(:all).sort.each do |name|
61
+ symbol, info = XfOOrth::SymbolMap.map_info(name)
62
+ (results << ["", ""]).concat(info)
63
+
64
+ spec, info = map_foorth_exclusive_info(symbol, :shallow)
65
+ results.concat(info).concat(spec.get_info)
66
+ end
67
+ end
68
+
69
+ unless foorth_shared.empty?
70
+ results.concat([["", ""], ["Methods", "Shared"]])
71
+
72
+ foorth_shared.extract_method_names(:all).sort.each do |name|
73
+ symbol, info = XfOOrth::SymbolMap.map_info(name)
74
+ (results << ["", ""]).concat(info)
75
+
76
+ spec, info = map_foorth_shared_info(symbol, :shallow)
77
+ results.concat(info).concat(spec.get_info)
78
+ end
79
+ end
80
+
81
+ results
82
+ end
83
+
84
+ end