node: implement switch, break, continue (basic)
This commit is contained in:
parent
cbcfb46de7
commit
78bd54ad13
16
fixtures/0014-switch.php
Normal file
16
fixtures/0014-switch.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$x = true;
|
||||||
|
switch($x) {
|
||||||
|
case true:
|
||||||
|
echo "true";
|
||||||
|
break;
|
||||||
|
echo "unreached";
|
||||||
|
|
||||||
|
case false:
|
||||||
|
echo "false";
|
||||||
|
// fallthrough
|
||||||
|
|
||||||
|
default:
|
||||||
|
echo "default";
|
||||||
|
}
|
63
node.go
63
node.go
@ -845,6 +845,69 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
||||||
|
case *stmt.Switch:
|
||||||
|
cond, err := this.convert(n.Cond)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{n, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := make([]string, 0, len(n.CaseList.Cases))
|
||||||
|
for _, ncase := range n.CaseList.Cases {
|
||||||
|
switch ncase.(type) {
|
||||||
|
case *stmt.Default, *stmt.Case:
|
||||||
|
caseStr, err := this.convert(ncase)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{n, err}
|
||||||
|
}
|
||||||
|
cases = append(cases, caseStr)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "", parseErr{ncase, fmt.Errorf("expected Case/Default")}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO use dead code elimination after `break` to clean up redundant fallthrough statements
|
||||||
|
return "switch " + cond + " {\n" + strings.Join(cases, "\n") + "}\n", nil
|
||||||
|
|
||||||
|
case *stmt.Case:
|
||||||
|
// Add a `fallthrough` to the end
|
||||||
|
// TODO then use dead code elimination to clean them up
|
||||||
|
stmtBody, err := this.convert(stmt.NewStmtList(n.Stmts))
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{n, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
cond, err := this.convert(n.Cond)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{n, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "case " + cond + ":\n" + stmtBody + "\nfallthrough\n", nil
|
||||||
|
|
||||||
|
case *stmt.Default:
|
||||||
|
// Add a `fallthrough` to the end
|
||||||
|
// TODO then use dead code elimination to clean them up
|
||||||
|
stmtBody, err := this.convert(stmt.NewStmtList(n.Stmts))
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{n, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "default: " + stmtBody + "\nfallthrough\n", nil
|
||||||
|
|
||||||
|
case *stmt.Break:
|
||||||
|
if n.Expr != nil {
|
||||||
|
return "", parseErr{n, fmt.Errorf("break {expr} is not yet supported")} // TODO implement numbered break
|
||||||
|
}
|
||||||
|
|
||||||
|
return "break\n", nil
|
||||||
|
|
||||||
|
case *stmt.Continue:
|
||||||
|
if n.Expr != nil {
|
||||||
|
return "", parseErr{n, fmt.Errorf("continue {expr} is not yet supported")} // TODO implement numbered continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return "continue\n", nil
|
||||||
|
|
||||||
case *stmt.Try:
|
case *stmt.Try:
|
||||||
|
|
||||||
// Generate an if err != nil {} block that we can bring up whenever
|
// Generate an if err != nil {} block that we can bring up whenever
|
||||||
|
Loading…
Reference in New Issue
Block a user