stmt: initial array support
This commit is contained in:
parent
3743866d9f
commit
68b554a6ec
16
fixtures/0004-arrays.php
Normal file
16
fixtures/0004-arrays.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$foo = array(1);
|
||||||
|
|
||||||
|
$foo = [2, 3, 4]; // overwrite
|
||||||
|
|
||||||
|
$foo[] = 5;
|
||||||
|
|
||||||
|
$bar = ["a" => "b", "c" => "d"];
|
||||||
|
$bar["x"] = 6;
|
||||||
|
|
||||||
|
function lookupIndex(): int {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $bar[lookupIndex() + 1];
|
98
node.go
98
node.go
@ -391,18 +391,34 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
case *assign.Assign:
|
case *assign.Assign:
|
||||||
lvalue, err := convert(n.Variable) // might be a more complicated lvalue
|
|
||||||
if err != nil {
|
|
||||||
return "", parseErr{n, err}
|
|
||||||
}
|
|
||||||
|
|
||||||
rvalue, err := convert(n.Expression)
|
rvalue, err := convert(n.Expression)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
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 := convert(dimf.Variable)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{dimf, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return arrayVar + ` = append(` + arrayVar + `, ` + rvalue + `)`, nil
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Normal assignment
|
||||||
|
|
||||||
|
lvalue, err := convert(n.Variable) // might be a more complicated lvalue
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{n, err}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO this may need to use `:=`
|
// TODO this may need to use `:=`
|
||||||
return lvalue + " = " + rvalue, nil
|
return lvalue + " = " + rvalue, nil
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// expr
|
// expr
|
||||||
@ -497,6 +513,32 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
case *expr.ConstFetch:
|
case *expr.ConstFetch:
|
||||||
return resolveName(n.Constant)
|
return resolveName(n.Constant)
|
||||||
|
|
||||||
|
case *expr.Array:
|
||||||
|
return convertArrayLiteralCommon(n.Items)
|
||||||
|
|
||||||
|
case *expr.ShortArray:
|
||||||
|
return convertArrayLiteralCommon(n.Items)
|
||||||
|
|
||||||
|
case *expr.ArrayDimFetch:
|
||||||
|
// Might be x[foo], might be x[] (i.e. append() call)
|
||||||
|
// In order to make the append() transformation, we need to lookahead
|
||||||
|
// for ArrayDimFetch in the `*assign.Assign` case
|
||||||
|
vv, err := convert(n.Variable)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{n, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.Dim == nil {
|
||||||
|
return "", parseErr{n, fmt.Errorf("found '%s[]' outside of lvalue assignment context", vv)}
|
||||||
|
}
|
||||||
|
|
||||||
|
idx, err := convert(n.Dim)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{n, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vv + `[` + idx + `]`, nil // Same syntax as PHP
|
||||||
|
|
||||||
//
|
//
|
||||||
// binary
|
// binary
|
||||||
//
|
//
|
||||||
@ -754,6 +796,54 @@ func convertFuncCallArgsCommon(args *node.ArgumentList) (string, error) {
|
|||||||
return "(" + strings.Join(callParams, `, `) + ")", nil // expr only, no semicolon/newline
|
return "(" + strings.Join(callParams, `, `) + ")", nil // expr only, no semicolon/newline
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertArrayLiteralCommon(items []node.Node) (string, error) {
|
||||||
|
// Array literal
|
||||||
|
// We need to know the type. See if we can guess it from the first child element
|
||||||
|
// At least, we may be able to determine if this is a map or an array
|
||||||
|
|
||||||
|
entries := []string{}
|
||||||
|
keyType := unknownVarType
|
||||||
|
valType := unknownVarType
|
||||||
|
|
||||||
|
isMapType := false
|
||||||
|
for idx, itm_ := range items {
|
||||||
|
itm, ok := itm_.(*expr.ArrayItem)
|
||||||
|
if !ok {
|
||||||
|
return "", parseErr{itm_, fmt.Errorf("expected ArrayItem")}
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx == 0 {
|
||||||
|
isMapType = (itm.Key != nil)
|
||||||
|
} else {
|
||||||
|
if isMapType != (itm.Key != nil) {
|
||||||
|
return "", parseErr{itm, fmt.Errorf("Can't represent array and map in a single type")}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vv, err := convert(itm.Val)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{itm, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
if itm.Key != nil {
|
||||||
|
kv, err := convert(itm.Key)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{itm, err}
|
||||||
|
}
|
||||||
|
entries = append(entries, kv+`: `+vv+`,`)
|
||||||
|
} else {
|
||||||
|
entries = append(entries, vv+`,`)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if isMapType {
|
||||||
|
return `map[` + keyType + `]` + valType + `{` + strings.Join(entries, " ") + `}`, nil
|
||||||
|
} else {
|
||||||
|
return `[]` + valType + `{` + strings.Join(entries, " ") + `}`, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func convertFunctionCommon(params []node.Node, returnType node.Node, returnsRef bool, bodyStmts []node.Node) (string, error) {
|
func convertFunctionCommon(params []node.Node, returnType node.Node, returnsRef bool, bodyStmts []node.Node) (string, error) {
|
||||||
|
|
||||||
// TODO scan function and see if it contains any return statements at all
|
// TODO scan function and see if it contains any return statements at all
|
||||||
|
Loading…
Reference in New Issue
Block a user