Skip to main content

Possible Type Constraints

rascal-0.40.17
php-analysis-0.2.4

This is design inspiration for the type inference algorithm.

Declarations:

There are differnt 'levels' of constraints.

  • On global level (what classes and functions do exist, what variables)
  • ?? not sure: on namespace level...
  • On class level (what fields and methods are there, what extends/implements)
  • On function/method level (what variables are used within the scope)
  • Between scopes (for method calls)

Types:

  • a variable $a has { t1, ..., tn } types. (within a certain scope)

  • assignement of variables: $x = $y (types of y = types of x)

  • return (method|function) can have {} of types: typeof x->a(); is the return value of public function a()

  • > this means that methods

  • call constructor when initializing a method

  • result of expression (e.g. $x + $y) has a set of possible types.

  • handle magic methods:

    • instantiation -> __construct (return type = null);
    • method call -> __call

Variable

  • The type of a variable is the type of the disjunction of all occurances of the variable within a within the scope.
  • On scopes:
    • global scope
    • function scope
    • method scope
    • exception for global key word, it is in the global scope AND in the function/method scope

Constants

  • Constant

Interface

  • Decl: name of the interface
  • Decl: extends (= subtype of ...)

Trait

?? out of scope ?? (not used alot, yet... can be added later)

Class

  • Decl: name of the class (including namespace)
  • Decl: extends (= subtype of ...)
  • Decl: implement
  • Decl: has constructor
  • Decl: constructor minimum re quired fields

Class Constant

  • Decl: name of the constant
  • Decl: class of the constant
  • Decl: type of the constant (?)

Class Property

  • Decl: name of the property
  • Decl: class of the property

Class Methods (/function)

  • Decl: name of the method
  • Decl: has parameter constraints (see below)
  • Decl: which class the method is in
  • The return type is the disjunction of the types of all return statements (or void/null when none provided)

Function

  • Decl: name of the function (including namespace)
  • Decl: has parameter constraints (see below)
  • The return type is the disjunction of the types of all return statements (or void/null when none provided)

Actual Parameter constraints

  • Decl: Minimum required params
  • Decl: type hints

Cast operators

CastsInputOutputRascalNotes
(array)anythingarraycast(array(), Expr e)
(bool|boolean)anythingbooleancast(\bool(), Expr e)
(int|integer)anythingintcast(\int(), Expr e)
(float|double|real)anythingdoublecast(float(), Expr e)
(string)anything besides an object\ stringcast(string(), Expr e)
(string)Objectstring or fatal errorcast(string(), Expr e)* only works if the object has __toString and returning a string
(object)anythingobjectcast(object(), Expr e)
(unset)anythingNULLcast(unset(), Expr e)

Arithmetic Operators:

  • please note that the priority is top to bottom (this can be implemented using rascal pattern matching).
  • '_' matches any type
  • Division and Modulus can trigger 'division by zero' warnings...

Rules for Negation operator: -l -> (double | int)

lresult
arrayerror
doubledouble
_integer

Rules for Addition operator: l + r -> (array | double | int)

lrresult
arrayarrayarray
array_fatal error
_arrayfatal error
double_double
_doubledouble
__integer

Rules for Division operator: l / r -> (double | int)

lrresult
_arrayfatal error
array_fatal error
double_double
_doubledouble
__integer

Rules for Modulus operator: l % r -> (int)

lrresult
__integer

Assignment Operators:

CodetypeOf($b)typeOf($a)Notes
$a &= $b;_integer
$a \|= $b;_integer
$a ^= $b;_integer
$a <<= $b;_integer
$a >>= $b;_integer
$a %= $b;_integer
$a .= $b;object*error*when object has no __toString() method
$a .= $b;_string
$a /= $b;arrayerror
$a /= $b;_integer
$a -= $b;arrayerror
$a -= $b;_integer
$a *= $b;bool|int|nullinteger
$a *= $b;_double
$a += $b;bool|int|nullinteger
$a += $b;_double

Rules for Bitwise Or (exclusive or) operator: $a ^ $b

typeOf($a)typeOf($b)ResultNotes
stringstringstring
__integer

Rules for Bitwise Shift right operator: $a >> $b

typeOf($a)typeOf($b)ResultNotes
__integeralways an integer

Rules for Bitwise Not operator: ~$a

typeOf($a)ResultNotes
integer|doubleinteger
stringstring
_error

Rules for Greater or equal operator: $a >= $b

typeOf($a)typeOf($b)ResultNotes
__booleanalways a boolean

Rules for Post-increment operator: $a++

typeOf($a)ResultNotes
string{string|integer|double}
nullinteger
__other types do not change type

Rules for Post-decrement operator: $a--

typeOf($a)ResultNotes
string{string|integer|double}
__other types do not change type

Rules for Or then operator: $a || $b

typeOf($a)typeOf($b)ResultNotes
__booleanalways a boolean

assignments

$b = $a // (sub)typeOf($b) is (sub)typeOf($a)
$c = $b = $a; // (sub)typeOf($a) = (sub)typeOf($b) && (sub)typeOf($b) = (sub)typeOf($c)

class instantiation

$a = new A; // type of $a is class with name "A"; (FQN: Full Qualified Name)
// minimum required params = 0;
$a = new A(1); // type of $a is class with name "A"; (FQN: Full Qualified Name)
// minimum required params = 0 OR 1;

Ternary operator (elvis)

$a ? $b : $c // result of this whole expression is: typeOf($b) OR typeOf($c)

Assumption

I assume that the program is correct. But because it is hard to check if programs are fine in dynamic languagues this is a thread to validity.

Other

?? Adding scope constraints??

hasClassConstant(classDecl, constDecl)
classCont(constDecl, value)
Examples:

hasClassConstant("A", "C");
> class A { const C = 1; }

hasField("A", "F");
> class A { public $F; }

hasMethod("A", "M");
> class A { public function M () {} }

Subtypes:

isSubType("A", "B")
> class A extends B {}

Note: add default classes, functions, variables and constants to the list of declarations

Symbols:

a <: b          | b is a subtype of a; 
| example: class b extends a {}
$a = $b;        | subtype of a is the subtype of b
| syntax: varType($a) <: varType($b);

$a->call() | typeOf(a) has method "call" OR magic method __call

$a->call($b) | typeOf(a) has method "call" OR magic method __call
| typeOf(b) is a subtype of formal parameter 1

// minimum number of params

Constraint Examples

syntax below: 

php code # constraint that can be derifed


class A {} # Type A is defined here.

$a = new A{}; # $a is of type A;
$b = $a; # $b is the same type as $a; ==> eq(typeOf(a),typeOf(b))
$b->do(); # type (or supertype) of $b has method "do"

$c = $b->do(new O) # type (or supertype) of b has method "do"
# return of b->do is of type c
$foo->call()->bar->chain();
# type of field bar has method "chain"

How to solve constraints: Keep resolving till you have non left.

Advantages: (what can we use it for?)

  • IDE support!!
  • Perform better (static) code analysis
  • Find source code l