Skip to content
This repository has been archived by the owner on Jun 4, 2019. It is now read-only.

Commit

Permalink
[pfff] support type constant definitions/declarations
Browse files Browse the repository at this point in the history
Summary:
This is diff 2/2; it adds support for declaring type consts in classes. I'm
reusing some of the AST constructs for `type` and `newtype`, and wrapping
them in a new type of const declaration.

This also adds one or two `%left` precedence thingies, these seem to
give ocamlyacc the right idea about "these are not the shift/reduce
conflicts you're looking for." It takes us from 5 reported conflicts
in the grammar to just the original 1. I'll need to test this change
separately to make sure it doesn't cause sadness.

Depends on D1880752.

Test Plan:
  make tests
  # this fails if I add an intentional parse error to good_tconst_decl.php

This test case should also cover the syntax introduced in D1880752; please
let me know if something looks inadequately covered.

Will run this on www when I get to the office.

Reviewers: dominik, dreeves

Reviewed By: dreeves

Subscribers: dominik

Differential Revision: https://phabricator.fb.com/D1880760

Tasks: 6358822

Signature: t1:1880760:1425321537:0d8da37962d49d524431d9d04106c5055c8d4ed8
  • Loading branch information
phooji committed Mar 3, 2015
1 parent ae6678b commit 7edb85d
Show file tree
Hide file tree
Showing 14 changed files with 132 additions and 5 deletions.
1 change: 1 addition & 0 deletions lang_php/analyze/foundation/ast_php_simple.ml
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ and type_def = {
and type_def_kind =
| Alias of hint_type
| Newtype of hint_type
| ClassConstType of hint_type option
(* with tarzan *)

(* ------------------------------------------------------------------------- *)
Expand Down
6 changes: 5 additions & 1 deletion lang_php/analyze/foundation/ast_php_simple_build.ml
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,10 @@ and type_def env def =
and type_def_kind env = function
| Alias t -> A.Alias (hint_type env t)
| Newtype t -> A.Newtype (hint_type env t)
| ClassConstType v1 -> A.ClassConstType
(match v1 with
| Some x -> Some (hint_type env x)
| None -> None)


and class_def env c =
Expand Down Expand Up @@ -707,7 +711,7 @@ and class_body env st (mets, flds) =
met::mets, more_flds @ flds

| ClassVariables _ | ClassConstants _ | UseTrait _
| XhpDecl _ | TraitConstraint _
| XhpDecl _ | TraitConstraint _ | ClassType _
-> (mets, flds)

and method_def env m =
Expand Down
1 change: 1 addition & 0 deletions lang_php/analyze/foundation/database_prolog_php.ml
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ let visit ~add readable ast =
)

| UseTrait _ -> ()
| ClassType _ -> ()
| TraitConstraint _ -> ()
)
| _ -> k x
Expand Down
1 change: 1 addition & 0 deletions lang_php/analyze/foundation/graph_code_php.ml
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,7 @@ and type_def env def =

and type_def_kind env = function
| Alias t | Newtype t -> hint_type env t
| ClassConstType _t -> ()

(* ---------------------------------------------------------------------- *)
(* Types *)
Expand Down
3 changes: 3 additions & 0 deletions lang_php/analyze/foundation/meta_ast_php_simple.ml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ and vof_type_def_kind =
| Alias v1 -> let v1 = vof_hint_type v1 in Ocaml.VSum (("Alias", [ v1 ]))
| Newtype v1 ->
let v1 = vof_hint_type v1 in Ocaml.VSum (("Newtype", [ v1 ]))
| ClassConstType v1 ->
let v1 = Ocaml.vof_option vof_hint_type v1 in
Ocaml.VSum (("ClassConstType", [v1]))

and vof_case =
function
Expand Down
3 changes: 2 additions & 1 deletion lang_php/analyze/visual/highlight_php.ml
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,8 @@ let visit_program ~tag _prefs hentities (ast, toks) =
tag info (Entity (Class, (Use2 fake_no_use2)));
);
k x
| Ast.TraitConstraint (_, _kind, _ty, _) ->
| Ast.TraitConstraint (_, _, _, _)
| Ast.ClassType _ ->
k x
);

Expand Down
2 changes: 1 addition & 1 deletion lang_php/matcher/php_vs_php.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2599,7 +2599,7 @@ and m_class_stmt a b =
B.TraitConstraint(b1, b2, b3, b4)
)
))))

| A.ClassType _, _
| A.ClassConstants _, _
| A.ClassVariables _, _
| A.Method _, _
Expand Down
3 changes: 2 additions & 1 deletion lang_php/parsing/ast_php.ml
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ and class_def = {
(* facebook-ext: 'require' can appear only in traits *)
| TraitConstraint of
tok (* require *) * trait_constraint_kind wrap * hint_type * tok (* ; *)

| ClassType of type_def
and class_constant = ident * static_scalar_affect option
and class_variable = dname * static_scalar_affect option
and class_var_modifier =
Expand Down Expand Up @@ -742,6 +742,7 @@ and type_def = {
and type_def_kind =
| Alias of hint_type
| Newtype of hint_type
| ClassConstType of hint_type option

(* ------------------------------------------------------------------------- *)
(* Other declarations *)
Expand Down
5 changes: 5 additions & 0 deletions lang_php/parsing/map_php.ml
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,9 @@ and map_class_stmt =
and v3 = map_hint_type v3
and v4 = map_tok v4
in TraitConstraint ((v1, v2, v3, v4))
| ClassType ((v1)) ->
let v1 = map_type_def v1
in ClassType ((v1))
| ClassConstants ((v1, v2, opt_ty, v3, v4)) ->
let v1 = map_option map_tok v1
and v2 = map_tok v2
Expand Down Expand Up @@ -1198,6 +1201,8 @@ and map_type_def_kind =
function
| Alias v1 -> let v1 = map_hint_type v1 in Alias ((v1))
| Newtype v1 -> let v1 = map_hint_type v1 in Newtype ((v1))
| ClassConstType v1 ->
let v1 = map_option map_hint_type v1 in ClassConstType ((v1))

and map_namespace_use_rule =
function
Expand Down
5 changes: 5 additions & 0 deletions lang_php/parsing/meta_ast_php.ml
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,9 @@ and vof_class_stmt =
and v3 = vof_hint_type v3
and v4 = vof_tok v4
in Ocaml.VSum (("TraitConstraint", [ v1; v2; v3; v4 ]))
| ClassType ((v1)) ->
let v1 = vof_type_def v1
in Ocaml.VSum (("ClassType", [v1]))
| ClassConstants ((v1, v2, opt_ty, v3, v4)) ->
let v1 = vof_option vof_tok v1
and v2 = vof_tok v2
Expand Down Expand Up @@ -1273,6 +1276,8 @@ and vof_type_def_kind =
| Alias v1 -> let v1 = vof_hint_type v1 in Ocaml.VSum (("Alias", [ v1 ]))
| Newtype v1 ->
let v1 = vof_hint_type v1 in Ocaml.VSum (("Newtype", [ v1 ]))
| ClassConstType v1 ->
let v1 = vof_option vof_hint_type v1 in Ocaml.VSum (("ClassConstType", [v1]))

and vof_namespace_use_rule =
function
Expand Down
36 changes: 35 additions & 1 deletion lang_php/parsing/parser_php.mly
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ module PI = Parse_info
T_SELF T_PARENT
/*(* facebook extension *)*/
T_TYPE T_NEWTYPE T_SHAPE

%left T_TYPE
%left T_IDENT
%right T_ELLIPSIS
/*(*-----------------------------------------*)*/
/*(*2 Symbol tokens *)*/
/*(*-----------------------------------------*)*/
Expand Down Expand Up @@ -688,6 +690,38 @@ class_statement:
let const_list = [Left const] in
ClassConstants(Some $1, $2, Some $3, const_list, $5) }

/*(* facebook-ext: type constants *)*/
| T_ABSTRACT T_CONST T_TYPE T_IDENT T_AS type_php TSEMICOLON
{ ClassType (* TODO (t6384084) add some fields here *) {
t_tok = $3;
t_name = Name $4;
t_tparams = None;
t_tconstraint = Some($5, $6);
t_tokeq = $5; (* doesn't exist here *)
t_kind = ClassConstType None;
t_sc = $7; }
}
| T_ABSTRACT T_CONST T_TYPE T_IDENT TSEMICOLON
{ ClassType (* TODO (t6384084) add some fields here *) {
t_tok = $3;
t_name = Name $4;
t_tparams = None;
t_tconstraint = None;
t_tokeq = $5; (* doesn't exist here *)
t_kind = ClassConstType None;
t_sc = $5; }
}
| T_CONST T_TYPE T_IDENT type_constr_opt TEQ type_php_or_shape TSEMICOLON
{ ClassType (* TODO (t6384084) add some fields here *) {
t_tok = $2;
t_name = Name $3;
t_tparams = None;
t_tconstraint = $4;
t_tokeq = $5;
t_kind = ClassConstType (Some $6);
t_sc = $7; }
}

/*(* class constants *)*/
| T_CONST class_constants_declaration TSEMICOLON
{ ClassConstants(None, $1, None, $2, $3) }
Expand Down
4 changes: 4 additions & 0 deletions lang_php/parsing/visitor_php.ml
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,9 @@ and v_class_stmt x =
and v3 = v_hint_type v3
and v4 = v_tok v4
in ()
| ClassType ((v1))->
let v1 = v_type_def v1
in ()
| ClassConstants ((v1, v2, opt_ty, v3, v4)) ->
let v1 = v_option v_tok v1
and v2 = v_tok v2
Expand Down Expand Up @@ -1146,6 +1149,7 @@ and v_type_def_kind =
function
| Alias v1 -> let v1 = v_hint_type v1 in ()
| Newtype v1 -> let v1 = v_hint_type v1 in ()
| ClassConstType v1 -> let v1 = v_option v_hint_type v1 in ()
and v_namespace_use_rule =
function
| ImportNamespace v1 -> let v1 = v_qualified_ident v1 in ()
Expand Down
1 change: 1 addition & 0 deletions lang_php/pretty/ast_pp_build.ml
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ and class_body env st acc =
| XhpDecl _ -> acc (* TODO xhp decl *)
| UseTrait _ -> raise (TodoConstruct "UseTrait")
| TraitConstraint _ -> raise (TodoConstruct "TraitConstraint")
| ClassType _ -> raise (TodoConstruct "ConstType")

and method_def env m =
let acc = [] in
Expand Down
66 changes: 66 additions & 0 deletions tests/php/parsing/good_tconst_decl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?hh
abstract class A {
abstract const type abs_class_by_class as arraykey;
const type TC as arraykey = arraykey;

final public function __construct (
private this::abs_class_by_class $id,
) {}

public function overriding(): Aint::vec {
return Vector {};
}

public function getID(): this::abs_class_by_class {
return $this->id;
}

public function testA(Aint::me::me::me::Aint $x): void {}
}

interface I {
abstract const type abs_class_by_class;
}

class Aint extends A {
const type abs_class_by_class = int;
const type me as Aint = Aint;
const type Aint = self::hop;
const type hop = int;
const type vec = ConstVector<int>;

public function test(): void {
$this->testA(101);
}

public function overriding(): ImmVector<int> {
return ImmVector {};
}
}

class Astr extends A {
const type abs_class_by_class = string;
}

abstract class B {
abstract const type AType as A;
abstract public static function getAID(): this::AType::abs_class_by_class;
}

class Bint extends B {
const type AType = Aint;
public static function getAID(): this::AType::abs_class_by_class {
return 0;
}
}

class Bstr extends B {
const type AType = Astr;
public static function getAID(): this::AType::abs_class_by_class {
return '';
}
}

function test(Aint $x): int {
return $x->getID();
}

0 comments on commit 7edb85d

Please sign in to comment.