Skip to content

Commit

Permalink
feat(shader-ast): add assignments, re-org types, update vec ctors
Browse files Browse the repository at this point in the history
- temp disable ret type check in defn()
  • Loading branch information
postspectacular committed Jun 13, 2019
1 parent 9dacac6 commit 7dc32d1
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 50 deletions.
56 changes: 29 additions & 27 deletions packages/shader-ast/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import {
Fn5,
Fn6,
Fn7,
Fn8,
IObjectOf
Fn8
} from "@thi.ng/api";
import { Implementation1 } from "@thi.ng/defmulti";

export type Tag =
| "sym"
Expand Down Expand Up @@ -38,6 +36,7 @@ export type Type =
export type Vec = "vec2" | "vec3" | "vec4";

export type Prim = "f32" | Vec;
export type Comparable = "f32";

export type MathOperator = "+" | "-" | "*" | "/";
export type LogicOperator = "!" | "||" | "&&";
Expand Down Expand Up @@ -276,8 +275,32 @@ export interface Sym<T extends Type> extends Term<T> {
}

export interface Swizzle<T extends Type> extends Term<T> {
val: Term<any>;
id: string;
val: Term<Vec>;
}

export interface Assign<T extends Type> extends Term<T> {
l: Sym<T>;
r: Term<T>;
}

export interface Op1<T extends Type> extends Term<T> {
op: Operator;
val: Term<any>;
}

export interface Op2<T extends Type> extends Term<T> {
op: Operator;
l: Term<any>;
r: Term<any>;
}

export interface Branch extends Term<any> {
tag: "if";
type: "void";
test: Term<"bool">;
t: Term<any>[];
f?: Term<any>[];
}

export interface FuncReturn<T extends Type> extends Term<T> {
Expand Down Expand Up @@ -386,31 +409,10 @@ export interface FnCall<T extends Type> extends Term<T> {
args: Term<any>[];
}

export interface Op1<T extends Type> extends Term<T> {
op: Operator;
val: Term<any>;
}

export interface Op2<T extends Type> extends Term<T> {
op: Operator;
l: Term<any>;
r: Term<any>;
}

export interface Branch extends Term<any> {
tag: "if";
type: "void";
test: Term<"bool">;
t: Term<any>[];
f?: Term<any>[];
}

export type TargetImpl = IObjectOf<Implementation1<Term<any>, string>>;

export interface TargetImpl2 extends Record<Tag, Fn<any, string>> {
export interface TargetImpl extends Record<Tag, Fn<any, string>> {
sym: Fn<Sym<any>, string>;
lit: Fn<Lit<any>, string>;
// assign: Fn<Assign<Sym<any>, Term<any>>, string>;
assign: Fn<Assign<any>, string>;
op1: Fn<Op1<any>, string>;
op2: Fn<Op2<any>, string>;
swizzle: Fn<Swizzle<any>, string>;
Expand Down
70 changes: 47 additions & 23 deletions packages/shader-ast/src/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
Arg7,
Arg8,
ArgQualifier,
Assign,
Branch,
Comparable,
FnBody0,
FnBody1,
FnBody2,
Expand Down Expand Up @@ -58,6 +60,8 @@ import {

export const isVec = (t: Term<any>) => t.type.indexOf("vec") == 0;

const wrapF32 = (x?: number | Term<"f32">) => (isNumber(x) ? float(x) : x);

export const sym = <T extends Type>(
type: T,
id: string,
Expand Down Expand Up @@ -107,42 +111,55 @@ export function swizzle(val: Term<any>, id: string): Swizzle<any> {
};
}

export const assign = <L extends Type, R extends L>(
l: Sym<L>,
r: Term<R>
): Assign<L> => ({
tag: "assign",
type: l.type,
l,
r
});

export function vec2(): Lit<"vec2">;
export function vec2(x: number | Term<"f32">): Lit<"vec2">;
// prettier-ignore
export function vec2(x: number | Term<"f32">, y: number | Term<"f32">): Lit<"vec2">;
// prettier-ignore
export function vec2(x: number | Term<"f32">, y?: number | Term<"f32">): Lit<"vec2"> {
export function vec2(x?: number | Term<"f32">, y?: number | Term<"f32">): Lit<"vec2"> {
return lit("vec2", [
isNumber(x) ? float(x) : x,
isNumber(y) ? float(y) : y
x === undefined ? float(0) : wrapF32(x),
wrapF32(y)
]);
}

export function vec3(): Lit<"vec3">;
export function vec3(x: number | Term<"f32">): Lit<"vec3">;
export function vec3(x: Term<"vec2">, y: number | Term<"f32">): Lit<"vec3">;
// prettier-ignore
export function vec3(x: number | Term<"f32">, y: number | Term<"f32">, z: number | Term<"f32">): Lit<"vec3">;
export function vec3(x: any, y?: any, z?: any): Lit<"vec3"> {
export function vec3(x?: any, y?: any, z?: any): Lit<"vec3"> {
return lit("vec3", [
isNumber(x) ? float(x) : x,
isNumber(y) ? float(y) : y,
isNumber(z) ? float(z) : z
x === undefined ? float(0) : wrapF32(x),
wrapF32(y),
wrapF32(z)
]);
}

export function vec4(): Lit<"vec4">;
export function vec4(x: number | Term<"f32">): Lit<"vec4">;
export function vec4(x: Term<"vec3">, y: number | Term<"f32">): Lit<"vec4">;
export function vec4(x: Term<"vec2">, y: Term<"vec2">): Lit<"vec4">;
// prettier-ignore
export function vec4(x: Term<"vec2">, y: number | Term<"f32">, z: number | Term<"f32">): Lit<"vec4">;
// prettier-ignore
export function vec4(x: number | Term<"f32">, y: number | Term<"f32">, z: number | Term<"f32">): Lit<"vec4">;
export function vec4(x: any, y?: any, z?: any, w?: any): Lit<"vec4"> {
export function vec4(x?: any, y?: any, z?: any, w?: any): Lit<"vec4"> {
return lit("vec4", [
isNumber(x) ? float(x) : x,
isNumber(y) ? float(y) : y,
isNumber(z) ? float(z) : z,
isNumber(w) ? float(w) : w
x === undefined ? float(0) : wrapF32(x),
wrapF32(y),
wrapF32(z),
wrapF32(w)
]);
}

Expand All @@ -153,6 +170,7 @@ export const op1 = <T extends Type>(op: Operator, val: Term<T>): Op1<T> => ({
val
});

// FIXME return types should not be defined here, but in higher-level ops
// prettier-ignore
export function op2(op: Operator, l: Term<"bool">, r: Term<"bool">): Op2<"bool">;
export function op2(op: Operator, l: Term<"i32">, r: Term<"i32">): Op2<"i32">;
Expand Down Expand Up @@ -248,6 +266,12 @@ export const or = (a: Term<"bool">, b: Term<"bool">) => op2("||", a, b);

export const and = (a: Term<"bool">, b: Term<"bool">) => op2("&&", a, b);

// FIXME
export const lt = <A extends Comparable, B extends A>(
a: Term<A>,
b: Term<B>
): Term<"bool"> => <any>op2("<", a, b);

const defArg = <T extends Type>([type, id, q]: Arg<T>): FuncArg<T> => ({
tag: "arg",
type,
Expand Down Expand Up @@ -279,17 +303,17 @@ export function defn(type: Type, id: string, _args: Arg<any>[], _body: (...xs: S
const body = _body(...args.map((x) => sym(x.type, x.id, x.q)));
// TODO properly filter AST return terms and check for type compatibility
// currently only top level terms are checked
const returns = body.filter((t) => t.tag === "ret");
const mismatched = returns.find((t) => t.type !== type);
if (mismatched) {
throw new Error(
`wrong return type for function '${id}', expected ${type}, got ${
mismatched.type
}`
);
} else if (type !== "void" && !returns.length) {
throw new Error(`function '${id}' must return a value of type ${type}`);
}
// const returns = body.filter((t) => t.tag === "ret");
// const mismatched = returns.find((t) => t.type !== type);
// if (mismatched) {
// throw new Error(
// `wrong return type for function '${id}', expected ${type}, got ${
// mismatched.type
// }`
// );
// } else if (type !== "void" && !returns.length) {
// throw new Error(`function '${id}' must return a value of type ${type}`);
// }
const $: any = (...xs: any[]) => funcall(id, type, ...xs);
return Object.assign($, {
tag: "fn",
Expand Down

0 comments on commit 7dc32d1

Please sign in to comment.