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/main.fy
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
if: (ARGV size == 1) then: {
|
|
8
8
|
ARGV for_options: ["-v", "--version"] do: {
|
|
9
9
|
"Fancy " ++ FANCY_VERSION println
|
|
10
|
-
"(C) 2010, 2011 Christopher Bertels <chris@fancy-lang.org>" println
|
|
10
|
+
"(C) 2010, 2011, 2012 Christopher Bertels <chris@fancy-lang.org>" println
|
|
11
11
|
System exit
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -24,6 +24,7 @@ if: (ARGV size == 1) then: {
|
|
|
24
24
|
"",
|
|
25
25
|
"Fancy package management:",
|
|
26
26
|
" install [packagename] Install a Fancy package with a given name to $FANCYPACK_DIR",
|
|
27
|
+
" install --deps Install dependencies specified in .fancypack file (expected in current directory).",
|
|
27
28
|
" uninstall [packagename] Uninstall a Fancy package with a given name from $FANCYPACK_DIR"] println
|
|
28
29
|
System exit # quit when running --help
|
|
29
30
|
}
|
|
@@ -59,7 +60,10 @@ ARGV for_option: "-cv" do: {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
ARGV for_option: "install" do: |package_name| {
|
|
62
|
-
|
|
63
|
+
match package_name {
|
|
64
|
+
case "--deps" -> Fancy Package install_dependencies
|
|
65
|
+
case _ -> Fancy Package install: package_name
|
|
66
|
+
}
|
|
63
67
|
System exit
|
|
64
68
|
}
|
|
65
69
|
|
data/lib/message_sink.fy
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class Fancy {
|
|
2
|
+
class MessageSink : BasicObject {
|
|
3
|
+
"""
|
|
4
|
+
A MessageSink just swallows all messages that are sent to it.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
def unknown_message: m with_params: p {
|
|
8
|
+
"""
|
|
9
|
+
@m Message sent to @self.
|
|
10
|
+
@p @Array@ of parameters sent along with @m.
|
|
11
|
+
@return @self.
|
|
12
|
+
|
|
13
|
+
Catches all messages and arguments and simply always returns @self.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
self
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
data/lib/number.fy
CHANGED
|
@@ -39,6 +39,25 @@ class Number {
|
|
|
39
39
|
self
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
def upto: num in_steps_of: steps do: block {
|
|
43
|
+
"""
|
|
44
|
+
@num Maximum @Number@ to call @block with.
|
|
45
|
+
@steps @Number@ of numbers to skip each step.
|
|
46
|
+
@block A @Block@ that should be called every @steps steps between @self and @num.
|
|
47
|
+
@return @self
|
|
48
|
+
|
|
49
|
+
Calls @block every @steps steps between @self and @num with the current @Number@.
|
|
50
|
+
Expects @num to be greater or equal to @self.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
i = self
|
|
54
|
+
while: { i <= num } do: {
|
|
55
|
+
block call: [i]
|
|
56
|
+
i = i + steps
|
|
57
|
+
}
|
|
58
|
+
self
|
|
59
|
+
}
|
|
60
|
+
|
|
42
61
|
def downto: num {
|
|
43
62
|
"""
|
|
44
63
|
@num @Number@ to create an @Array@ down to.
|
|
@@ -75,6 +94,25 @@ class Number {
|
|
|
75
94
|
self
|
|
76
95
|
}
|
|
77
96
|
|
|
97
|
+
def downto: num in_steps_of: steps do: block {
|
|
98
|
+
"""
|
|
99
|
+
@num Minimum @Number@ to call @block with.
|
|
100
|
+
@steps @Number@ of numbers to skip each step.
|
|
101
|
+
@block A @Block@ that should be called every @steps steps between @self and @num.
|
|
102
|
+
@return @self
|
|
103
|
+
|
|
104
|
+
Calls @block every @steps steps between @self and @num with the current @Number@.
|
|
105
|
+
Expects @num to be smaller or equal to @self.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
i = self
|
|
109
|
+
while: { i >= num } do: {
|
|
110
|
+
block call: [i]
|
|
111
|
+
i = i - steps
|
|
112
|
+
}
|
|
113
|
+
self
|
|
114
|
+
}
|
|
115
|
+
|
|
78
116
|
def squared {
|
|
79
117
|
"""
|
|
80
118
|
@return Squared value of @self.
|
|
@@ -95,6 +133,16 @@ class Number {
|
|
|
95
133
|
self + self
|
|
96
134
|
}
|
|
97
135
|
|
|
136
|
+
def cubed {
|
|
137
|
+
"""
|
|
138
|
+
@return Cubed value of @self.
|
|
139
|
+
|
|
140
|
+
Returns the cubed value of a Number.
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
self ** 3
|
|
144
|
+
}
|
|
145
|
+
|
|
98
146
|
def abs {
|
|
99
147
|
"""
|
|
100
148
|
@return Absolute (positive) value of @self.
|
data/lib/object.fy
CHANGED
|
@@ -29,9 +29,9 @@ class Object {
|
|
|
29
29
|
def println {
|
|
30
30
|
"""
|
|
31
31
|
Same as:
|
|
32
|
-
|
|
32
|
+
*stdout* println: self
|
|
33
33
|
|
|
34
|
-
Prints @self on
|
|
34
|
+
Prints @self on @*stdout*, followed by a newline.
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
37
|
*stdout* println: to_s
|
|
@@ -40,9 +40,9 @@ class Object {
|
|
|
40
40
|
def print {
|
|
41
41
|
"""
|
|
42
42
|
Same as:
|
|
43
|
-
|
|
43
|
+
*stdout* print: self
|
|
44
44
|
|
|
45
|
-
Prints @self on
|
|
45
|
+
Prints @self on @*stdout*.
|
|
46
46
|
"""
|
|
47
47
|
|
|
48
48
|
*stdout* print: to_s
|
|
@@ -149,19 +149,19 @@ class Object {
|
|
|
149
149
|
|
|
150
150
|
def to_enum {
|
|
151
151
|
"""
|
|
152
|
-
@return @
|
|
152
|
+
@return @Fancy::Enumerator@ for @self using 'each: for iteration.
|
|
153
153
|
"""
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
Fancy Enumerator new: self
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
def to_enum: iterator {
|
|
159
159
|
"""
|
|
160
160
|
@iterator Message to use for iteration on @self.
|
|
161
|
-
@return @
|
|
161
|
+
@return @Fancy::Enumerator@ for @self using @iterator for iteration.
|
|
162
162
|
"""
|
|
163
163
|
|
|
164
|
-
|
|
164
|
+
Fancy Enumerator new: self with: iterator
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
def and: other {
|
|
@@ -539,11 +539,28 @@ class Object {
|
|
|
539
539
|
}
|
|
540
540
|
|
|
541
541
|
def copy_slots: slots from: object {
|
|
542
|
+
"""
|
|
543
|
+
@slots @Fancy::Enumerable@ of slot names to copy from @object.
|
|
544
|
+
@object Target @Object@ to copy slots from.
|
|
545
|
+
|
|
546
|
+
Copies slots from @object to @self.
|
|
547
|
+
"""
|
|
548
|
+
|
|
542
549
|
slots each: |s| {
|
|
543
550
|
set_slot: s value: (object get_slot: s)
|
|
544
551
|
}
|
|
545
552
|
}
|
|
546
553
|
|
|
554
|
+
def copy_slots_from: object {
|
|
555
|
+
"""
|
|
556
|
+
@object @Object@ to copy slots from.
|
|
557
|
+
|
|
558
|
+
Copies all slots from @object to @self.
|
|
559
|
+
"""
|
|
560
|
+
|
|
561
|
+
copy_slots: (object slots) from: object
|
|
562
|
+
}
|
|
563
|
+
|
|
547
564
|
def get_slots: slots {
|
|
548
565
|
"""
|
|
549
566
|
@slots @Array@ of slot names to retrieve from @self.
|
|
@@ -590,14 +607,24 @@ class Object {
|
|
|
590
607
|
self
|
|
591
608
|
}
|
|
592
609
|
|
|
610
|
+
def tap: block {
|
|
611
|
+
"""
|
|
612
|
+
@block @Block@ to be called with @self.
|
|
613
|
+
@return @self.
|
|
614
|
+
|
|
615
|
+
Calls a given @Block@ with @self before returning @self.
|
|
616
|
+
"""
|
|
617
|
+
|
|
618
|
+
block call: [self]
|
|
619
|
+
self
|
|
620
|
+
}
|
|
621
|
+
|
|
593
622
|
def slots {
|
|
594
623
|
"""
|
|
595
|
-
@return @
|
|
624
|
+
@return @Array@ of slot names that @self has.
|
|
596
625
|
"""
|
|
597
626
|
|
|
598
|
-
|
|
599
|
-
s rest to_sym
|
|
600
|
-
}
|
|
627
|
+
instance_variables map: @{ rest to_sym }
|
|
601
628
|
}
|
|
602
629
|
|
|
603
630
|
def sleep: seconds {
|
|
@@ -620,7 +647,7 @@ class Object {
|
|
|
620
647
|
Dynamically rebinds @var_name as dynamic variable with @value as the value within @block.
|
|
621
648
|
|
|
622
649
|
Example:
|
|
623
|
-
File
|
|
650
|
+
File write: \"/tmp/output.txt\" with: |f| {
|
|
624
651
|
let: '*stdout* be: f in: {
|
|
625
652
|
\"hello, world!\" println # writes it to file not STDOUT
|
|
626
653
|
}
|
|
@@ -638,9 +665,34 @@ class Object {
|
|
|
638
665
|
try {
|
|
639
666
|
Thread current[var_name]: value
|
|
640
667
|
retval = block call
|
|
668
|
+
} catch Exception => e {
|
|
669
|
+
e raise!
|
|
641
670
|
} finally {
|
|
642
671
|
Thread current[var_name]: oldval
|
|
643
672
|
return retval
|
|
644
673
|
}
|
|
645
674
|
}
|
|
675
|
+
|
|
676
|
+
def with_output_to: filename do: block {
|
|
677
|
+
"""
|
|
678
|
+
@filename Filename of file to write to.
|
|
679
|
+
@block @Block@ to be executed with *stdout* being bound to the output file.
|
|
680
|
+
|
|
681
|
+
Opens @filename and rebinds `*stdout*` to it within @block.
|
|
682
|
+
|
|
683
|
+
Example:
|
|
684
|
+
with_output_to: \"/tmp/hello_world.txt\" do: {
|
|
685
|
+
\"hello\" println
|
|
686
|
+
\"world\" println
|
|
687
|
+
}
|
|
688
|
+
This writes
|
|
689
|
+
hello
|
|
690
|
+
world
|
|
691
|
+
to /tmp/hello_world.txt
|
|
692
|
+
"""
|
|
693
|
+
|
|
694
|
+
File write: filename with: |f| {
|
|
695
|
+
let: '*stdout* be: f in: block
|
|
696
|
+
}
|
|
697
|
+
}
|
|
646
698
|
}
|
data/lib/package.fy
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require: "package/installer"
|
|
2
|
+
require: "package/dependency_installer"
|
|
2
3
|
require: "package/uninstaller"
|
|
3
4
|
require: "package/dependency"
|
|
4
5
|
require: "package/specification"
|
|
@@ -29,7 +30,7 @@ class Fancy Package {
|
|
|
29
30
|
DEFAULT_PACKAGES_PATH = DEFAULT_FANCY_ROOT ++ "/packages"
|
|
30
31
|
DEFAULT_PACKAGES_LIB_PATH = DEFAULT_PACKAGES_PATH ++ "/lib"
|
|
31
32
|
|
|
32
|
-
def self install: package_name {
|
|
33
|
+
def self install: package_name version: version ('latest) {
|
|
33
34
|
"""
|
|
34
35
|
@package_name Name of package to install.
|
|
35
36
|
|
|
@@ -39,7 +40,16 @@ class Fancy Package {
|
|
|
39
40
|
Which would get the package code from github.com/user/repo
|
|
40
41
|
"""
|
|
41
42
|
|
|
42
|
-
Installer new: package_name . run
|
|
43
|
+
Installer new: package_name version: version . run
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
def self install_dependencies {
|
|
47
|
+
"""
|
|
48
|
+
Installs dependencies found in .fancypack file in the current directory.
|
|
49
|
+
If no .fancypack file is found, fails and quits.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
DependencyInstaller new run
|
|
43
53
|
}
|
|
44
54
|
|
|
45
55
|
def self uninstall: package_name {
|
data/lib/package/dependency.fy
CHANGED
|
@@ -20,5 +20,18 @@ class Fancy Package {
|
|
|
20
20
|
|
|
21
21
|
def initialize: @gem_name version: @version ('latest) {
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
def install {
|
|
25
|
+
"""
|
|
26
|
+
Installs the RubyDependency (a RubyGem) via rbx -S gem on the system.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
match @version {
|
|
30
|
+
case 'latest ->
|
|
31
|
+
System do: "rbx gem install #{@gem_name}"
|
|
32
|
+
case _ ->
|
|
33
|
+
System do: "rbx gem install -v=#{@version} #{@gem_name}"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
23
36
|
}
|
|
24
37
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class Fancy {
|
|
2
|
+
class Package {
|
|
3
|
+
class DependencyInstaller {
|
|
4
|
+
def run {
|
|
5
|
+
packfile = Dir glob("*.fancypack") first
|
|
6
|
+
unless: packfile do: {
|
|
7
|
+
*stderr* println: "No .fancypack file found. Quitting."
|
|
8
|
+
return nil
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
require: packfile
|
|
12
|
+
|
|
13
|
+
spec_name = packfile split: ".fancypack" . first
|
|
14
|
+
if: (Specification[spec_name]) then: |s| {
|
|
15
|
+
s dependencies each: |dep| {
|
|
16
|
+
"Installing dependency: #{dep name} (#{dep version})" println
|
|
17
|
+
Fancy Package install: (dep name) version: (dep version)
|
|
18
|
+
}
|
|
19
|
+
s rubygem_dependencies each: |dep| {
|
|
20
|
+
"Installing Ruby dependency: #{dep gem_name} (#{dep version})" println
|
|
21
|
+
dep install
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
data/lib/package/installer.fy
CHANGED
|
@@ -13,10 +13,10 @@ class Fancy Package {
|
|
|
13
13
|
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
-
def initialize: @package_name version: @version (
|
|
16
|
+
def initialize: @package_name version: @version ('latest) install_path: @install_path (ENV["FANCY_PACKAGE_DIR"]) {
|
|
17
17
|
"""
|
|
18
18
|
Creates a new @Package Installer@ for a given package name, an
|
|
19
|
-
optional version (default is 'latest
|
|
19
|
+
optional version (default is 'latest) and an optional
|
|
20
20
|
installation path (default is the standard installation path for
|
|
21
21
|
Fancy packages).
|
|
22
22
|
"""
|
|
@@ -50,7 +50,7 @@ class Fancy Package {
|
|
|
50
50
|
"""
|
|
51
51
|
|
|
52
52
|
filename = nil
|
|
53
|
-
if: (@version ==
|
|
53
|
+
if: (@version == 'latest) then: {
|
|
54
54
|
if: latest_tag then: |tag| {
|
|
55
55
|
@version = tag
|
|
56
56
|
} else: {
|
|
@@ -200,13 +200,7 @@ class Fancy Package {
|
|
|
200
200
|
Package install: dep
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
spec rubygem_dependencies each: |dep| {
|
|
204
|
-
if: (dep version == 'latest) then: {
|
|
205
|
-
System do: $ "rbx gem install " ++ (dep gem_name)
|
|
206
|
-
} else: {
|
|
207
|
-
System do: $ "rbx gem install -v=" ++ (dep version) ++ " " ++ (dep gem_name)
|
|
208
|
-
}
|
|
209
|
-
}
|
|
203
|
+
spec rubygem_dependencies each: |dep| { dep install }
|
|
210
204
|
}
|
|
211
205
|
}
|
|
212
206
|
}
|
data/lib/package/uninstaller.fy
CHANGED
data/lib/parser/ext/lexer.lex
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#include "ruby.h"
|
|
3
3
|
#include "parser.h"
|
|
4
4
|
|
|
5
|
-
int yyerror(char *s);
|
|
5
|
+
int yyerror(VALUE self, char *s);
|
|
6
6
|
%}
|
|
7
7
|
|
|
8
8
|
%option yylineno
|
|
@@ -54,7 +54,7 @@ identifier @?@?({lower}|[_&*])({letter}|{digit}|{special_under})*
|
|
|
54
54
|
selector ({letter}|[_&*])({letter}|{digit}|{special_under})*":"
|
|
55
55
|
constant {capital}({letter}|{digit}|{special_under})*
|
|
56
56
|
nested_constant ({constant}::)+{constant}
|
|
57
|
-
symbol_lit \'({identifier}|{operator}|{constant}|:|"[]"|"|")+
|
|
57
|
+
symbol_lit \'({identifier}|{operator}|{constant}|:|"[]"|"|"|".")+
|
|
58
58
|
ruby_send_open ({constant}|{identifier}){lparen}
|
|
59
59
|
ruby_oper_open {operator}{lparen}
|
|
60
60
|
regexp_lit "/".*"/"
|
|
@@ -186,5 +186,10 @@ escaped_newline "\\".*\n
|
|
|
186
186
|
{escaped_newline} {}
|
|
187
187
|
[\n] { return NL; }
|
|
188
188
|
|
|
189
|
-
. {
|
|
189
|
+
. {
|
|
190
|
+
fprintf(stderr, "Invalid token: %s\n", yytext);
|
|
191
|
+
VALUE fancy = rb_const_get(rb_cObject, rb_intern("Fancy"));
|
|
192
|
+
VALUE parser = rb_const_get(fancy, rb_intern("Parser"));
|
|
193
|
+
yyerror(parser, yytext);
|
|
194
|
+
}
|
|
190
195
|
|
data/lib/parser/ext/parser.y
CHANGED
|
@@ -273,6 +273,9 @@ identifier: IDENTIFIER {
|
|
|
273
273
|
| CLASS {
|
|
274
274
|
$$ = fy_terminal_node_from(self, "ast:identifier:", "class");
|
|
275
275
|
}
|
|
276
|
+
| RETURN {
|
|
277
|
+
$$ = fy_terminal_node_from(self, "ast:identifier:", "return");
|
|
278
|
+
}
|
|
276
279
|
;
|
|
277
280
|
|
|
278
281
|
any_identifier: const_identifier
|
|
@@ -821,7 +824,7 @@ VALUE fy_terminal_node_from(VALUE self, char* method, char* text) {
|
|
|
821
824
|
|
|
822
825
|
int yyerror(VALUE self, char *s)
|
|
823
826
|
{
|
|
824
|
-
rb_funcall(self, rb_intern("ast:parse_error:"), 2, INT2NUM(yylineno), rb_str_new2(
|
|
827
|
+
rb_funcall(self, rb_intern("ast:parse_error:"), 2, INT2NUM(yylineno), rb_str_new2(s));
|
|
825
828
|
return 1;
|
|
826
829
|
}
|
|
827
830
|
|
data/lib/parser/methods.fy
CHANGED
|
@@ -13,9 +13,13 @@ class Fancy {
|
|
|
13
13
|
new: filename line: line . parse_string: code . script
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
def self ast: line parse_error: text {
|
|
17
|
+
ParseError new: line message: text filename: (Thread current['__fancy__parser__filename__]) . raise!
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
read_write_slots: ['filename, 'line, 'script]
|
|
17
21
|
|
|
18
|
-
def initialize: @filename line: @line { }
|
|
22
|
+
def initialize: @filename line: @line { Thread current['__fancy__parser__filename__]: @filename }
|
|
19
23
|
|
|
20
24
|
def body: body {
|
|
21
25
|
@script = AST Script new: @line file: @filename body: body
|
|
@@ -69,7 +73,7 @@ class Fancy {
|
|
|
69
73
|
# TODO: Clean this up or make it simpler...
|
|
70
74
|
|
|
71
75
|
# this case handles string interpolation
|
|
72
|
-
case /(.*)#{(.*)}(.*)/ -> |matches|
|
|
76
|
+
case /(.*)#{(.*)}(.*)/m -> |matches|
|
|
73
77
|
prefix = matches[1]
|
|
74
78
|
interpol_str = matches[2]
|
|
75
79
|
suffix = matches[3]
|
|
@@ -78,7 +82,7 @@ class Fancy {
|
|
|
78
82
|
suffix_str = ast: line string: (" " + suffix + " ")
|
|
79
83
|
interpol_ast = AST StringInterpolation new: line code: interpol_str
|
|
80
84
|
# create messagesend to concatenate:
|
|
81
|
-
concat_ident = ast: line identifier: "
|
|
85
|
+
concat_ident = ast: line identifier: "<<"
|
|
82
86
|
interpol_send = AST MessageSend new: line message: concat_ident to: prefix_str args: (AST MessageArgs new: line args: [interpol_ast])
|
|
83
87
|
|
|
84
88
|
# don't concatenate suffix if it's empty..
|