Skip to content
This repository has been archived by the owner on Feb 20, 2024. It is now read-only.

Commit

Permalink
revert a2fed2e, allow expression statements after void return stateme…
Browse files Browse the repository at this point in the history
…nts again
  • Loading branch information
evanw committed Feb 26, 2016
1 parent a375f7c commit 4050934
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 32 deletions.
35 changes: 21 additions & 14 deletions skewc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11400,20 +11400,9 @@
context.next();
}

// There is a well-known bug in JavaScript where a return statement
// followed by a newline and a value is parsed as two statements,
// a return statement without a value and an expression statement.
// This is dumb so don't do this. Parse this as a single return
// statement with a value instead.
if (previous != null && previous.kind == Skew.NodeKind.RETURN && previous.returnValue() == null && statement1.kind == Skew.NodeKind.EXPRESSION) {
previous.appendChild(statement1.expressionValue().remove());
}

else {
previous = statement1;
statement1.comments = comments;
parent.appendChild(statement1);
}
previous = statement1;
statement1.comments = comments;
parent.appendChild(statement1);
}

// Special-case semicolons before comments for better parser recovery
Expand Down Expand Up @@ -18936,6 +18925,24 @@

for (var child = node.firstChild(), next = null; child != null; child = next) {
next = child.nextSibling();

// There is a well-known ambiguity in languages like JavaScript where
// a return statement followed by a newline and a value can either be
// parsed as a single return statement with a value or as two
// statements, a return statement without a value and an expression
// statement. Luckily, we're better off than JavaScript since we know
// the type of the function. Parse a single statement in a non-void
// function but two statements in a void function.
if (child.kind == Skew.NodeKind.RETURN && next != null && child.returnValue() == null && next.kind == Skew.NodeKind.EXPRESSION) {
var $function = scope.findEnclosingFunctionOrLambda().symbol;

if ($function.kind != Skew.SymbolKind.FUNCTION_CONSTRUCTOR && $function.resolvedType.returnType != null) {
child.appendChild(next.remove().expressionValue().remove());
next = child.nextSibling();
assert(child.returnValue() != null);
}
}

this._resolveNode(child, scope, null);

// Stop now if the child was removed
Expand Down
17 changes: 3 additions & 14 deletions src/frontend/parser.sk
Original file line number Diff line number Diff line change
Expand Up @@ -712,20 +712,9 @@ namespace Skew.Parsing {
context.next
}

# There is a well-known bug in JavaScript where a return statement
# followed by a newline and a value is parsed as two statements,
# a return statement without a value and an expression statement.
# This is dumb so don't do this. Parse this as a single return
# statement with a value instead.
if previous != null && previous.kind == .RETURN && previous.returnValue == null && statement.kind == .EXPRESSION {
previous.appendChild(statement.expressionValue.remove)
}

else {
previous = statement
statement.comments = comments
parent.appendChild(statement)
}
previous = statement
statement.comments = comments
parent.appendChild(statement)
}

# Special-case semicolons before comments for better parser recovery
Expand Down
17 changes: 17 additions & 0 deletions src/middle/resolving.sk
Original file line number Diff line number Diff line change
Expand Up @@ -1613,6 +1613,23 @@ namespace Skew.Resolving {

for child = node.firstChild, next Node = null; child != null; child = next {
next = child.nextSibling

# There is a well-known ambiguity in languages like JavaScript where
# a return statement followed by a newline and a value can either be
# parsed as a single return statement with a value or as two
# statements, a return statement without a value and an expression
# statement. Luckily, we're better off than JavaScript since we know
# the type of the function. Parse a single statement in a non-void
# function but two statements in a void function.
if child.kind == .RETURN && next != null && child.returnValue == null && next.kind == .EXPRESSION {
var function = scope.findEnclosingFunctionOrLambda.symbol
if function.kind != .FUNCTION_CONSTRUCTOR && function.resolvedType.returnType != null {
child.appendChild(next.remove.expressionValue.remove)
next = child.nextSibling
assert(child.returnValue != null)
}
}

_resolveNode(child, scope, null)

# Stop now if the child was removed
Expand Down
3 changes: 0 additions & 3 deletions tests/parsing.sk
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,6 @@ def test {
<stdin>:16:3: error: \"foo\" is not declared
foo(
~~~
<stdin>:16:3: error: Cannot return a value inside a function without a return type
foo(
~~~~
<stdin>:17:3: error: Cannot use \"break\" outside a loop
break
~~~~~
Expand Down
2 changes: 1 addition & 1 deletion tests/simple.sk
Original file line number Diff line number Diff line change
Expand Up @@ -6945,7 +6945,7 @@ def bar2 {
<stdin>:7:3: error: Must return a value of type \"int\"
return
~~~~~~
<stdin>:12:3: error: Cannot return a value inside a function without a return type
<stdin>:12:3: warning: Unused expression
false
~~~~~
")
Expand Down

0 comments on commit 4050934

Please sign in to comment.