stmt: propagate err checks to top-level function calls and assignment calls
This commit is contained in:
parent
52ccea5d65
commit
e9aa553216
@ -6,7 +6,7 @@ function Foo(): int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
echo Foo();
|
Foo();
|
||||||
} catch (\BarException | \BazException $e) {
|
} catch (\BarException | \BazException $e) {
|
||||||
echo "bar or baz exception " . $e->getMessage() . "\n";
|
echo "bar or baz exception " . $e->getMessage() . "\n";
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
109
node.go
109
node.go
@ -528,16 +528,35 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regular case
|
// Assignment expressions can take on better error-handling behaviour
|
||||||
|
// when we know the assignment is a top-level expression
|
||||||
|
if a, ok := n.Expr.(*assign.Assign); ok {
|
||||||
|
return this.convertAssignment(a, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-assignment expression
|
||||||
child, err := this.convert(n.Expr)
|
child, err := this.convert(n.Expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := child + "\n" // standalone expression statement
|
// If this is a simple expression (func call; indirect/method call; assignment of func/method call) then
|
||||||
|
// we need to propagate errors
|
||||||
|
switch n.Expr.(type) {
|
||||||
|
case *expr.FunctionCall, *expr.StaticCall, *expr.New:
|
||||||
|
ret := "_, err = " + child + "\n"
|
||||||
|
ret += "if err != nil {\n"
|
||||||
|
ret += this.currentErrHandler
|
||||||
|
ret += "}\n"
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Some other kind of general expression - no special error handling needed
|
||||||
|
ret := child + "\n" // standalone expression statement
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
case *stmt.Echo:
|
case *stmt.Echo:
|
||||||
// Convert into fmt.Print
|
// Convert into fmt.Print
|
||||||
args := make([]string, 0, len(n.Exprs))
|
args := make([]string, 0, len(n.Exprs))
|
||||||
@ -699,34 +718,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
//
|
//
|
||||||
|
|
||||||
case *assign.Assign:
|
case *assign.Assign:
|
||||||
|
return this.convertAssignment(n, false /* no reason to believe we are a top-level statement */)
|
||||||
rvalue, err := this.convert(n.Expression)
|
|
||||||
if err != nil {
|
|
||||||
return "", parseErr{n, err}
|
|
||||||
}
|
|
||||||
|
|
||||||
if dimf, ok := n.Variable.(*expr.ArrayDimFetch); ok && dimf.Dim == nil {
|
|
||||||
// Special handling for the case of foo[] = bar
|
|
||||||
// Transform into append()
|
|
||||||
arrayVar, err := this.convert(dimf.Variable)
|
|
||||||
if err != nil {
|
|
||||||
return "", parseErr{dimf, err}
|
|
||||||
}
|
|
||||||
|
|
||||||
return arrayVar + ` = append(` + arrayVar + `, ` + rvalue + `)`, nil
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Normal assignment
|
|
||||||
|
|
||||||
lvalue, err := this.convert(n.Variable) // might be a more complicated lvalue
|
|
||||||
if err != nil {
|
|
||||||
return "", parseErr{n, err}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO this may need to use `:=`
|
|
||||||
return lvalue + " = " + rvalue, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// expr
|
// expr
|
||||||
@ -1152,6 +1144,63 @@ func (this *conversionState) resolveName(n node.Node) (string, error) {
|
|||||||
return paramType, nil
|
return paramType, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *conversionState) convertAssignment(n *assign.Assign, isTopLevelStatement bool) (string, error) {
|
||||||
|
|
||||||
|
rvalue, err := this.convert(n.Expression)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{n, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
if dimf, ok := n.Variable.(*expr.ArrayDimFetch); ok && dimf.Dim == nil {
|
||||||
|
// Special handling for the case of foo[] = bar
|
||||||
|
// Transform into append()
|
||||||
|
arrayVar, err := this.convert(dimf.Variable)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{dimf, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := arrayVar + ` = append(` + arrayVar + `, ` + rvalue + `)`
|
||||||
|
if isTopLevelStatement {
|
||||||
|
ret += "\n"
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Normal assignment
|
||||||
|
|
||||||
|
lvalue, err := this.convert(n.Variable) // might be a more complicated lvalue
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{n, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO this may need to use `:=`
|
||||||
|
|
||||||
|
if isTopLevelStatement {
|
||||||
|
|
||||||
|
// If this is a simple expression (func call; indirect/method call; assignment of func/method call) then
|
||||||
|
// we need to propagate errors
|
||||||
|
switch n.Expression.(type) {
|
||||||
|
case *expr.FunctionCall, *expr.StaticCall, *expr.New:
|
||||||
|
ret := "_, " + lvalue + " = " + rvalue + "\n"
|
||||||
|
ret += "if err != nil {\n"
|
||||||
|
ret += this.currentErrHandler
|
||||||
|
ret += "}\n"
|
||||||
|
return ret, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret := lvalue + " = " + rvalue + "\n" // Just the basic assignment - with trailing NL
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return lvalue + " = " + rvalue, nil // Just the basic assignment - without trailing NL
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// convertToStmtList asserts that the node is either a StmtList or wraps it in a
|
// convertToStmtList asserts that the node is either a StmtList or wraps it in a
|
||||||
// single-stmt StmtList if not.
|
// single-stmt StmtList if not.
|
||||||
// Loop bodies may be a StmtList if it is wrapped in {}, or a single statement
|
// Loop bodies may be a StmtList if it is wrapped in {}, or a single statement
|
||||||
|
Loading…
Reference in New Issue
Block a user