gloo 1.4.2 → 2.0.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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/.gitignore +1 -0
  4. data/gloo.gemspec +0 -2
  5. data/lib/VERSION +1 -1
  6. data/lib/dependencies.rb +4 -4
  7. data/lib/gloo/app/args.rb +112 -0
  8. data/lib/gloo/app/engine.rb +247 -0
  9. data/lib/gloo/app/engine_context.rb +25 -0
  10. data/lib/gloo/app/info.rb +20 -3
  11. data/lib/gloo/app/log.rb +73 -1
  12. data/lib/gloo/app/mode.rb +27 -0
  13. data/lib/gloo/app/platform.rb +8 -1
  14. data/lib/gloo/app/settings.rb +202 -0
  15. data/lib/gloo/convert/converter.rb +42 -0
  16. data/lib/gloo/convert/string_to_date.rb +21 -0
  17. data/lib/gloo/convert/string_to_datetime.rb +21 -0
  18. data/lib/gloo/convert/string_to_decimal.rb +20 -0
  19. data/lib/gloo/convert/string_to_integer.rb +20 -0
  20. data/lib/gloo/convert/string_to_time.rb +21 -0
  21. data/lib/gloo/core/baseo.rb +31 -0
  22. data/lib/gloo/core/dictionary.rb +245 -0
  23. data/lib/gloo/core/error.rb +61 -0
  24. data/lib/gloo/core/event_manager.rb +45 -0
  25. data/lib/gloo/core/factory.rb +211 -0
  26. data/lib/gloo/core/gloo_system.rb +267 -0
  27. data/lib/gloo/core/heap.rb +53 -0
  28. data/lib/gloo/core/here.rb +36 -0
  29. data/lib/gloo/core/it.rb +36 -0
  30. data/lib/gloo/core/literal.rb +30 -0
  31. data/lib/gloo/core/obj.rb +318 -0
  32. data/lib/gloo/core/obj_finder.rb +30 -0
  33. data/lib/gloo/core/op.rb +40 -0
  34. data/lib/gloo/core/parser.rb +60 -0
  35. data/lib/gloo/core/pn.rb +212 -0
  36. data/lib/gloo/core/tokens.rb +165 -0
  37. data/lib/gloo/core/verb.rb +87 -0
  38. data/lib/gloo/exec/action.rb +48 -0
  39. data/lib/gloo/exec/dispatch.rb +40 -0
  40. data/lib/gloo/exec/exec_env.rb +75 -0
  41. data/lib/gloo/exec/runner.rb +45 -0
  42. data/lib/gloo/exec/script.rb +50 -0
  43. data/lib/gloo/exec/stack.rb +79 -0
  44. data/lib/gloo/expr/expression.rb +119 -0
  45. data/lib/gloo/expr/l_boolean.rb +36 -0
  46. data/lib/gloo/expr/l_decimal.rb +39 -0
  47. data/lib/gloo/expr/l_integer.rb +37 -0
  48. data/lib/gloo/expr/l_string.rb +58 -0
  49. data/lib/gloo/expr/op_div.rb +22 -0
  50. data/lib/gloo/expr/op_minus.rb +22 -0
  51. data/lib/gloo/expr/op_mult.rb +22 -0
  52. data/lib/gloo/expr/op_plus.rb +24 -0
  53. data/lib/gloo/objs/basic/alias.rb +78 -0
  54. data/lib/gloo/objs/basic/boolean.rb +120 -0
  55. data/lib/gloo/objs/basic/container.rb +65 -0
  56. data/lib/gloo/objs/basic/decimal.rb +76 -0
  57. data/lib/gloo/objs/basic/integer.rb +73 -0
  58. data/lib/gloo/objs/basic/script.rb +99 -0
  59. data/lib/gloo/objs/basic/string.rb +77 -0
  60. data/lib/gloo/objs/basic/text.rb +79 -0
  61. data/lib/gloo/objs/basic/untyped.rb +41 -0
  62. data/lib/gloo/objs/cli/banner.rb +1 -1
  63. data/lib/gloo/objs/cli/bar.rb +3 -3
  64. data/lib/gloo/objs/cli/colorize.rb +1 -1
  65. data/lib/gloo/objs/cli/confirm.rb +1 -1
  66. data/lib/gloo/objs/cli/menu.rb +6 -6
  67. data/lib/gloo/objs/cli/menu_item.rb +1 -1
  68. data/lib/gloo/objs/cli/pastel.rb +1 -1
  69. data/lib/gloo/objs/cli/prompt.rb +1 -1
  70. data/lib/gloo/objs/cli/select.rb +2 -2
  71. data/lib/gloo/objs/ctrl/each.rb +279 -0
  72. data/lib/gloo/objs/ctrl/repeat.rb +108 -0
  73. data/lib/gloo/objs/data/markdown.rb +79 -0
  74. data/lib/gloo/objs/data/mysql.rb +5 -5
  75. data/lib/gloo/objs/data/query.rb +4 -4
  76. data/lib/gloo/objs/data/sqlite.rb +1 -1
  77. data/lib/gloo/objs/data/table.rb +112 -0
  78. data/lib/gloo/objs/dev/git.rb +2 -2
  79. data/lib/gloo/objs/dev/stats.rb +4 -4
  80. data/lib/gloo/objs/dt/date.rb +65 -0
  81. data/lib/gloo/objs/dt/datetime.rb +120 -0
  82. data/lib/gloo/objs/dt/dt_tools.rb +100 -0
  83. data/lib/gloo/objs/dt/time.rb +65 -0
  84. data/lib/gloo/objs/ror/erb.rb +116 -0
  85. data/lib/gloo/objs/ror/eval.rb +107 -0
  86. data/lib/gloo/objs/snd/play.rb +1 -1
  87. data/lib/gloo/objs/snd/say.rb +1 -1
  88. data/lib/gloo/objs/system/file_handle.rb +4 -4
  89. data/lib/gloo/objs/system/ssh_exec.rb +1 -1
  90. data/lib/gloo/objs/system/system.rb +1 -1
  91. data/lib/gloo/objs/web/http_get.rb +159 -0
  92. data/lib/gloo/objs/web/http_post.rb +183 -0
  93. data/lib/gloo/objs/web/json.rb +135 -0
  94. data/lib/gloo/objs/web/slack.rb +130 -0
  95. data/lib/gloo/objs/web/teams.rb +117 -0
  96. data/lib/gloo/objs/web/uri.rb +148 -0
  97. data/lib/gloo/persist/disc_mech.rb +87 -0
  98. data/lib/gloo/persist/file_loader.rb +193 -0
  99. data/lib/gloo/persist/file_saver.rb +51 -0
  100. data/lib/gloo/persist/file_storage.rb +46 -0
  101. data/lib/gloo/persist/line_splitter.rb +81 -0
  102. data/lib/gloo/persist/persist_man.rb +153 -0
  103. data/lib/gloo/utils/format.rb +21 -0
  104. data/lib/gloo/utils/stats.rb +206 -0
  105. data/lib/gloo/utils/words.rb +19 -0
  106. data/lib/gloo/verbs/alert.rb +2 -2
  107. data/lib/gloo/verbs/beep.rb +1 -1
  108. data/lib/gloo/verbs/cls.rb +1 -1
  109. data/lib/gloo/verbs/context.rb +62 -0
  110. data/lib/gloo/verbs/create.rb +68 -0
  111. data/lib/gloo/verbs/execute.rb +56 -0
  112. data/lib/gloo/verbs/files.rb +49 -0
  113. data/lib/gloo/verbs/help.rb +1 -1
  114. data/lib/gloo/verbs/if.rb +92 -0
  115. data/lib/gloo/verbs/list.rb +98 -0
  116. data/lib/gloo/verbs/load.rb +45 -0
  117. data/lib/gloo/verbs/move.rb +89 -0
  118. data/lib/gloo/verbs/put.rb +94 -0
  119. data/lib/gloo/verbs/quit.rb +40 -0
  120. data/lib/gloo/verbs/reload.rb +43 -0
  121. data/lib/gloo/verbs/run.rb +75 -0
  122. data/lib/gloo/verbs/save.rb +39 -0
  123. data/lib/gloo/verbs/show.rb +63 -0
  124. data/lib/gloo/verbs/tell.rb +80 -0
  125. data/lib/gloo/verbs/unless.rb +92 -0
  126. data/lib/gloo/verbs/unload.rb +46 -0
  127. data/lib/gloo/verbs/version.rb +3 -3
  128. data/lib/gloo/verbs/wait.rb +42 -0
  129. data/lib/gloo.rb +2 -2
  130. data/lib/run.rb +2 -2
  131. metadata +97 -22
@@ -0,0 +1,165 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2019 Eric Crane. All rights reserved.
3
+ #
4
+ # An ordered list of tokens.
5
+ # The list of tokens makes up a command.
6
+ #
7
+
8
+ module Gloo
9
+ module Core
10
+ class Tokens
11
+
12
+ attr_reader :cmd, :tokens
13
+
14
+ # ---------------------------------------------------------------------
15
+ # Constructor
16
+ # ---------------------------------------------------------------------
17
+
18
+ #
19
+ # Set up the tokens.
20
+ # The command string is parsed into tokens during creation.
21
+ #
22
+ def initialize( cmd_string )
23
+ @cmd = cmd_string
24
+ @tokens = []
25
+ tokenize @cmd
26
+ end
27
+
28
+ # ---------------------------------------------------------------------
29
+ # Public functions
30
+ # ---------------------------------------------------------------------
31
+
32
+ #
33
+ # Get the number of tokens
34
+ #
35
+ def token_count
36
+ return @tokens.size
37
+ end
38
+
39
+ #
40
+ # Get the verb (the first word)
41
+ #
42
+ def verb
43
+ return first
44
+ end
45
+
46
+ #
47
+ # Get all tokens except the first.
48
+ #
49
+ def params
50
+ return @tokens[ 1..-1 ]
51
+ end
52
+
53
+ #
54
+ # Get the first token.
55
+ #
56
+ def first
57
+ return @tokens.first if @tokens
58
+ end
59
+
60
+ #
61
+ # Get the last token.
62
+ #
63
+ def last
64
+ return @tokens.last if @tokens
65
+ end
66
+
67
+ #
68
+ # Get the second token.
69
+ #
70
+ def second
71
+ return @tokens[ 1 ] if @tokens&.size&.positive?
72
+ end
73
+
74
+ #
75
+ # Get the token at the the requested index.
76
+ #
77
+ def at( index )
78
+ return @tokens[ index ] if @tokens && @tokens.size >= index
79
+ end
80
+
81
+ #
82
+ # Get the index of the given token.
83
+ #
84
+ def index_of( token )
85
+ return nil unless @tokens
86
+
87
+ return @tokens.find_index { |o| o.casecmp( token ).zero? }
88
+ end
89
+
90
+ #
91
+ # Get the list of tokens after the given token
92
+ #
93
+ def tokens_after( token )
94
+ i = index_of token
95
+ return @tokens[ i + 1..-1 ] if i && @tokens && @tokens.size > ( i + 1 )
96
+
97
+ return nil
98
+ end
99
+
100
+ #
101
+ # Get the expression after the given token
102
+ #
103
+ def expr_after( token )
104
+ str = ''
105
+ tokens_after( token ).each do |t|
106
+ str << ' ' unless str.empty?
107
+ str << t.to_s
108
+ end
109
+ return str
110
+ end
111
+
112
+ #
113
+ # Get the item after a given token.
114
+ #
115
+ def after_token( token )
116
+ i = index_of token
117
+ return @tokens[ i + 1 ] if i && @tokens && @tokens.size > ( i + 1 )
118
+
119
+ return nil
120
+ end
121
+
122
+ #
123
+ # Get the item after a given token.
124
+ #
125
+ def before_token( token )
126
+ i = index_of token
127
+ return @tokens[ 0..i - 1 ] if i && @tokens && @tokens.size >= i
128
+
129
+ return nil
130
+ end
131
+
132
+ # ---------------------------------------------------------------------
133
+ # Private functions
134
+ # ---------------------------------------------------------------------
135
+
136
+ private
137
+
138
+ #
139
+ # Create a list of token from the given string.
140
+ #
141
+ def tokenize( str )
142
+ if str.index( '"' )
143
+ i = str.index( '"' )
144
+ j = str.index( '"', i + 1 )
145
+ j ||= str.length
146
+
147
+ tokenize( str[ 0..i - 1 ] ) if i > 1
148
+ @tokens << str[ i..j ]
149
+ tokenize( str[ j + 1..-1 ] ) if j + 1 < str.length
150
+ elsif str.index( "'" )
151
+ i = str.index( "'" )
152
+ j = str.index( "'", i + 1 )
153
+ j ||= str.length
154
+
155
+ tokenize( str[ 0..i - 1 ] ) if i > 1
156
+ @tokens << str[ i..j ]
157
+ tokenize( str[ j + 1..-1 ] ) if j + 1 < str.length
158
+ else
159
+ str.strip.split( ' ' ).each { |t| @tokens << t }
160
+ end
161
+ end
162
+
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,87 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2019 Eric Crane. All rights reserved.
3
+ #
4
+ # An abstract base verb.
5
+ # Derives from the Baseo object.
6
+ # It is a special type of object in that it can be run
7
+ # and can perform an action.
8
+ #
9
+
10
+ module Gloo
11
+ module Core
12
+ class Verb < Baseo
13
+
14
+ attr_reader :tokens, :params
15
+
16
+ #
17
+ # Set up the verb.
18
+ #
19
+ def initialize( engine, tokens, params = [] )
20
+ @engine = engine
21
+ @tokens = tokens
22
+ @params = params
23
+ end
24
+
25
+ #
26
+ # Register verbs when they are loaded.
27
+ #
28
+ def self.inherited( subclass )
29
+ Dictionary.instance.register_verb( subclass )
30
+ end
31
+
32
+ #
33
+ # Run the verb.
34
+ #
35
+ # We'll mark the application as not running and let the
36
+ # engine stop gracefully next time through the loop.
37
+ #
38
+ def run
39
+ raise 'this method should be overriden'
40
+ end
41
+
42
+ #
43
+ # Get the Verb's keyword.
44
+ #
45
+ # The keyword will be in lower case only.
46
+ # It is used by the parser.
47
+ #
48
+ def self.keyword
49
+ raise 'this method should be overriden'
50
+ end
51
+
52
+ #
53
+ # Get the Verb's keyword shortcut.
54
+ #
55
+ def self.keyword_shortcut
56
+ raise 'this method should be overriden'
57
+ end
58
+
59
+ #
60
+ # The object type, suitable for display.
61
+ #
62
+ def type_display
63
+ return self.class.keyword
64
+ end
65
+
66
+ #
67
+ # Generic function to get display value.
68
+ # Can be used for debugging, etc.
69
+ #
70
+ def display_value
71
+ return self.class.keyword
72
+ end
73
+
74
+ # ---------------------------------------------------------------------
75
+ # Help
76
+ # ---------------------------------------------------------------------
77
+
78
+ #
79
+ # Get help for this verb.
80
+ #
81
+ def self.help
82
+ return 'No help found.'
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,48 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # An action is a message sent to an object with optional parameters.
5
+ #
6
+
7
+ module Gloo
8
+ module Exec
9
+ class Action
10
+
11
+ attr_accessor :msg, :to, :params
12
+
13
+ #
14
+ # Set up the action.
15
+ #
16
+ def initialize( msg, to, params = nil )
17
+ @msg = msg
18
+ @to = to
19
+ @params = params
20
+ end
21
+
22
+ #
23
+ # The action is valid if the object can receive
24
+ # the message specified.
25
+ #
26
+ def valid?
27
+ return @to.can_receive_message?( @msg )
28
+ end
29
+
30
+ #
31
+ # Execute the action.
32
+ # Dispatch the message to the object.
33
+ #
34
+ def dispatch
35
+ @to.send_message @msg, @params
36
+ end
37
+
38
+ #
39
+ # Generic function to get display value.
40
+ # Can be used for debugging, etc.
41
+ #
42
+ def display_value
43
+ return "#{@msg} -> #{@to.pn}"
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,40 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # Central Message Dispatch.
5
+ # Responsible for sending message to objects.
6
+ # All object messaging goes through here so we can uniformly
7
+ # manage things like checking to make sure object can
8
+ # receive the messages sent, handling errors, etc.
9
+ #
10
+
11
+ module Gloo
12
+ module Exec
13
+ class Dispatch
14
+
15
+ #
16
+ # Dispatch the given message to the given object.
17
+ #
18
+ def self.message( engine, msg, to_obj, params = nil )
19
+ engine.log.debug "Dispatch message #{msg} to #{to_obj.name}"
20
+ a = Gloo::Exec::Action.new msg, to_obj, params
21
+ Gloo::Exec::Dispatch.action( engine, a )
22
+ end
23
+
24
+ #
25
+ # Dispatch an action.
26
+ #
27
+ def self.action( engine, action )
28
+ unless action.valid?
29
+ engine.log.warn "Object #{action.to.name} does not respond to #{action.msg}"
30
+ end
31
+
32
+ engine.exec_env.push_action action
33
+ engine.log.debug "Sending message #{action.msg} to #{action.to.name}"
34
+ action.dispatch
35
+ engine.exec_env.pop_action
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,75 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # The execution environment.
5
+ # The current state of running scripts and messaging.
6
+ #
7
+
8
+ module Gloo
9
+ module Exec
10
+ class ExecEnv
11
+
12
+ attr_accessor :verbs, :actions, :scripts, :here
13
+
14
+ VERB_STACK = 'verbs'.freeze
15
+ ACTION_STACK = 'actions'.freeze
16
+ SCRIPT_STACK = 'scripts'.freeze
17
+ HERE_STACK = 'here'.freeze
18
+
19
+ #
20
+ # Set up the execution environment.
21
+ #
22
+ def initialize( engine )
23
+ @engine = engine
24
+ @engine.log.debug 'exec env intialized...'
25
+
26
+ @verbs = Gloo::Exec::Stack.new( @engine, VERB_STACK )
27
+ @actions = Gloo::Exec::Stack.new( @engine, ACTION_STACK )
28
+ @scripts = Gloo::Exec::Stack.new( @engine, SCRIPT_STACK )
29
+ @here = Gloo::Exec::Stack.new( @engine, HERE_STACK )
30
+ end
31
+
32
+ #
33
+ # Get the here object.
34
+ #
35
+ def here_obj
36
+ return nil if @here.stack.empty?
37
+
38
+ return @here.stack.last
39
+ end
40
+
41
+ #
42
+ # Push a script onto the stack.
43
+ #
44
+ def push_script( script )
45
+ @scripts.push script
46
+ @here.push script.obj
47
+ end
48
+
49
+ #
50
+ # Pop a script off the stack.
51
+ #
52
+ def pop_script
53
+ @scripts.pop
54
+ @here.pop
55
+ end
56
+
57
+ #
58
+ # Push an action onto the stack.
59
+ #
60
+ def push_action( action )
61
+ @actions.push action
62
+ # @here.push action.to
63
+ end
64
+
65
+ #
66
+ # Pop an action off the stack.
67
+ #
68
+ def pop_action
69
+ @actions.pop
70
+ # @here.pop
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,45 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # The Runner is a static helper function.
5
+ # It is used to send the run command to verbs.
6
+ #
7
+
8
+ module Gloo
9
+ module Exec
10
+ class Runner
11
+
12
+ #
13
+ # Dispatch run command to a verb.
14
+ # We abstract this out in case there are things
15
+ # that need to be done before or after a verb
16
+ # is done running.
17
+ #
18
+ def self.go( engine, verb )
19
+ engine.log.debug "running verb #{verb.type_display}"
20
+ engine.heap.error.start_tracking
21
+ engine.exec_env.verbs.push verb
22
+ verb&.run
23
+ engine.exec_env.verbs.pop
24
+ engine.heap.error.clear_if_no_errors
25
+ end
26
+
27
+ #
28
+ # Send 'run' message to the object.
29
+ # Resolve the path_name and then send the run message.
30
+ #
31
+ def self.run( engine, path_name )
32
+ engine.log.debug "running script at #{path_name}"
33
+ pn = Gloo::Core::Pn.new( engine, path_name )
34
+ o = pn.resolve
35
+
36
+ if o
37
+ o.send_message 'run'
38
+ else
39
+ engine.log.error "Could not send message to object. Bad path: #{path_name}"
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,50 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2019 Eric Crane. All rights reserved.
3
+ #
4
+ # A script to be run.
5
+ #
6
+
7
+ module Gloo
8
+ module Exec
9
+ class Script
10
+
11
+ attr_accessor :obj
12
+
13
+ #
14
+ # Set up the script.
15
+ #
16
+ def initialize( engine, obj )
17
+ @engine = engine
18
+ @obj = obj
19
+ end
20
+
21
+ #
22
+ # Run the script.
23
+ # The script might be a single string or an array
24
+ # of lines.
25
+ #
26
+ def run
27
+ @engine.exec_env.push_script self
28
+
29
+ if @obj.value.is_a? String
30
+ @engine.parser.run @obj.value
31
+ elsif @obj.value.is_a? Array
32
+ @obj.value.each do |line|
33
+ @engine.parser.run line
34
+ end
35
+ end
36
+
37
+ @engine.exec_env.pop_script
38
+ end
39
+
40
+ #
41
+ # Generic function to get display value.
42
+ # Can be used for debugging, etc.
43
+ #
44
+ def display_value
45
+ return @obj.pn
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,79 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # A stack of items, a call stack.
5
+ #
6
+
7
+ module Gloo
8
+ module Exec
9
+ class Stack
10
+
11
+ attr_accessor :stack
12
+
13
+ #
14
+ # Set up the stack.
15
+ #
16
+ def initialize( engine, name )
17
+ @engine = engine
18
+ @name = name
19
+ clear_stack
20
+ @engine.log.debug "#{name} stack intialized..."
21
+ end
22
+
23
+ #
24
+ # Push an item onto the stack.
25
+ #
26
+ def push( obj )
27
+ @engine.log.debug "#{@name}:push #{obj.display_value}"
28
+ @stack.push obj
29
+ self.update_out_file if @engine.settings.debug
30
+ end
31
+
32
+ #
33
+ # Pop an item from the stack.
34
+ #
35
+ def pop
36
+ o = @stack.pop
37
+ @engine.log.debug "#{@name}:pop #{o.display_value}"
38
+ self.update_out_file if @engine.settings.debug
39
+ end
40
+
41
+ #
42
+ # Get the current size of the call stack.
43
+ #
44
+ def size
45
+ return @stack.size
46
+ end
47
+
48
+ #
49
+ # Get stack data for output.
50
+ #
51
+ def out_data
52
+ return @stack.map( &:display_value ).join( "\n" )
53
+ end
54
+
55
+ #
56
+ # Get the file we'll write debug information for the stack.
57
+ #
58
+ def out_file
59
+ return File.join( @engine.settings.debug_path, @name )
60
+ end
61
+
62
+ #
63
+ # Update the stack trace file.
64
+ #
65
+ def update_out_file
66
+ File.write( self.out_file, self.out_data )
67
+ end
68
+
69
+ #
70
+ # Clear the stack and the output file.
71
+ #
72
+ def clear_stack
73
+ @stack = []
74
+ self.update_out_file
75
+ end
76
+
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,119 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2019 Eric Crane. All rights reserved.
3
+ #
4
+ # An Expression that can be evaluated.
5
+ #
6
+
7
+ module Gloo
8
+ module Expr
9
+ class Expression
10
+
11
+ # ---------------------------------------------------------------------
12
+ # Constructor
13
+ # ---------------------------------------------------------------------
14
+
15
+ #
16
+ # Create the expression from a list of tokens.
17
+ #
18
+ def initialize( engine, tokens )
19
+ @engine = engine
20
+ @tokens = tokens
21
+ @symbols = []
22
+ @left = nil
23
+ @right = nil
24
+ @op = nil
25
+ end
26
+
27
+ # ---------------------------------------------------------------------
28
+ # Evaluate Expression
29
+ # ---------------------------------------------------------------------
30
+
31
+ #
32
+ # Evaluate the expression and return the value.
33
+ #
34
+ def evaluate
35
+ identify_tokens
36
+
37
+ @symbols.each do |sym|
38
+ if sym.is_a? Gloo::Core::Op
39
+ @op = sym
40
+ elsif @left.nil?
41
+ @left = sym
42
+ else
43
+ @right = sym
44
+ end
45
+
46
+ perform_op if @left && @right
47
+ end
48
+
49
+ return @left.value if @left.is_a? Gloo::Core::Literal
50
+ return resolve_ref @left if @left.is_a? Gloo::Core::Pn
51
+
52
+ return @left
53
+ end
54
+
55
+ # ---------------------------------------------------------------------
56
+ # Private functions
57
+ # ---------------------------------------------------------------------
58
+
59
+ private
60
+
61
+ #
62
+ # Perform the operation.
63
+ #
64
+ def perform_op
65
+ @op ||= Gloo::Core::Op.default_op
66
+ l = evaluate_sym @left
67
+ r = evaluate_sym @right
68
+ @left = @op.perform l, r
69
+ @right = nil
70
+ @op = nil
71
+ end
72
+
73
+ #
74
+ # Evaluate the symbol and get a simple value.
75
+ #
76
+ def evaluate_sym( sym )
77
+ return sym.value if sym.is_a? Gloo::Core::Literal
78
+ return resolve_ref sym if sym.is_a? Gloo::Core::Pn
79
+
80
+ return sym
81
+ end
82
+
83
+ #
84
+ # resolve an object reference and get the value.
85
+ #
86
+ def resolve_ref( ref )
87
+ return ref.src if ref.named_color?
88
+
89
+ ob = ref.resolve
90
+ return ob.value if ob
91
+ end
92
+
93
+ #
94
+ # Identify each token in the list.
95
+ #
96
+ def identify_tokens
97
+ @tokens.each do |o|
98
+ @symbols << identify_token( o )
99
+ end
100
+ end
101
+
102
+ #
103
+ # Identify the tokens and create appropriate symbols.
104
+ #
105
+ def identify_token( token )
106
+ return Gloo::Core::Op.create_op( token ) if Gloo::Core::Op.op?( token )
107
+
108
+ return LBoolean.new( token ) if LBoolean.boolean?( token )
109
+ return LInteger.new( token ) if LInteger.integer?( token )
110
+ return LString.new( token ) if LString.string?( token )
111
+ return LDecimal.new( token ) if LDecimal.decimal?( token )
112
+
113
+ # last chance: an Object reference
114
+ return Gloo::Core::Pn.new( @engine, token )
115
+ end
116
+
117
+ end
118
+ end
119
+ end