Inferring during transpilation

Abierto
#1,069 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
25/100
Tipo de issue
Nueva funcionalidad
Claridad
Bastante claro
Estado de actividad
Estancado
Stack tecnológico
cpp, php
Área
compilers

Línea de trabajo

Start with the provided main.php reproducer and run the shown kphp compilation command. Investigate constant-condition handling and type inference for the ternary involving KPHP_VERSION, then verify that the single-line assignment compiles while preserving the KPHP branch and PHP branch behavior.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

If I do someting like:

EmulatedEnumInt.php:

<?php
class EmulatedEnumInt {

 protected int $value;

 protected function __construct(int $value) {

  $this->value = $value;
 }

 public function __toString() : string {
  return (string) $this->value;
 }
}

CfgType.php:

<?php
#ifndef KPHP
enum CfgType : int {
case STRING = 1;
case INT = 2;
case BOOL = 3;
case ARRAY  = 4;
}
if (false) {
 #endif
 final class CfgType extends EmulatedEnumInt
 {
  const STRING = 1;
  const INT = 2;
  const BOOL = 3;
  const ARRAY  = 4;

  // GENERATED
  public static function STRING() : static {
   return new static(1);
  }

  public static function INT() : static {
   return new static(2);
  }

  public static function BOOL() : static {
   return new static(3);
  }

  public static function ARRAY() : static {
   return new static(4);
  }

  private static $fromMap = [
   1       =>      'STRING',
   2       =>      'INT',
   3       =>      'BOOL',
   4       =>      'ARRAY',
  ];

  public static function tryFrom(string|int $value) : static {
   if (isset(self::$fromMap[$value])) return new static(self::$fromMap[$value]);
   throw new \Exception("No such enum value:".$value);
  }
 }
 #ifndef KPHP
}
#endif

code.php:

<?php
include_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
 */
function cfg(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
  */
 function cfg(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 // PHP
define('KPHP_VERSION', 0);
if (false)
#endif // KPHP
define('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 ?

 
Lenguaje dominante
C++
Estrellas
1.5k
Forks
116
Merge medio
5 d 17 h
PR fusionados (30 d)
11

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de VKCOM/kphp

Todos los issues de VKCOM/kphp

Issues similares

Más issues de C++

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.