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
@@ -43,4 +43,20 @@ class ProcedureLibraryTester < Minitest::Test
43
43
  foorth_equal('{{ 42 var: a a @ }} .call', [42])
44
44
  end
45
45
 
46
+ def test_instance_data
47
+ foorth_run('42 Object .new .with{{ val@: @test self val$: $t_i_d_1 }}')
48
+ foorth_run('$t_i_d_1 .:: .mulby @test * ; ')
49
+ foorth_equal('2 $t_i_d_1 .mulby', [84])
50
+
51
+ foorth_run('99 $t_i_d_1 .with{{ var@: @boot }} ')
52
+ foorth_run('$t_i_d_1 .:: .addby @boot @ + ; ')
53
+ foorth_equal('2 $t_i_d_1 .addby', [101])
54
+
55
+ foorth_run('$t_i_d_1 .:: .set_boot @boot ! ;')
56
+ foorth_run('56 $t_i_d_1 .set_boot')
57
+ foorth_equal('2 $t_i_d_1 .addby', [58])
58
+
59
+ foorth_run('128 $t_i_d_1 .set_boot')
60
+ foorth_equal('64 $t_i_d_1 .addby', [192])
61
+ end
46
62
  end
@@ -42,8 +42,9 @@ class QueueLibraryTester < Minitest::Test
42
42
 
43
43
  foorth_equal('5 $q .push', [])
44
44
  foorth_equal('$q .empty?', [false])
45
+ foorth_equal('$q .present?', [true])
45
46
  foorth_equal('$q .length', [1])
46
- foorth_equal('$q .clear', [])
47
+ foorth_equal('$q .clear!', [])
47
48
  foorth_equal('$q .empty?', [true])
48
49
  foorth_equal('$q .length', [0])
49
50
 
@@ -60,8 +60,9 @@ class StackLibraryTester < Minitest::Test
60
60
  foorth_run('42 $s .push')
61
61
  foorth_equal('$s .empty?', [false])
62
62
  foorth_equal('$s .peek', [42])
63
+ foorth_equal('$s .present?', [true])
63
64
 
64
- foorth_run('$s .clear')
65
+ foorth_run('$s .clear!')
65
66
 
66
67
  foorth_equal('$s .empty?', [true])
67
68
  foorth_raises('$s .peek')
@@ -49,4 +49,66 @@ class StdioLibraryTester < Minitest::Test
49
49
  foorth_raises('1+1i .emit')
50
50
  end
51
51
 
52
+ #Looks like some unit testing has crept into integration testing. OK.
53
+ def test_some_formatting
54
+ assert_equal("1 4\n2 5\n3 ", [1,2,3,4,5].format_foorth_columns(false, 5))
55
+ assert_equal(["1 4", "2 5", "3 "], [1,2,3,4,5].format_description(5))
56
+
57
+ assert_equal(["1 2", "3 4", "5"], "1 2 3 4 5".format_description(5))
58
+
59
+ assert_equal([], [].format_description(5))
60
+ assert_equal([], nil.format_description(5))
61
+
62
+ result =
63
+ "1 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 97 \n" +
64
+ "2 6 10 14 18 22 26 30 34 38 42 46 50 54 58 62 66 70 74 78 82 86 90 94 98 \n" +
65
+ "3 7 11 15 19 23 27 31 35 39 43 47 51 55 59 63 67 71 75 79 83 87 91 95 99 \n" +
66
+ "4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100"
67
+
68
+ assert_equal(result, (1..100).to_a.format_foorth_columns(false, 80) )
69
+
70
+ data =
71
+ [["key_largo", "/long_folder_name_one/long_folder_name_two/long_folder_name_three/fine_descriptive_name"],
72
+ ["key_west", "Semper ubi sub ubi. Semper ubi sub ubi. Semper ubi sub ubi. Semper ubi sub ubi. "],
73
+ ["counting", Array.new(100) {|i| i} ],
74
+ ["pie", Math::PI]
75
+ ]
76
+
77
+ result =
78
+ "key_largo /long_folder_name_one/long_folder_name_two/long_folder_name_three/fin\n" +
79
+ " e_descriptive_name\n" +
80
+ "key_west Semper ubi sub ubi. Semper ubi sub ubi. Semper ubi sub ubi. Semper\n" +
81
+ " ubi sub ubi.\n" +
82
+ "counting 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95\n" +
83
+ " 1 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 81 86 91 96\n" +
84
+ " 2 7 12 17 22 27 32 37 42 47 52 57 62 67 72 77 82 87 92 97\n" +
85
+ " 3 8 13 18 23 28 33 38 43 48 53 58 63 68 73 78 83 88 93 98\n" +
86
+ " 4 9 14 19 24 29 34 39 44 49 54 59 64 69 74 79 84 89 94 99\n" +
87
+ "pie 3.141592653589793"
88
+
89
+ assert_equal(result, data.foorth_format_bullets(80))
90
+
91
+ assert_equal("", [].foorth_format_bullets(80))
92
+
93
+
94
+ data =
95
+ {"key_largo" => "/long_folder_name_one/long_folder_name_two/long_folder_name_three/fine_descriptive_name",
96
+ "key_west" => "Semper ubi sub ubi. Semper ubi sub ubi. Semper ubi sub ubi. Semper ubi sub ubi. ",
97
+ "counting" => Array.new(100) {|i| i},
98
+ "pie" => Math::PI
99
+ }
100
+
101
+ assert_equal(result, data.foorth_format_bullets(80))
102
+
103
+ end
104
+
105
+ def test_formatting_some_more
106
+ foorth_run('5 $chars_per_line !')
107
+ foorth_equal('[ 1 2 3 4 5 ] .format_columns', ["1 4\n2 5\n3 "])
108
+
109
+ foorth_run('80 $chars_per_line !')
110
+ foorth_equal('[ [ 1 "apple" ] [ 2 "cherry" ] [ 3 "prune" ] ] .format_bullets',
111
+ ["1 apple\n2 cherry\n3 prune"])
112
+ end
113
+
52
114
  end
@@ -523,4 +523,15 @@ class StringLibraryTester < Minitest::Test
523
523
  foorth_equal('"Hello World" p"%s %s" .map{{ v .mutable? }}', [[false, false]])
524
524
  end
525
525
 
526
+ def test_string_emptiness
527
+ foorth_equal('"" .empty?', [true])
528
+ foorth_equal('"1" .empty?', [false])
529
+
530
+ foorth_equal('"" .present?', [false])
531
+ foorth_equal('"1" .present?', [true])
532
+
533
+ foorth_equal('"1"* dup .clear!', [""])
534
+ end
535
+
536
+
526
537
  end
@@ -72,12 +72,26 @@ class ThreadLibraryTester < Minitest::Test
72
72
  foorth_equal('$tmtx .do{{ 3 4 + }}', [7])
73
73
 
74
74
  foorth_run('""* val$: $tmtx_str')
75
- foorth_equal('{{ $tmtx .do{{ 0 10 do $tmtx_str "@" << loop }} }} ' +
76
- '.start drop $tmtx .do{{ $tmtx_str }} ', ["@"*10])
77
75
 
78
- foorth_run('""* val$: $tmtx_str')
79
- foorth_equal('{{ Mutex .do{{ 0 10 do $tmtx_str "@" << loop }} }} ' +
80
- '.start drop Mutex .do{{ $tmtx_str }} ', ["@"*10])
76
+ code = ': test_mutex_one $tmtx_str .clear! ' +
77
+ '{{ $tmtx .do{{ 0 10 do $tmtx_str "@" << loop }} }} .start drop ' +
78
+ 'begin $tmtx .do{{ $tmtx_str }} .present? until $tmtx_str ;'
79
+
80
+ foorth_run(code)
81
+
82
+ 10.times do
83
+ foorth_equal('test_mutex_one', ["@"*10])
84
+ end
85
+
86
+ code = ': test_mutex_two $tmtx_str .clear! ' +
87
+ '{{ Mutex .do{{ 0 10 do $tmtx_str "@" << loop }} }} .start drop ' +
88
+ 'begin Mutex .do{{ $tmtx_str }} .present? until $tmtx_str ;'
89
+
90
+ foorth_run(code)
91
+
92
+ 10.times do
93
+ foorth_equal('test_mutex_two', ["@"*10])
94
+ end
81
95
  end
82
96
 
83
97
  end
data/lib/fOOrth.rb CHANGED
@@ -10,8 +10,6 @@ require 'ruby_sscanf'
10
10
  require 'English'
11
11
 
12
12
  require 'pp'
13
-
14
- $no_alias_read_line_module = true
15
13
  require 'mini_readline'
16
14
 
17
15
  require_relative 'fOOrth/version'
@@ -1,64 +1,64 @@
1
- # coding: utf-8
2
-
3
- require_relative 'context/map_name'
4
- require_relative 'context/tags'
5
- require_relative 'context/locals'
6
-
7
- #* compiler/context.rb - The compile progress context manager of the fOOrth
8
- # language system.
9
- module XfOOrth
10
-
11
- #A class for the management of global, hierarchical, and nested compile time contexts.
12
- #* compiler/context.rb - \Context constructor, tag support, and local defs.
13
- class Context
14
-
15
- #The previous context object that this one builds on. Set to nil if there
16
- #is none.
17
- attr_reader :previous
18
-
19
- #Setup an instance of compiler context.
20
- #<br>Parameters:
21
- #* previous - The previous context object or nil if there is none.
22
- #* data - A hash of context data.
23
- def initialize(previous, data={})
24
- @previous, @data = previous, data
25
- end
26
-
27
- #How many levels of nested context are there?
28
- def depth
29
- 1 + (previous ? previous.depth : 0)
30
- end
31
-
32
- #Is the current nesting level what is expected?
33
- #<br>Parameters
34
- #* expected_depth - the expected nesting depth.
35
- #<br>Notes
36
- #* Raises an error (F12) on incorrect nesting.
37
- def check_depth(expected_depth)
38
- if expected_depth - self.depth != 0
39
- error "F12: Error, Invalid control/structure nesting."
40
- end
41
- end
42
-
43
- #Get the current target.
44
- def target
45
- self[:obj] || self[:cls] || self[:vm] || no_target_error
46
- end
47
-
48
- #Get the current target object.
49
- def target_object
50
- self[:obj] || no_target_error
51
- end
52
-
53
- #Get the current target class.
54
- def target_class
55
- self[:cls] || no_target_error
56
- end
57
-
58
- #Signal that no receiver was found in this context.
59
- #This is an internal error indication.
60
- def no_target_error
61
- error("F90: No target found in context.")
62
- end
63
- end
64
- end
1
+ # coding: utf-8
2
+
3
+ require_relative 'context/map_name'
4
+ require_relative 'context/tags'
5
+ require_relative 'context/locals'
6
+
7
+ #* compiler/context.rb - The compile progress context manager of the fOOrth
8
+ # language system.
9
+ module XfOOrth
10
+
11
+ #A class for the management of global, hierarchical, and nested compile time contexts.
12
+ #* compiler/context.rb - \Context constructor, tag support, and local defs.
13
+ class Context
14
+
15
+ #The previous context object that this one builds on. Set to nil if there
16
+ #is none.
17
+ attr_reader :previous
18
+
19
+ #Setup an instance of compiler context.
20
+ #<br>Parameters:
21
+ #* previous - The previous context object or nil if there is none.
22
+ #* data - A hash of context data.
23
+ def initialize(previous, data={})
24
+ @previous, @data = previous, data
25
+ end
26
+
27
+ #How many levels of nested context are there?
28
+ def depth
29
+ 1 + (previous ? previous.depth : 0)
30
+ end
31
+
32
+ #Is the current nesting level what is expected?
33
+ #<br>Parameters
34
+ #* expected_depth - the expected nesting depth.
35
+ #<br>Notes
36
+ #* Raises an error (F12) on incorrect nesting.
37
+ def check_depth(expected_depth)
38
+ if expected_depth - self.depth != 0
39
+ error "F12: Error, Invalid control/structure nesting."
40
+ end
41
+ end
42
+
43
+ #Get the current target.
44
+ def target
45
+ self[:obj] || self[:cls] || self[:vm] || no_target_error
46
+ end
47
+
48
+ #Get the current target object.
49
+ def target_object
50
+ self[:obj] || no_target_error
51
+ end
52
+
53
+ #Get the current target class.
54
+ def target_class
55
+ self[:cls] || no_target_error
56
+ end
57
+
58
+ #Signal that no receiver was found in this context.
59
+ #This is an internal error indication.
60
+ def no_target_error
61
+ error("F90: No target found in context.")
62
+ end
63
+ end
64
+ end
@@ -1,34 +1,34 @@
1
- # coding: utf-8
2
-
3
- #* compiler/context/locals.rb - Support local methods in context.
4
- module XfOOrth
5
-
6
- #* compiler/context/locals.rb - Support local methods in context.
7
- class Context
8
-
9
- #Create a local method on this context.
10
- #<br>Parameters:
11
- #* name - The name of the method to create.
12
- #* spec_class - The specification class to use.
13
- #* options - An array of options.
14
- #* block - A block to associate with the name.
15
- #<br>Returns
16
- #* The spec created for the shared method.
17
- def create_local_method(name, spec_class, options, &block)
18
- sym = SymbolMap.add_entry(name)
19
- self[sym] = spec_class.new(name, sym, options, &block)
20
- end
21
-
22
- #Remove a local method on this context.
23
- #<br>Parameters:
24
- #* The name of the method to remove.
25
- def remove_local_method(name)
26
- if (sym = SymbolMap.map(name))
27
- @data.delete(sym)
28
- else
29
- error "F90: Unable to remove local method #{name}"
30
- end
31
- end
32
-
33
- end
34
- end
1
+ # coding: utf-8
2
+
3
+ #* compiler/context/locals.rb - Support local methods in context.
4
+ module XfOOrth
5
+
6
+ #* compiler/context/locals.rb - Support local methods in context.
7
+ class Context
8
+
9
+ #Create a local method on this context.
10
+ #<br>Parameters:
11
+ #* name - The name of the method to create.
12
+ #* spec_class - The specification class to use.
13
+ #* options - An array of options.
14
+ #* block - A block to associate with the name.
15
+ #<br>Returns
16
+ #* The spec created for the shared method.
17
+ def create_local_method(name, spec_class, options, &block)
18
+ sym = SymbolMap.add_entry(name)
19
+ self[sym] = spec_class.new(name, sym, options, &block)
20
+ end
21
+
22
+ #Remove a local method on this context.
23
+ #<br>Parameters:
24
+ #* The name of the method to remove.
25
+ def remove_local_method(name)
26
+ if (sym = SymbolMap.map(name))
27
+ @data.delete(sym)
28
+ else
29
+ error "F90: Unable to remove local method #{name}"
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -1,74 +1,85 @@
1
- # coding: utf-8
2
-
3
- #* compiler/context/map_name.rb - The fOOrth language mapping of names in a context.
4
- module XfOOrth
5
-
6
- #* compiler/context/map_name.rb - The fOOrth language mapping of names in a context.
7
- class Context
8
-
9
- #Map a name to a specification.
10
- #<br>Parameters:
11
- #* name - The string to be mapped.
12
- #<br>Returns:
13
- #* The specification that corresponds to the name or nil if none found.
14
- def map(name, allow_defaults=:allow)
15
- if (@symbol = SymbolMap.map(@name = name))
16
- do_map_name(allow_defaults)
17
- end
18
- end
19
-
20
- #Private methods follow.
21
- private
22
-
23
- #Do a search of dictionaries based on the syntax of the name.
24
- def do_map_name(allow_defaults)
25
- self[@symbol] ||
26
- do_target_class_map ||
27
- do_target_object_map ||
28
- do_target_vm_map ||
29
- do_object_class_map ||
30
- do_global_map ||
31
- (allow_defaults && case @name[0]
32
- when '.'
33
- TosSpec.new(@name, @symbol, [:temp])
34
-
35
- when '~'
36
- SelfSpec.new(@name, @symbol, [:temp])
37
-
38
- else
39
- spec_error
40
- end)
41
- end
42
-
43
- #Do a search of the Object class for the item.
44
- def do_object_class_map
45
- Object.map_foorth_shared(@symbol)
46
- end
47
-
48
- #Do a search of the :cls tag if it is specified.
49
- def do_target_class_map
50
- (tc = self[:cls]) && tc.map_foorth_shared(@symbol)
51
- end
52
-
53
- #Do a search of the :obj tag if it is specified.
54
- def do_target_object_map
55
- (to = self[:obj]) && to.map_foorth_exclusive(@symbol)
56
- end
57
-
58
- #Do a search of the :vm tag if it is specified.
59
- def do_target_vm_map
60
- (vm = self[:vm]) && vm.map_foorth_exclusive(@symbol)
61
- end
62
-
63
- #Do a search of the globals.
64
- def do_global_map
65
- $FOORTH_GLOBALS[@symbol]
66
- end
67
-
68
- #Error: Unable to find a specification.
69
- def spec_error
70
- error "F11: ?#{@name}?"
71
- end
72
-
73
- end
74
- end
1
+ # coding: utf-8
2
+
3
+ #* compiler/context/map_name.rb - The fOOrth language mapping of names in a context.
4
+ module XfOOrth
5
+
6
+ #* compiler/context/map_name.rb - The fOOrth language mapping of names in a context.
7
+ class Context
8
+
9
+ #Map a name to a specification.
10
+ #<br>Parameters:
11
+ #* name - The string to be mapped.
12
+ #<br>Returns:
13
+ #* The specification that corresponds to the name or nil if none found.
14
+ def map_with_defaults(name)
15
+ if (@symbol = SymbolMap.map(@name = name))
16
+ do_map_name ||
17
+ case @name[0]
18
+ when '.'
19
+ TosSpec.new(@name, @symbol, [:temp])
20
+
21
+ when '~'
22
+ SelfSpec.new(@name, @symbol, [:temp])
23
+
24
+ else
25
+ spec_error
26
+ end
27
+ end
28
+ end
29
+
30
+ #Map a name to a specification.
31
+ #<br>Parameters:
32
+ #* name - The string to be mapped.
33
+ #<br>Returns:
34
+ #* The specification that corresponds to the name or nil if none found.
35
+ def map_without_defaults(name)
36
+ if (@symbol = SymbolMap.map(@name = name))
37
+ do_map_name
38
+ end
39
+ end
40
+
41
+ #Private methods follow.
42
+ private
43
+
44
+ #Do a search of dictionaries based on the syntax of the name.
45
+ def do_map_name
46
+ self[@symbol] ||
47
+ do_target_class_map ||
48
+ do_target_object_map ||
49
+ do_target_vm_map ||
50
+ do_object_class_map ||
51
+ do_global_map
52
+ end
53
+
54
+ #Do a search of the Object class for the item.
55
+ def do_object_class_map
56
+ Object.map_foorth_shared(@symbol)
57
+ end
58
+
59
+ #Do a search of the :cls tag if it is specified.
60
+ def do_target_class_map
61
+ (tc = self[:cls]) && tc.map_foorth_shared(@symbol)
62
+ end
63
+
64
+ #Do a search of the :obj tag if it is specified.
65
+ def do_target_object_map
66
+ (to = self[:obj]) && to.map_foorth_exclusive(@symbol)
67
+ end
68
+
69
+ #Do a search of the :vm tag if it is specified.
70
+ def do_target_vm_map
71
+ (vm = self[:vm]) && vm.map_foorth_exclusive(@symbol)
72
+ end
73
+
74
+ #Do a search of the globals.
75
+ def do_global_map
76
+ $FOORTH_GLOBALS[@symbol]
77
+ end
78
+
79
+ #Error: Unable to find a specification.
80
+ def spec_error
81
+ error "F11: ?#{@name}?"
82
+ end
83
+
84
+ end
85
+ end