Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement returning from functions.
  • Loading branch information
arnsholt committed Nov 21, 2014
1 parent 94f5928 commit ab62836
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/Snake/Actions.nqp
Expand Up @@ -118,6 +118,13 @@ method simple-statement($/) {

method ordinary-statement:sym<EXPR>($/) { make $<EXPR>.ast; }
method ordinary-statement:sym<pass>($/) { make QAST::Stmts.new(); }

method ordinary-statement:sym<return>($/) {
# TODO: Bare return should return None.
make QAST::Op.new(:op<call>, :name<$RETURN>,
$<EXPR> ?? $<EXPR>.ast !! QAST::Stmts.new());
}

method ordinary-statement:sym<break>($/) { make QAST::Op.new(:op<control>, :name<last>); }
method ordinary-statement:sym<continue>($/) { make QAST::Op.new(:op<control>, :name<next>); }

Expand Down Expand Up @@ -160,12 +167,19 @@ method compound-statement:sym<for>($/) {
))
}

# TODO: A function without an explicit return should return None in Python. We
# currently have the same semantics as Perl (and others), returning the value
# of the last statement in the block.
method compound-statement:sym<def>($/) {
# TODO: Check for $*IN_CLASS and push_s name to @*METHODS if true.
my $block := $<new_scope>.ast;
my $name := $<identifier>.ast.name;
$block.name: $name;

if $*HAS_RETURN {
$block[1] := QAST::Op.new(:op<lexotic>, :name<$RETURN>, $block[1]);
}

my $ast := QAST::Stmts.new(QAST::Op.new(:op<bind>,
QAST::Var.new(:name($name), :scope<lexical>),
$block));
Expand Down
9 changes: 9 additions & 0 deletions src/Snake/Grammar.nqp
Expand Up @@ -44,6 +44,7 @@ method TOP() {
my $*DEFAULTS := 0;

my $*IN_CLASS := 0;
my $*IN_DEF := 0;

return self.file-input;
}
Expand Down Expand Up @@ -243,6 +244,11 @@ token simple-statement { <stmt=.assignment> || <stmt=.ordinary-statement> }
proto token ordinary-statement {*}
token ordinary-statement:sym<EXPR> { <EXPR> }
token ordinary-statement:sym<pass> { <sym> }
# TODO: Return actually takes a list of expressions, not a single one.
token ordinary-statement:sym<return> {
<sym> <.ws> <EXPR>?
[ <?{ $*IN_DEF == 1 }> {$*HAS_RETURN := 1} || <.panic: "Can only return when inside a function."> ]
}

# TODO: Handle all possible assignments.
rule assignment { <identifier> '=' <EXPR> }
Expand Down Expand Up @@ -282,6 +288,8 @@ token compound-statement:sym<def> {
[:s<sym> <identifier>
{Snake::Actions.add-declaration: $<identifier>.ast.name}
'(' ~ ')' <parameter_list> ':'
:my $*IN_DEF := 1;
:my $*HAS_RETURN := 0;
<new_scope>]
}

Expand All @@ -292,6 +300,7 @@ token compound-statement:sym<class> {
{Snake::Actions.add-declaration: $<identifier>.ast.name}
':'
:my $*IN_CLASS := 1;
:my $*IN_DEF := 0;
:my @*METHODS := nqp::list_s();
<new_scope>]
}
Expand Down

0 comments on commit ab62836

Please sign in to comment.