fancy 0.3.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 +7 -0
- data/LICENSE +19 -0
- data/README +173 -0
- data/Rakefile +255 -0
- data/bin/fancy +40 -0
- data/bin/fdoc +23 -0
- data/bin/fyi +22 -0
- data/bin/ifancy +46 -0
- data/boot/README +12 -0
- data/boot/code_loader.rb +165 -0
- data/boot/compile.fy +3 -0
- data/boot/fancy_ext.rb +13 -0
- data/boot/fancy_ext/block_env.rb +29 -0
- data/boot/fancy_ext/class.rb +26 -0
- data/boot/fancy_ext/kernel.rb +12 -0
- data/boot/fancy_ext/module.rb +89 -0
- data/boot/fancy_ext/object.rb +34 -0
- data/boot/fancy_ext/string_helper.rb +10 -0
- data/boot/load.rb +72 -0
- data/boot/rbx-compiler/README +12 -0
- data/boot/rbx-compiler/compiler.rb +24 -0
- data/boot/rbx-compiler/compiler/ast.rb +23 -0
- data/boot/rbx-compiler/compiler/ast/README +11 -0
- data/boot/rbx-compiler/compiler/ast/array_literal.rb +13 -0
- data/boot/rbx-compiler/compiler/ast/assign.rb +57 -0
- data/boot/rbx-compiler/compiler/ast/block.rb +70 -0
- data/boot/rbx-compiler/compiler/ast/class_def.rb +35 -0
- data/boot/rbx-compiler/compiler/ast/expression_list.rb +57 -0
- data/boot/rbx-compiler/compiler/ast/hash_literal.rb +11 -0
- data/boot/rbx-compiler/compiler/ast/identifier.rb +120 -0
- data/boot/rbx-compiler/compiler/ast/match.rb +81 -0
- data/boot/rbx-compiler/compiler/ast/message_send.rb +71 -0
- data/boot/rbx-compiler/compiler/ast/method_def.rb +116 -0
- data/boot/rbx-compiler/compiler/ast/node.rb +6 -0
- data/boot/rbx-compiler/compiler/ast/range_literal.rb +22 -0
- data/boot/rbx-compiler/compiler/ast/require.rb +20 -0
- data/boot/rbx-compiler/compiler/ast/return.rb +29 -0
- data/boot/rbx-compiler/compiler/ast/ruby_args.rb +35 -0
- data/boot/rbx-compiler/compiler/ast/script.rb +56 -0
- data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +39 -0
- data/boot/rbx-compiler/compiler/ast/string_literal.rb +14 -0
- data/boot/rbx-compiler/compiler/ast/super.rb +25 -0
- data/boot/rbx-compiler/compiler/ast/try_catch_block.rb +220 -0
- data/boot/rbx-compiler/compiler/ast/tuple_literal.rb +33 -0
- data/boot/rbx-compiler/compiler/command.rb +39 -0
- data/boot/rbx-compiler/compiler/compiler.rb +83 -0
- data/boot/rbx-compiler/compiler/stages.rb +99 -0
- data/boot/rbx-compiler/parser.rb +2 -0
- data/boot/rbx-compiler/parser/README +15 -0
- data/boot/rbx-compiler/parser/Rakefile +54 -0
- data/boot/rbx-compiler/parser/extconf.rb +3 -0
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/fancy_parser.c +46 -0
- data/boot/rbx-compiler/parser/fancy_parser.h +8 -0
- data/boot/rbx-compiler/parser/lexer.lex +180 -0
- data/boot/rbx-compiler/parser/parser.rb +356 -0
- data/boot/rbx-compiler/parser/parser.y +711 -0
- data/boot/rsexp_pretty_printer.rb +76 -0
- data/doc/api/fancy.css +93 -0
- data/doc/api/fancy.jsonp +1 -0
- data/doc/api/fdoc.js +187 -0
- data/doc/api/index.html +57 -0
- data/doc/api/underscore-min.js +18 -0
- data/doc/features.md +228 -0
- data/examples/argv.fy +8 -0
- data/examples/arithmetic.fy +7 -0
- data/examples/armstrong_numbers.fy +33 -0
- data/examples/array.fy +52 -0
- data/examples/blocks.fy +15 -0
- data/examples/boolean.fy +24 -0
- data/examples/call_with_receiver.fy +9 -0
- data/examples/class.fy +68 -0
- data/examples/closures.fy +24 -0
- data/examples/constant_access.fy +15 -0
- data/examples/default_args.fy +17 -0
- data/examples/define_methods.fy +15 -0
- data/examples/documentation.fy +57 -0
- data/examples/documentation_formatters.fy +25 -0
- data/examples/echo.fy +16 -0
- data/examples/empty_catch.fy +4 -0
- data/examples/exception.fy +9 -0
- data/examples/factorial.fy +12 -0
- data/examples/fibonacci.fy +16 -0
- data/examples/files.fy +23 -0
- data/examples/finally.fy +5 -0
- data/examples/game_of_life.fy +148 -0
- data/examples/hashes.fy +7 -0
- data/examples/hello_world.fy +6 -0
- data/examples/html_generator.fy +54 -0
- data/examples/implicit_return.fy +3 -0
- data/examples/matchers.fy +6 -0
- data/examples/methods.fy +29 -0
- data/examples/nested_classes.fy +27 -0
- data/examples/nested_try.fy +9 -0
- data/examples/numbers.fy +12 -0
- data/examples/pattern_matching.fy +40 -0
- data/examples/person.fy +65 -0
- data/examples/project-euler/01.fy +8 -0
- data/examples/project-euler/02.fy +21 -0
- data/examples/project-euler/28.fy +33 -0
- data/examples/rbx/and_or.fy +7 -0
- data/examples/rbx/blocks.fy +22 -0
- data/examples/rbx/classes.fy +32 -0
- data/examples/rbx/hello.fy +8 -0
- data/examples/rbx/include.fy +12 -0
- data/examples/rbx/inherit.fy +11 -0
- data/examples/rbx/methods.fy +15 -0
- data/examples/rbx/nested_classes.fy +9 -0
- data/examples/rbx/require.fy +3 -0
- data/examples/rbx/strings.fy +5 -0
- data/examples/regex.fy +7 -0
- data/examples/require.fy +7 -0
- data/examples/retry.fy +12 -0
- data/examples/return.fy +13 -0
- data/examples/ruby_require.fy +7 -0
- data/examples/ruby_send.fy +3 -0
- data/examples/singleton_methods.fy +21 -0
- data/examples/stupid_quicksort.fy +12 -0
- data/examples/threads.fy +18 -0
- data/examples/tuple.fy +8 -0
- data/examples/webserver/webserver.fy +18 -0
- data/lib/argv.fy +36 -0
- data/lib/array.fy +207 -0
- data/lib/block.fy +88 -0
- data/lib/boot.fy +41 -0
- data/lib/class.fy +106 -0
- data/lib/compiler.fy +14 -0
- data/lib/compiler/ast.fy +40 -0
- data/lib/compiler/ast/assign.fy +96 -0
- data/lib/compiler/ast/block.fy +84 -0
- data/lib/compiler/ast/class_def.fy +33 -0
- data/lib/compiler/ast/expression_list.fy +47 -0
- data/lib/compiler/ast/identifier.fy +113 -0
- data/lib/compiler/ast/literals.fy +122 -0
- data/lib/compiler/ast/match.fy +88 -0
- data/lib/compiler/ast/message_send.fy +110 -0
- data/lib/compiler/ast/method_def.fy +90 -0
- data/lib/compiler/ast/node.fy +7 -0
- data/lib/compiler/ast/range.fy +16 -0
- data/lib/compiler/ast/require.fy +15 -0
- data/lib/compiler/ast/return.fy +23 -0
- data/lib/compiler/ast/script.fy +52 -0
- data/lib/compiler/ast/singleton_method_def.fy +35 -0
- data/lib/compiler/ast/super.fy +17 -0
- data/lib/compiler/ast/try_catch.fy +176 -0
- data/lib/compiler/ast/tuple_literal.fy +34 -0
- data/lib/compiler/command.fy +51 -0
- data/lib/compiler/compiler.fy +73 -0
- data/lib/compiler/stages.fy +81 -0
- data/lib/directory.fy +17 -0
- data/lib/documentation.fy +115 -0
- data/lib/enumerable.fy +269 -0
- data/lib/eval.fy +31 -0
- data/lib/fancy_spec.fy +202 -0
- data/lib/fdoc.fy +359 -0
- data/lib/fdoc_hook.fy +10 -0
- data/lib/file.fy +54 -0
- data/lib/hash.fy +56 -0
- data/lib/main.fy +80 -0
- data/lib/method.fy +22 -0
- data/lib/nil_class.fy +56 -0
- data/lib/number.fy +87 -0
- data/lib/object.fy +170 -0
- data/lib/package.fy +61 -0
- data/lib/package/dependency.fy +24 -0
- data/lib/package/installer.fy +180 -0
- data/lib/package/specification.fy +55 -0
- data/lib/package/uninstaller.fy +15 -0
- data/lib/parser.fy +4 -0
- data/lib/parser/ext/README +15 -0
- data/lib/parser/ext/ext.c +42 -0
- data/lib/parser/ext/ext.h +8 -0
- data/lib/parser/ext/extconf.rb +3 -0
- data/lib/parser/ext/lexer.lex +187 -0
- data/lib/parser/ext/parser.y +744 -0
- data/lib/parser/methods.fy +297 -0
- data/lib/rbx.fy +37 -0
- data/lib/rbx/array.fy +237 -0
- data/lib/rbx/bignum.fy +23 -0
- data/lib/rbx/block.fy +9 -0
- data/lib/rbx/class.fy +129 -0
- data/lib/rbx/code_loader.fy +192 -0
- data/lib/rbx/console.fy +63 -0
- data/lib/rbx/directory.fy +46 -0
- data/lib/rbx/documentation.fy +64 -0
- data/lib/rbx/environment_variables.fy +3 -0
- data/lib/rbx/exception.fy +30 -0
- data/lib/rbx/false_class.fy +58 -0
- data/lib/rbx/fiber.fy +25 -0
- data/lib/rbx/file.fy +191 -0
- data/lib/rbx/fixnum.fy +25 -0
- data/lib/rbx/float.fy +14 -0
- data/lib/rbx/hash.fy +38 -0
- data/lib/rbx/integer.fy +15 -0
- data/lib/rbx/io.fy +30 -0
- data/lib/rbx/match_data.fy +9 -0
- data/lib/rbx/method.fy +22 -0
- data/lib/rbx/name_error.fy +3 -0
- data/lib/rbx/no_method_error.fy +15 -0
- data/lib/rbx/object.fy +117 -0
- data/lib/rbx/range.fy +15 -0
- data/lib/rbx/regexp.fy +9 -0
- data/lib/rbx/string.fy +63 -0
- data/lib/rbx/symbol.fy +12 -0
- data/lib/rbx/system.fy +37 -0
- data/lib/rbx/tcp_server.fy +6 -0
- data/lib/rbx/tcp_socket.fy +7 -0
- data/lib/rbx/thread.fy +75 -0
- data/lib/rbx/tuple.fy +37 -0
- data/lib/set.fy +61 -0
- data/lib/stack.fy +51 -0
- data/lib/string.fy +58 -0
- data/lib/struct.fy +13 -0
- data/lib/symbol.fy +23 -0
- data/lib/true_class.fy +43 -0
- data/lib/tuple.fy +68 -0
- data/lib/version.fy +6 -0
- data/tests/argv.fy +13 -0
- data/tests/array.fy +343 -0
- data/tests/assignment.fy +53 -0
- data/tests/block.fy +103 -0
- data/tests/class.fy +409 -0
- data/tests/control_flow.fy +79 -0
- data/tests/documentation.fy +24 -0
- data/tests/exception.fy +115 -0
- data/tests/file.fy +86 -0
- data/tests/hash.fy +101 -0
- data/tests/method.fy +131 -0
- data/tests/nil_class.fy +55 -0
- data/tests/number.fy +128 -0
- data/tests/object.fy +125 -0
- data/tests/parsing/sexp.fy +50 -0
- data/tests/pattern_matching.fy +82 -0
- data/tests/range.fy +11 -0
- data/tests/set.fy +10 -0
- data/tests/stack.fy +22 -0
- data/tests/string.fy +102 -0
- data/tests/symbol.fy +17 -0
- data/tests/true_class.fy +63 -0
- data/tests/tuple.fy +21 -0
- data/tools/fancy-mode.el +63 -0
- metadata +321 -0
data/lib/block.fy
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
class Block {
|
2
|
+
"""
|
3
|
+
The Block class (also BlockEnvironment) is the class of all
|
4
|
+
Block-literal values.
|
5
|
+
A Block is a piece of unevaluated code, that can be passed around as
|
6
|
+
any other value and evaluated by calling the +call+ or +call:+ methods.
|
7
|
+
|
8
|
+
Blocks also work properly with their enclosing environment in that
|
9
|
+
they preserve any local variables that get used within the Block,
|
10
|
+
even if the context in which they got defined has been destroyed.
|
11
|
+
=> Blocks are proper closures.
|
12
|
+
|
13
|
+
See: http://en.wikipedia.org/wiki/Closure_(computer_science) for
|
14
|
+
more information.
|
15
|
+
"""
|
16
|
+
|
17
|
+
def while_false: block {
|
18
|
+
"""
|
19
|
+
Executes a given Block while self evals to nil
|
20
|
+
Example:
|
21
|
+
i = 0
|
22
|
+
{ i >= 10 } while_false: {
|
23
|
+
i println
|
24
|
+
i = i + 1
|
25
|
+
}
|
26
|
+
"""
|
27
|
+
|
28
|
+
{ self call not } while_true: block
|
29
|
+
}
|
30
|
+
|
31
|
+
def while_nil: block {
|
32
|
+
"Same as Block#while_false:"
|
33
|
+
|
34
|
+
while_false: block
|
35
|
+
}
|
36
|
+
|
37
|
+
alias_method: 'while_do: for: 'while_true:
|
38
|
+
|
39
|
+
def until_do: block {
|
40
|
+
"""
|
41
|
+
Calls a given Block as long as @self returns @nil or @false.
|
42
|
+
"""
|
43
|
+
|
44
|
+
loop: {
|
45
|
+
self call if_do: |val| {
|
46
|
+
return val
|
47
|
+
} else: {
|
48
|
+
block call
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
def && other_block {
|
54
|
+
"""
|
55
|
+
Short-circuiting && (boolean AND).
|
56
|
+
"""
|
57
|
+
|
58
|
+
if: (self call) then: {
|
59
|
+
other_block call
|
60
|
+
} else: {
|
61
|
+
return false
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
def || other_block {
|
66
|
+
"""
|
67
|
+
Short-circuiting || (boolean OR).
|
68
|
+
"""
|
69
|
+
|
70
|
+
if: (self call) then: {
|
71
|
+
return true
|
72
|
+
} else: {
|
73
|
+
other_block call
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
def if: obj {
|
78
|
+
"Calls itself if the given object is true-ish."
|
79
|
+
|
80
|
+
if: obj then: { self call }
|
81
|
+
}
|
82
|
+
|
83
|
+
def unless: obj {
|
84
|
+
"Opposite of Block#if:. Calls itself if the given object is false-ish."
|
85
|
+
|
86
|
+
unless: obj do: { self call }
|
87
|
+
}
|
88
|
+
}
|
data/lib/boot.fy
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# boot.fnc
|
2
|
+
# This file gets loaded & run by Fancy automatically.
|
3
|
+
# It loads in Fancy's standard library & core classes.
|
4
|
+
|
5
|
+
# NOTE:
|
6
|
+
# Order DOES matter here, so watch out what you're doing.
|
7
|
+
# In general, it's best to add any autoload-files at the end of the
|
8
|
+
# current list (if adding them here is really necessary at all).
|
9
|
+
|
10
|
+
# rbx.fy loads all the files in lib/rbx/ in the correct order, which
|
11
|
+
# define all the functionality to let fancy run on rbx.
|
12
|
+
# also, they might override functionality defined in lib/ to reuse
|
13
|
+
# existing ruby methods etc.
|
14
|
+
require: "rbx.fy"
|
15
|
+
|
16
|
+
require: "object"
|
17
|
+
require: "class"
|
18
|
+
require: "true_class"
|
19
|
+
require: "nil_class"
|
20
|
+
require: "number"
|
21
|
+
require: "enumerable"
|
22
|
+
require: "string"
|
23
|
+
require: "array"
|
24
|
+
require: "tuple"
|
25
|
+
require: "block"
|
26
|
+
require: "file"
|
27
|
+
require: "directory"
|
28
|
+
require: "fancy_spec"
|
29
|
+
require: "hash"
|
30
|
+
require: "set"
|
31
|
+
require: "symbol"
|
32
|
+
require: "method"
|
33
|
+
require: "stack"
|
34
|
+
|
35
|
+
# version holds fancy's version number
|
36
|
+
require: "version"
|
37
|
+
require: "argv"
|
38
|
+
|
39
|
+
require: "documentation"
|
40
|
+
|
41
|
+
require: "package.fy"
|
data/lib/class.fy
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
class Class {
|
2
|
+
"""
|
3
|
+
This class is the class of @Class@ objects - e.g. @Object@, @Array@,
|
4
|
+
@String@ etc.
|
5
|
+
Any class in the language is an instance of this class, as in Ruby
|
6
|
+
or Smalltalk.
|
7
|
+
"""
|
8
|
+
|
9
|
+
def define_slot_reader: slotname {
|
10
|
+
"""
|
11
|
+
@slotname Name of the slot to define a getter method for.
|
12
|
+
|
13
|
+
Defines a slot reader method with a given name.
|
14
|
+
E.g. for a slotname @count it will define the following method:
|
15
|
+
def count {
|
16
|
+
get_slot: 'count
|
17
|
+
}
|
18
|
+
"""
|
19
|
+
|
20
|
+
define_method: slotname with: {
|
21
|
+
get_slot: slotname
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
def define_slot_writer: slotname {
|
26
|
+
"""
|
27
|
+
@slotname Name of the slot to defnie define a setter method for.
|
28
|
+
|
29
|
+
Defines a slot writer method with a given name.
|
30
|
+
E.g. for a slotname @count it will define the following method:
|
31
|
+
def count: c {
|
32
|
+
set_slot: 'count value: c
|
33
|
+
}
|
34
|
+
"""
|
35
|
+
|
36
|
+
define_method: (slotname to_s + ":") with: |val| {
|
37
|
+
set_slot: slotname value: val
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
def read_slots: slots {
|
42
|
+
"""
|
43
|
+
@slots @Array@ of slotnames to define getter methods for.
|
44
|
+
|
45
|
+
Defines slot reader methods for all given slotnames.
|
46
|
+
"""
|
47
|
+
|
48
|
+
slots each: |s| {
|
49
|
+
define_slot_reader: s
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
def write_slots: slots {
|
54
|
+
"""
|
55
|
+
@slots @Array@ of slotnames to define setter methods for.
|
56
|
+
|
57
|
+
Defines slot writer methods for all given slotnames.
|
58
|
+
"""
|
59
|
+
|
60
|
+
slots each: |s| {
|
61
|
+
define_slot_writer: s
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
def read_write_slots: slots {
|
66
|
+
"""
|
67
|
+
@slots @Array@ of slotnames to define getter & setter methods for.
|
68
|
+
|
69
|
+
Defines slot reader & writer methods for all given slotnames.
|
70
|
+
"""
|
71
|
+
|
72
|
+
slots each: |s| {
|
73
|
+
define_slot_reader: s
|
74
|
+
define_slot_writer: s
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
def subclass?: class_obj {
|
79
|
+
"""
|
80
|
+
@class_obj Class object to check for, if @self is a subclass of @class_obj.
|
81
|
+
@return @true, if @self is a subclass of @class_obj, @false otherwise.
|
82
|
+
|
83
|
+
Indicates, if a Class is a subclass of another Class.
|
84
|
+
"""
|
85
|
+
|
86
|
+
if: (self == class_obj) then: {
|
87
|
+
true
|
88
|
+
} else: {
|
89
|
+
# take care of Object class, as Object is its own superclass
|
90
|
+
unless: (self superclass nil?) do: {
|
91
|
+
self superclass subclass?: class_obj
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
def alias_method: new_method_name for: old_method_name {
|
97
|
+
"""
|
98
|
+
@new_method_name New method name to be used as an alias for @old_method_name.
|
99
|
+
@old_method_name Name of method to alias (must exist in the @Class@).
|
100
|
+
|
101
|
+
Defines an alias method for another method.
|
102
|
+
"""
|
103
|
+
|
104
|
+
alias_method_rbx: new_method_name for: old_method_name
|
105
|
+
}
|
106
|
+
}
|
data/lib/compiler.fy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env fancy
|
2
|
+
|
3
|
+
# A Fancy to rbx bytecode compiler.
|
4
|
+
|
5
|
+
require: "compiler/compiler"
|
6
|
+
require: "compiler/stages"
|
7
|
+
require: "compiler/ast"
|
8
|
+
|
9
|
+
require: "parser"
|
10
|
+
|
11
|
+
if: (__FILE__ == (ARGV[0])) then: {
|
12
|
+
require: "compiler/command"
|
13
|
+
Fancy Compiler Command run: ARGV
|
14
|
+
}
|
data/lib/compiler/ast.fy
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
"""
|
2
|
+
AST nodes are an object representation of source files.
|
3
|
+
|
4
|
+
|
5
|
+
For example for a source code containing only the following expression:
|
6
|
+
|
7
|
+
Console println: hello
|
8
|
+
|
9
|
+
An AST tree like the following will be created:
|
10
|
+
|
11
|
+
Script:
|
12
|
+
@body: ExpressionList
|
13
|
+
@expressions:
|
14
|
+
- MessageSend
|
15
|
+
@receiver:
|
16
|
+
Constant @string: Console
|
17
|
+
@name:
|
18
|
+
Identifier @string: println:
|
19
|
+
@args:
|
20
|
+
- Identifier @string: hello
|
21
|
+
"""
|
22
|
+
|
23
|
+
require: "ast/node"
|
24
|
+
require: "ast/script"
|
25
|
+
require: "ast/expression_list"
|
26
|
+
require: "ast/identifier"
|
27
|
+
require: "ast/message_send"
|
28
|
+
require: "ast/method_def"
|
29
|
+
require: "ast/singleton_method_def"
|
30
|
+
require: "ast/super"
|
31
|
+
require: "ast/literals"
|
32
|
+
require: "ast/assign"
|
33
|
+
require: "ast/block"
|
34
|
+
require: "ast/class_def"
|
35
|
+
require: "ast/tuple_literal"
|
36
|
+
require: "ast/range"
|
37
|
+
require: "ast/require"
|
38
|
+
require: "ast/match"
|
39
|
+
require: "ast/try_catch"
|
40
|
+
require: "ast/return"
|
@@ -0,0 +1,96 @@
|
|
1
|
+
class Fancy AST {
|
2
|
+
|
3
|
+
class Assignment : Node {
|
4
|
+
def initialize: @line var: @lvalue value: @rvalue { }
|
5
|
+
|
6
|
+
def bytecode: g {
|
7
|
+
pos(g)
|
8
|
+
@lvalue bytecode: g assign: @rvalue
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
class MultipleAssignment : Node {
|
13
|
+
class MultipleAssignmentExpr : Node {
|
14
|
+
def initialize: @line index: @index {
|
15
|
+
}
|
16
|
+
|
17
|
+
def bytecode: g {
|
18
|
+
pos(g)
|
19
|
+
margs = MessageArgs new: @line args: [FixnumLiteral new: @line value: @index]
|
20
|
+
recv = StackTop new: @line
|
21
|
+
msg = Identifier from: "at:" line: @line
|
22
|
+
MessageSend new: @line message: msg to: recv args: margs . bytecode: g
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
class SplatAssignmentExpr : Node {
|
27
|
+
def initialize: @line start_index: @start_index {
|
28
|
+
}
|
29
|
+
|
30
|
+
def bytecode: g {
|
31
|
+
pos(g)
|
32
|
+
margs = MessageArgs new: @line args: [FixnumLiteral new: @line value: @start_index, FixnumLiteral new: @line value: -1]
|
33
|
+
recv = StackTop new: @line
|
34
|
+
msg = Identifier from: "from:to:" line: @line
|
35
|
+
MessageSend new: @line message: msg to: recv args: margs . bytecode: g
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
def initialize: @line var: @idents value: @values {
|
40
|
+
}
|
41
|
+
|
42
|
+
def bytecode: g {
|
43
|
+
pos(g)
|
44
|
+
if: (@values size > 1) then: {
|
45
|
+
ArrayLiteral new: @line array: @values . bytecode: g
|
46
|
+
} else: {
|
47
|
+
# in this case we just have one value for multi-assign
|
48
|
+
# so we expect it to be a collection type and get values by
|
49
|
+
# calling "at:" method (see above)
|
50
|
+
@values first bytecode: g
|
51
|
+
}
|
52
|
+
|
53
|
+
max_idx = @idents size - 1
|
54
|
+
@idents each_with_index: |ident idx| {
|
55
|
+
var = ident
|
56
|
+
value = MultipleAssignmentExpr new: @line index: idx
|
57
|
+
match ident string -> {
|
58
|
+
case /^\*/ ->
|
59
|
+
value = SplatAssignmentExpr new: @line start_index: idx
|
60
|
+
var = Identifier from: (ident string rest) line: (ident line)
|
61
|
+
}
|
62
|
+
Assignment new: @line var: var value: value . bytecode: g
|
63
|
+
g pop()
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
class Identifier {
|
69
|
+
def bytecode: g assign: value {
|
70
|
+
pos(g)
|
71
|
+
Rubinius AST LocalVariableAssignment new(@line, self name, value) bytecode(g)
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
class InstanceVariable {
|
76
|
+
def bytecode: g assign: value {
|
77
|
+
pos(g)
|
78
|
+
Rubinius AST InstanceVariableAssignment new(@line, self name, value) bytecode(g)
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
class ClassVariable {
|
83
|
+
def bytecode: g assign: value {
|
84
|
+
pos(g)
|
85
|
+
Rubinius AST ClassVariableAssignment new(@line, self name, value) bytecode(g)
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
class Constant {
|
90
|
+
def bytecode: g assign: value {
|
91
|
+
pos(g)
|
92
|
+
Rubinius AST ConstantAssignment new(@line, self name, value) bytecode(g)
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
}
|
@@ -0,0 +1,84 @@
|
|
1
|
+
class Fancy AST {
|
2
|
+
class BlockLiteral : Rubinius AST Iter {
|
3
|
+
def initialize: @line args: @args body: @body (NilLiteral new: line) partial: @partial (false) {
|
4
|
+
if: (@body empty?) then: {
|
5
|
+
@body unshift_expression: $ NilLiteral new: @line
|
6
|
+
}
|
7
|
+
initialize(@line, @args, @body)
|
8
|
+
@args create_locals: self
|
9
|
+
if: (@args total_args == 0) then: {
|
10
|
+
@arguments prelude=(nil)
|
11
|
+
}
|
12
|
+
if: (@args.total_args > 1) then: {
|
13
|
+
@arguments prelude=('multi)
|
14
|
+
}
|
15
|
+
@arguments required_args=(@args required_args)
|
16
|
+
|
17
|
+
if: @partial then: {
|
18
|
+
first_expr = @body expressions first
|
19
|
+
|
20
|
+
# if first expression is an identifier, use that as a 0-arg
|
21
|
+
# method name to send to new receiver (use a generated symbol
|
22
|
+
# name created in lib/parser/methods.fy / Fancy Parser#ast:partial_block:)
|
23
|
+
# if first expression is a message send where its receiver is
|
24
|
+
# an identifier, use that as the message name in a send to
|
25
|
+
# self and use the result as the receiver value for the rest.
|
26
|
+
new_receiver = Identifier from: (@args args first to_s) line: @line
|
27
|
+
match first_expr -> {
|
28
|
+
case Identifier ->
|
29
|
+
@body expressions shift()
|
30
|
+
@body unshift_expression: $ MessageSend new: @line message: first_expr to: (new_receiver) args: (MessageArgs new: @line args: [])
|
31
|
+
case MessageSend ->
|
32
|
+
match first_expr receiver -> {
|
33
|
+
case Self ->
|
34
|
+
first_expr receiver: new_receiver
|
35
|
+
case Identifier ->
|
36
|
+
first_expr receiver: $ MessageSend new: @line message: (first_expr receiver) to: (new_receiver) args: (MessageArgs new: @line args: [])
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
def bytecode: g {
|
43
|
+
pos(g)
|
44
|
+
bytecode(g)
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
class BlockArgs : Node {
|
49
|
+
read_write_slots: ['args, 'block]
|
50
|
+
|
51
|
+
def initialize: @line args: @args ([]) {
|
52
|
+
@args = @args map: |a| { a name to_sym() }
|
53
|
+
}
|
54
|
+
|
55
|
+
def bytecode: g {
|
56
|
+
pos(g)
|
57
|
+
if: (@args size > 1) then: {
|
58
|
+
@args each_with_index: |a i| {
|
59
|
+
g shift_array()
|
60
|
+
g set_local(i)
|
61
|
+
g pop()
|
62
|
+
}
|
63
|
+
} else: {
|
64
|
+
@args each_with_index: |a i| {
|
65
|
+
g set_local(i)
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
def total_args {
|
71
|
+
@args size
|
72
|
+
}
|
73
|
+
|
74
|
+
def required_args {
|
75
|
+
self total_args
|
76
|
+
}
|
77
|
+
|
78
|
+
def create_locals: block {
|
79
|
+
@args each: |a| {
|
80
|
+
block new_local(a)
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|