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];
|
102
node.go
102
node.go
@ -391,18 +391,34 @@ func convert(n_ node.Node) (string, error) {
|
||||
//
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
return "", parseErr{n, err}
|
||||
}
|
||||
|
||||
// TODO this may need to use `:=`
|
||||
return lvalue + " = " + rvalue, nil
|
||||
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 `:=`
|
||||
return lvalue + " = " + rvalue, nil
|
||||
}
|
||||
|
||||
//
|
||||
// expr
|
||||
@ -497,6 +513,32 @@ func convert(n_ node.Node) (string, error) {
|
||||
case *expr.ConstFetch:
|
||||
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
|
||||
//
|
||||
@ -754,6 +796,54 @@ func convertFuncCallArgsCommon(args *node.ArgumentList) (string, error) {
|
||||
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) {
|
||||
|
||||
// TODO scan function and see if it contains any return statements at all
|
||||
|
Loading…
Reference in New Issue
Block a user