Revert "Fix PHP parameter type declarations compatibility"

I missed that this change breaks cpp_static, which seems to be to do
with handling the combined getter and setter we emit for static
member variables.  Reverting while I figure out how to handle that.

This reverts commit a277748870.
This commit is contained in:
Olly Betts 2022-06-09 17:55:09 +12:00
commit d43d62cd7a
2 changed files with 34 additions and 156 deletions

View file

@ -1,79 +0,0 @@
<?php
require "tests.php";
// No new functions
check::functions(array());
// New classes
check::classes(array('director_classes', 'Base', 'BaseClass', 'Caller', 'Derived', 'DerivedClass', 'DoubleHolder'));
// New vars
check::globals(array('PrintDebug'));
class PHPDerived extends Base {
function Val(DoubleHolder $x) { return $x; }
function Ref(DoubleHolder $x) { return $x; }
function Ptr(?DoubleHolder $x) { var_dump($x); return $x; }
function ConstPtrRef(?DoubleHolder $x) { return $x; }
function FullyOverloaded($x) {
$rv = parent::FullyOverloaded($x);
$rv = preg_replace('/Base/', 'PHPDerived', $rv);
return $rv;
}
function SemiOverloaded($x) {
# this is going to be awkward because we can't really
# semi-overload in PHP, but we can sort of fake it.
if (!is_int($x)) {
return parent::SemiOverloaded($x);
}
$rv = parent::SemiOverloaded($x);
$rv = preg_replace('/Base/', 'PHPDerived', $rv);
return $rv;
}
function DefaultParms(int $x, float $y = 1.1) {
$rv = parent::DefaultParms($x, $y);
$rv = preg_replace('/Base/', 'PHPDerived', $rv);
return $rv;
}
}
{
$c = new Caller();
makeCalls($c, new Base(100.0));
makeCalls($c, new Derived(200.0));
makeCalls($c, new PHPDerived(300.0));
}
function makeCalls($caller, $base) {
$bname = get_class($base);
if ($bname == 'PHPDerived') {
// TODO: Debug and make this work:
return;
}
$caller->set($base);
$dh = new DoubleHolder(444.555);
check::equal($caller->ValCall($dh)->val, $dh->val, "$bname.Val");
check::equal($caller->RefCall($dh)->val, $dh->val, "$bname.Ref");
check::equal($caller->PtrCall($dh)->val, $dh->val, "$bname.Ptr");
check::equal($caller->ConstPtrRefCall($dh)->val, $dh->val, "$bname.ConstPtrRef");
check::equal($caller->FullyOverloadedCall(1),
"${bname}::FullyOverloaded(int)",
"$bname.FullyOverloaded(int)");
check::equal($caller->FullyOverloadedCall(false),
"${bname}::FullyOverloaded(bool)",
"$bname.FullyOverloaded(bool)");
// This next one is TODO for Perl with PerlDerived.
check::equal($caller->SemiOverloadedCall(-678),
"${bname}::SemiOverloaded(int)",
"$bname.SemiOverloaded(int)");
check::equal($caller->SemiOverloadedCall(false),
"Base::SemiOverloaded(bool)",
"$bname.SemiOverloaded(bool)");
check::equal($caller->DefaultParmsCall(10, 2.2),
"${bname}::DefaultParms(int, double)",
"$bname.DefaultParms(int, double)");
check::equal($caller->DefaultParmsCall(10),
"${bname}::DefaultParms(int)",
"$bname.DefaultParms(int)");
$caller->reset();
}
check::done();

View file

@ -185,27 +185,10 @@ static void SwigPHP_emit_pointer_type_registrations() {
} }
} }
static Hash *create_php_type_flags() {
Hash *h = NewHash();
Setattr(h, "array", "MAY_BE_ARRAY");
Setattr(h, "bool", "MAY_BE_BOOL");
Setattr(h, "callable", "MAY_BE_CALLABLE");
Setattr(h, "float", "MAY_BE_DOUBLE");
Setattr(h, "int", "MAY_BE_LONG");
Setattr(h, "iterable", "MAY_BE_ITERABLE");
Setattr(h, "mixed", "MAY_BE_MIXED");
Setattr(h, "null", "MAY_BE_NULL");
Setattr(h, "object", "MAY_BE_OBJECT");
Setattr(h, "resource", "MAY_BE_RESOURCE");
Setattr(h, "string", "MAY_BE_STRING");
Setattr(h, "void", "MAY_BE_VOID");
return h;
}
static Hash *php_type_flags = create_php_type_flags();
// Class encapsulating the machinery to add PHP type declarations. // Class encapsulating the machinery to add PHP type declarations.
class PHPTypes { class PHPTypes {
Hash *phptypes;
// List with an entry for each parameter and one for the return type. // List with an entry for each parameter and one for the return type.
// //
// We assemble the types in here before emitting them so for an overloaded // We assemble the types in here before emitting them so for an overloaded
@ -218,14 +201,26 @@ class PHPTypes {
List *byref; List *byref;
public: public:
PHPTypes() : merged_types(NewList()), byref(NULL) { } PHPTypes() : phptypes(NewHash()), merged_types(NULL), byref(NULL) {
Setattr(phptypes, "array", "MAY_BE_ARRAY");
Setattr(phptypes, "bool", "MAY_BE_BOOL");
Setattr(phptypes, "callable", "MAY_BE_CALLABLE");
Setattr(phptypes, "float", "MAY_BE_DOUBLE");
Setattr(phptypes, "int", "MAY_BE_LONG");
Setattr(phptypes, "iterable", "MAY_BE_ITERABLE");
Setattr(phptypes, "mixed", "MAY_BE_MIXED");
Setattr(phptypes, "null", "MAY_BE_NULL");
Setattr(phptypes, "object", "MAY_BE_OBJECT");
Setattr(phptypes, "resource", "MAY_BE_RESOURCE");
Setattr(phptypes, "string", "MAY_BE_STRING");
Setattr(phptypes, "void", "MAY_BE_VOID");
}
PHPTypes(const PHPTypes *o) void reset() {
: merged_types(Copy(o->merged_types)), byref(Copy(o->byref)) { }
~PHPTypes() {
Delete(merged_types); Delete(merged_types);
merged_types = NewList();
Delete(byref); Delete(byref);
byref = NULL;
} }
// key is 0 for return type, or >= 1 for parameters numbered from 1 // key is 0 for return type, or >= 1 for parameters numbered from 1
@ -243,7 +238,7 @@ public:
// Skip duplicates when merging. // Skip duplicates when merging.
continue; continue;
} }
String *c = Getattr(php_type_flags, i.item); String *c = Getattr(phptypes, i.item);
if (c) { if (c) {
if (Len(result) > 0) Append(result, "|"); if (Len(result) > 0) Append(result, "|");
Append(result, c); Append(result, c);
@ -277,18 +272,9 @@ public:
} }
}; };
static PHPTypes *phptypes = NULL;
// Track if the current phptypes is for a non-class function.
static PHPTypes *non_class_phptypes = NULL;
// class + ":" + method -> PHPTypes*
static Hash *all_phptypes = NewHash();
// php_class_name -> php_parent_class_name
static Hash *php_parent_class = NewHash();
class PHP : public Language { class PHP : public Language {
PHPTypes phptypes;
public: public:
PHP() { PHP() {
director_language = 1; director_language = 1;
@ -742,7 +728,7 @@ public:
// it inherits from is directed, which is what we care about here. // it inherits from is directed, which is what we care about here.
// Using (!is_member_director(n)) would get it wrong for testcase // Using (!is_member_director(n)) would get it wrong for testcase
// director_frob. // director_frob.
out_phptype = phptypes->get_phptype(0, out_phpclasses); out_phptype = phptypes.get_phptype(0, out_phpclasses);
} }
} }
@ -777,17 +763,17 @@ public:
String *phpclasses = NewStringEmpty(); String *phpclasses = NewStringEmpty();
String *phptype = NULL; String *phptype = NULL;
if (GetFlag(n, "feature:php:type")) { if (GetFlag(n, "feature:php:type")) {
phptype = phptypes->get_phptype(param_count, phpclasses); phptype = phptypes.get_phptype(param_count, phpclasses);
} }
int byref; int byref;
if (!dispatch) { if (!dispatch) {
byref = GetFlag(p, "tmap:in:byref"); byref = GetFlag(p, "tmap:in:byref");
if (byref) phptypes->set_byref(param_count); if (byref) phptypes.set_byref(param_count);
} else { } else {
// If any overload takes a particular parameter by reference then the // If any overload takes a particular parameter by reference then the
// dispatch function also needs to take that parameter by reference. // dispatch function also needs to take that parameter by reference.
byref = phptypes->get_byref(param_count); byref = phptypes.get_byref(param_count);
} }
// FIXME: Should we be doing byref for return value as well? // FIXME: Should we be doing byref for return value as well?
@ -1155,6 +1141,12 @@ public:
return SWIG_ERROR; return SWIG_ERROR;
} }
if (!Getattr(n, "sym:previousSibling")) {
// First function of an overloaded group or a function which isn't part
// of a group so reset the phptype information.
phptypes.reset();
}
if (constructor) { if (constructor) {
wname = NewString("__construct"); wname = NewString("__construct");
} else if (wrapperType == membervar) { } else if (wrapperType == membervar) {
@ -1205,40 +1197,6 @@ public:
return SWIG_OK; return SWIG_OK;
} }
if (!Getattr(n, "sym:previousSibling")) {
// First function of an overloaded group or a function which isn't part
// of a group so reset the phptype information.
if (non_class_phptypes) {
delete non_class_phptypes;
non_class_phptypes = NULL;
}
phptypes = NULL;
if (class_name) {
// See if there's a parent class which implements this method, and if
// so copy the PHPTypes of that method as a starting point as we need
// to be compatible with it (whether it is virtual or not).
String *parent = class_name;
while ((parent = Getattr(php_parent_class, parent)) != NULL) {
String *key = NewStringf("%s:%s", parent, wname);
PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, key);
Delete(key);
if (p) {
phptypes = new PHPTypes(p);
break;
}
}
}
if (!phptypes) {
phptypes = new PHPTypes();
}
if (class_name) {
SetVoid(all_phptypes, NewStringf("%s:%s", class_name, wname), phptypes);
} else {
non_class_phptypes = phptypes;
}
}
f = NewWrapper(); f = NewWrapper();
if (static_getter) { if (static_getter) {
@ -1355,7 +1313,7 @@ public:
continue; continue;
} }
phptypes->process_phptype(p, i + 1, "tmap:in:phptype"); phptypes.process_phptype(p, i + 1, "tmap:in:phptype");
String *source = NewStringf("args[%d]", i); String *source = NewStringf("args[%d]", i);
Replaceall(tm, "$input", source); Replaceall(tm, "$input", source);
@ -1441,7 +1399,7 @@ public:
} }
emit_return_variable(n, d, f); emit_return_variable(n, d, f);
phptypes->process_phptype(n, 0, "tmap:out:phptype"); phptypes.process_phptype(n, 0, "tmap:out:phptype");
if (outarg) { if (outarg) {
Printv(f->code, outarg, NIL); Printv(f->code, outarg, NIL);
@ -1685,7 +1643,6 @@ public:
Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, zend_ce_exception);\n", class_name); Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, zend_ce_exception);\n", class_name);
} else if (is_class_wrapped(base_class)) { } else if (is_class_wrapped(base_class)) {
Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, SWIG_Php_ce_%s);\n", class_name, base_class); Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, SWIG_Php_ce_%s);\n", class_name, base_class);
Setattr(php_parent_class, class_name, base_class);
} else { } else {
Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name); Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name);
} }