flor 0.13.0 → 0.14.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.
- data/CHANGELOG.md +8 -0
- data/lib/flor.rb +1 -1
- data/lib/flor/core.rb +7 -0
- data/lib/flor/core/executor.rb +43 -8
- data/lib/flor/core/node.rb +84 -54
- data/lib/flor/core/procedure.rb +36 -19
- data/lib/flor/core/texecutor.rb +4 -1
- data/lib/flor/deep.rb +43 -51
- data/lib/flor/dollar.rb +2 -3
- data/lib/flor/flor.rb +38 -9
- data/lib/flor/parser.rb +123 -72
- data/lib/flor/pcore/_arr.rb +15 -0
- data/lib/flor/pcore/_atom.rb +6 -5
- data/lib/flor/pcore/_att.rb +9 -4
- data/lib/flor/pcore/_obj.rb +28 -34
- data/lib/flor/pcore/_pat_.rb +77 -0
- data/lib/flor/pcore/_pat_arr.rb +131 -0
- data/lib/flor/pcore/_pat_guard.rb +70 -0
- data/lib/flor/pcore/_pat_obj.rb +143 -0
- data/lib/flor/pcore/_pat_or.rb +46 -0
- data/lib/flor/pcore/_val.rb +20 -0
- data/lib/flor/pcore/arith.rb +7 -1
- data/lib/flor/pcore/case.rb +46 -69
- data/lib/flor/pcore/cursor.rb +24 -24
- data/lib/flor/pcore/define.rb +5 -1
- data/lib/flor/pcore/do_return.rb +32 -0
- data/lib/flor/pcore/length.rb +18 -0
- data/lib/flor/pcore/logo.rb +47 -0
- data/lib/flor/pcore/map.rb +12 -10
- data/lib/flor/pcore/match.rb +276 -0
- data/lib/flor/pcore/not.rb +13 -0
- data/lib/flor/pcore/push.rb +52 -13
- data/lib/flor/pcore/range.rb +69 -0
- data/lib/flor/pcore/set.rb +82 -24
- data/lib/flor/unit/hook.rb +28 -0
- data/lib/flor/unit/hooker.rb +5 -0
- data/lib/flor/unit/loader.rb +4 -1
- data/lib/flor/unit/storage.rb +5 -3
- data/lib/flor/unit/waiter.rb +12 -2
- data/lib/flor/unit/wlist.rb +4 -3
- data/match.md +22 -0
- metadata +15 -5
- data/lib/flor/pcore/_happly.rb +0 -49
- data/lib/flor/pcore/val.rb +0 -16
- data/t.txt +0 -4
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
require 'flor/pcore/_pat_'
|
3
|
+
|
4
|
+
|
5
|
+
class Flor::Pro::PatOr < Flor::Pro::PatContainer
|
6
|
+
|
7
|
+
name '_pat_or'
|
8
|
+
|
9
|
+
def pre_execute
|
10
|
+
|
11
|
+
unatt_unkeyed_children
|
12
|
+
end
|
13
|
+
|
14
|
+
def receive_non_att
|
15
|
+
|
16
|
+
ct = child_type(@fcid)
|
17
|
+
|
18
|
+
if ct == :pattern
|
19
|
+
|
20
|
+
b = payload.delete('_pat_binding')
|
21
|
+
return wrap_match_reply(b) if b
|
22
|
+
|
23
|
+
elsif payload['ret'] == val
|
24
|
+
|
25
|
+
return wrap_match_reply({})
|
26
|
+
end
|
27
|
+
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def receive_last
|
32
|
+
|
33
|
+
wrap_no_match_reply
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def wrap_match_reply(binding)
|
39
|
+
|
40
|
+
payload['_pat_binding'] = binding
|
41
|
+
payload.delete('_pat_val')
|
42
|
+
|
43
|
+
wrap_reply
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
class Flor::Pro::Val < Flor::Procedure
|
3
|
+
|
4
|
+
name '_val'
|
5
|
+
|
6
|
+
def wrap_reply
|
7
|
+
|
8
|
+
if node_open?
|
9
|
+
|
10
|
+
heat = @node['heat']
|
11
|
+
#heat = nil if heat == [ '_proc', 'val', -1 ] || heat[0] == '_nul'
|
12
|
+
heat = nil if heat[0] == '_nul'
|
13
|
+
|
14
|
+
payload['ret'] = heat
|
15
|
+
end
|
16
|
+
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/lib/flor/pcore/arith.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
class Flor::Pro::Arith < Flor::Procedure
|
3
3
|
|
4
|
-
names %w[ + - * / ]
|
4
|
+
names %w[ + - * / % ]
|
5
5
|
|
6
6
|
DEFAULTS = { :+ => 0, :* => 1, :- => 0, :/ => 1 }
|
7
7
|
|
@@ -13,6 +13,12 @@ class Flor::Pro::Arith < Flor::Procedure
|
|
13
13
|
def receive_last
|
14
14
|
|
15
15
|
sign = tree.first.to_sym
|
16
|
+
count = @node['rets'].size
|
17
|
+
|
18
|
+
if sign == :% && count < 2
|
19
|
+
fail ArgumentError.new(
|
20
|
+
"modulo % requires at least 2 arguments (line #{tree[2]})")
|
21
|
+
end
|
16
22
|
|
17
23
|
payload['ret'] = @node['rets'].reduce(&sign) || DEFAULTS[sign]
|
18
24
|
|
data/lib/flor/pcore/case.rb
CHANGED
@@ -9,11 +9,11 @@ class Flor::Pro::Case < Flor::Procedure
|
|
9
9
|
#
|
10
10
|
# ```
|
11
11
|
# case level
|
12
|
-
# [ 0 1 2 ]
|
13
|
-
# [ 3 4 5 ]
|
14
|
-
# else
|
12
|
+
# [ 0 1 2 ]; 'low'
|
13
|
+
# [ 3 4 5 ]; 'medium'
|
14
|
+
# else; 'high'
|
15
15
|
# ```
|
16
|
-
# which is a "
|
16
|
+
# which is a ";"ed version of
|
17
17
|
# ```
|
18
18
|
# case level
|
19
19
|
# [ 0 1 2 ]
|
@@ -37,89 +37,66 @@ class Flor::Pro::Case < Flor::Procedure
|
|
37
37
|
def pre_execute
|
38
38
|
|
39
39
|
unatt_unkeyed_children
|
40
|
-
|
40
|
+
|
41
|
+
@node['val'] = payload['ret'] if non_att_children.size.even?
|
41
42
|
end
|
42
43
|
|
43
|
-
def
|
44
|
+
def receive
|
44
45
|
|
45
46
|
return wrap_reply if @node['found']
|
46
47
|
|
47
|
-
|
48
|
+
determine_fcid_and_ncid
|
49
|
+
|
50
|
+
return execute_child(@ncid) if @fcid == nil
|
51
|
+
|
52
|
+
has_no_val = ! @node.has_key?('val')
|
48
53
|
|
49
|
-
|
50
|
-
|
54
|
+
if has_no_val && ! from_att?
|
55
|
+
@node['val'] = payload['ret']
|
56
|
+
execute_conditional
|
57
|
+
elsif has_no_val
|
58
|
+
execute_child(@ncid)
|
59
|
+
elsif m = match?
|
60
|
+
execute_then(@ncid, m)
|
61
|
+
else
|
62
|
+
execute_conditional(@ncid + 1)
|
63
|
+
end
|
51
64
|
end
|
52
65
|
|
53
66
|
protected
|
54
67
|
|
55
|
-
def
|
68
|
+
def execute_conditional(ncid=@ncid)
|
56
69
|
|
57
|
-
|
58
|
-
|
70
|
+
if else?(ncid)
|
71
|
+
execute_then(ncid + 1)
|
72
|
+
else
|
73
|
+
payload['ret'] = node_payload_ret
|
74
|
+
execute_child(ncid)
|
75
|
+
end
|
76
|
+
end
|
59
77
|
|
60
|
-
|
78
|
+
def execute_then(ncid, vars=nil)
|
61
79
|
|
62
|
-
|
80
|
+
payload['ret'] = node_payload_ret
|
81
|
+
@node['found'] = true
|
63
82
|
|
64
|
-
|
65
|
-
execute_child(@fcid + 1)
|
83
|
+
h = vars.is_a?(Hash) ? { 'vars' => vars } : nil
|
66
84
|
|
67
|
-
|
85
|
+
execute_child(ncid, nil, h)
|
86
|
+
end
|
68
87
|
|
69
|
-
|
88
|
+
def else?(ncid)
|
70
89
|
|
71
|
-
|
72
|
-
|
73
|
-
execute_child(@fcid + 3)
|
74
|
-
else
|
75
|
-
execute_child(@fcid + 2)
|
76
|
-
end
|
77
|
-
end
|
90
|
+
(t = tree[1][ncid]) &&
|
91
|
+
t[0, 2] == [ 'else', [] ]
|
78
92
|
end
|
79
93
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
#
|
88
|
-
# #t[1][1..-1].each do |ct|
|
89
|
-
# non_att_children.each do |ct|
|
90
|
-
#
|
91
|
-
# if nchildren.empty? || mode == :clause
|
92
|
-
# nchildren << ct
|
93
|
-
# mode = :array
|
94
|
-
# next
|
95
|
-
# end
|
96
|
-
#
|
97
|
-
# ct0, ct1, ct2 = ct
|
98
|
-
#
|
99
|
-
# if (Flor.is_tree?(ct0) || ct0 == 'else') && ct1.any?
|
100
|
-
# nchildren << (ct0 == 'else' ? [ 'else', [], ct2 ] : ct0)
|
101
|
-
# if ct1.size == 1
|
102
|
-
# nchildren << ct1.first
|
103
|
-
# else # ct1.size > 1
|
104
|
-
# sequence = [ 'sequence', ct1, ct1.first[2] ]
|
105
|
-
# nchildren << sequence
|
106
|
-
# end
|
107
|
-
# #elsif ct0.is_a?(String) && ct1.is_a?(Array) && ct1.any?
|
108
|
-
# # p ct
|
109
|
-
# # dct0 = deref(ct0)
|
110
|
-
# # hct0 = reheap(ct, dct0)
|
111
|
-
# # p dct0
|
112
|
-
# # p hct0
|
113
|
-
# else
|
114
|
-
# nchildren << ct
|
115
|
-
# mode = :clause
|
116
|
-
# end
|
117
|
-
# end
|
118
|
-
#
|
119
|
-
# t[1] = nchildren
|
120
|
-
#pp nchildren
|
121
|
-
#
|
122
|
-
# @node['tree'] = t if t != ot
|
123
|
-
# end
|
94
|
+
def match?
|
95
|
+
|
96
|
+
a = payload['ret']
|
97
|
+
a = a.nil? ? [ a ] : Array(a)
|
98
|
+
|
99
|
+
a.include?(@node['val'])
|
100
|
+
end
|
124
101
|
end
|
125
102
|
|
data/lib/flor/pcore/cursor.rb
CHANGED
@@ -132,20 +132,27 @@ class Flor::Pro::Cursor < Flor::Procedure
|
|
132
132
|
fail("move target #{to.inspect} not found")
|
133
133
|
end
|
134
134
|
|
135
|
+
def is_tag_tree?(t, tagname)
|
136
|
+
|
137
|
+
Flor.is_att_tree?(t) &&
|
138
|
+
t[1].size == 2 &&
|
139
|
+
t[1][0][0, 2] == [ 'tag', [] ] &&
|
140
|
+
Flor.is_string_tree?(t[1][1], tagname)
|
141
|
+
end
|
142
|
+
|
143
|
+
def is_att_string_tree?(t, s)
|
144
|
+
|
145
|
+
Flor.is_att_tree?(t) &&
|
146
|
+
t[1].size == 1 &&
|
147
|
+
Flor.is_string_tree?(t[1].first, s)
|
148
|
+
end
|
149
|
+
|
135
150
|
def find_tag_target(to)
|
136
151
|
|
137
152
|
tree[1]
|
138
|
-
.index { |
|
139
|
-
|
140
|
-
|
141
|
-
Flor.is_tree?(cc) &&
|
142
|
-
cc[0] == '_att' &&
|
143
|
-
cc[1].size == 2 &&
|
144
|
-
cc[1][0][0] == 'tag' &&
|
145
|
-
%w[ _sqs _dqs ].include?(cc[1][1][0]) &&
|
146
|
-
cc[1][1][1] == to
|
147
|
-
}
|
148
|
-
}
|
153
|
+
.index { |ct|
|
154
|
+
ct[1].is_a?(Array) &&
|
155
|
+
ct[1].index { |cc| is_tag_tree?(cc, to) } }
|
149
156
|
end
|
150
157
|
|
151
158
|
def find_string_arg_target(to)
|
@@ -153,24 +160,19 @@ class Flor::Pro::Cursor < Flor::Procedure
|
|
153
160
|
tree[1]
|
154
161
|
.index { |c|
|
155
162
|
c[1].is_a?(Array) &&
|
156
|
-
c[1].index { |cc|
|
157
|
-
Flor.is_tree?(cc) &&
|
158
|
-
cc[0] == '_att' &&
|
159
|
-
cc[1].size == 1 &&
|
160
|
-
%w[ _sqs _dqs ].include?(cc[1][0][0]) &&
|
161
|
-
cc[1][0][1] == to
|
162
|
-
}
|
163
|
-
}
|
163
|
+
c[1].index { |cc| is_att_string_tree?(cc, to) } }
|
164
164
|
end
|
165
165
|
|
166
166
|
def find_string_target(to)
|
167
167
|
|
168
|
-
tree[1]
|
168
|
+
tree[1]
|
169
|
+
.index { |ct| Flor.is_string_tree?(ct, to) }
|
169
170
|
end
|
170
171
|
|
171
172
|
def find_name_target(to)
|
172
173
|
|
173
|
-
tree[1]
|
174
|
+
tree[1]
|
175
|
+
.index { |ct| ct[0] == to }
|
174
176
|
end
|
175
177
|
|
176
178
|
def find_att_target(to)
|
@@ -182,9 +184,7 @@ class Flor::Pro::Cursor < Flor::Procedure
|
|
182
184
|
c[1].find { |cc|
|
183
185
|
cc[0] == '_att' &&
|
184
186
|
cc[1].is_a?(Array) &&
|
185
|
-
cc[1][0][0, 2] == [ 'here', [] ]
|
186
|
-
}
|
187
|
-
}
|
187
|
+
cc[1][0][0, 2] == [ 'here', [] ] } } # FIXME hardcoded...
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
data/lib/flor/pcore/define.rb
CHANGED
@@ -50,9 +50,13 @@ class Flor::Pro::Define < Flor::Procedure
|
|
50
50
|
cnode = lookup_var_node(@node, 'l')
|
51
51
|
cnid = cnode['nid']
|
52
52
|
fun = counter_next('funs') - 1
|
53
|
+
|
53
54
|
(cnode['closures'] ||= []) << fun
|
54
55
|
|
55
|
-
val = [
|
56
|
+
val = [
|
57
|
+
'_func',
|
58
|
+
{ 'nid' => nid, 'tree' => t, 'cnid' => cnid, 'fun' => fun },
|
59
|
+
t[2] ]
|
56
60
|
|
57
61
|
if t[0] == 'define'
|
58
62
|
name =
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
class Flor::Pro::DoReturn < Flor::Macro
|
3
|
+
#
|
4
|
+
# Takes a set of arguments and returns a function
|
5
|
+
# that will return those arguments again.
|
6
|
+
#
|
7
|
+
# ```
|
8
|
+
# set a
|
9
|
+
# do-return 1
|
10
|
+
# a _
|
11
|
+
# ```
|
12
|
+
# will set 1 in the payload `ret`.
|
13
|
+
#
|
14
|
+
# It might be useful in cases like:
|
15
|
+
# ```
|
16
|
+
# sequence on_error: (do-return 1)
|
17
|
+
# do-this-failure-prone-thing _
|
18
|
+
# ```
|
19
|
+
#
|
20
|
+
|
21
|
+
name 'do-return'
|
22
|
+
|
23
|
+
def rewrite_tree
|
24
|
+
|
25
|
+
l = tree[2]
|
26
|
+
|
27
|
+
[ 'sequence', [
|
28
|
+
[ 'def', att_children.first[1], l ]
|
29
|
+
], l ]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
class Flor::Pro::Logo < Flor::Procedure
|
3
|
+
|
4
|
+
names %w[ and or ]
|
5
|
+
|
6
|
+
def execute
|
7
|
+
|
8
|
+
payload['ret'] = @node['heat0'] == 'and'
|
9
|
+
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def receive_att
|
14
|
+
|
15
|
+
c = children[@fcid]; return super if c[0] == '_att' && [1].size == 2
|
16
|
+
|
17
|
+
h0 = @node['heat0']
|
18
|
+
|
19
|
+
ret = Flor.true?(payload['ret'])
|
20
|
+
|
21
|
+
return wrap_reply if ((h0 == 'or' && ret) || (h0 == 'and' && ! ret))
|
22
|
+
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
alias receive_non_att receive_att
|
27
|
+
|
28
|
+
# def pre_execute
|
29
|
+
#
|
30
|
+
# @node['rets'] = []
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# def receive_last
|
34
|
+
#
|
35
|
+
# payload['ret'] =
|
36
|
+
# if @node['heat0'] == 'or'
|
37
|
+
# !! @node['rets'].index { |r| Flor.true?(r) }
|
38
|
+
# else
|
39
|
+
# ! @node['rets'].index { |r| Flor.false?(r) }
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# wrap_reply
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# Keep me around for a "aand" and a "oor"... Maybe...
|
46
|
+
end
|
47
|
+
|
data/lib/flor/pcore/map.rb
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
|
2
2
|
class Flor::Pro::Map < Flor::Procedure
|
3
3
|
|
4
|
-
|
4
|
+
names %w[ map for-each ]
|
5
5
|
|
6
6
|
def pre_execute
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
@node['vars'] = {}
|
11
|
-
# just to store the local idx
|
8
|
+
@node['vars'] ||= {}
|
12
9
|
|
13
10
|
@node['col'] = nil
|
14
11
|
@node['idx'] = -1
|
15
12
|
@node['fun'] = nil
|
16
|
-
|
13
|
+
|
14
|
+
@node['res'] = @node['heat0'] == 'map' ? [] : nil
|
17
15
|
|
18
16
|
unatt_unkeyed_children
|
19
17
|
end
|
@@ -33,15 +31,19 @@ class Flor::Pro::Map < Flor::Procedure
|
|
33
31
|
|
34
32
|
if @node['idx'] < 0
|
35
33
|
@node['fun'] = payload['ret']
|
36
|
-
|
37
|
-
|
34
|
+
elsif res = @node['res']
|
35
|
+
res << payload['ret']
|
38
36
|
end
|
39
37
|
|
40
38
|
@node['idx'] += 1
|
41
39
|
@node['mtime'] = Flor.tstamp
|
42
40
|
|
43
|
-
|
44
|
-
if
|
41
|
+
if @node['idx'] == @node['col'].size
|
42
|
+
if res = @node['res']
|
43
|
+
payload['ret'] = @node['res']
|
44
|
+
end
|
45
|
+
return wrap_reply
|
46
|
+
end
|
45
47
|
|
46
48
|
@node['vars']['idx'] = @node['idx']
|
47
49
|
|