================================================================================
Simple vertex shader
================================================================================

[shader("vertex")]
float4 vertexMain(
    float3 modelPosition : POSITION,
    uint vertexID : SV_VertexID,
    uniform float4x4 mvp)
    : SV_Position
{ /* ... */ }

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (hlsl_attribute
      (call_expression
        (identifier)
        (argument_list
          (string_literal
            (string_content)))))
    (type_identifier)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (type_identifier)
          (identifier)
          (semantics
            (identifier)))
        (parameter_declaration
          (type_identifier)
          (identifier)
          (semantics
            (identifier)))
        (parameter_declaration
          (qualifiers)
          (type_identifier)
          (identifier)))
      (semantics
        (identifier)))
    (compound_statement
      (comment))))

================================================================================
Type inference
================================================================================

main() {
  var a = 1; // OK, `a` is an `int`.
  var b = float3(0, 1, 2); // OK, `b` is a `float3`.
  var a : int = 1; // OK.
  var b : int; // OK.
  let a = 5; // OK, `a` is `int`.
  let b : int = 5; // OK.
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (declaration
        (placeholder_type_specifier)
        (init_declarator
          (identifier)
          (number_literal)))
      (comment)
      (declaration
        (placeholder_type_specifier)
        (init_declarator
          (identifier)
          (call_expression
            (identifier)
            (argument_list
              (number_literal)
              (number_literal)
              (number_literal)))))
      (comment)
      (declaration
        (placeholder_type_specifier)
        (init_declarator
          (type_hinted_declarator
            (identifier)
            (type_hint
              (primitive_type)))
          (number_literal)))
      (comment)
      (declaration
        (placeholder_type_specifier)
        (type_hinted_declarator
          (identifier)
          (type_hint
            (primitive_type))))
      (comment)
      (declaration
        (placeholder_type_specifier)
        (init_declarator
          (identifier)
          (number_literal)))
      (comment)
      (declaration
        (placeholder_type_specifier)
        (init_declarator
          (type_hinted_declarator
            (identifier)
            (type_hint
              (primitive_type)))
          (number_literal)))
      (comment))))

================================================================================
Interfaces
================================================================================

interface IFoo
{
    int myMethod(float arg);
};

--------------------------------------------------------------------------------

(translation_unit
  (interface_specifier
    (type_identifier)
    (field_declaration_list
      (field_declaration
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list
            (parameter_declaration
              (primitive_type)
              (identifier))))))))

================================================================================
Generics
================================================================================

int myGenericMethod<T: IFoo>(T arg)
{
    return arg.myMethod(1.0);
}

--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (template_function
        (identifier)
        (template_argument_list
          (type_descriptor
            (type_identifier))
          (interface_requirements
            (identifier))))
      (parameter_list
        (parameter_declaration
          (type_identifier)
          (identifier))))
    (compound_statement
      (return_statement
        (call_expression
          (field_expression
            (identifier)
            (field_identifier))
          (argument_list
            (number_literal)))))))

================================================================================
Is/as operator
================================================================================
void main() {
  bool t = foo is MyImpl; // true
  Optional<MyImpl> optV = foo as MyImpl;
}
--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list))
    (compound_statement
      (declaration
        (primitive_type)
        (init_declarator
          (identifier)
          (binary_expression
            (identifier)
            (identifier))))
      (comment)
      (declaration
        (template_type
          (type_identifier)
          (template_argument_list
            (type_descriptor
              (type_identifier))))
        (init_declarator
          (identifier)
          (binary_expression
            (identifier)
            (identifier)))))))

================================================================================
Extensions
================================================================================
extension MyObject : IBar, IBar2
{
    float bar() { return 1.0f; }
    float bar2() { return 2.0f; }
};
--------------------------------------------------------------------------------

(translation_unit
  (extension_specifier
    (type_identifier)
    (base_class_clause
      (type_identifier)
      (type_identifier))
    (field_declaration_list
      (function_definition
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list))
        (compound_statement
          (return_statement
            (number_literal))))
      (function_definition
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list))
        (compound_statement
          (return_statement
            (number_literal)))))))

================================================================================
This
================================================================================
interface IComparable
{
    int comparesTo(This other);
};
--------------------------------------------------------------------------------

(translation_unit
  (interface_specifier
    (type_identifier)
    (field_declaration_list
      (field_declaration
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list
            (parameter_declaration
              (placeholder_type_specifier)
              (identifier))))))))

================================================================================
Import
================================================================================

__exported import a.b;
__exported import a;
import ab;

--------------------------------------------------------------------------------

(translation_unit
  (import_statement
    (identifier)
    (identifier))
  (import_statement
    (identifier))
  (import_statement
    (identifier)))

================================================================================
__subscript
================================================================================

struct MyType
{
    int val[12];
    __subscript(int x, int y) -> int
    {
        get { return val[x*3 + y]; }
        set { val[x*3+y] = newValue; }
    }
};
--------------------------------------------------------------------------------

(translation_unit
  (struct_specifier
    (type_identifier)
    (field_declaration_list
      (field_declaration
        (primitive_type)
        (array_declarator
          (field_identifier)
          (number_literal)))
      (subscript_declaration
        (parameter_list
          (parameter_declaration
            (primitive_type)
            (identifier))
          (parameter_declaration
            (primitive_type)
            (identifier)))
        (trailing_return_type
          (type_descriptor
            (primitive_type)))
        (compound_statement)
        (compound_statement
          (property_get
            (compound_statement
              (return_statement
                (subscript_expression
                  (identifier)
                  (subscript_argument_list
                    (binary_expression
                      (binary_expression
                        (identifier)
                        (number_literal))
                      (identifier)))))))
          (property_set
            (compound_statement
              (expression_statement
                (assignment_expression
                  (subscript_expression
                    (identifier)
                    (subscript_argument_list
                      (binary_expression
                        (binary_expression
                          (identifier)
                          (number_literal))
                        (identifier))))
                  (identifier))))))
        (compound_statement)))))

================================================================================
property
================================================================================

struct MyType
{
    property highBits : uint
    {
        get { return flag >> 16; }
        set { flag = (flag & 0xFF) + (newValue << 16); }
    }
    property int oldSyntax
    {
        get { return flag >> 16; }
        set { flag = (flag & 0xFF) + (newValue << 16); }
    }
};

--------------------------------------------------------------------------------

(translation_unit
  (struct_specifier
    (type_identifier)
    (field_declaration_list
      (property_declaration
        (identifier)
        (type_descriptor
          (type_identifier))
        (compound_statement)
        (compound_statement
          (property_get
            (compound_statement
              (return_statement
                (binary_expression
                  (identifier)
                  (number_literal)))))
          (property_set
            (compound_statement
              (expression_statement
                (assignment_expression
                  (identifier)
                  (binary_expression
                    (parenthesized_expression
                      (binary_expression
                        (identifier)
                        (number_literal)))
                    (parenthesized_expression
                      (binary_expression
                        (identifier)
                        (number_literal)))))))))
        (compound_statement))
      (property_declaration
        (type_descriptor
          (primitive_type))
        (identifier)
        (compound_statement)
        (compound_statement
          (property_get
            (compound_statement
              (return_statement
                (binary_expression
                  (identifier)
                  (number_literal)))))
          (property_set
            (compound_statement
              (expression_statement
                (assignment_expression
                  (identifier)
                  (binary_expression
                    (parenthesized_expression
                      (binary_expression
                        (identifier)
                        (number_literal)))
                    (parenthesized_expression
                      (binary_expression
                        (identifier)
                        (number_literal)))))))))
        (compound_statement)))))

================================================================================
property get/set without block
================================================================================

interface IFoo
{
    property int count {get; set;}
};

--------------------------------------------------------------------------------

(translation_unit
  (interface_specifier
    (type_identifier)
    (field_declaration_list
      (property_declaration
        (type_descriptor
          (primitive_type))
        (identifier)
        (compound_statement)
        (compound_statement
          (property_get)
          (property_set))
        (compound_statement)))))

================================================================================
Missing ";" ok
================================================================================

extension uint : IPrintf
{
    // A `uint` only consumes one word in the variadic payload.
    //
    // Note: unlike the case for `IPrintable` above, the encoding
    // for format args for `printf()` doesn't include type information.
    //
    uint getPrintfWordCount() { return 1; }

    // Writing the required data to the payload for `printf()` is simple
    void writePrintfWords(RWStructuredBuffer<uint> buffer, uint offset)
    {
        buffer[offset++] = this;
    }
}

extension String : IPrintf
{
    uint getPrintfWordCount() { return 1; }

    void writePrintfWords(RWStructuredBuffer<uint> buffer, uint offset)
    {
        buffer[offset++] = getStringHash(this);
    }
}
--------------------------------------------------------------------------------

(translation_unit
  (extension_specifier
    (type_identifier)
    (base_class_clause
      (type_identifier))
    (field_declaration_list
      (comment)
      (comment)
      (comment)
      (comment)
      (comment)
      (function_definition
        (type_identifier)
        (function_declarator
          (field_identifier)
          (parameter_list))
        (compound_statement
          (return_statement
            (number_literal))))
      (comment)
      (function_definition
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list
            (parameter_declaration
              (template_type
                (type_identifier)
                (template_argument_list
                  (type_descriptor
                    (type_identifier))))
              (identifier))
            (parameter_declaration
              (type_identifier)
              (identifier))))
        (compound_statement
          (expression_statement
            (assignment_expression
              (subscript_expression
                (identifier)
                (subscript_argument_list
                  (update_expression
                    (identifier))))
              (this)))))))
  (extension_specifier
    (type_identifier)
    (base_class_clause
      (type_identifier))
    (field_declaration_list
      (function_definition
        (type_identifier)
        (function_declarator
          (field_identifier)
          (parameter_list))
        (compound_statement
          (return_statement
            (number_literal))))
      (function_definition
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list
            (parameter_declaration
              (template_type
                (type_identifier)
                (template_argument_list
                  (type_descriptor
                    (type_identifier))))
              (identifier))
            (parameter_declaration
              (type_identifier)
              (identifier))))
        (compound_statement
          (expression_statement
            (assignment_expression
              (subscript_expression
                (identifier)
                (subscript_argument_list
                  (update_expression
                    (identifier))))
              (call_expression
                (identifier)
                (argument_list
                  (this))))))))))

================================================================================
Missing ";" ok in namespace
================================================================================

namespace foo {
extension uint : IPrintf
{
    void writePrintfWords(RWStructuredBuffer<uint> buffer, uint offset)
    {
        buffer[offset++] = this;
    }
}

struct
{
    int x,y;
}
}
--------------------------------------------------------------------------------

(translation_unit
  (namespace_definition
    (namespace_identifier)
    (declaration_list
      (extension_specifier
        (type_identifier)
        (base_class_clause
          (type_identifier))
        (field_declaration_list
          (function_definition
            (primitive_type)
            (function_declarator
              (field_identifier)
              (parameter_list
                (parameter_declaration
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (type_identifier))))
                  (identifier))
                (parameter_declaration
                  (type_identifier)
                  (identifier))))
            (compound_statement
              (expression_statement
                (assignment_expression
                  (subscript_expression
                    (identifier)
                    (subscript_argument_list
                      (update_expression
                        (identifier))))
                  (this)))))))
      (struct_specifier
        (field_declaration_list
          (field_declaration
            (primitive_type)
            (field_identifier)
            (field_identifier)))))))

================================================================================
Associated type
================================================================================


interface IBase
{
     associatedtype V;
     V sub(V a0, V a1);
}

--------------------------------------------------------------------------------

(translation_unit
  (interface_specifier
    (type_identifier)
    (field_declaration_list
      (associatedtype_declaration
        (type_identifier))
      (field_declaration
        (type_identifier)
        (function_declarator
          (field_identifier)
          (parameter_list
            (parameter_declaration
              (type_identifier)
              (identifier))
            (parameter_declaration
              (type_identifier)
              (identifier))))))))

================================================================================
Associated type descriptor
================================================================================

struct Simple : ISimple
{
    typedef Val U;
    Val.V add(U v0, U v1)
    {
        return v0.sub(4, v1.sub(1,2));
    }
};

interface ISimple
{
    associatedtype U : IBase;
    U.V add(U v0, U v1);
}
--------------------------------------------------------------------------------

(translation_unit
  (struct_specifier
    (type_identifier)
    (base_class_clause
      (type_identifier))
    (field_declaration_list
      (type_definition
        (type_identifier)
        (type_identifier))
      (function_definition
        (associatedtype_specifier
          (type_identifier)
          (type_identifier))
        (function_declarator
          (field_identifier)
          (parameter_list
            (parameter_declaration
              (type_identifier)
              (identifier))
            (parameter_declaration
              (type_identifier)
              (identifier))))
        (compound_statement
          (return_statement
            (call_expression
              (field_expression
                (identifier)
                (field_identifier))
              (argument_list
                (number_literal)
                (call_expression
                  (field_expression
                    (identifier)
                    (field_identifier))
                  (argument_list
                    (number_literal)
                    (number_literal))))))))))
  (interface_specifier
    (type_identifier)
    (field_declaration_list
      (associatedtype_declaration
        (type_identifier)
        (base_class_clause
          (type_identifier)))
      (field_declaration
        (associatedtype_specifier
          (type_identifier)
          (type_identifier))
        (function_declarator
          (field_identifier)
          (parameter_list
            (parameter_declaration
              (type_identifier)
              (identifier))
            (parameter_declaration
              (type_identifier)
              (identifier))))))))

================================================================================
Random things in a namespace
================================================================================
namespace foo {
extension uint : IPrintf
{
    void writePrintfWords(RWStructuredBuffer<uint> buffer, uint offset)
    {
        buffer[offset++] = this;
    }
}

struct
{
    int x,y;
}
}


struct Val : IBase
{
    typedef int V;
    int base;
    V sub(V a0, V a1)
    {
        return a0 - a1 + base;
    }
};

--------------------------------------------------------------------------------

(translation_unit
  (namespace_definition
    (namespace_identifier)
    (declaration_list
      (extension_specifier
        (type_identifier)
        (base_class_clause
          (type_identifier))
        (field_declaration_list
          (function_definition
            (primitive_type)
            (function_declarator
              (field_identifier)
              (parameter_list
                (parameter_declaration
                  (template_type
                    (type_identifier)
                    (template_argument_list
                      (type_descriptor
                        (type_identifier))))
                  (identifier))
                (parameter_declaration
                  (type_identifier)
                  (identifier))))
            (compound_statement
              (expression_statement
                (assignment_expression
                  (subscript_expression
                    (identifier)
                    (subscript_argument_list
                      (update_expression
                        (identifier))))
                  (this)))))))
      (struct_specifier
        (field_declaration_list
          (field_declaration
            (primitive_type)
            (field_identifier)
            (field_identifier))))))
  (struct_specifier
    (type_identifier)
    (base_class_clause
      (type_identifier))
    (field_declaration_list
      (type_definition
        (primitive_type)
        (type_identifier))
      (field_declaration
        (primitive_type)
        (field_identifier))
      (function_definition
        (type_identifier)
        (function_declarator
          (field_identifier)
          (parameter_list
            (parameter_declaration
              (type_identifier)
              (identifier))
            (parameter_declaration
              (type_identifier)
              (identifier))))
        (compound_statement
          (return_statement
            (binary_expression
              (binary_expression
                (identifier)
                (identifier))
              (identifier))))))))

================================================================================
Double iface
================================================================================

void some_func<TParam:IPackable&IFloat>(TParam a)
{

}
void some_func<TParam:IPackable&IFloat, Foo: Bar, T>(TParam a)
{

}
--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (template_function
        (identifier)
        (template_argument_list
          (type_descriptor
            (type_identifier))
          (interface_requirements
            (identifier)
            (identifier))))
      (parameter_list
        (parameter_declaration
          (type_identifier)
          (identifier))))
    (compound_statement))
  (function_definition
    (primitive_type)
    (function_declarator
      (template_function
        (identifier)
        (template_argument_list
          (type_descriptor
            (type_identifier))
          (interface_requirements
            (identifier)
            (identifier))
          (type_descriptor
            (type_identifier))
          (interface_requirements
            (identifier))
          (type_descriptor
            (type_identifier))))
      (parameter_list
        (parameter_declaration
          (type_identifier)
          (identifier))))
    (compound_statement)))

================================================================================
Where clause
================================================================================
    void myFunc<T>(T val)
        where T : Foo,
        	  T : Bar
    {}
--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (template_function
        (identifier)
        (template_argument_list
          (type_descriptor
            (type_identifier))))
      (parameter_list
        (parameter_declaration
          (type_identifier)
          (identifier)))
      (where_clause
        (type_descriptor
          (type_identifier))
        (interface_requirements
          (identifier))
        (type_descriptor
          (type_identifier)))
      (semantics
        (identifier)))
    (compound_statement)))

================================================================================
Fancy generics
================================================================================

    void someFunc<
    	T, 					// type parameter
    	T : X, 				// type parameter with constraint
    	T = Y, 				// type parameter with default
    	T : X = Y, 			// type parameter with constraint and default
    	let N : int,		// value parameter (type must be explicit)
    	let N : int = 3>	// value parameter with default
    	()
    { }
--------------------------------------------------------------------------------

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (template_function
        (identifier)
        (template_argument_list
          (type_descriptor
            (type_identifier))
          (comment)
          (type_descriptor
            (type_identifier))
          (interface_requirements
            (identifier))
          (comment)
          (type_descriptor
            (type_identifier))
          (type_descriptor
            (type_identifier))
          (comment)
          (type_descriptor
            (type_identifier))
          (interface_requirements
            (identifier))
          (type_descriptor
            (type_identifier))
          (comment)
          (identifier)
          (interface_requirements
            (identifier))
          (comment)
          (identifier)
          (interface_requirements
            (identifier))
          (number_literal)))
      (comment)
      (parameter_list))
    (compound_statement)))
