Implement checks for generators returning values.

Patch from Roshan James, roshanj@google.com.
This commit is contained in:
nboyd%atg.com 2007-06-06 14:32:40 +00:00
Родитель 08e940f4ab
Коммит a6099a8648
3 изменённых файлов: 67 добавлений и 23 удалений

Просмотреть файл

@ -643,6 +643,7 @@ public class Node
static final int END_DROPS_OFF = 1;
static final int END_RETURNS = 2;
static final int END_RETURNS_VALUE = 4;
static final int END_YIELDS = 8;
/**
* Checks that every return usage in a function body is consistent with the
@ -653,7 +654,7 @@ public class Node
{
int n = endCheck();
return (n & END_RETURNS_VALUE) == 0 ||
(n & (END_DROPS_OFF|END_RETURNS)) == 0;
(n & (END_DROPS_OFF|END_RETURNS|END_YIELDS)) == 0;
}
/**
@ -868,6 +869,14 @@ public class Node
case Token.BREAK:
return endCheckBreak();
case Token.EXPR_VOID:
if (this.first != null)
return first.endCheck();
return END_DROPS_OFF;
case Token.YIELD:
return END_YIELDS;
case Token.CONTINUE:
case Token.THROW:
return END_UNREACHED;

Просмотреть файл

@ -95,7 +95,7 @@ public class Parser
private ObjArray loopSet;
private ObjArray loopAndSwitchSet;
private boolean hasReturnValue;
private int functionEndFlags;
private int endFlags;
// end of per function variables
// Exception to unwind
@ -517,7 +517,7 @@ public class Parser
ObjArray savedLoopAndSwitchSet = loopAndSwitchSet;
loopAndSwitchSet = null;
boolean savedHasReturnValue = hasReturnValue;
int savedFunctionEndFlags = functionEndFlags;
int savedFunctionEndFlags = endFlags;
Node body;
try {
@ -574,7 +574,7 @@ public class Parser
}
finally {
hasReturnValue = savedHasReturnValue;
functionEndFlags = savedFunctionEndFlags;
endFlags = savedFunctionEndFlags;
loopAndSwitchSet = savedLoopAndSwitchSet;
loopSet = savedLoopSet;
labelSet = savedLabelSet;
@ -1206,6 +1206,19 @@ public class Parser
return pn;
}
/**
* Returns whether or not the bits in the mask have changed to all set.
* @param before bits before change
* @param after bits after change
* @param mask mask for bits
* @return true if all the bits in the mask are set in "after" but not
* "before"
*/
private static final boolean nowAllSet(int before, int after, int mask)
{
return ((before & mask) != mask) && ((after & mask) == mask);
}
private Node returnOrYield(int tt, boolean exprContext)
throws IOException, ParserException
@ -1235,28 +1248,44 @@ public class Parser
e = expr(false);
break;
}
int before = endFlags;
Node ret;
if (tt == Token.RETURN) {
// see if we need a strict mode warning
// TODO(js1.7gen): check for mixture of yield and value returns
if (e == null) {
if (functionEndFlags == Node.END_RETURNS_VALUE)
addStrictWarning("msg.return.inconsistent", "");
functionEndFlags |= Node.END_RETURNS;
} else {
hasReturnValue = true;
if (functionEndFlags == Node.END_RETURNS)
addStrictWarning("msg.return.inconsistent", "");
functionEndFlags |= Node.END_RETURNS_VALUE;
}
return nf.createReturn(e, lineno);
if (e == null ) {
endFlags |= Node.END_RETURNS;
} else {
endFlags |= Node.END_RETURNS_VALUE;
hasReturnValue = true;
}
ret = nf.createReturn(e, lineno);
// see if we need a strict mode warning
if (nowAllSet(before, endFlags,
Node.END_RETURNS|Node.END_RETURNS_VALUE))
{
addStrictWarning("msg.return.inconsistent", "");
}
} else {
Node n = nf.createYield(e, lineno);
if (exprContext)
return n;
return new Node(Token.EXPR_VOID, n, lineno);
endFlags |= Node.END_YIELDS;
ret = nf.createYield(e, lineno);
if (!exprContext)
ret = new Node(Token.EXPR_VOID, ret, lineno);
}
// see if we are mixing yields and value returns.
if (nowAllSet(before, endFlags,
Node.END_YIELDS|Node.END_RETURNS_VALUE))
{
String name = ((FunctionNode)currentScriptOrFn).getFunctionName();
if (name.length() == 0)
addError("msg.anon.generator.returns", "");
else
addError("msg.generator.returns", name);
}
return ret;
}
/**

Просмотреть файл

@ -422,6 +422,12 @@ msg.anon.no.return.value =\
msg.return.inconsistent =\
return statement is inconsistent with previous usage
msg.generator.returns =\
generator function {0} returns a value
msg.anon.generator.returns =\
anonymous generator function returns a value
msg.syntax =\
syntax error