statsailr 0.7.2 → 0.7.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 428f469213d12c0613eb7eeab1690cad296ac94cff448bea96f140b55f2d8a24
4
- data.tar.gz: 684382167f17c762e22c752ac3303ec6a5666cbf83f02ef672f515167e43d2b6
3
+ metadata.gz: 3404e4a53509861318d70a8309cf54fb82326f98d3715893ac3a1fe447eb94f5
4
+ data.tar.gz: cd48566b46c5ea5bdfd9fb38beb2381095f857b58ad1d0cbf2998ad5de4dded9
5
5
  SHA512:
6
- metadata.gz: 64352807559d052da5415f75f0917f629146cf5b9671bdce7b294720795404b954f16569930d5ad6d68c40465a46efc2ab2a2d9e4d5d9f18b2673926d98045e5
7
- data.tar.gz: 4bf58f63503187e3e8a33aae1485ef226123c03e8741593c2f6cf434e90d24b055d119b921edf8ccc69f43e5d93398ec46fcb6067eb2f1be4c9cd9f4c192361f
6
+ metadata.gz: f4ec746898a33f909803d6dbc4fc284818e3a65ba89c1e93199b0582c061e85ca6be472f77abdde9b9c9937bb43315e3ac8e9f4caa8e9d947b062c7c098c048d
7
+ data.tar.gz: ba926958960340cbd9ad2e278ef78841509ca2db771a1cab93def58b6b8eb305e7b40b29adb8410d8d48662c2e3568868183f739f89ce02937928f0f7d9a6010
data/README.md CHANGED
@@ -254,7 +254,7 @@ END
254
254
  + How main argument part is parsed varies on each instruction. This is defined in main_arg_and_how_to_treat variable in setting.
255
255
  + opt_args
256
256
  + Optional arguments. Values specified in opt_args are also passed to R function's argument.
257
- + opt_args part consists of (a) key-value(s) or key(s).
257
+ + opt_args part consists of (a) key-value(s).
258
258
  + Internally, this argument parsing is conducted by methods in STSBlockParseProcOpts.
259
259
 
260
260
 
@@ -1,8 +1,82 @@
1
1
  require "r_bridge"
2
2
  require_relative "./sts_block_parse_proc_opts.rb"
3
3
 
4
+ module QuotedStringSupport
5
+ def interpret_escape_sequences(str)
6
+ # This deals with escape sequences in double quoted string literals
7
+ # The behavior should be same as libsailr (or datasailr)
8
+ new_str = ""
9
+ str_array = str.split(//)
10
+ idx = 0
11
+ while( idx < str_array.size) do
12
+ c = str_array[idx]
13
+ if(c == "\\")
14
+ idx = idx + 1
15
+ c = str_array[idx]
16
+ raise "Tokenizer error: double quoted string literal should never end with \\" if idx >= str_array.size
17
+ case c
18
+ when 't'
19
+ new_str << "\t"
20
+ when 'n'
21
+ new_str << "\n"
22
+ when 'r'
23
+ new_str << "\r"
24
+ when "\\"
25
+ new_str << "\\"
26
+ when "\'"
27
+ new_str << "\'"
28
+ when "\""
29
+ new_str << "\""
30
+ when '?'
31
+ new_str << '?'
32
+ else
33
+ new_str << c
34
+ end
35
+ else
36
+ new_str << c
37
+ end
38
+ idx = idx + 1
39
+ end
40
+ return new_str
41
+ end
42
+
43
+ def escape_backslashes(str)
44
+ str.gsub("\\", "\\\\")
45
+ end
46
+ end
47
+
4
48
  module BlockSupport
5
- def type_adjust(obj , type)
49
+ include QuotedStringSupport
50
+ class QuotedStringR
51
+ include QuotedStringSupport
52
+ def initialize(str, quote_type)
53
+ raise ":dq or :sq should be specified for quote_type" unless [:dq, :sq].include? quote_type
54
+ @ori_str = str
55
+ @quote_type = quote_type
56
+ end
57
+
58
+ def to_s
59
+ to_s_for_r_bridge
60
+ end
61
+
62
+ def to_s_for_r_bridge
63
+ if @quote_type == :dq
64
+ interpret_escape_sequences( @ori_str )
65
+ elsif
66
+ @ori_str
67
+ end
68
+ end
69
+
70
+ def to_s_for_r_parsing
71
+ if @quote_type == :dq
72
+ %q{"} + @ori_str + %q{"}
73
+ elsif @quote_type == :sq
74
+ %q{'} + escape_backslashes( @ori_str ) + %q{'}
75
+ end
76
+ end
77
+ end
78
+
79
+ def type_adjust(obj , type , *opts)
6
80
  case type
7
81
  when :ident
8
82
  if obj.is_a?(String)
@@ -22,6 +96,28 @@ module BlockSupport
22
96
  else
23
97
  raise "GramNode with inconsistent type(#{type.to_s}) and object(#{obj.class})"
24
98
  end
99
+ when :sq_string
100
+ if obj.is_a?(String)
101
+ unless opts.include?( :retain_input_string )
102
+ # default behavior
103
+ result = obj
104
+ else
105
+ result = QuotedStringR.new( obj, :sq )
106
+ end
107
+ else
108
+ raise "GramNode with inconsistent type(#{type.to_s}) and object(#{obj.class})"
109
+ end
110
+ when :dq_string
111
+ if obj.is_a?(String)
112
+ unless opts.include?( :retain_input_string )
113
+ # default behavior
114
+ result = interpret_escape_sequences( obj )
115
+ else
116
+ result = QuotedStringR.new( obj, :dq )
117
+ end
118
+ else
119
+ raise "GramNode with inconsistent type(#{type.to_s}) and object(#{obj.class})"
120
+ end
25
121
  when :sign
26
122
  if obj.is_a?(String)
27
123
  result = RBridge::SignR.new(obj)
@@ -137,10 +233,16 @@ class ProcBlock
137
233
  idx = 0
138
234
  while idx < proc_stmt_arg_ori.size() do
139
235
  elem = proc_stmt_arg_ori[idx]
140
- if( elem.type == :sign && elem.e1 == "/" )
141
- break
236
+ next_elem = proc_stmt_arg_ori[idx + 1]
237
+ next_next_elem = proc_stmt_arg_ori[idx + 2]
238
+ if(elem.type == :sign && elem.e1 == "/" ) then
239
+ if( ! next_elem.nil? && next_elem.type == :ident && # After /, optional arguments start
240
+ ! next_next_elem.nil? && next_next_elem.type == :sign && next_next_elem.e1 == "=") ||
241
+ next_elem.nil? then # After /, there is nothing
242
+ break
243
+ end
142
244
  else
143
- x = type_adjust( elem.e1, elem.type )
245
+ x = type_adjust( elem.e1, elem.type, :retain_input_string )
144
246
  proc_stmt_arg << x
145
247
  idx = idx + 1
146
248
  end
@@ -50,7 +50,6 @@ class STSBlockParseProcOpts
50
50
  # arg_opt : IDENT = primary
51
51
  # | IDENT = array
52
52
  # | IDENT = func
53
- # | IDENT
54
53
  #
55
54
  # parimary : STRING
56
55
  # | NUM
@@ -87,15 +86,15 @@ class STSBlockParseProcOpts
87
86
  else
88
87
  opt_value = ident() # According to BNF, this should be parimary(). However, ident() is more direct and makes sense here.
89
88
  end
90
- elsif [:string, :num].include? peek.type
89
+ elsif [:dq_string, :sq_string, :num].include? peek.type
91
90
  next_token()
92
91
  opt_value = primary()
93
92
  else
94
93
  p current_token()
95
- raise "the token should be :ident or primaries such as :ident, :num and :string after = . Current token: " + current_token().type.to_s
94
+ raise "the token should be :ident or primaries such as :ident, :num and :string after = . Next token: " + peek.type.to_s
96
95
  end
97
96
  else
98
- opt_value = true
97
+ raise "proc instruction optional argumeents should be in the form of a sequence of 'key = value'"
99
98
  end
100
99
  @result_hash[opt_key.to_s] = opt_value
101
100
  end
@@ -127,12 +126,14 @@ class STSBlockParseProcOpts
127
126
  case current_token.type
128
127
  when :ident
129
128
  return ident()
130
- when :string
129
+ when :dq_string
130
+ return string()
131
+ when :sq_string
131
132
  return string()
132
133
  when :num
133
134
  return num()
134
135
  else
135
- raise "the current token should be :ident, :string or :num."
136
+ raise "the current token should be :ident, :dq_string, :sq_string or :num."
136
137
  end
137
138
  end
138
139
 
@@ -155,8 +156,13 @@ class STSBlockParseProcOpts
155
156
  end
156
157
 
157
158
  def string()
158
- raise "the current token should be string" if current_token.type != :string
159
- return type_adjust( current_token.e1, :string)
159
+ if (current_token.type != :dq_string)
160
+ return type_adjust( current_token.e1, :dq_string)
161
+ elsif (current_token.type != :sq_string)
162
+ return type_adjust( current_token.e1, :sq_string)
163
+ else
164
+ raise "the current token should be string (:dq_string or :sq_string)"
165
+ end
160
166
  end
161
167
 
162
168
  def num()
@@ -0,0 +1,10 @@
1
+ class ProcBlockFinalizer
2
+ attr :enabled, true
3
+ def initialize
4
+ @enabled = false
5
+ end
6
+
7
+ def enabled?
8
+ return @enabled
9
+ end
10
+ end
@@ -18,7 +18,7 @@ class ProcOptValidator
18
18
  raise "#{opt_name} is required for this PROC option"
19
19
  end
20
20
  end
21
- if ! validator["is_a"].nil?
21
+ if ! param_manager.param_hash[opt_name].nil? && ! validator["is_a"].nil?
22
22
  if validator["is_a"].is_a?(Array)
23
23
  if ! validator["is_a"].include? class_name_in_param_manager
24
24
  raise "#{opt_name} needs to be one of #{validator["is_a"].join("|")}, but #{class_name_in_param_manager} is assigned"
@@ -30,7 +30,7 @@ class ProcOptValidator
30
30
  end
31
31
 
32
32
  end
33
- if ! validator["as"].nil?
33
+ if ! param_manager.param_hash[opt_name].nil? && ! validator["as"].nil?
34
34
  if validator["as"] != class_name_in_param_manager
35
35
  case validator["as"]
36
36
  when "SymbolR"
@@ -1,10 +1,12 @@
1
1
  require "pathname"
2
2
  require_relative("./proc_opt_validator.rb")
3
+ require_relative("./proc_block_finalizer.rb")
3
4
 
4
5
  module ProcSettingModule
5
6
  def self.included base
6
7
  base.extend ClassMethods
7
8
  base.instance_variable_set(:@validator, ProcOptValidator.new())
9
+ base.instance_variable_set(:@finalizer, ProcBlockFinalizer.new())
8
10
  base.send :include, InstanceMethods
9
11
  end
10
12
 
@@ -12,6 +14,8 @@ module ProcSettingModule
12
14
  def extend_object( extender )
13
15
  extender.instance_variable_set(:@validator, @validator)
14
16
  extender.singleton_class.__send__( :attr_accessor, :validator)
17
+ extender.instance_variable_set(:@finalizer, @finalizer)
18
+ extender.singleton_class.__send__( :attr_accessor, :finalizer)
15
19
  super
16
20
  end
17
21
 
@@ -36,6 +40,14 @@ module ProcSettingModule
36
40
  def validator
37
41
  @validator
38
42
  end
43
+
44
+ def finalizer_enabled
45
+ @finalizer.enabled = true
46
+ end
47
+
48
+ def finalizer
49
+ @finalizer
50
+ end
39
51
  end
40
52
 
41
53
  module InstanceMethods
@@ -69,6 +69,8 @@ require_relative("proc_setting_support/proc_setting_module.rb")
69
69
 
70
70
  module ProcBlockToR
71
71
  include BlockToRSupport
72
+ FINALIZER_NAME = "finalizer"
73
+
72
74
  def self.create_lazy_funcs( blk , proc_setting_manager )
73
75
  proc_command = blk.command
74
76
  param_manager = RBridge::RParamManager.new( blk.opts )
@@ -90,6 +92,13 @@ module ProcBlockToR
90
92
  proc_lazy_funcs_with_print_result_opts = proc_stmts.map(){|proc_stmt|
91
93
  lzf_gen.gen_lazy_func( proc_command, proc_stmt, param_manager )
92
94
  }
95
+
96
+ finalizer = lzf_gen.finalizer
97
+ if finalizer.enabled?
98
+ finalizer_func = lzf_gen.gen_lazy_func( proc_command , [ FINALIZER_NAME, "", nil] , param_manager )
99
+ proc_lazy_funcs_with_print_result_opts.push( finalizer_func )
100
+ end
101
+
93
102
  return proc_lazy_funcs_with_print_result_opts
94
103
  end
95
104
  end
@@ -40,6 +40,132 @@ module LazyFuncGeneratorSettingUtility
40
40
  return RBridge.create_strvec( ary.map(){|elem| elem.to_s } )
41
41
  end
42
42
 
43
+ def read_symbols_or_functions_as_strvec(ary)
44
+ deapth_ary = Array.new( ary.size )
45
+ idx = 0
46
+ last_idx = ary.size - 1
47
+ deapth = 0
48
+ while( idx <= last_idx )
49
+ if( ary[idx].is_a?(RBridge::SymbolR) && (ary[idx + 1].is_a?(RBridge::SignR) && ary[idx + 1].to_s == "("))
50
+ # function starts
51
+ deapth_ary[idx] = deapth
52
+ deapth = deapth + 1
53
+ idx = idx + 1
54
+ deapth_ary[idx] = deapth
55
+ elsif( ary[idx].is_a?(RBridge::SignR) && ary[idx].to_s == "(")
56
+ # parenthesis starts
57
+ deapth = deapth + 1
58
+ deapth_ary[idx] = deapth
59
+ elsif( ary[idx].is_a?(RBridge::SignR) && ary[idx].to_s == ")")
60
+ # parenthesis ends or function ends
61
+ deapth_ary[idx] = deapth
62
+ deapth = deapth - 1
63
+ else
64
+ deapth_ary[idx] = deapth
65
+ end
66
+ idx = idx + 1
67
+ end
68
+
69
+ result_ary = []
70
+ ary.zip( deapth_ary).each(){|elem, deapth|
71
+ if elem.respond_to? :to_s_for_r_parsing
72
+ elem_str = elem.to_s_for_r_parsing
73
+ else
74
+ elem_str = elem.to_s
75
+ end
76
+
77
+ if( deapth == 0)
78
+ result_ary.push( elem_str )
79
+ else
80
+ result_ary.last << " " << elem_str
81
+ end
82
+ }
83
+
84
+ return RBridge.create_strvec( result_ary )
85
+ end
86
+
87
+ def read_named_args_as_named_strvec(ary)
88
+ arg_num_ary = Array.new( ary.size )
89
+ deapth_ary = Array.new( ary.size )
90
+ idx = 0
91
+ last_idx = ary.size - 1
92
+ arg_num = nil
93
+ deapth = nil
94
+
95
+ while( idx <= last_idx )
96
+ if( idx == 0 )
97
+ # name starts
98
+ unless ( deapth.nil? && ary[idx].is_a?(RBridge::SymbolR) && (ary[idx + 1].is_a?(RBridge::SignR) && ary[idx + 1].to_s == "="))
99
+ raise "read_named_args_as_named_strvec requires an argument to start with name=expr"
100
+ end
101
+ arg_num = 0
102
+ deapth = 0
103
+ elsif( deapth == 0 && ary[idx].is_a?(RBridge::SymbolR) && (ary[idx + 1].is_a?(RBridge::SignR) && ary[idx + 1].to_s == "="))
104
+ # name starts
105
+ arg_num = arg_num + 1
106
+ elsif( ary[idx].is_a?(RBridge::SymbolR) && (ary[idx + 1].is_a?(RBridge::SignR) && ary[idx + 1].to_s == "("))
107
+ # function starts
108
+ deapth_ary[idx] = deapth
109
+ arg_num_ary[idx] = arg_num
110
+ deapth = deapth + 1
111
+ idx = idx + 1
112
+ deapth_ary[idx] = deapth
113
+ elsif( ary[idx].is_a?(RBridge::SignR) && ary[idx].to_s == "(")
114
+ # parenthesis starts
115
+ deapth = deapth + 1
116
+ deapth_ary[idx] = deapth
117
+ elsif( ary[idx].is_a?(RBridge::SignR) && ary[idx].to_s == ")")
118
+ # parenthesis ends or function ends
119
+ deapth_ary[idx] = deapth
120
+ deapth = deapth - 1
121
+ else
122
+ deapth_ary[idx] = deapth
123
+ end
124
+ arg_num_ary[idx] = arg_num
125
+ idx = idx + 1
126
+ end
127
+
128
+ result_ary = []
129
+ name_ary = []
130
+ prev_arg_num = -1
131
+ idx = 0
132
+ elem_arg_num_ary = ary.zip( arg_num_ary )
133
+ while( idx < elem_arg_num_ary.size )
134
+ elem = ary[idx]
135
+ arg_num = arg_num_ary[idx]
136
+ if elem.respond_to? :to_s_for_r_parsing
137
+ elem_str = elem.to_s_for_r_parsing
138
+ else
139
+ elem_str = elem.to_s
140
+ end
141
+
142
+ if( arg_num != prev_arg_num ) # starts new 'name=expr'
143
+ name_ary.push elem_str
144
+ idx = idx + 1
145
+ if( ary[idx].to_s != "=" )
146
+ raise "An argument should be in the form of 'name=expr'"
147
+ end
148
+ else
149
+ if( result_ary[arg_num].nil? )
150
+ unless result_ary.size == arg_num
151
+ raise "arg_num is not an appropriate number."
152
+ end
153
+ result_ary[arg_num] = [elem_str]
154
+ else
155
+ result_ary[arg_num].push( elem_str )
156
+ end
157
+ end
158
+ idx = idx + 1
159
+ prev_arg_num = arg_num
160
+ end
161
+
162
+ result_vec = RBridge.create_strvec( result_ary.map(){|ary| ary.join(" ") } )
163
+ name_vec = RBridge.create_strvec( name_ary )
164
+ add_name_func = RBridge.create_ns_function_call("stats", "setNames", {"object" => result_vec, "nm" => name_vec })
165
+ result_name_vec = RBridge.exec_function( add_name_func )
166
+ return result_name_vec
167
+ end
168
+
43
169
  def result( name , *addl )
44
170
  if addl.empty?
45
171
  return RBridge::RResultName.new(name)
@@ -59,6 +185,10 @@ module LazyFuncGeneratorSettingUtility
59
185
  return RBridge::RResultPrevious.new( default_obj )
60
186
  end
61
187
 
188
+ def previous_inst_name()
189
+ return RBridge::RInstPrevious.new()
190
+ end
191
+
62
192
  def r_obj( val )
63
193
  return RBridge.convert_to_r_object( val )
64
194
  end