gloo 5.1.0 → 5.2.0

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/lib/VERSION +1 -1
  3. data/lib/VERSION_NOTES +15 -1
  4. data/lib/gloo/app/args.rb +9 -0
  5. data/lib/gloo/app/engine.rb +48 -2
  6. data/lib/gloo/app/mode.rb +1 -1
  7. data/lib/gloo/core/it.rb +14 -0
  8. data/lib/gloo/core/obj.rb +22 -1
  9. data/lib/gloo/core/obj_finder.rb +21 -0
  10. data/lib/gloo/expr/op_eq.rb +5 -0
  11. data/lib/gloo/objs/basic/string.rb +5 -228
  12. data/lib/gloo/objs/basic/string_msgs.rb +269 -0
  13. data/lib/gloo/objs/basic/text.rb +7 -1
  14. data/lib/gloo/objs/ctrl/each.rb +2 -0
  15. data/lib/gloo/objs/ctrl/each_dir.rb +72 -0
  16. data/lib/gloo/persist/disc_mech.rb +10 -1
  17. data/lib/gloo/persist/persist_man.rb +11 -2
  18. data/lib/gloo/plugin/ext_manager.rb +5 -0
  19. data/lib/gloo/plugin/lib_manager.rb +6 -0
  20. data/lib/gloo/verbs/eval.rb +43 -0
  21. data/lib/gloo/verbs/exists.rb +13 -0
  22. data/lib/gloo/verbs/reload.rb +2 -0
  23. data/lib/gloo/verbs/unload.rb +1 -0
  24. data/test.gloo/basic.test.gloo +53 -0
  25. data/test.gloo/lang/gloo_sys.test.gloo +91 -0
  26. data/test.gloo/lang/ops.test.gloo +79 -0
  27. data/test.gloo/math/add.test.gloo +46 -0
  28. data/test.gloo/math/div.test.gloo +37 -0
  29. data/test.gloo/math/mult.test.gloo +37 -0
  30. data/test.gloo/math/sub.test.gloo +37 -0
  31. data/test.gloo/objs/bool.test.gloo +60 -0
  32. data/test.gloo/objs/can.test.gloo +47 -0
  33. data/test.gloo/objs/int.test.gloo +56 -0
  34. data/test.gloo/objs/obj.test.gloo +52 -0
  35. data/test.gloo/objs/script.test.gloo +23 -0
  36. data/test.gloo/objs/text.test.gloo +84 -0
  37. data/test.gloo/objs/untyped.test.gloo +25 -0
  38. data/test.gloo/string/str.test.gloo +118 -0
  39. data/test.gloo/string/str_gen.test.gloo +76 -0
  40. data/test.gloo/verbs/break.test.gloo +22 -0
  41. data/test.gloo/verbs/check.test.gloo +35 -0
  42. data/test.gloo/verbs/eval.test.gloo +19 -0
  43. data/test.gloo/verbs/exists.test.gloo +49 -0
  44. data/test.gloo/verbs/if.test.gloo +16 -0
  45. data/test.gloo/verbs/log.test.gloo +14 -0
  46. data/test.gloo/verbs/move.test.gloo +20 -0
  47. data/test.gloo/verbs/put.test.gloo +19 -0
  48. data/test.gloo/verbs/run.test.gloo +16 -0
  49. data/test.gloo/verbs/tell.test.gloo +16 -0
  50. metadata +31 -3
  51. data/lib/gloo/objs/system/eval.rb +0 -107
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3997abc49fe622dedcf93aeadd68fe5e18414e3b48daec0e466fce8bcf1c418f
4
- data.tar.gz: c918a567e8a5a8a7f69791f41b36ff5fe3bca5d9c9f984f8be63a6c4f3bf79f0
3
+ metadata.gz: 4d8c482026223309622ed85dc80193049e31fae2e870a684ed06b3f2efd569db
4
+ data.tar.gz: 03c8934d55dd19011f4f5b2d8c83f94421cd0e6dcd38aae2ef1f5b805afac074
5
5
  SHA512:
6
- metadata.gz: ae3cad6a557a66d1150222709d9ef6f5a9d95082663e67e53e6e3dbe8a7c1ff65b724f1413a114375dcc02b748048cd75169713e9bfe4caf885a96793efb8015
7
- data.tar.gz: 7cd96ee3680c5a987eae9ab4f5e52575dd00deb95660ae37c5d2bf63d9950b99e8cf410c3b9b351cb7fef230eb6a026e7abd6d62cf6790f180940193f02bc5f2
6
+ metadata.gz: 6b871e91af4d2c1fdba956fc3a3cd2f8a0c260785b00aa3777aed042b6d1b6a7bfaab874e86dfd8201f7d72b2ea8ed43700a22630363a595c02382b4e28510b7
7
+ data.tar.gz: 7a421e84aec1e38174484a82125e257b237022be96f361d9abea009e0ed3e9d3b4b1ce60600055647a9851754391f5d4c91b18c1f25b987efaafd4db93a0e297
data/lib/VERSION CHANGED
@@ -1 +1 @@
1
- 5.1.0
1
+ 5.2.0
data/lib/VERSION_NOTES CHANGED
@@ -1,3 +1,18 @@
1
+ 5.2.0 - 2026.03.06
2
+ - Adds check to prevent loading lib or ext twice.
3
+ - Updates the load and reload to support loading and unloading tests.
4
+ - Removes ruby eval object (unused)
5
+ - Adds eval verb
6
+ - Adds directory iterator
7
+ - Adds support for single file load from common
8
+ - Extends exists? verb to check for instance of an object
9
+ - Fixes issue with boolean comparison
10
+ - Adds messages to string: count_lines count_words count_chars
11
+ - Text now also responds to string messages
12
+ - Updates string 'contains?' message to 'substring?' so it doesn't conflict with obj.contains?
13
+ - Adds responds_to? message to all objects
14
+
15
+
1
16
  5.1.0 - 2026.02.15
2
17
  - Fixes issue with int * dec
3
18
  - Some code cleanup
@@ -96,7 +111,6 @@ adds tag helper for apple touch icon
96
111
  - Adds starts_with?, ends_with?, contains?, and format_for_html messages to string
97
112
 
98
113
 
99
-
100
114
  3.8.0 - 2025.01.23
101
115
  - Fixes issue with sessions
102
116
  - Adds authenticity token tag and supporting session id and validation
data/lib/gloo/app/args.rb CHANGED
@@ -92,6 +92,13 @@ module Gloo
92
92
  @switches.include?( Gloo::App::Mode::EMBED.to_s )
93
93
  end
94
94
 
95
+ #
96
+ # Is the test switch set?
97
+ #
98
+ def test?
99
+ @switches.include?( Gloo::App::Mode::TEST.to_s )
100
+ end
101
+
95
102
  #
96
103
  # Detect the mode to be run in.
97
104
  # Start by seeing if a mode is specified.
@@ -111,6 +118,8 @@ module Gloo
111
118
  Mode::CLI
112
119
  elsif embed?
113
120
  Mode::EMBED
121
+ elsif test?
122
+ Mode::TEST
114
123
  elsif @files.count.positive?
115
124
  Mode::SCRIPT
116
125
  else
@@ -11,12 +11,18 @@ module Gloo
11
11
  module App
12
12
  class Engine
13
13
 
14
+ #
15
+ # Constants for the name of the test library.
16
+ # This is the short name as it would be used with the load verb.
17
+ #
18
+ TEST_LIB_NAME = 'test'
19
+
14
20
  attr_reader :settings, :log, :running_app
15
21
  attr_reader :args, :mode, :running, :platform,
16
22
  :dictionary, :parser, :heap, :factory,
17
23
  :ext_manager, :lib_manager
18
24
  attr_accessor :last_cmd, :persist_man, :event_manager,
19
- :exec_env, :converter
25
+ :exec_env, :converter, :context_object
20
26
 
21
27
  #
22
28
  # Set up the engine with basic elements.
@@ -61,6 +67,27 @@ module Gloo
61
67
  run_mode
62
68
  end
63
69
 
70
+ #
71
+ # Reset the engine state.
72
+ # Clear out anything that needs clearing or resetting
73
+ # to get the engine back to a clean state.
74
+ #
75
+ def reset_state
76
+ stop_running_app
77
+ @heap = Gloo::Core::Heap.new( self )
78
+ @persist_man = Gloo::Persist::PersistMan.new( self )
79
+ end
80
+
81
+ #
82
+ # Restart the engine with the same settings
83
+ # and the same mode (with files, etc).
84
+ #
85
+ def restart
86
+ @log.info 'Restarting the engine...'
87
+ reset_state
88
+ run_mode
89
+ end
90
+
64
91
 
65
92
  # ---------------------------------------------------------------------
66
93
  # Run
@@ -81,6 +108,8 @@ module Gloo
81
108
  elsif @mode == Mode::APP
82
109
  @settings.override_project_path @args.app_path
83
110
  run
111
+ elsif @mode == Mode::TEST
112
+ run_test
84
113
  else
85
114
  run
86
115
  end
@@ -102,6 +131,23 @@ module Gloo
102
131
  @args.files.each { |f| @persist_man.load( f ) }
103
132
  end
104
133
 
134
+ #
135
+ # Run in gloo unit test mode.
136
+ #
137
+ def run_test
138
+ @log.debug 'Running in Test mode…'
139
+
140
+ begin
141
+ @lib_manager.load_lib TEST_LIB_NAME
142
+ TestRunner.new( self, @args.files ).run
143
+ rescue => ex
144
+ log_exception ex
145
+ end
146
+
147
+ @log.debug 'Tests complete.'
148
+ quit
149
+ end
150
+
105
151
  #
106
152
  # Run in interactive mode.
107
153
  #
@@ -124,7 +170,7 @@ module Gloo
124
170
  # start the engine, but wait for external inputs.
125
171
  #
126
172
  def run_keep_alive
127
- @log.debug 'Running in Embedded mode...'
173
+ @log.debug 'Running in Embedded mode'
128
174
  end
129
175
 
130
176
  #
data/lib/gloo/app/mode.rb CHANGED
@@ -14,7 +14,7 @@ module Gloo
14
14
  SCRIPT = :script # Run a script
15
15
  VERSION = :version # Show version information
16
16
  HELP = :help # Show the help screen
17
- TEST = :test # Running in Unit Test mode.
17
+ TEST = :test # Running in Gloo Unit Test mode.
18
18
 
19
19
  #
20
20
  # Get the default mode.
data/lib/gloo/core/it.rb CHANGED
@@ -38,6 +38,20 @@ module Gloo
38
38
  return false
39
39
  end
40
40
 
41
+ #
42
+ # Is [it] true?
43
+ #
44
+ def is_true?
45
+ return @value == true
46
+ end
47
+
48
+ #
49
+ # Is [it] false?
50
+ #
51
+ def is_false?
52
+ return @value == false
53
+ end
54
+
41
55
  end
42
56
  end
43
57
  end
data/lib/gloo/core/obj.rb CHANGED
@@ -302,7 +302,7 @@ module Gloo
302
302
  # Get a list of message names that this object receives.
303
303
  #
304
304
  def self.messages
305
- return %w[reload unload blank? contains?]
305
+ return %w[reload unload blank? contains? responds_to?]
306
306
  end
307
307
 
308
308
  #
@@ -340,6 +340,8 @@ module Gloo
340
340
 
341
341
  #
342
342
  # Send the object the unload message.
343
+ # This will unload the object but the rest of the engine state will
344
+ # remain unchanged.
343
345
  #
344
346
  def msg_unload
345
347
  if self.root?
@@ -353,6 +355,8 @@ module Gloo
353
355
  #
354
356
  # Send the object the reload message.
355
357
  # Note that this will only work for objects with file assoications.
358
+ # This will reload the object but the rest of the engine state will
359
+ # remain unchanged.
356
360
  #
357
361
  def msg_reload
358
362
  if self.root?
@@ -381,6 +385,23 @@ module Gloo
381
385
  return has_children
382
386
  end
383
387
 
388
+ #
389
+ # Check to see if the object responds to a message.
390
+ #
391
+ def msg_responds_to?
392
+ if @params&.token_count&.positive?
393
+ expr = Gloo::Expr::Expression.new( @engine, @params.tokens )
394
+ data = expr.evaluate
395
+
396
+ result = self.can_receive_message?( data )
397
+ @engine.heap.it.set_to result
398
+ return result
399
+ else
400
+ @engine.heap.it.set_to false
401
+ return false
402
+ end
403
+ end
404
+
384
405
 
385
406
  # ---------------------------------------------------------------------
386
407
  # Render
@@ -13,6 +13,8 @@ module Gloo
13
13
  # the given name.
14
14
  # If the container isn't provided, root will be used.
15
15
  #
16
+ # This is a recursive function.
17
+ #
16
18
  def self.by_name( engine, name, container = nil )
17
19
  container = engine.heap.root if container.nil?
18
20
  arr = []
@@ -25,6 +27,25 @@ module Gloo
25
27
  return arr
26
28
  end
27
29
 
30
+ #
31
+ # Find all objects in the given container of a given type.
32
+ # If the container isn't provided, root will be used.
33
+ #
34
+ # This is a recursive function.
35
+ #
36
+ def self.by_type( engine, type, container = nil )
37
+ container = engine.heap.root if container.nil?
38
+ arr = []
39
+
40
+ container.children.each do |o|
41
+ # puts "#{o.class.typename} == #{type}"
42
+ arr << o if o.class.typename == type
43
+ arr += by_type( engine, type, o ) if o.child_count.positive?
44
+ end
45
+
46
+ return arr
47
+ end
48
+
28
49
  end
29
50
  end
30
51
  end
@@ -21,6 +21,11 @@ module Gloo
21
21
 
22
22
  return left == right.to_f if left.is_a? Numeric
23
23
 
24
+ # puts "left: #{left}, right: #{right}"
25
+ if Gloo::Objs::Boolean.boolean?( left ) && Gloo::Objs::Boolean.boolean?( right )
26
+ return left == right
27
+ end
28
+
24
29
  return false
25
30
  end
26
31
 
@@ -3,13 +3,14 @@
3
3
  #
4
4
  # A String.
5
5
  #
6
- require 'base64'
7
- require 'uri'
6
+ require_relative 'string_msgs'
8
7
 
9
8
  module Gloo
10
9
  module Objs
11
10
  class String < Gloo::Core::Obj
12
11
 
12
+ include StringMsgs
13
+
13
14
  KEYWORD = 'string'.freeze
14
15
  KEYWORD_SHORT = 'str'.freeze
15
16
  MISSING_PARAM_MSG = 'Missing parameter!'.freeze
@@ -43,236 +44,12 @@ module Gloo
43
44
  # Get a list of message names that this object receives.
44
45
  #
45
46
  def self.messages
46
- return super + %w[up down size starts_with? ends_with? contains?
47
+ return super + %w[up down size starts_with? ends_with? substring?
48
+ count_lines count_words count_chars
47
49
  format_for_html encode64 decode64 escape unescape
48
50
  gen_alphanumeric gen_uuid gen_hex gen_base64]
49
51
  end
50
52
 
51
- #
52
- # Convert whitespace to HTML friendly spaces.
53
- #
54
- def msg_format_for_html
55
- text = self.value
56
- out = ""
57
- return out unless text
58
-
59
- # indentation
60
- text.each_line do |line|
61
- i = 0
62
- while line[i] == ' '
63
- i += 1
64
- out << "&nbsp;"
65
- end
66
-
67
- i = 0
68
- while line[i] == "\t"
69
- i += 1
70
- out << "&nbsp;&nbsp;&nbsp;&nbsp;"
71
- end
72
- out << line
73
- end
74
-
75
- self.value = out.gsub( "\n", "<br/>" )
76
- end
77
-
78
- #
79
- # Does the string start with the given string?
80
- #
81
- def msg_starts_with?
82
- if @params&.token_count&.positive?
83
- expr = Gloo::Expr::Expression.new( @engine, @params.tokens )
84
- data = expr.evaluate
85
-
86
- result = self.value.start_with?( data )
87
- @engine.heap.it.set_to result
88
- return result
89
- else
90
- # Error
91
- @engine.log.error MISSING_PARAM_MSG
92
- @engine.heap.it.set_to false
93
- return false
94
- end
95
- end
96
-
97
- #
98
- # Does the string end with the given string?
99
- #
100
- def msg_ends_with?
101
- if @params&.token_count&.positive?
102
- expr = Gloo::Expr::Expression.new( @engine, @params.tokens )
103
- data = expr.evaluate
104
-
105
- result = value.end_with?( data )
106
- @engine.heap.it.set_to result
107
- return result
108
- else
109
- # Error
110
- @engine.log.error MISSING_PARAM_MSG
111
- @engine.heap.it.set_to false
112
- return false
113
- end
114
- end
115
-
116
- #
117
- # Does the string contain the given string?
118
- #
119
- def msg_contains?
120
- if @params&.token_count&.positive?
121
- expr = Gloo::Expr::Expression.new( @engine, @params.tokens )
122
- data = expr.evaluate
123
-
124
- result = value.include?( data )
125
- @engine.heap.it.set_to result
126
- return result
127
- else
128
- # Error
129
- @engine.log.error MISSING_PARAM_MSG
130
- @engine.heap.it.set_to false
131
- return false
132
- end
133
- end
134
-
135
- #
136
- # Get the size of the string.
137
- #
138
- def msg_size
139
- s = value.size
140
- @engine.heap.it.set_to s
141
- return s
142
- end
143
-
144
- #
145
- # Escape the string.
146
- # Make it URL safe.
147
- # The value of the string is changed.
148
- #
149
- def msg_escape
150
- s = URI::DEFAULT_PARSER.escape( value )
151
- set_value s
152
- @engine.heap.it.set_to s
153
- return s
154
- end
155
-
156
- #
157
- # Unescape the string.
158
- # The value of the string is changed.
159
- #
160
- def msg_unescape
161
- s = URI::DEFAULT_PARSER.unescape( value )
162
- set_value s
163
- @engine.heap.it.set_to s
164
- return s
165
- end
166
-
167
- #
168
- # Encode the string as base64.
169
- # Changes the value of the string.
170
- #
171
- def msg_encode64
172
- s = Base64.encode64( value )
173
- set_value s
174
- @engine.heap.it.set_to s
175
- return s
176
- end
177
-
178
- #
179
- # Decode the string from base64.
180
- # Changes the value of the string.
181
- #
182
- def msg_decode64
183
- s = Base64.decode64( value )
184
- set_value s
185
- @engine.heap.it.set_to s
186
- return s
187
- end
188
-
189
- #
190
- # Generate a new UUID in the string.
191
- #
192
- def msg_gen_uuid
193
- s = StringGenerator.uuid
194
- set_value s
195
- @engine.heap.it.set_to s
196
- return s
197
- end
198
-
199
- #
200
- # Generate a random alphanumeric string.
201
- # By default the length is 10 characters.
202
- # Set the length with an optional parameter.
203
- #
204
- def msg_gen_alphanumeric
205
- len = 10
206
- if @params&.token_count&.positive?
207
- expr = Gloo::Expr::Expression.new( @engine, @params.tokens )
208
- data = expr.evaluate
209
- len = data.to_i
210
- end
211
-
212
- s = StringGenerator.alphanumeric( len )
213
- set_value s
214
- @engine.heap.it.set_to s
215
- return s
216
- end
217
-
218
- #
219
- # Generate a random hex string.
220
- # By default the length is 10 hex characters.
221
- # Set the length with an optional parameter.
222
- #
223
- def msg_gen_hex
224
- len = 10
225
- if @params&.token_count&.positive?
226
- expr = Gloo::Expr::Expression.new( @engine, @params.tokens )
227
- data = expr.evaluate
228
- len = data.to_i
229
- end
230
-
231
- s = StringGenerator.hex( len )
232
- set_value s
233
- @engine.heap.it.set_to s
234
- return s
235
- end
236
-
237
- #
238
- # Generate a random base64 string.
239
- # By default the length is 12 characters.
240
- # Set the length with an optional parameter.
241
- #
242
- def msg_gen_base64
243
- len = 12
244
- if @params&.token_count&.positive?
245
- expr = Gloo::Expr::Expression.new( @engine, @params.tokens )
246
- data = expr.evaluate
247
- len = data.to_i
248
- end
249
-
250
- s = StringGenerator.base64( len )
251
- set_value s
252
- @engine.heap.it.set_to s
253
- return s
254
- end
255
-
256
- #
257
- # Convert string to upper case
258
- #
259
- def msg_up
260
- s = value.upcase
261
- set_value s
262
- @engine.heap.it.set_to s
263
- return s
264
- end
265
-
266
- #
267
- # Convert string to lower case
268
- #
269
- def msg_down
270
- s = value.downcase
271
- set_value s
272
- @engine.heap.it.set_to s
273
- return s
274
- end
275
-
276
53
  end
277
54
  end
278
55
  end