flor 0.13.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|