Skip to content
Benjamin Wilson Friedman edited this page Apr 29, 2021 · 12 revisions

FDSSL (name pending) wiki.

Overall, the flow should look something like this.

Define semantic domain

  • We've been thinking: Env -> Env -> (Env,Expr) -> Env
  • where type Env = [(Key,Expr)]
  • and type Expr = AST representation of a program
  • verbose semantic domain is: UniversalEnv -> ShaderPassedEnv -> (ShaderEnv,ShaderExpr) -> ShaderResultEnv
    • every shader gets the universal env, plus whatever prior environment the prior stage passes along, and the specific shader stage environment an expression is evaluated within (fragment, vertex, etc.).

Concrete Syntax / Grammar

program := env [shader]    -- global environment + shaders

env := [func]

unitName   := String                -- Fragment, Vertex... This won't be defined by the user.
shaderEnvs := [(unitName, env)]     -- This will be written in the language, but won't be written by the user

shader := unitName name expr       -- a shader contains it's functions (decl & def) and it's primary expr (corresponding to main)

name := String

cmpop := == | != | <= | >= | < | >
bitop :=  & | \|  | ^
logiop := And | Or
arithop := + | - | * | /
shaderComp := .
binop := arithop | cmpop | logiop | bitop | shaderComp
unop := FlipBits | Not

vdim := 2 | 3 | 4
floatType := Float | Double
discreteType := Bool | Int | UInt
baseType := floatType | discreteType
type     := baseType | baseType[int] | Vec vdim baseType | Mat vdim vdim floatType

typeDecl := name [name : type]  -- may or may not include this...

func := name signature expr
signature := type | type -> signature

lit := int | bool | float | double   -- Literal value

expr := lit |
name |                      -- name of let bound name, function name, etc.
(expr,...,expr) |           -- N-ary vector (tuple) or mat | 2 <= N <= 4
unop expr |                 -- Unary operator application
let name : type = expr \n expr |   -- let binding
name(expr,...,expr)         -- prefix app
expr binop expr             -- infix app
name[(name | int)]          -- structure access
//...\n                     -- single-line comment
/*...*/                     -- block comment
if expr then expr else expr -- branching
for (int) do (?:|name|) (expr)         -- produces a value from evaluating expr 'int' times, e.x. let x = 1+x \n let x = 1+x \n ... let x = 1+x \n x (optional index name can be given after do
[expr]                      -- lists, which correspond to arrays

Also, some built in functionality...

  • (.) as function composition. I believe we can implement this by combining the exprs of both functions in the proper order, and adding a let to represent the params
  • (.) as shader composition. shaderA . shaderBproduces a new shader C, whereC = exprA . exprB`, but the environments are passed along, (TODO, not done yet, needs work, can use semantic domain to help reason about this part)

Abstract Syntax & Parser

TODO...

Type Checker & UV checker

  • UV checking is going to be limited to what's defined within the pipeline, so it'll be a partial UV checker.

Pretty printer

  • from the AST, produce the corresponding GLSL program in concrete syntax.
  • put together a wrapped WebGL app (or some other GL context) to demonstrate and observe whether output shaders behave as expected

Report (Week 10)

TODO...