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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
class MalformedLogEntry : Error {
|
|
2
|
+
read_slot: 'text
|
|
3
|
+
def initialize: @text
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
class LogEntry {
|
|
7
|
+
read_write_slots: ('word, 'number)
|
|
8
|
+
|
|
9
|
+
def LogEntry parse_entry: text {
|
|
10
|
+
word, number = text split: "|"
|
|
11
|
+
number = number to_i
|
|
12
|
+
if: (word && number) then: {
|
|
13
|
+
LogEntry new do: {
|
|
14
|
+
word: word
|
|
15
|
+
number: number
|
|
16
|
+
}
|
|
17
|
+
} else: {
|
|
18
|
+
MalformedLogEntry new: text signal!
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class LogFile {
|
|
24
|
+
read_slots: ('filename, 'entries)
|
|
25
|
+
def initialize: @filename entries: @entries ([]);
|
|
26
|
+
def parse {
|
|
27
|
+
@text = File read: @filename
|
|
28
|
+
with_restarts: {
|
|
29
|
+
skip_entry: { nil }
|
|
30
|
+
} do: {
|
|
31
|
+
@text lines each: |line| {
|
|
32
|
+
@entries << (LogEntry parse_entry: line)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class LogAnalyzer {
|
|
39
|
+
read_slots: ('words, 'numbers)
|
|
40
|
+
def initialize: @logfiles {
|
|
41
|
+
@words = <[]>
|
|
42
|
+
@numbers = <[]>
|
|
43
|
+
}
|
|
44
|
+
def analyze_all {
|
|
45
|
+
@entries = @logfiles map: |f| {
|
|
46
|
+
LogFile new: f . do: { parse } . entries
|
|
47
|
+
} flatten
|
|
48
|
+
|
|
49
|
+
@entries each: |e| { analyze: e }
|
|
50
|
+
}
|
|
51
|
+
def analyze: entry {
|
|
52
|
+
if: (@words[entry word]) then: |val| {
|
|
53
|
+
@words[entry word]: (val + 1)
|
|
54
|
+
} else: {
|
|
55
|
+
@words[entry word]: 1
|
|
56
|
+
}
|
|
57
|
+
if: (@numbers[entry number]) then: |val| {
|
|
58
|
+
@numbers[entry number]: (val + 1)
|
|
59
|
+
} else: {
|
|
60
|
+
@numbers[entry number]: 1
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
l = LogAnalyzer new: ["examples/conditions_parsing_log.log"]
|
|
66
|
+
l analyze_all
|
|
67
|
+
" words: #{l words to_a sort_by: 'second reverse inspect}" println
|
|
68
|
+
"numbers: #{l numbers to_a sort_by: 'second reverse inspect}" println
|
data/examples/greeter.fy
ADDED
data/examples/html_generator.fy
CHANGED
|
@@ -10,45 +10,75 @@ class String {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
class HTML {
|
|
13
|
-
def
|
|
14
|
-
|
|
13
|
+
def initialize {
|
|
14
|
+
@buf = ""
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def initialize: block {
|
|
18
|
+
initialize
|
|
19
|
+
block call_with_receiver: self
|
|
20
|
+
self
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
def open_tag: name attrs: attrs (<[]>) {
|
|
24
|
+
@buf << "<" << (name but_last)
|
|
25
|
+
unless: (attrs empty?) do: {
|
|
26
|
+
@buf << " "
|
|
27
|
+
attrs each: |k v| {
|
|
28
|
+
@buf << k << "=" << (v inspect)
|
|
29
|
+
} in_between: {
|
|
30
|
+
@buf << " "
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
@buf << ">"
|
|
15
34
|
}
|
|
16
35
|
|
|
17
36
|
def close_tag: name {
|
|
18
|
-
"</"
|
|
37
|
+
@buf << "</" << (name but_last) << ">"
|
|
19
38
|
}
|
|
20
39
|
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
|
|
40
|
+
def html_block: tag body: body attrs: attrs (<[]>) {
|
|
41
|
+
open_tag: tag attrs: attrs
|
|
42
|
+
match body first {
|
|
43
|
+
case Block -> @buf << (body first call)
|
|
44
|
+
case _ -> @buf << (body first)
|
|
45
|
+
}
|
|
46
|
+
close_tag: tag
|
|
47
|
+
}
|
|
24
48
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
49
|
+
def unknown_message: m with_params: p {
|
|
50
|
+
match m to_s {
|
|
51
|
+
case /with:$/ ->
|
|
52
|
+
tag = m to_s substitute: /with:$/ with: ""
|
|
53
|
+
html_block: tag body: (p rest) attrs: (p first)
|
|
54
|
+
case _ ->
|
|
55
|
+
html_block: (m to_s) body: p
|
|
28
56
|
}
|
|
57
|
+
nil
|
|
58
|
+
}
|
|
29
59
|
|
|
30
|
-
|
|
60
|
+
def to_s {
|
|
61
|
+
@buf
|
|
31
62
|
}
|
|
32
63
|
}
|
|
33
64
|
|
|
34
|
-
# lets generate some simple HTML output )
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
]
|
|
65
|
+
# lets generate some simple HTML output :)
|
|
66
|
+
HTML new: |h| {
|
|
67
|
+
html: {
|
|
68
|
+
body: <['id => "body id" ]> with: {
|
|
69
|
+
div: {
|
|
70
|
+
"hello, world!"
|
|
71
|
+
}
|
|
72
|
+
div: {
|
|
73
|
+
p: {
|
|
74
|
+
"OKIDOKI"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
div: {
|
|
78
|
+
h3: {
|
|
79
|
+
"oh no!"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
53
83
|
}
|
|
54
84
|
} . println
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
# webserver.fy
|
|
2
2
|
# Example of a simple webserver written in fancy, using Ruby socket library
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
port = 3000
|
|
7
|
-
webserver = TCPServer new(host, port)
|
|
4
|
+
host, port = "127.0.0.1", 3000
|
|
5
|
+
webserver = TCPServer new: host port: port
|
|
8
6
|
"Webserver running at: #{host}:#{port}" println
|
|
7
|
+
|
|
9
8
|
loop: {
|
|
10
9
|
session = webserver accept
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
session print: content
|
|
17
|
-
session close
|
|
10
|
+
Thread new: {
|
|
11
|
+
session print: "HTTP/1.1 200/OK\r\nContent-type:text/html\r\n\r\n"
|
|
12
|
+
session print: $ File read: "examples/webserver/index.html"
|
|
13
|
+
session close
|
|
14
|
+
}
|
|
18
15
|
}
|
data/lib/argv.fy
CHANGED
data/lib/array.fy
CHANGED
|
@@ -5,7 +5,7 @@ class Array {
|
|
|
5
5
|
index-based access to members.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
include:
|
|
8
|
+
include: Fancy Enumerable
|
|
9
9
|
|
|
10
10
|
def Array new: size {
|
|
11
11
|
"""
|
|
@@ -160,22 +160,6 @@ class Array {
|
|
|
160
160
|
self
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
def each_with_index: block {
|
|
164
|
-
"""
|
|
165
|
-
@block @Block@ to be called with each element and its inde in the @Array@.
|
|
166
|
-
@return @self
|
|
167
|
-
|
|
168
|
-
Iterate over all elements in @Array@.
|
|
169
|
-
Calls a given @Block@ with each element and its index.
|
|
170
|
-
"""
|
|
171
|
-
|
|
172
|
-
i = 0
|
|
173
|
-
each: |x| {
|
|
174
|
-
block call: [x, i]
|
|
175
|
-
i = i + 1
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
163
|
def =? other {
|
|
180
164
|
"""
|
|
181
165
|
@other Other @Array@ to compare this one to.
|
|
@@ -441,24 +425,6 @@ class Array {
|
|
|
441
425
|
subarr
|
|
442
426
|
}
|
|
443
427
|
|
|
444
|
-
def select: block {
|
|
445
|
-
"""
|
|
446
|
-
@block Predicate @Block@ to be used as filter.
|
|
447
|
-
@return @Array@ of all the elements for which @block doesn't yield @false or @nil.
|
|
448
|
-
|
|
449
|
-
Returns a new Array with all the elements in self that yield a
|
|
450
|
-
true-ish value when called with the given Block.
|
|
451
|
-
"""
|
|
452
|
-
|
|
453
|
-
tmp = []
|
|
454
|
-
each: |x| {
|
|
455
|
-
if: (block call: [x]) then: {
|
|
456
|
-
tmp << x
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
return tmp
|
|
460
|
-
}
|
|
461
|
-
|
|
462
428
|
def select_with_index: block {
|
|
463
429
|
"""
|
|
464
430
|
Same as #select:, just gets also called with an additional argument
|
|
@@ -474,6 +440,22 @@ class Array {
|
|
|
474
440
|
tmp
|
|
475
441
|
}
|
|
476
442
|
|
|
443
|
+
def to_hash {
|
|
444
|
+
"""
|
|
445
|
+
Returns a @Hash@ with each key-value pair in @self.
|
|
446
|
+
|
|
447
|
+
Example:
|
|
448
|
+
[[1,2],[3,4]] to_hash # => <[1 => 2, 3 => 4]>
|
|
449
|
+
"""
|
|
450
|
+
|
|
451
|
+
h = <[]>
|
|
452
|
+
self each: |pair| {
|
|
453
|
+
k,v = pair
|
|
454
|
+
h[k]: v
|
|
455
|
+
}
|
|
456
|
+
h
|
|
457
|
+
}
|
|
458
|
+
|
|
477
459
|
def Array === object {
|
|
478
460
|
"""
|
|
479
461
|
@object Object to match @self against.
|
data/lib/block.fy
CHANGED
|
@@ -120,7 +120,88 @@ class Block {
|
|
|
120
120
|
call: [val]
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
def Block inspect {
|
|
124
|
+
name
|
|
125
|
+
}
|
|
126
|
+
|
|
123
127
|
def Block name {
|
|
124
128
|
"Block"
|
|
125
129
|
}
|
|
126
|
-
|
|
130
|
+
|
|
131
|
+
def [args] {
|
|
132
|
+
"""
|
|
133
|
+
Same as Block#call:
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
call: args
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
def to_object {
|
|
140
|
+
"""
|
|
141
|
+
Creates and returns a new @Object@ with slots defined dynamically in @self.
|
|
142
|
+
Looks and feels similar to Javascript object literals.
|
|
143
|
+
|
|
144
|
+
Example:
|
|
145
|
+
o = {
|
|
146
|
+
something: \"foo bar baz\"
|
|
147
|
+
with: 42
|
|
148
|
+
} to_object
|
|
149
|
+
|
|
150
|
+
o something # => \"foo bar baz\"
|
|
151
|
+
o with # => 42
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
obj = DynamicSlotObject new do: self . object
|
|
155
|
+
obj metaclass read_write_slots: (obj slots)
|
|
156
|
+
obj
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
def to_hash {
|
|
160
|
+
"""
|
|
161
|
+
Creates and returns a new @Hash@ with keys and values defined dynamically in @self.
|
|
162
|
+
Similar to @Block#object@ but returning a @Hash@ instead of an @Object@
|
|
163
|
+
|
|
164
|
+
Example:
|
|
165
|
+
o = {
|
|
166
|
+
something: \"foo bar baz\"
|
|
167
|
+
with: 42
|
|
168
|
+
} to_hash # => <['something => \"foo bar baz\", 'with => 42]>
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
DynamicKeyHash new do: self . hash
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
def to_hash_deep {
|
|
175
|
+
"""
|
|
176
|
+
Creates and returns a new @Hash@ with keys and values defined dynamically in @self.
|
|
177
|
+
Similar to @Block#to_hash@ but converting any value that's a @Block@ to a @Hash@ as well.
|
|
178
|
+
|
|
179
|
+
Example:
|
|
180
|
+
o = {
|
|
181
|
+
something: \"foo bar baz\"
|
|
182
|
+
with: 42
|
|
183
|
+
and: {
|
|
184
|
+
another: 'field
|
|
185
|
+
}
|
|
186
|
+
} to_hash_deep # => <['something => \"foo bar baz\", 'with => 42, 'and => <['another => 'field]>]>
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
DynamicKeyHash new: true . do: self . hash
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
def to_a {
|
|
193
|
+
"""
|
|
194
|
+
Creates and returns a new @Array@ with values defined dynamically in @self.
|
|
195
|
+
Similar to @Block#to_hash@ but returning an @Array@ instead of a @Hash@
|
|
196
|
+
|
|
197
|
+
Example:
|
|
198
|
+
a = {
|
|
199
|
+
something: \"foo bar baz\"
|
|
200
|
+
with: 42
|
|
201
|
+
something; else
|
|
202
|
+
} to_a # => [['something, \"foo bar baz\"], ['with, 42], 'something, 'else]
|
|
203
|
+
"""
|
|
204
|
+
|
|
205
|
+
DynamicValueArray new do: self . array
|
|
206
|
+
}
|
|
207
|
+
}
|
data/lib/boot.fy
CHANGED
|
@@ -24,6 +24,7 @@ require: "string"
|
|
|
24
24
|
require: "array"
|
|
25
25
|
require: "range"
|
|
26
26
|
require: "tuple"
|
|
27
|
+
require: "dynamic_slot_object"
|
|
27
28
|
require: "block"
|
|
28
29
|
require: "iteration"
|
|
29
30
|
require: "integer"
|
|
@@ -33,19 +34,20 @@ require: "directory"
|
|
|
33
34
|
require: "hash"
|
|
34
35
|
require: "set"
|
|
35
36
|
require: "symbol"
|
|
36
|
-
require: "method"
|
|
37
37
|
require: "stack"
|
|
38
38
|
require: "proxy"
|
|
39
39
|
require: "thread_pool"
|
|
40
40
|
require: "fiber"
|
|
41
|
-
require: "fiber_pool"
|
|
42
41
|
require: "future"
|
|
43
42
|
require: "struct"
|
|
43
|
+
require: "message_sink"
|
|
44
|
+
require: "kvo"
|
|
44
45
|
|
|
45
46
|
# version holds fancy's version number
|
|
46
47
|
require: "version"
|
|
47
48
|
require: "argv"
|
|
48
49
|
require: "vars"
|
|
50
|
+
require: "system"
|
|
49
51
|
|
|
50
52
|
require: "documentation"
|
|
51
53
|
|
data/lib/compiler.fy
CHANGED