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*
|
||||
- [X] Static methods
|
||||
- [X] Inheritance *partial*
|
||||
- [ ] Interfaces
|
||||
- [X] Interfaces
|
||||
- [X] super
|
||||
- [X] Need to track current conversion state through into function generator, to select the concrete 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() {}
|
||||
}
|
58
node.go
58
node.go
@ -105,7 +105,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
||||
}
|
||||
|
||||
switch s.(type) {
|
||||
case *stmt.Class, *stmt.Function:
|
||||
case *stmt.Class, *stmt.Function, *stmt.Interface:
|
||||
// Declaration - emit immediately (hoist)
|
||||
ret += sm + "\n"
|
||||
|
||||
@ -265,12 +265,56 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
||||
// Create all member functions
|
||||
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
|
||||
// Reinstate parent state before returning
|
||||
this.currentClassName = prevClassName
|
||||
this.currentClassParentName = prevClassParentName
|
||||
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:
|
||||
// Top-level function definition
|
||||
// TODO parse doc comment
|
||||
@ -1154,12 +1198,14 @@ func (this *conversionState) convertFunctionCommon(params []node.Node, returnTyp
|
||||
|
||||
// Recurse through body statements
|
||||
|
||||
fullBody, err := this.convert(stmt.NewStmtList(bodyStmts))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if bodyStmts != nil {
|
||||
fullBody, err := this.convert(stmt.NewStmtList(bodyStmts))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ret += fullBody + "\n"
|
||||
ret += fullBody + "\n"
|
||||
}
|
||||
|
||||
// Done
|
||||
// No extra trailing newline in case this is part of a large expression
|
||||
|
Loading…
Reference in New Issue
Block a user