// -*- javascript -*-
// Syntactic extensions to ES5 for Syndicate/js. See compiler.js for
// the rest of the translator.

Syndicate <: ES5 {
  //---------------------------------------------------------------------------
  // Extensions to expressions.

  Statement
    += ActorStatement
    | DataspaceStatement
    | ActorFacetStatement
    | ActorEndpointStatement
    | AssertionTypeDeclarationStatement
    | FieldDeclarationStatement
    | SendMessageStatement

  FunctionBodyBlock = "{" FunctionBody "}"   // odd that this isn't in es5.ohm somewhere

  ActorStatement
    = actorStar (named Expression<withIn>)? FunctionBodyBlock -- noReact
    | actor (named Expression<withIn>)? FunctionBodyBlock     -- withReact

  DataspaceStatement
    = ground dataspace identifier? FunctionBodyBlock -- ground
    | dataspace FunctionBodyBlock                    -- normal

  ActorFacetStatement
    = react FunctionBodyBlock

  ActorEndpointStatement
    = on start FunctionBodyBlock                                              -- start
    | on stop FunctionBodyBlock                                               -- stop
    | assert FacetPattern AssertWhenClause? #(sc)                             -- assert
    | on FacetEventPattern FunctionBodyBlock                                  -- event
    | on event identifier FunctionBodyBlock                                   -- onEvent
    | stop on FacetTransitionEventPattern FunctionBodyBlock                   -- stopOnWithCont
    | stop on FacetTransitionEventPattern #(sc)                               -- stopOnNoCont
    | dataflow FunctionBodyBlock                                              -- dataflow
    | during FacetPattern FunctionBodyBlock                                   -- during
    | during FacetPattern actor (named Expression<withIn>)? FunctionBodyBlock -- duringActor

  AssertWhenClause = when "(" Expression<withIn> ")"

  AssertionTypeDeclarationStatement
    = (assertion | message) type identifier "(" FormalParameterList ")" ("=" stringLiteral)? #(sc)

  FieldDeclarationStatement = field MemberExpression ("=" AssignmentExpression<withIn>)? #(sc)
  MemberExpression += field MemberExpression -- fieldRefExp
  UnaryExpression += delete field MemberExpression -- fieldDelExp

  SendMessageStatement = "::" Expression<withIn> #(sc)

  FacetEventPattern
    = message FacetPattern   -- messageEvent
    | asserted FacetPattern  -- assertedEvent
    | retracted FacetPattern -- retractedEvent

  FacetTransitionEventPattern
    = FacetEventPattern          -- facetEvent
    | "(" Expression<withIn> ")" -- risingEdge

  FacetPattern
    = LeftHandSideExpression metalevel decimalIntegerLiteral -- withMetalevel
    | LeftHandSideExpression                                 -- noMetalevel

  //---------------------------------------------------------------------------
  // Keywords. We don't add them to the "keyword" production because
  // we don't want to make them unavailable to programs as
  // identifiers.

  actorStar = "actor*" ~identifierPart
  actor = "actor" ~("*" | identifierPart)
  assert = "assert" ~identifierPart
  asserted = "asserted" ~identifierPart
  assertion = "assertion" ~identifierPart
  dataflow = "dataflow" ~identifierPart
  dataspace = "dataspace" ~identifierPart
  during = "during" ~identifierPart
  event = "event" ~identifierPart
  field = "field" ~identifierPart
  ground = "ground" ~identifierPart
  message = "message" ~identifierPart
  metalevel = "metalevel" ~identifierPart
  named = "named" ~identifierPart
  on = "on" ~identifierPart
  react = "react" ~identifierPart
  retracted = "retracted" ~identifierPart
  start = "start" ~identifierPart
  stop = "stop" ~identifierPart
  type = "type" ~identifierPart
  when = "when" ~identifierPart
}
