node: support interfaces
This commit is contained in:
parent
8752e8349c
commit
19d7cc469a
@ -52,7 +52,7 @@ The goal is to produce idiomatic, maintainable Go code as part of a one-off conv
|
|||||||
- *PHP variable names are case-sensitive, function names are case-insensitive*
|
- *PHP variable names are case-sensitive, function names are case-insensitive*
|
||||||
- [X] Static methods
|
- [X] Static methods
|
||||||
- [X] Inheritance *partial*
|
- [X] Inheritance *partial*
|
||||||
- [ ] Interfaces
|
- [X] Interfaces
|
||||||
- [X] super
|
- [X] super
|
||||||
- [X] Need to track current conversion state through into function generator, to select the concrete parent
|
- [X] Need to track current conversion state through into function generator, to select the concrete parent
|
||||||
- [X] parent::
|
- [X] parent::
|
||||||
|
9
fixtures/0007-interfaces.php
Normal file
9
fixtures/0007-interfaces.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
interface Base {
|
||||||
|
function Foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
class Child implements Base {
|
||||||
|
function Foo() {}
|
||||||
|
}
|
48
node.go
48
node.go
@ -105,7 +105,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch s.(type) {
|
switch s.(type) {
|
||||||
case *stmt.Class, *stmt.Function:
|
case *stmt.Class, *stmt.Function, *stmt.Interface:
|
||||||
// Declaration - emit immediately (hoist)
|
// Declaration - emit immediately (hoist)
|
||||||
ret += sm + "\n"
|
ret += sm + "\n"
|
||||||
|
|
||||||
@ -265,12 +265,56 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
// Create all member functions
|
// Create all member functions
|
||||||
ret += strings.Join(memberFuncs, "\n\n")
|
ret += strings.Join(memberFuncs, "\n\n")
|
||||||
|
|
||||||
|
if n.Implements != nil {
|
||||||
|
for _, ifaceName_ := range n.Implements.InterfaceNames {
|
||||||
|
ifaceName, err := this.resolveName(ifaceName_)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{ifaceName_, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add extra interface assertion statement
|
||||||
|
ret += "var _ " + ifaceName + " = &" + className + "{} // interface assertion\n"
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
// Reinstate parent state before returning
|
// Reinstate parent state before returning
|
||||||
this.currentClassName = prevClassName
|
this.currentClassName = prevClassName
|
||||||
this.currentClassParentName = prevClassParentName
|
this.currentClassParentName = prevClassParentName
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
||||||
|
case *stmt.Interface:
|
||||||
|
|
||||||
|
ifaceName := n.InterfaceName.(*node.Identifier).Value
|
||||||
|
|
||||||
|
ret := "type " + ifaceName + " interface {\n"
|
||||||
|
|
||||||
|
for _, ss := range n.Stmts {
|
||||||
|
classMethod, ok := ss.(*stmt.ClassMethod)
|
||||||
|
if !ok {
|
||||||
|
return "", parseErr{ss, fmt.Errorf("expected stmt.ClassMethod")}
|
||||||
|
}
|
||||||
|
|
||||||
|
methodName, err := applyVisibilityModifier(classMethod.MethodName.(*node.Identifier).Value, classMethod.Modifiers)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{ss, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO classMethod.PhpDocComment
|
||||||
|
|
||||||
|
arglist, err := this.convertFunctionCommon(classMethod.Params, classMethod.ReturnType, classMethod.ReturnsRef, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", parseErr{ss, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += methodName + arglist + "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += "}\n"
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
|
||||||
case *stmt.Function:
|
case *stmt.Function:
|
||||||
// Top-level function definition
|
// Top-level function definition
|
||||||
// TODO parse doc comment
|
// TODO parse doc comment
|
||||||
@ -1154,12 +1198,14 @@ func (this *conversionState) convertFunctionCommon(params []node.Node, returnTyp
|
|||||||
|
|
||||||
// Recurse through body statements
|
// Recurse through body statements
|
||||||
|
|
||||||
|
if bodyStmts != nil {
|
||||||
fullBody, err := this.convert(stmt.NewStmtList(bodyStmts))
|
fullBody, err := this.convert(stmt.NewStmtList(bodyStmts))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
ret += fullBody + "\n"
|
ret += fullBody + "\n"
|
||||||
|
}
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
// No extra trailing newline in case this is part of a large expression
|
// No extra trailing newline in case this is part of a large expression
|
||||||
|
Loading…
Reference in New Issue
Block a user