fancy 0.5.0 → 0.6.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/AUTHORS +2 -0
- data/README.md +6 -1
- data/bin/fancy +6 -0
- data/bin/ifancy +44 -3
- data/boot/fancy_ext/module.rb +4 -0
- data/boot/fancy_ext/object.rb +4 -0
- data/boot/rbx-compiler/compiler/ast/block.rb +29 -1
- data/boot/rbx-compiler/compiler/ast/identifier.rb +6 -0
- data/boot/rbx-compiler/compiler/ast/message_send.rb +1 -0
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/lexer.lex +2 -0
- data/boot/rbx-compiler/parser/parser.rb +6 -0
- data/boot/rbx-compiler/parser/parser.y +14 -1
- data/doc/api/fancy.jsonp +1 -1
- data/doc/features.md +24 -0
- data/examples/99bottles.fy +5 -0
- data/examples/conditions_exceptions.fy +9 -0
- data/examples/conditions_parsing.fy +68 -0
- data/examples/greeter.fy +9 -0
- data/examples/html_generator.fy +59 -29
- data/examples/webserver/webserver.fy +8 -11
- data/lib/argv.fy +6 -0
- data/lib/array.fy +17 -35
- data/lib/block.fy +82 -1
- data/lib/boot.fy +4 -2
- data/lib/compiler.fy +2 -2
- data/lib/compiler/ast/block.fy +24 -20
- data/lib/compiler/ast/message_send.fy +11 -0
- data/lib/contracts.fy +60 -0
- data/lib/dynamic_slot_object.fy +61 -0
- data/lib/enumerable.fy +432 -394
- data/lib/enumerator.fy +152 -150
- data/lib/fdoc.fy +4 -17
- data/lib/fiber.fy +4 -10
- data/lib/file.fy +33 -25
- data/lib/future.fy +59 -5
- data/lib/hash.fy +54 -1
- data/lib/html.fy +107 -0
- data/lib/kvo.fy +173 -0
- data/lib/main.fy +6 -2
- data/lib/message_sink.fy +19 -0
- data/lib/number.fy +48 -0
- data/lib/object.fy +65 -13
- data/lib/package.fy +12 -2
- data/lib/package/dependency.fy +13 -0
- data/lib/package/dependency_installer.fy +27 -0
- data/lib/package/installer.fy +4 -10
- data/lib/package/uninstaller.fy +1 -3
- data/lib/parser/ext/lexer.lex +8 -3
- data/lib/parser/ext/parser.y +4 -1
- data/lib/parser/methods.fy +7 -3
- data/lib/range.fy +1 -1
- data/lib/rbx.fy +2 -1
- data/lib/rbx/array.fy +28 -12
- data/lib/rbx/bignum.fy +1 -1
- data/lib/rbx/block.fy +27 -0
- data/lib/rbx/console.fy +6 -6
- data/lib/rbx/date.fy +6 -1
- data/lib/rbx/documentation.fy +8 -3
- data/lib/rbx/exception.fy +5 -0
- data/lib/rbx/file.fy +40 -7
- data/lib/rbx/fixnum.fy +12 -1
- data/lib/rbx/method.fy +9 -2
- data/lib/rbx/module.fy +24 -0
- data/lib/rbx/regexp.fy +8 -0
- data/lib/rbx/string.fy +23 -7
- data/lib/rbx/tcp_server.fy +4 -2
- data/lib/rbx/tcp_socket.fy +14 -0
- data/lib/remote_object.fy +59 -0
- data/lib/set.fy +15 -4
- data/lib/string.fy +38 -5
- data/lib/stringio.fy +1 -0
- data/lib/symbol.fy +4 -0
- data/lib/system.fy +22 -0
- data/lib/thread_pool.fy +2 -2
- data/lib/tuple.fy +18 -1
- data/lib/vars.fy +17 -0
- data/lib/version.fy +1 -1
- data/ruby_lib/fancy +6 -0
- data/tests/array.fy +30 -0
- data/tests/block.fy +106 -0
- data/tests/class.fy +19 -0
- data/tests/enumerable.fy +1 -1
- data/tests/enumerator.fy +5 -5
- data/tests/file.fy +28 -0
- data/tests/fixnum.fy +0 -50
- data/tests/future.fy +9 -24
- data/tests/hash.fy +35 -0
- data/tests/html.fy +33 -0
- data/tests/kvo.fy +101 -0
- data/tests/number.fy +75 -0
- data/tests/object.fy +50 -3
- data/tests/string.fy +19 -10
- data/tests/symbol.fy +5 -0
- data/tests/tuple.fy +7 -0
- data/tools/fancy-mode.el +5 -1
- metadata +22 -21
- data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/Makefile +0 -156
- data/boot/rbx-compiler/parser/lexer.c +0 -2310
- data/boot/rbx-compiler/parser/lexer.h +0 -315
- data/boot/rbx-compiler/parser/parser.c +0 -2946
- data/boot/rbx-compiler/parser/parser.h +0 -151
- data/lib/fiber_pool.fy +0 -78
- data/lib/method.fy +0 -6
- data/lib/parser/ext/Makefile +0 -156
- data/lib/parser/ext/fancy_parser.bundle +0 -0
- data/lib/parser/ext/lexer.c +0 -2392
- data/lib/parser/ext/lexer.h +0 -315
- data/lib/parser/ext/parser.c +0 -3251
- data/lib/parser/ext/parser.h +0 -161
data/lib/range.fy
CHANGED
data/lib/rbx.fy
CHANGED
|
@@ -25,8 +25,8 @@ require: "rbx/system"
|
|
|
25
25
|
require: "rbx/exception"
|
|
26
26
|
require: "rbx/io"
|
|
27
27
|
require: "rbx/file"
|
|
28
|
-
require: "rbx/tcp_server"
|
|
29
28
|
require: "rbx/tcp_socket"
|
|
29
|
+
require: "rbx/tcp_server"
|
|
30
30
|
require: "rbx/match_data"
|
|
31
31
|
require: "rbx/regexp"
|
|
32
32
|
require: "rbx/directory"
|
|
@@ -40,3 +40,4 @@ require: "rbx/date"
|
|
|
40
40
|
require: "rbx/time"
|
|
41
41
|
require: "rbx/actor"
|
|
42
42
|
require: "rbx/mutex"
|
|
43
|
+
require: "rbx/module"
|
data/lib/rbx/array.fy
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
class Array {
|
|
2
|
-
ruby_aliases: [ '==, '<<, 'pop, 'last, 'shift ]
|
|
2
|
+
ruby_aliases: [ '==, '<<, 'pop, 'last, 'shift, 'flatten ]
|
|
3
3
|
|
|
4
4
|
forwards_unary_ruby_methods
|
|
5
5
|
|
|
6
6
|
def Array new: size with: default {
|
|
7
|
-
"
|
|
7
|
+
"""
|
|
8
|
+
Creates a new Array with a given size and default-value.
|
|
9
|
+
If @default is a @Block@, call that block for each element instead.
|
|
10
|
+
"""
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
match default {
|
|
13
|
+
case Block -> Array new(size, &default)
|
|
14
|
+
case _ -> Array new(size, default)
|
|
15
|
+
}
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
def includes?: obj {
|
|
@@ -32,16 +38,14 @@ class Array {
|
|
|
32
38
|
delete_at(index)
|
|
33
39
|
return deleted
|
|
34
40
|
} else: {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
count = count + 1
|
|
42
|
-
}
|
|
43
|
-
return deleted_values
|
|
41
|
+
count = 0
|
|
42
|
+
deleted_values = []
|
|
43
|
+
index each: |idx| {
|
|
44
|
+
deleted_values << (at: (idx - count))
|
|
45
|
+
delete_at(idx - count)
|
|
46
|
+
count = count + 1
|
|
44
47
|
}
|
|
48
|
+
return deleted_values
|
|
45
49
|
}
|
|
46
50
|
nil
|
|
47
51
|
}
|
|
@@ -106,6 +110,18 @@ class Array {
|
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
def unshift: value {
|
|
113
|
+
"""
|
|
114
|
+
@value Value to be added at the front of @self.
|
|
115
|
+
@return @self.
|
|
116
|
+
|
|
117
|
+
Inserts a value at the front of @self.
|
|
118
|
+
|
|
119
|
+
Example:
|
|
120
|
+
a = [1,2,3]
|
|
121
|
+
a unshift: 10
|
|
122
|
+
a # => [10,1,2,3]
|
|
123
|
+
"""
|
|
124
|
+
|
|
109
125
|
unshift(value)
|
|
110
126
|
}
|
|
111
127
|
}
|
data/lib/rbx/bignum.fy
CHANGED
data/lib/rbx/block.fy
CHANGED
|
@@ -50,6 +50,19 @@ class Block {
|
|
|
50
50
|
# Ugh. HACK.
|
|
51
51
|
# Use try/catch to deal with older and latest version of rbx (method got changed)
|
|
52
52
|
def call_with_receiver: receiver {
|
|
53
|
+
"""
|
|
54
|
+
@receiver Receiver (value of @self) when calling the @Block@.
|
|
55
|
+
|
|
56
|
+
Calls a @Block@ with @receiver as the receiver (referenced by @self within the Block).
|
|
57
|
+
|
|
58
|
+
Example:
|
|
59
|
+
r1 = [1,2,3]
|
|
60
|
+
r2 = \"hello world\"
|
|
61
|
+
b = { self class }
|
|
62
|
+
b call_with_receiver: r1 # => Array
|
|
63
|
+
b call_with_receiver: r2 # => String
|
|
64
|
+
"""
|
|
65
|
+
|
|
53
66
|
try {
|
|
54
67
|
return call_under(receiver, method() scope())
|
|
55
68
|
} catch {
|
|
@@ -58,6 +71,20 @@ class Block {
|
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
def call: args with_receiver: receiver {
|
|
74
|
+
"""
|
|
75
|
+
@args @Array@ of arguments passed to @self for invocation.
|
|
76
|
+
@receiver Receiver (value of @self) when calling the @Block@.
|
|
77
|
+
|
|
78
|
+
Same as @call_with_receiver: but passing along arguments to the @Block@.
|
|
79
|
+
|
|
80
|
+
Example:
|
|
81
|
+
r1 = [1,2,3]
|
|
82
|
+
r2 = \"hello world\"
|
|
83
|
+
b = |arg| { self to_s + arg }
|
|
84
|
+
b call: [\"foo\"] with_receiver: r1 # => \"123foo\"
|
|
85
|
+
b call: [\"foo\"] with_receiver: r2 # => \"hello worldfoo\"
|
|
86
|
+
"""
|
|
87
|
+
|
|
61
88
|
try {
|
|
62
89
|
return call_under(receiver, method() scope(), *args)
|
|
63
90
|
} catch {
|
data/lib/rbx/console.fy
CHANGED
|
@@ -38,11 +38,7 @@ class Console {
|
|
|
38
38
|
"""
|
|
39
39
|
|
|
40
40
|
Console print: message
|
|
41
|
-
|
|
42
|
-
nil
|
|
43
|
-
} else: {
|
|
44
|
-
STDIN gets() chomp
|
|
45
|
-
}
|
|
41
|
+
Console readln
|
|
46
42
|
}
|
|
47
43
|
|
|
48
44
|
def Console readln {
|
|
@@ -52,7 +48,11 @@ class Console {
|
|
|
52
48
|
Reads a line from @STDIN and returns it as a @String@.
|
|
53
49
|
"""
|
|
54
50
|
|
|
55
|
-
STDIN
|
|
51
|
+
if: (STDIN eof?) then: {
|
|
52
|
+
nil
|
|
53
|
+
} else: {
|
|
54
|
+
STDIN gets() chomp
|
|
55
|
+
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
def Console clear {
|
data/lib/rbx/date.fy
CHANGED
|
@@ -9,9 +9,14 @@ class Date {
|
|
|
9
9
|
metaclass forwards_unary_ruby_methods
|
|
10
10
|
|
|
11
11
|
metaclass ruby_alias: 'today
|
|
12
|
-
ruby_aliases: [ '==, '-, '+, '<, '
|
|
12
|
+
ruby_aliases: [ '==, '-, '+, '<, '>, 'cwday, 'wday ]
|
|
13
13
|
|
|
14
14
|
def != other {
|
|
15
|
+
"""
|
|
16
|
+
@other Other @Date@ to compare to.
|
|
17
|
+
@return @true if equal, @false otherwhise.
|
|
18
|
+
"""
|
|
19
|
+
|
|
15
20
|
self == other not
|
|
16
21
|
}
|
|
17
22
|
}
|
data/lib/rbx/documentation.fy
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
class Fancy {}
|
|
3
3
|
|
|
4
4
|
class Fancy Documentation {
|
|
5
|
-
|
|
6
5
|
def initialize: docstring {
|
|
7
6
|
@docs = [docstring]
|
|
8
7
|
}
|
|
@@ -42,6 +41,14 @@ class Fancy Documentation {
|
|
|
42
41
|
doc
|
|
43
42
|
}
|
|
44
43
|
|
|
44
|
+
def self for_method: method_name on_class: class is: docstring {
|
|
45
|
+
"""
|
|
46
|
+
Similar to @Fancy::Documentation##for:is:@ but taking the method name and the @Class@ for which @Method@ to define the docstring.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
class instance_method: method_name . documentation: docstring
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
for: (instance_method('initialize:)) is: "Create a new documentation object."
|
|
46
53
|
for: (method('for:is:)) is: "Sets the documentation for obj."
|
|
47
54
|
|
|
@@ -59,6 +66,4 @@ class Fancy Documentation {
|
|
|
59
66
|
"Append docstring to docs."
|
|
60
67
|
for: obj is: docstring
|
|
61
68
|
}
|
|
62
|
-
|
|
63
69
|
}
|
|
64
|
-
|
data/lib/rbx/exception.fy
CHANGED
data/lib/rbx/file.fy
CHANGED
|
@@ -8,6 +8,9 @@ class File {
|
|
|
8
8
|
'truncate => "w+"]>
|
|
9
9
|
|
|
10
10
|
ruby_aliases: [ 'eof?, 'closed?, 'flush ]
|
|
11
|
+
metaclass alias_method: 'expand_path: for_ruby: 'expand_path
|
|
12
|
+
|
|
13
|
+
forwards_unary_ruby_methods
|
|
11
14
|
|
|
12
15
|
def File open: filename modes: modes_arr with: block {
|
|
13
16
|
"""
|
|
@@ -46,16 +49,30 @@ class File {
|
|
|
46
49
|
File exists?(filename)
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
def
|
|
52
|
+
def File read: filename {
|
|
50
53
|
"""
|
|
51
|
-
|
|
54
|
+
@filename @String@ containing the path of the File to be read.
|
|
55
|
+
@return Contents of the File as a @String@.
|
|
56
|
+
|
|
57
|
+
Reads all the contens (in ASCII mode) of a given file and returns
|
|
58
|
+
them as an Array of lines being read.
|
|
52
59
|
"""
|
|
53
60
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
File read(filename)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
def File read: filename length: length offset: offset (0) {
|
|
65
|
+
"""
|
|
66
|
+
@filename @String@ containing the path of the File to be read.
|
|
67
|
+
@length @Fixnum@ being the maximum length to read from the File.
|
|
68
|
+
@offset @Fixnum@ being the offset in bytes to start reading from the File.
|
|
69
|
+
@return Contents of the File as a @String@.
|
|
70
|
+
|
|
71
|
+
Reads all the contens (in ASCII mode) of a given file, length and offset
|
|
72
|
+
and returns them as an Array of lines being read.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
File read(filename, length, offset)
|
|
59
76
|
}
|
|
60
77
|
|
|
61
78
|
def File open: filename modes: modes_arr {
|
|
@@ -131,6 +148,22 @@ class File {
|
|
|
131
148
|
File rename(old_name, new_name)
|
|
132
149
|
}
|
|
133
150
|
|
|
151
|
+
def initialize: path {
|
|
152
|
+
initialize(path)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
def close {
|
|
156
|
+
"""
|
|
157
|
+
Closes an opened @File@.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
close()
|
|
162
|
+
} catch Errno::ENOENT => e {
|
|
163
|
+
IOError new: (e message) . raise!
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
134
167
|
def modes {
|
|
135
168
|
"""
|
|
136
169
|
@return @File@ access modes @Array@.
|
data/lib/rbx/fixnum.fy
CHANGED
|
@@ -9,11 +9,22 @@ class Fixnum {
|
|
|
9
9
|
|
|
10
10
|
ruby_aliases: [
|
|
11
11
|
'==, '-, '+, '*, '/, '<, '>, '<=, '>=,
|
|
12
|
-
'===, 'chr, 'to_i, 'to_f, '**, '&, '
|
|
12
|
+
'===, 'chr, 'to_i, 'to_f, '**, '&, '|,
|
|
13
|
+
'<<, '>>
|
|
13
14
|
]
|
|
14
15
|
|
|
15
16
|
alias_method: 'to_s: for: 'to_s
|
|
16
17
|
alias_method: 'modulo: for: 'modulo
|
|
17
18
|
alias_method: ":%" for: "modulo:" # use a : so we dont overwrite ruby's % operator
|
|
18
19
|
alias_method: 'div: for: 'div
|
|
20
|
+
|
|
21
|
+
def random {
|
|
22
|
+
"""
|
|
23
|
+
@return Random number between 0 and @self.
|
|
24
|
+
|
|
25
|
+
Returns a random number between 0 and @self.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
rand(self)
|
|
29
|
+
}
|
|
19
30
|
}
|
data/lib/rbx/method.fy
CHANGED
|
@@ -8,7 +8,7 @@ class MethodMixin {
|
|
|
8
8
|
@return Docstring for @self.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
Fancy Documentation for:
|
|
11
|
+
Fancy Documentation for: executable
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
def documentation: docstring {
|
|
@@ -16,7 +16,7 @@ class MethodMixin {
|
|
|
16
16
|
@docstring New docstring for @self.
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
|
-
Fancy Documentation for:
|
|
19
|
+
Fancy Documentation for: executable is: docstring
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
def visibility {
|
|
@@ -66,7 +66,13 @@ class MethodMixin {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
class Method {
|
|
69
|
+
"""
|
|
70
|
+
An instance of Method represents a method on a Class.
|
|
71
|
+
Every method in Fancy is an instance of the Method class.
|
|
72
|
+
"""
|
|
73
|
+
|
|
69
74
|
ruby_alias: 'arity
|
|
75
|
+
ruby_alias: 'executable
|
|
70
76
|
include: MethodMixin
|
|
71
77
|
forwards_unary_ruby_methods
|
|
72
78
|
}
|
|
@@ -77,6 +83,7 @@ class UnboundMethod {
|
|
|
77
83
|
"""
|
|
78
84
|
|
|
79
85
|
ruby_alias: 'arity
|
|
86
|
+
ruby_alias: 'executable
|
|
80
87
|
include: MethodMixin
|
|
81
88
|
forwards_unary_ruby_methods
|
|
82
89
|
}
|
data/lib/rbx/module.fy
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class Module {
|
|
2
|
+
forwards_unary_ruby_methods
|
|
3
|
+
|
|
4
|
+
def [constant_name] {
|
|
5
|
+
"""
|
|
6
|
+
@constant_name Name (@String@) of constant's name.
|
|
7
|
+
@return @constant_name's value.
|
|
8
|
+
|
|
9
|
+
Returns the value of the constant with the given name in @self.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
const_get(constant_name)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
def included: module {
|
|
16
|
+
"""
|
|
17
|
+
@module @Module@ or @Class@ that has been included into @self.
|
|
18
|
+
Gets called when a @Class@ or @Module@ is included into another @Class@.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
# do nothing by default
|
|
22
|
+
nil
|
|
23
|
+
}
|
|
24
|
+
}
|
data/lib/rbx/regexp.fy
CHANGED
data/lib/rbx/string.fy
CHANGED
|
@@ -6,20 +6,25 @@ class String {
|
|
|
6
6
|
'chomp, 'inspect, 'to_sym, '<, '>
|
|
7
7
|
]
|
|
8
8
|
|
|
9
|
+
alias_method: 'ruby_idx: for_ruby: '[]
|
|
9
10
|
alias_method: '[]: for_ruby: '[]=
|
|
10
11
|
alias_method: 'scan: for_ruby: 'scan
|
|
12
|
+
alias_method: 'uppercase for: 'upcase
|
|
13
|
+
alias_method: 'lowercase for: 'downcase
|
|
11
14
|
|
|
12
15
|
forwards_unary_ruby_methods
|
|
13
16
|
|
|
14
17
|
def [index] {
|
|
15
|
-
"""
|
|
16
|
-
|
|
18
|
+
"""
|
|
19
|
+
Given an Array of 2 Numbers, it returns the substring between the given indices.
|
|
20
|
+
If given a Number, returns the character at that index.
|
|
21
|
+
"""
|
|
17
22
|
|
|
18
23
|
# if given an Array, interpret it as a from:to: range substring
|
|
19
|
-
|
|
20
|
-
from: (index[0]) to: (index[1])
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
match index {
|
|
25
|
+
case Array -> from: (index[0]) to: (index[1])
|
|
26
|
+
case Tuple -> ruby_idx: index
|
|
27
|
+
case _ -> ruby_idx: index . chr()
|
|
23
28
|
}
|
|
24
29
|
}
|
|
25
30
|
|
|
@@ -31,7 +36,8 @@ class String {
|
|
|
31
36
|
|
|
32
37
|
Returns a Substring from @from to @to.
|
|
33
38
|
"""
|
|
34
|
-
|
|
39
|
+
|
|
40
|
+
ruby_idx: (from .. to)
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
def each: block {
|
|
@@ -146,4 +152,14 @@ class String {
|
|
|
146
152
|
|
|
147
153
|
include?(substring)
|
|
148
154
|
}
|
|
155
|
+
|
|
156
|
+
def substitute: substring with: substitution {
|
|
157
|
+
"""
|
|
158
|
+
@substring @String@ or @Regexp@ to be substituted.
|
|
159
|
+
@substitution @String@ to replace @substring with.
|
|
160
|
+
@return A new @String@ where @substring is substituted by @substitution.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
gsub(substring, substitution)
|
|
164
|
+
}
|
|
149
165
|
}
|