---input---
import Math.Vector3 (..)
import Math.Matrix4 (..)
import Graphics.WebGL (..)

-- Create a mesh with two triangles

type Vertex = { position:Vec3, color:Vec3 }

mesh : [Triangle Vertex]
mesh = [ ( Vertex (vec3 0  0 0) (vec3 1 0 0)
         , Vertex (vec3 1  1 0) (vec3 0 1 0)
         , Vertex (vec3 1 -1 0) (vec3 0 0 1)
         )
       ]

-- Create the scene

main : Signal Element
main = scene <~ foldp (+) 0 (fps 30)

scene : Float -> Element
scene t =
    webgl (400,400)
    [ entity vertexShader fragmentShader mesh { view = view (t / 1000) } ]

view : Float -> Mat4
view t =
    mul (makePerspective 45 1 0.01 100)
        (makeLookAt (vec3 (4 * cos t) 0 (4 * sin t)) (vec3 0 0 0) (vec3 0 1 0))

-- Shaders

vertexShader : Shader { attr | position:Vec3, color:Vec3 } { unif | view:Mat4 } { vcolor:Vec3 }
vertexShader = [glsl|

attribute vec3 position;
attribute vec3 color;
uniform mat4 view;
varying vec3 vcolor;

void main () {
    gl_Position = view * vec4(position, 1.0);
    vcolor = color;
}

|]

fragmentShader : Shader {} u { vcolor:Vec3 }
fragmentShader = [glsl|

precision mediump float;
varying vec3 vcolor;

void main () {
    gl_FragColor = vec4(vcolor, 1.0);
}

|]

---tokens---
'import '     Keyword.Namespace
'Math.Vector3' Name.Class
' '           Text
'(..)'        Name.Function
'\n'          Text

'import '     Keyword.Namespace
'Math.Matrix4' Name.Class
' '           Text
'(..)'        Name.Function
'\n'          Text

'import '     Keyword.Namespace
'Graphics.WebGL' Name.Class
' '           Text
'(..)'        Name.Function
'\n\n'        Text

'-- Create a mesh with two triangles' Comment.Single
'\n\n'        Text

'type'        Keyword.Reserved
' '           Text
'Vertex'      Keyword.Type
' '           Text
'='           Name.Function
' '           Text
'{'           Punctuation
' '           Text
'position'    Name.Variable
':'           Name.Function
'Vec3'        Keyword.Type
','           Punctuation
' '           Text
'color'       Name.Variable
':'           Name.Function
'Vec3'        Keyword.Type
' '           Text
'}'           Punctuation
'\n\n'        Text

'mesh'        Name.Variable
' '           Text
':'           Name.Function
' '           Text
'['           Punctuation
'Triangle'    Keyword.Type
' '           Text
'Vertex'      Keyword.Type
']'           Punctuation
'\n'          Text

'mesh'        Name.Variable
' '           Text
'='           Name.Function
' '           Text
'['           Punctuation
' '           Text
'('           Punctuation
' '           Text
'Vertex'      Keyword.Type
' '           Text
'('           Punctuation
'vec3'        Name.Variable
' '           Text
'0'           Literal.Number.Integer
'  '          Text
'0'           Literal.Number.Integer
' '           Text
'0'           Literal.Number.Integer
')'           Punctuation
' '           Text
'('           Punctuation
'vec3'        Name.Variable
' '           Text
'1'           Literal.Number.Integer
' '           Text
'0'           Literal.Number.Integer
' '           Text
'0'           Literal.Number.Integer
')'           Punctuation
'\n         ' Text
','           Punctuation
' '           Text
'Vertex'      Keyword.Type
' '           Text
'('           Punctuation
'vec3'        Name.Variable
' '           Text
'1'           Literal.Number.Integer
'  '          Text
'1'           Literal.Number.Integer
' '           Text
'0'           Literal.Number.Integer
')'           Punctuation
' '           Text
'('           Punctuation
'vec3'        Name.Variable
' '           Text
'0'           Literal.Number.Integer
' '           Text
'1'           Literal.Number.Integer
' '           Text
'0'           Literal.Number.Integer
')'           Punctuation
'\n         ' Text
','           Punctuation
' '           Text
'Vertex'      Keyword.Type
' '           Text
'('           Punctuation
'vec3'        Name.Variable
' '           Text
'1'           Literal.Number.Integer
' '           Text
'-'           Name.Function
'1'           Literal.Number.Integer
' '           Text
'0'           Literal.Number.Integer
')'           Punctuation
' '           Text
'('           Punctuation
'vec3'        Name.Variable
' '           Text
'0'           Literal.Number.Integer
' '           Text
'0'           Literal.Number.Integer
' '           Text
'1'           Literal.Number.Integer
')'           Punctuation
'\n         ' Text
')'           Punctuation
'\n       '   Text
']'           Punctuation
'\n\n'        Text

'-- Create the scene' Comment.Single
'\n\n'        Text

'main '       Keyword.Reserved
':'           Name.Function
' '           Text
'Signal'      Keyword.Type
' '           Text
'Element'     Keyword.Type
'\n'          Text

'main '       Keyword.Reserved
'='           Name.Function
' '           Text
'scene'       Name.Variable
' '           Text
'<~'          Name.Function
' '           Text
'foldp'       Name.Variable
' '           Text
'(+)'         Name.Function
' '           Text
'0'           Literal.Number.Integer
' '           Text
'('           Punctuation
'fps'         Name.Variable
' '           Text
'30'          Literal.Number.Integer
')'           Punctuation
'\n\n'        Text

'scene'       Name.Variable
' '           Text
':'           Name.Function
' '           Text
'Float'       Keyword.Type
' '           Text
'->'          Name.Function
' '           Text
'Element'     Keyword.Type
'\n'          Text

'scene'       Name.Variable
' '           Text
't'           Name.Variable
' '           Text
'='           Name.Function
'\n    '      Text
'webgl'       Name.Variable
' '           Text
'('           Punctuation
'400'         Literal.Number.Integer
','           Punctuation
'400'         Literal.Number.Integer
')'           Punctuation
'\n    '      Text
'['           Punctuation
' '           Text
'entity'      Name.Variable
' '           Text
'vertexShader' Name.Variable
' '           Text
'fragmentShader' Name.Variable
' '           Text
'mesh'        Name.Variable
' '           Text
'{'           Punctuation
' '           Text
'view'        Name.Variable
' '           Text
'='           Name.Function
' '           Text
'view'        Name.Variable
' '           Text
'('           Punctuation
't'           Name.Variable
' '           Text
'/'           Name.Function
' '           Text
'1000'        Literal.Number.Integer
')'           Punctuation
' '           Text
'}'           Punctuation
' '           Text
']'           Punctuation
'\n\n'        Text

'view'        Name.Variable
' '           Text
':'           Name.Function
' '           Text
'Float'       Keyword.Type
' '           Text
'->'          Name.Function
' '           Text
'Mat4'        Keyword.Type
'\n'          Text

'view'        Name.Variable
' '           Text
't'           Name.Variable
' '           Text
'='           Name.Function
'\n    '      Text
'mul'         Name.Variable
' '           Text
'('           Punctuation
'makePerspective' Name.Variable
' '           Text
'45'          Literal.Number.Integer
' '           Text
'1'           Literal.Number.Integer
' '           Text
'0.'          Literal.Number.Float
'01'          Literal.Number.Integer
' '           Text
'100'         Literal.Number.Integer
')'           Punctuation
'\n        '  Text
'('           Punctuation
'makeLookAt'  Name.Variable
' '           Text
'('           Punctuation
'vec3'        Name.Variable
' '           Text
'('           Punctuation
'4'           Literal.Number.Integer
' '           Text
'*'           Name.Function
' '           Text
'cos'         Name.Variable
' '           Text
't'           Name.Variable
')'           Punctuation
' '           Text
'0'           Literal.Number.Integer
' '           Text
'('           Punctuation
'4'           Literal.Number.Integer
' '           Text
'*'           Name.Function
' '           Text
'sin'         Name.Variable
' '           Text
't'           Name.Variable
')'           Punctuation
')'           Punctuation
' '           Text
'('           Punctuation
'vec3'        Name.Variable
' '           Text
'0'           Literal.Number.Integer
' '           Text
'0'           Literal.Number.Integer
' '           Text
'0'           Literal.Number.Integer
')'           Punctuation
' '           Text
'('           Punctuation
'vec3'        Name.Variable
' '           Text
'0'           Literal.Number.Integer
' '           Text
'1'           Literal.Number.Integer
' '           Text
'0'           Literal.Number.Integer
')'           Punctuation
')'           Punctuation
'\n\n'        Text

'-- Shaders'  Comment.Single
'\n\n'        Text

'vertexShader' Name.Variable
' '           Text
':'           Name.Function
' '           Text
'Shader'      Keyword.Type
' '           Text
'{'           Punctuation
' '           Text
'attr'        Name.Variable
' '           Text
'|'           Name.Function
' '           Text
'position'    Name.Variable
':'           Name.Function
'Vec3'        Keyword.Type
','           Punctuation
' '           Text
'color'       Name.Variable
':'           Name.Function
'Vec3'        Keyword.Type
' '           Text
'}'           Punctuation
' '           Text
'{'           Punctuation
' '           Text
'unif'        Name.Variable
' '           Text
'|'           Name.Function
' '           Text
'view'        Name.Variable
':'           Name.Function
'Mat4'        Keyword.Type
' '           Text
'}'           Punctuation
' '           Text
'{'           Punctuation
' '           Text
'vcolor'      Name.Variable
':'           Name.Function
'Vec3'        Keyword.Type
' '           Text
'}'           Punctuation
'\n'          Text

'vertexShader' Name.Variable
' '           Text
'='           Name.Function
' '           Text
'[glsl|'      Name.Entity
'\n'          Name.Entity

'\n'          Name.Entity

'attribute vec3 position;\n' Name.Entity

'attribute vec3 color;\n' Name.Entity

'uniform mat4 view;\n' Name.Entity

'varying vec3 vcolor;\n' Name.Entity

'\n'          Name.Entity

'void main () {\n' Name.Entity

'    gl_Position = view * vec4(position, 1.0);\n' Name.Entity

'    vcolor = color;\n' Name.Entity

'}\n'         Name.Entity

'\n'          Name.Entity

'|]'          Name.Entity
'\n\n'        Text

'fragmentShader' Name.Variable
' '           Text
':'           Name.Function
' '           Text
'Shader'      Keyword.Type
' '           Text
'{'           Punctuation
'}'           Punctuation
' '           Text
'u'           Name.Variable
' '           Text
'{'           Punctuation
' '           Text
'vcolor'      Name.Variable
':'           Name.Function
'Vec3'        Keyword.Type
' '           Text
'}'           Punctuation
'\n'          Text

'fragmentShader' Name.Variable
' '           Text
'='           Name.Function
' '           Text
'[glsl|'      Name.Entity
'\n'          Name.Entity

'\n'          Name.Entity

'precision mediump float;\n' Name.Entity

'varying vec3 vcolor;\n' Name.Entity

'\n'          Name.Entity

'void main () {\n' Name.Entity

'    gl_FragColor = vec4(vcolor, 1.0);\n' Name.Entity

'}\n'         Name.Entity

'\n'          Name.Entity

'|]'          Name.Entity
'\n'          Text
