Skip to content

Inferring during transpilation #1069

Description

@henrywood

If I do someting like:

EmulatedEnumInt.php:

<?phpclass EmulatedEnumInt {
protectedint$value;
protectedfunction__construct(int$value) {
$this->value = $value;
}
publicfunction__toString() : string {
return (string) $this->value;
}
}

CfgType.php:

<?php#ifndef KPHPenum CfgType : int {
caseSTRING = 1;
caseINT = 2;
caseBOOL = 3;
caseARRAY = 4;
}
if (false) {
#endiffinalclass CfgType extends EmulatedEnumInt
{
constSTRING = 1;
constINT = 2;
constBOOL = 3;
constARRAY = 4;
// GENERATEDpublicstaticfunctionSTRING() : static {
returnnewstatic(1);
}
publicstaticfunctionINT() : static {
returnnewstatic(2);
}
publicstaticfunctionBOOL() : static {
returnnewstatic(3);
}
publicstaticfunctionARRAY() : static {
returnnewstatic(4);
}
privatestatic$fromMap = [
1 => 'STRING',
2 => 'INT',
3 => 'BOOL',
4 => 'ARRAY',
];
publicstaticfunctiontryFrom(string|int$value) : static {
if (isset(self::$fromMap[$value])) returnnewstatic(self::$fromMap[$value]);
thrownew \Exception("No such enum value:".$value);
}
}
#ifndef KPHP
}
#endif

code.php:

<?phpinclude_once('CfgType.php');
#ifndef KPHP/** * Get a configuration value (PHP VERSION) * * (Assumes Config object is already stored in Memcache (in KEY: '___PROJECT_SHORT____CONFIG') ) * * @param string $settingName * @param CfgType $type * @param int $ttl * * @return ?int|?string|boolean|array */functioncfg(string$settingName, CfgType$type = CfgType::STRING, int$ttl = 86400) {
switch($type) {
case CfgType::STRING:
$value = (time() % 2 === 0) ? NULL : (string)$settingName;
return$value;
case CfgType::INT:
$value = (time() % 2 === 0) ? NULL : (int)80;
return$value;
case CfgType::BOOL:
$value = (time() % 2 === 0) ? NULL : (bool) $settingName;
return$value;
case CfgType::ARRAY:
$value = (time() % 2 === 0) ? NULL : ['foo', 'bar'];
return$value;
}
}
if (false) {
#endif/** * Get a configuration value (KPHP VERSION) * * (Assumes Config object is already stored in Memcache (in KEY: '___PROJECT_SHORT____CONFIG') ) * * @param string $settingName * @param CfgType $type * @param int $ttl * * @return ?int|?string|boolean|array */functioncfg(string$settingName, CfgType$type, int$ttl = 86400) {
$value = (string) $type;
switch($value) {
case (string)CfgType::STRING():
$value = (time() % 2 === 0) ? NULL : (string)$settingName;
return$value;
case (string)CfgType::INT():
$value = (time() % 2 === 0) ? NULL : (int)80;
return$value;
case (string)CfgType::BOOL():
$value = (time() % 2 === 0) ? NULL : (bool)$settingName;
return (bool) $settingName;
case (string)CfgType::ARRAY():
$value = (time() % 2 === 0) ? NULL : (array) ['foo', 'bar'];
return$value;
default:
return (string) $settingName.'_default';
}
}
#ifndef KPHP
}
#endif

main.php:

<?php#ifndef KPHP // PHPdefine('KPHP_VERSION', 0);
if (false)
#endif // KPHPdefine('KPHP_VERSION', 1);
include('EmulatedEnumInt.php');
include('CfgType.php');
include('code.php');
$user = (KPHP_VERSION) ? cfg('USER', CfgType::STRING()) : cfg('USER', CfgType::STRING);
echo"User=".$user.PHP_EOL; 

to cater for the fact that enums are not supported in KPHP (the code base I am trying to convert uses many enums), I would expect the transpiler to be able to deduce that the above statement can be re-written as:

$user = cfg('USER', CfgType::STRING());

since KPHP_VERSION is defined to be 1 when compiling with KPHP (and the else part of the ternary will only be taken when running in a PHP context)

However, if I compile like this:

# kphp main.php --mode server --include-dir $(pwd) -o ./server

I get this error:

Compilation error at stage: Calc actual calls, gen by type-inferer.cpp:53
main.php:14 in global scope
$user = (KPHP_VERSION) ? cfg('USER', CfgType::STRING()) : cfg('USER', CfgType::STRING);
pass int to argument $type of cfg
but it's declared as @param CfgType main.php:14 in global scope $user = (KPHP_VERSION) ? cfg('USER', CfgType::STRING()) : cfg('USER', CfgType::STRING); 1 is int

apparently because it takes the else part into account ?

I would like to be able to do assignments like ($user = ) on a single line.
However, I am aware that the $user = ... line can be replaced by:

#ifndef KPHP // PHP$user = cfg('USER', CfgType::STRING);
if (FALSE) { // KPHP#endif$user = cfg('USER', CfgType::STRING());
#ifndef KPHP // PHP
}
#endif 
but that syntax is rather cumbersome ...
So can't the transpiler be improved in this regard ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions