Permalink
Browse files

backported support for partial blocks to bootstrap compiler

  • Loading branch information...
1 parent 011ea28 commit 0800ae2ba2fddf1e93ddb6d5b9078ae7775d8fe3 @bakkdoor committed Jan 25, 2012
@@ -2,7 +2,7 @@ class Fancy
class AST
class BlockLiteral < Rubinius::AST::Iter
- def initialize(line, args, body)
+ def initialize(line, args, body, partial = false)
@args = args
body = body || Rubinius::AST::NilLiteral.new(line)
@@ -20,6 +20,34 @@ def initialize(line, args, body)
@arguments.prelude = :multi
end
@arguments.required_args = args.required_args
+
+ @partial = partial
+
+ if @partial
+ @body = ExpressionList.new @line, *@body.expressions.map{ |e| convert_to_implicit_arg_send(e) }
+ end
+ end
+
+ def convert_to_implicit_arg_send(expr)
+ # see self-hosted version in lib/compiler/block.fy
+ # this is just a port of it so we can use partial blocks
+ # in fancy's stdlib
+
+ new_receiver = Identifier.new(@line, @args.args.first.to_s)
+ case expr
+ when Identifier
+ expr = MessageSend.new(@line, new_receiver, expr, MessageArgs.new(@line))
+ when MessageSend
+ case expr.receiver
+ when Self
+ expr.receiver = new_receiver
+ when Identifier
+ expr.receiver = MessageSend.new(@line, new_receiver, expr.receiver, MessageArgs.new(@line))
+ when MessageSend
+ expr.receiver = convert_to_implicit_arg_send(expr.receiver)
+ end
+ end
+ expr
end
def bytecode(g)
@@ -4,6 +4,12 @@ class AST
class Identifier < Node
attr_reader :identifier
+ @@gen_ident_start = 0
+ def Identifier.generate(line)
+ @@gen_ident_start += 1
+ Identifier.new(line, "______gen_ident______#{@@gen_ident_start}")
+ end
+
def initialize(line, identifier)
super(line)
@identifier = identifier
@@ -2,6 +2,7 @@ class Fancy
class AST
class MessageSend < Node
+ attr_accessor :receiver
def initialize(line, receiver, message_name, message_args)
super(line)
@receiver = receiver
@@ -26,6 +26,7 @@ string_lit L?\"(\\.|[^\\"])*\"
multiline_string L?\"\"\"(\\.|[^\\"])*\"\"\"
lparen \(
rparen \)
+at_lcurly "@{"
lcurly "{"
rcurly "}"
lbracket "["
@@ -99,6 +100,7 @@ escaped_newline "\\".*\n
}
{lparen} { return LPAREN; }
{rparen} { return RPAREN; }
+{at_lcurly} { return AT_LCURLY; }
{lcurly} { return LCURLY; }
{rcurly} { return RCURLY; }
{lbracket} { return LBRACKET; }
@@ -243,6 +243,12 @@ def nil_literal(line)
Rubinius::AST::NilLiteral.new(line)
end
+ def partial_block(line, block_body)
+ gen_blockarg = AST::Identifier.generate(line)
+ args = AST::BlockArgs.new line, gen_blockarg
+ AST::BlockLiteral.new(line, args, block_body, true)
+ end
+
def block_literal(line, block_args, block_body)
block_args ||= Array.new
args = AST::BlockArgs.new line, *block_args
@@ -24,6 +24,7 @@ extern char *yytext;
%token LPAREN
%token RPAREN
+%token AT_LCURLY
%token LCURLY
%token RCURLY
%token LBRACKET
@@ -101,6 +102,7 @@ extern char *yytext;
%type <object> code
%type <object> expression_list
%type <object> expression_block
+%type <object> partial_expression_block
%type <object> exp
%type <object> assignment
%type <object> multiple_assignment
@@ -194,6 +196,11 @@ expression_block: LCURLY space expression_list space RCURLY {
}
;
+partial_expression_block: AT_LCURLY space expression_list space RCURLY {
+ $$ = $3;
+ }
+ ;
+
statement: assignment
| return_local_statement
| return_statement
@@ -643,7 +650,10 @@ hash_literal: LEFTHASH space key_value_list space RIGHTHASH {
}
;
-block_literal: expression_block {
+block_literal: partial_expression_block {
+ $$ = rb_funcall(self, rb_intern("partial_block"), 2, INT2NUM(yylineno), $1);
+ }
+ | expression_block {
$$ = rb_funcall(self, rb_intern("block_literal"), 3, INT2NUM(yylineno), Qnil, $1);
}
| STAB block_args STAB space expression_block {
@@ -30,7 +30,7 @@ class Fancy AST {
new_receiver = Identifier from: (@args args first to_s) line: @line
match expr {
case Identifier ->
- expr = MessageSend new: @line message: expr to: (new_receiver) args: (MessageArgs new: @line args: [])
+ expr = MessageSend new: @line message: expr to: new_receiver args: (MessageArgs new: @line args: [])
case MessageSend ->
match expr receiver {
case Self ->

0 comments on commit 0800ae2

Please sign in to comment.