@thi.ng/shader-ast
Version:
DSL to define shader code in TypeScript and cross-compile to GLSL, JS and other targets
165 lines (164 loc) • 3.03 kB
JavaScript
import { isNumber } from "@thi.ng/checks/is-number";
import { assign } from "./assign.js";
import { isMat, isVec } from "./checks.js";
import { numberWithMatchingType } from "./item.js";
import { float } from "./lit.js";
const op1 = (op, val, post = false) => ({
tag: "op1",
type: val.type,
op,
val,
post
});
const OP_INFO = {
mave: "mv",
vema: "vm",
vefl: "vn",
mafl: "vn",
flve: "nv",
flma: "nv",
ivin: "vn",
iniv: "nv",
uvui: "vn",
uiuv: "nv"
};
const op2 = (op, _l, _r, rtype, info) => {
const nl = isNumber(_l);
const nr = isNumber(_r);
let type;
let l;
let r;
if (nl) {
if (nr) {
l = float(_l);
r = float(_r);
type = "float";
} else {
r = _r;
l = numberWithMatchingType(r, _l);
type = r.type;
}
} else if (nr) {
l = _l;
r = numberWithMatchingType(l, _r);
type = l.type;
} else {
l = _l;
r = _r;
type = rtype || (isVec(l) ? l.type : isVec(r) ? r.type : isMat(r) ? r.type : l.type);
}
return {
tag: "op2",
type: rtype || type,
info: info || OP_INFO[l.type.substring(0, 2) + r.type.substring(0, 2)],
op,
l,
r
};
};
const inc = (t) => op1("++", t, true);
const dec = (t) => op1("--", t, true);
function add(l, r) {
return op2("+", l, r);
}
function addSelf(l, r) {
return assign(l, add(l, r));
}
function sub(l, r) {
return op2("-", l, r);
}
function subSelf(l, r) {
return assign(l, sub(l, r));
}
function mul(l, r) {
return op2(
"*",
l,
r,
!isNumber(l) && !isNumber(r) && isMat(l) && isVec(r) ? r.type : void 0
);
}
function mulSelf(l, r) {
return assign(l, mul(l, r));
}
function div(l, r) {
return op2("/", l, r);
}
function divSelf(l, r) {
return assign(l, div(l, r));
}
function modi(l, r) {
return op2(
"%",
isNumber(l) ? numberWithMatchingType(r, l) : l,
isNumber(r) ? numberWithMatchingType(l, r) : r
);
}
const neg = (val) => op1("-", val);
const reciprocal = (val) => op2("/", 1, val);
function madd(a, b, c) {
return add(mul(a, b), c);
}
function addm(a, b, c) {
return mul(add(a, b), c);
}
const not = (val) => op1("!", val);
const or = (a, b) => op2("||", a, b);
const and = (a, b) => op2("&&", a, b);
const __cmp = (op) => (a, b) => op2(op, a, b, "bool");
const eq = __cmp("==");
const neq = __cmp("!=");
const lt = __cmp("<");
const lte = __cmp("<=");
const gt = __cmp(">");
const gte = __cmp(">=");
const bitnot = (val) => op1("~", val);
function bitand(l, r) {
return op2("&", l, r, void 0);
}
function bitor(l, r) {
return op2("|", l, r, void 0);
}
function bitxor(l, r) {
return op2("^", l, r, void 0);
}
function lshift(l, r) {
return op2("<<", l, r, void 0);
}
function rshift(l, r) {
return op2(">>", l, r, void 0);
}
export {
add,
addSelf,
addm,
and,
bitand,
bitnot,
bitor,
bitxor,
dec,
div,
divSelf,
eq,
gt,
gte,
inc,
lshift,
lt,
lte,
madd,
modi,
mul,
mulSelf,
neg,
neq,
not,
op1,
op2,
or,
reciprocal,
rshift,
sub,
subSelf
};