fOOrth 0.6.4 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
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