private/syntax/ast-core.ss
#lang scheme/base

(provide (all-defined-out))

;; TODO: save location information for operators?

;; ===========================================================================
;; TERMS
;; ===========================================================================

(define-struct Term (location) #:transparent)

(define-struct (Declaration Term) () #:transparent)
(define-struct (Statement Term) () #:transparent)
(define-struct (Expression Term) () #:transparent)

;; ===========================================================================
;; DECLARATIONS
;; ===========================================================================

;; Identifier * (listof Identifier) * (listof SourceElement)
(define-struct (FunctionDeclaration Declaration) (name args body) #:transparent)

;; (nelistof VariableInitializer)
(define-struct (VariableDeclaration Declaration) (bindings) #:transparent)

;; Identifier * (optional Expression)
(define-struct (VariableInitializer Term) (id init) #:transparent)

;; TODO: should `let-ness' be a property of FunctionDeclarations, rather than
;;       wrapping FunctionDeclarations inside LetDeclarations?
;; (union (nelistof VariableInitializer) (nelistof FunctionDeclaration))
(define-struct (LetDeclaration Declaration) (bindings) #:transparent)

;; ===========================================================================
;; EXPRESSIONS
;; ===========================================================================

;; string
(define-struct (StringLiteral Expression) (value) #:transparent)

;; number
(define-struct (NumericLiteral Expression) (value) #:transparent)

;; boolean
(define-struct (BooleanLiteral Expression) (value) #:transparent)

;;
(define-struct (NullLiteral Expression) () #:transparent)

;; string * boolean * boolean
(define-struct (RegexpLiteral Expression) (pattern global? case-insensitive?) #:transparent)

;; (listof (optional Expression))
(define-struct (ArrayLiteral Expression) (elements) #:transparent)

;; (listof (cons Property Expression))
(define-struct (ObjectLiteral Expression) (properties) #:transparent)

;;
(define-struct (ThisReference Expression) () #:transparent)

;; Identifier
(define-struct (VarReference Expression) (id) #:transparent)

;; Expression * Expression
(define-struct (BracketReference Expression) (container key) #:transparent)

;; Expression * Identifier
(define-struct (DotReference Expression) (container id) #:transparent)

;; Expression * (listof Expression)
(define-struct (NewExpression Expression) (constructor arguments) #:transparent)

;; Expression * PostfixOperator
(define-struct (PostfixExpression Expression) (expression operator) #:transparent)

;; PrefixOperator * Expression
(define-struct (PrefixExpression Expression) (operator expression) #:transparent)

;; Expression * InfixOperator * Expression
(define-struct (InfixExpression Expression) (left operator right) #:transparent)

;; Expression * Expression * Expression
(define-struct (ConditionalExpression Expression) (test consequent alternate) #:transparent)

;; Expression * AssignmentOperator * Expression
(define-struct (AssignmentExpression Expression) (lhs operator rhs) #:transparent)

;; (optional Identifier) * (listof Identifier) * (listof SourceElement)
(define-struct (FunctionExpression Expression) (name args body) #:transparent)

;; (listof VariableInitializer) Expression
(define-struct (LetExpression Expression) (bindings body) #:transparent)

;; Expression * (listof Expression)
(define-struct (CallExpression Expression) (method args) #:transparent)

;; Expression
(define-struct (ParenExpression Expression) (expression) #:transparent)

;; (listof Expression)
(define-struct (ListExpression Expression) (expressions) #:transparent)

;; ===========================================================================
;; STATEMENTS
;; ===========================================================================

;; (listof SubStatement)
(define-struct (BlockStatement Statement) (statements) #:transparent)

;;
(define-struct (EmptyStatement Statement) () #:transparent)

;; Expression
(define-struct (ExpressionStatement Statement) (expression) #:transparent)

;; Expression * SubStatement * (optional SubStatement)
(define-struct (IfStatement Statement) (test consequent alternate) #:transparent)

;; SubStatement * Expression
(define-struct (DoWhileStatement Statement) (body test) #:transparent)

;; Expression * SubStatement
(define-struct (WhileStatement Statement) (test body) #:transparent)

;; (union (optional Expression) VariableDeclaration) * (optional Expression) * (optional Expression) * SubStatement
(define-struct (ForStatement Statement) (init test incr body) #:transparent)

;; (union Expression VariableDeclaration) * Expression * SubStatement
(define-struct (ForInStatement Statement) (lhs container body) #:transparent)

;; (optional Identifier)
(define-struct (ContinueStatement Statement) (label) #:transparent)

;; (optional Identifier)
(define-struct (BreakStatement Statement) (label) #:transparent)

;; (optional Expression)
(define-struct (ReturnStatement Statement) (value) #:transparent)

;; (listof VariableInitializer) SubStatement
(define-struct (LetStatement Statement) (bindings body) #:transparent)

;; Expression * SubStatement
(define-struct (WithStatement Statement) (context body) #:transparent)

;; Expression * (listof CaseClause)
(define-struct (SwitchStatement Statement) (expression cases) #:transparent)

;; Identifier * SubStatement
(define-struct (LabelledStatement Statement) (label statement) #:transparent)

;; Expression
(define-struct (ThrowStatement Statement) (value) #:transparent)

;; Statement * (listof CatchClause) * (optional Statement)
(define-struct (TryStatement Statement) (body catch finally) #:transparent)

;; symbol
(define-struct (Identifier Term) (name) #:transparent)

;; (optional Expression) * (listof SubStatement)
(define-struct (CaseClause Term) (question answer) #:transparent)

;; Identifier * Statement
(define-struct (CatchClause Term) (id body) #:transparent)