GithubHelp home page GithubHelp logo

hack-langspec's Introduction

Deprecated, Unmaintained

This repo contains the Hack Language Specification, a modified version of the PHP specification. It is no longer maintained and does not reflect the current version of Hack.

Hack Language Specification

The easiest way to navigate the specification is via the table of contents.

The latest official release of the specification is 1.1.

You can run the specification tests with HHVM via its test runner and the Hack typechecker via hh_client.

Pull requests, issue filings and comments are extremely welcome.

Make sure you understand the contribution process.

hack-langspec's People

Contributors

facebook-github-bot avatar jesseschalken avatar joelmarcey avatar jra3 avatar jwatzman avatar lazytype avatar matt-schellhas avatar milesj avatar pborreli avatar peterhal avatar rexjaeschke avatar siebelstim avatar simonwelsh avatar stof avatar wilfred avatar yogu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hack-langspec's Issues

Open/closed generic types

https://github.com/hhvm/hack-langspec/blob/master/spec/14-generic-types-methods-and-functions.md#open-and-closed-generic-types

I'm not sure why this distinction is being made at all, actually.

Each closed generic type, method, or function has its own set of static variables, which are not shared with any other closed generic types, methods, or functions.

I read this to mean that Blah<int> and Blah<string> don't share statics, which I'm fairly certain is incorrect (given our runtime type erasure semantics).

Resolve // UNSAFE markers in spec tests

When importing new and updating current tests for Hack 1.1, there were some discrepancies on where @RexJaeschke saw that the type checker passed a code block and where I saw it not pass those blocks.

If you search for // UNSAFE in the *.php in the tests directory, you will see 5-6 places where this happened.

We need to figure out why.

Additional use clause kinds in ch 20

Chapter 20 says that the legal use-clause kinds are

namespace-use-kind:
  function
  const

This is incomplete; we also accept "namespace" and "type".

Problems with "noreturn" as generic type argument

In the chapter on types we have:

Although this specification doesn’t treat the return-type noreturn as a type, per se, noreturn is regarded as a subtype of all other types, and a supertype of none.

And

generic-type-argument:
type-specifier
name

But "noreturn" is not indicated as a type-specifier, in keeping with the comment above. This is problematic because we need to accept "Awaitable" as a bona-fide generic type, so noreturn has to be a valid generic type argument.

Likely the best way out is simply to allow "noreturn" in the production for generic-type-argument.

typo in ch 22

In chapter 22 we have that postfix-expression can be "-expression". This was intended to say "primary-expression".

"void" enhancements

@elgenie tweaked the way we deal with void to be more in line with what you'd expect. We also reserved $_ to always be of type void. I think the spec goes on at some length about the issues with the former; we can remove most of that. Then we need to add the latter.

Attribute grammar should allow trailing commas

The attribute list, and the interior list of values have grammars:

attribute-list:
  attribute
  attribute-list  ,  attribute

attribute-values
  attribute-value
  attribute-values  ,  attribute-value

Both of which imply that the lists may not end in a comma. We wish to allow non-empty lists to end in a comma in both cases.

Field specifier list may have a trailing comma

In the type chapter, the grammar for field specifiers of shape types is:

shape-specifier:
  shape ( field-specifier-list-opt )
field-specifier-list:
  field-specifier
  field-specifier-list  ,  field-specifier

But this is allowed to have a trailing comma. Probably the grammar should be something like:

shape-specifier:
  shape ( field-specifier-list-opt )
field-specifier-list:
  field-specifiers  ,-opt
field-specifiers:
  field-specifier
  field-specifiers  ,  field-specifier

Typo in list intrinsic description

In the section on list intrinsics in the expressions chapter we have

"Only the right-most list-or-variable can be omitted."

First, this appears to be a mis-edit; there is no production called "list-or-variable".

Second, if we want the restriction that only the right-most expression can be omitted then we can solve this problem in the grammar rather than allowing list(,,,,) syntactically and then making a note that says that's wrong.

My suggestion is that regardless, the text should be changed to omit the undefined production.

If we wish to say that the list is an optional list of expressions that may be comma terminated then let's fix the grammar to say

  list-intrinsic:
    list  (  list-expression-list-opt  )
  list-expression-list:
    list-expressions    ,-opt
  list-expressions: 
    expression
    list-expressions  ,  expression

use clause grammar is incorrect for "simple" clauses

The grammar in Ch 20 for "simple" use clauses is incorrect. It states that

use function \N\F, \N\G;

is legal, but

use function \N\F, function \N\G;

is illegal. Though this IS illegal in PHP, in Hack we wish it to be legal.

The spec should be updated to say so. The grammar can be emended by changing

use namespace-use-kindopt  namespace-use-clauses  ;

to

use namespace-use-kind-clauses  ;

use clause grammar is incorrect for group clauses

The grammar in ch 20 says that the following are legal:

use \N\ { function C, function D };
use function \N\ { C, D };
use \N\ { C, D };

but this is illegal:

use function \N\ { function C, function D };

HHVM does not actually follow that rule; HHVM allows any use of a kind inside the { }, so only the second and third are legal.

We should fix the grammar so that the contents of the { } list is a use clause list, not a use kind clause list.

Type constants

This is a new feature from dreeves, not even announced yet, but it's 80% done, let's not forget to add it to the spec.

Restrictions on interface methods should be clarified

The text of chapter 17 on interface methods says

"Methods declared in an interface must not be declared abstract."

That's correct but incomplete. We should add to this:

  • Methods declared in an interface may be static.

This is good to point out because many languages do not allow static interface methods.

  • Methods declared in an interface must not be declared protected or private.

Clearly it makes no sense to have a protected or private interface member; they're implicitly public.

  • Methods declared in an interface may be marked public.

HHVM allows the "public" to be elided, even though technically that is not quite grammatical. I think that's a reasonable rule.

Case-sensitive enum values

An enum-declaration defines an enumerated type by the name name. Enumerated type names are case-insensitive.

This is either wrong, or a bug in the typechecker. AIUI everything should be case sensitive.

Namespaces are permitted to be nested

In chapter 20, Namespaces, we have the line

"The declaration-list must not contain a namespace-definition."

indicating that namespace declarations of the form

namespace foo {
namespace bar { }
}

are illegal.

This is incorrect; nested namespaces in this form are legal.

The text which says that you cannot mix the "namespace foo { ... } " form with the "namespace bar;" form is correct.

Mistakes and omissions regarding awaitables

Chapter 10 says

If async is present, return-type must be a type that implements Awaitable.

That is incorrect; the type must be exactly Awaitable or Awaitable for some T. An interface which extends Awaitable or a class which implements Awaitable is not legal here.

Chapter 16 does not mention at all that an async method must have a particular return type. (Though this is subtly implied by the note which says that an abstract non-async method may be awaitable.)

Typo in chapter 14

In chapter 14 we have

The type-specifier in generic-type-constraint must not be this or ?this.

But the text it is referring to says

generic-type-parameter-varianceopt generic-type-parameter-name type-constraintopt

That is, "type-constraint", not "generic-type-constraint". Looks like a mis-edit.

list intrinsic grammar is too permissive

The grammar says

  list-intrinsic:
     list  (  list-expression-list-opt  )
  list-expression-list:
    expression
    ,
    list-expression-list  ,  expression-opt

And then goes on to say

Only the right-most list-or-variable can be omitted.

This is a weird way to characterize that the grammar permits a trailing comma. I don't think of

list($x, $y,)

as having omitted a variable after the comma, but rather, having added an unnecessary comma. Characterizing this as an "omission" implies that something ought to be there.

I would remove the sentence entirely and enforce the rule in the grammar:

  list-intrinsic:
     list  (  expression-list-opt  )
  expression-list:
    expressions ,-opt
  expressions:
    expression
    expressions  ,  expression

Now there is no need for the supporting text, and the only things that can be "omitted" are (1) the entire list, or (2) the trailing comma.

Grammar problems

The grammar has a number of ambiguities, missing productions, and inconsistencies.
Has it actually been processed by some tool, like yacc?

If you're interested, I can report the problems I've found.

expression derivation problems in grammar

In reading through ch 22 we can see that there is no way to get from "expression" to many of the kinds of expressions. A few oddities:

"conditional-expression" is defined as

conditional-expression:
logical-inc-OR-expression
logical-inc-OR-expression ? expressionopt : conditional-expression

But this is the only place that "conditional-expression" appears in ch 22, so there is no path from "expression" to "conditional-expression".

In fact there is no path from "expression" to "primary-expression". We have

expression:
assignment-expression

assignment-expression:
lambda-expression
simple-assignment-expression  -- this is what it says on the tin
compound-assignment-expression -- as is this

lambda-expression:
piped-expression
asyncopt lambda-function-signature ==> lambda-body

piped-expression:
coalesce-expression
piped-expression |> coalesce-expression

But coalesce-expression is not defined in ch 22. It is defined in ch 10 as

coalesce-expression:
logical-inc-OR-expression ?? expression

So (1) coalesce-expression definitely needs to be defined in ch 22, and (2) it probably needs to make progress towards primary-expression.

Typos in ch 20

All occurrence of a namespace-definition in a script must have the declaration-list form or must have the "semicolon" form; the two forms cannot be mixed.

Should be "occurrences", not "occurrence", to be grammatical.

When a script contains source code that is not inside a namespace, and source code that is inside one or namespaces, the namespaced code must use the declaration-list form of namespace-definition.

"inside one or namespaces" appears to be missing the word "more".

Problems with variadic parameters

There are numerous problems with variadic parameters.

In ordinary functions and methods, the grammar given is

  parameter-list:
    ...
    parameter-declaration-list  ,opt
    parameter-declaration-list  ,  ... 

But this isn't complete; the "..." is allowed to have an attribute, a type and a name, the same as any other parameter. The grammar should be

    variadic-parameter:
      ...
      attribute-specification-opt type-specifier ...  variable-name

Note that if it has a type then it must have a name, and if it has a name then it must have a type.

The grammar for constructor parameters is even more wrong:

  constructor-parameter-declaration-list:
    constructor-parameter-declaration
    constructor-parameter-declaration-list  ,  constructor-parameter-declaration

First of all, this does not allow a trailing comma when it should. Second, it makes no mention of variadic parameters, which are legal in a constructor.

Note that a variadic parameter with a name in a constructor is also allowed to have a visibility modifier, so that should be in the grammar as well.

Typo in basic concepts

In the memory model system.

Unsetting $a causes variable $a to be destroyed and its corresponding alias to the VStore to be removed, leaving $c’s VSlot as the only pointer remaining to the VStore.

Should be $b instead of $c.

Unsetting $a causes variable $a to be destroyed and its corresponding alias to the VStore to be removed, leaving $b’s VSlot as the only pointer remaining to the VStore.

Problems with async

https://github.com/hhvm/hack-langspec/blob/master/spec/10-expressions.md#expressions should probably mention await. Might be missing in other syntax specifiers too.

When an async function is compiled, a special transformation is performed, so that an object that implements Awaitable (§§) is returned to the caller (where T is the function's return-type).

Need to check the definition of return-type, but this transform happens at runtime, the static return type is still always Awaitable<T>, that's what you write down in the source file.

When yielding control, the implementation of await may choose to yield control back to the current async function's caller.

Not sure what this is getting at here since the caller is still blocked.

Restriction on contents of abstract final classes needs description

Chapter 16 correctly notes the rules for abstract classes and final classes, but does not state anywhere the rule that a class which is both abstract and final may only declare static methods and properties. Since the class cannot be instantiated, it is pointless to declare an instance method or property; it would never be used.

"require" clauses need to be able to take generic types

The require clauses have the grammars:

    require-extends-clause:
      require  extends  qualified-name  ;

    require-implements-clause:
      require  implements  qualified-name  ;

But we wish to allow parsing

class Foo<T> { }
trait Bar { 
    require extends Foo<int>; 
}

which does note match that grammar. The grammar should be updated to allow more than just qualified names here.

Error in ch 20 regarding nested namespaces

Chapter 20 makes the following statements about namespaces:

(1)

"All occurrence of a namespace-definition in a script must have the declaration-list form or must have the "semicolon" form; the two forms cannot be mixed."

This is correct.

(2) "The declaration-list must not contain a namespace-definition."

This is not correct. It should be legal to say

namespace foo {
namespace bar {
class C { }
}
new \foo\bar\C();
}

Now, it should still be illegal to say

namespace foo {
namespace bar;

and so on, but this is covered by the first rule.

The second rule can simply be deleted.

Add grammar and description for "where" clauses

Hack supports an optional "where" clause on a function definition; it comes last (after the return type, before the body.)

The grammar is

  where-clause:
    where constraint-list
  constraint-list:
    constraint
    constraint-list , constraint
  constraint:
    type-specifier  constraint-operator  type-specifier
  constraint-operator:
    =
    as
    super

Note that a trailing comma is not accepted in a constraint list.

The grammar should be amended to include these productions, and the description of a function header should describe the semantics of the clause.

Problems with type constraint specification

First off, a typo.

In the chapter on types we have:

generic-type-parameter-variance-opt generic-type-parameter-name type-constraint-opt

And then later

The type-specifier in generic-type-constraint must not be this or ?this.

The latter is correct. The former must be generic-type-constraint-opt.

Second, a type constraint is specified as

as type-specifier

but in a generic type parameter declaration we also allow:

super type-specifier

I've entered another issue to track the fact that "super" is not listed as a keyword.

However, we use type-constraint as a production in more places than just generic type parameters, and it is not yet clear to me which ones allow "super" and which ones allow only "as". I'll do some looking into that. But for now what we should probably do is have two productions:

generic-type-parameter-constraint:
as type-specifier
super type-specifier

type-parameter-constraint:
as type-specifier

Third, we now permit more than one type constraint on a generic type parameter. So the grammar should be changed to indicate that this is a list of zero or more generic-type-constraints. (Note that the list is NOT comma separated for obvious reasons!)

Add "super" keyword

The keyword "super" -- which is used in generic type constraints -- needs to be added to the list of keywords.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.