Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some fixes #59

Merged
merged 7 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .travis.yml

This file was deleted.

10 changes: 5 additions & 5 deletions lib/descriptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ import pick from 'pick-by-alias'
* @param {string|array} options.include List of stdlib methods to include for a node, if complex version is applied
* @param {bool} options.optimize Whether to try to optimize the result.
*/
function Descriptor (str, options) {
function Descriptor(str, options) {
//strings which are rendered to something
if (str != null) {
var descriptor = new String((str+'').trim());
var descriptor = new String((str + '').trim());
descriptor.visible = true;
}
//strings which are rendered to nothing, like preprocessors etc
Expand All @@ -49,7 +49,7 @@ function Descriptor (str, options) {

//set type based on number of components.
if (descriptor.type === undefined) {
if (!(descriptor+'')) {
if (!(descriptor + '')) {
descriptor.type = 'void';
descriptor.components = [];
}
Expand All @@ -61,11 +61,11 @@ function Descriptor (str, options) {
var l = descriptor.components.length;
if (l === 1) descriptor.type = 'float';
else if (l <= 4) descriptor.type = 'vec' + l;
else descriptor.type = 'mat' + Math.sqrt(l)|0;
else descriptor.type = 'mat' + Math.sqrt(l) | 0;
}
}
// null type means type can be any
else if (descriptor.type === null) {}
else if (descriptor.type === null) { }
//type !== undefined (any), components == null → set components as item-access
else if (descriptor.components == null) {
descriptor.components = [];
Expand Down
120 changes: 73 additions & 47 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var swizzleRE = /^[xyzwstpdrgba]{1,4}$/
*
* @constructor
*/
function GLSL (options) {
function GLSL(options) {
if (!(this instanceof GLSL)) return new GLSL(options)

Object.assign(this, options)
Expand Down Expand Up @@ -142,7 +142,7 @@ GLSL.prototype.reset = function () {
/**
* Compile whether string or tree to js
*/
GLSL.prototype.compile = function compile (arg) {
GLSL.prototype.compile = function compile(arg) {
//apply preprocessor
if (this.preprocess) {
if (this.preprocess instanceof Function) {
Expand Down Expand Up @@ -187,7 +187,7 @@ GLSL.prototype.process = function (node, arg) {
typeof node === 'number' ||
typeof node === 'string' ||
typeof node === 'boolean') {
return this.cache(node, Descriptor(node, {complexity: 0}))
return this.cache(node, Descriptor(node, { complexity: 0 }))
}


Expand Down Expand Up @@ -251,14 +251,14 @@ GLSL.prototype.optimizeDescriptor = function (descriptor) {
//try to optimize
if (this.optimize && descriptor.optimize !== false && descriptor.components) {
var complexity = descriptor.components.reduce(function (prev, curr) {
return prev + curr.complexity||0
}, 0)
return prev + curr.complexity || 0
}, 0)

if (complexity < descriptor.complexity) {
//expand array, if complexity is ok
if (descriptor.components && descriptor.components.length > 1) {
var include = descriptor.components.map(function (c) { return c.include;}, this).filter(Boolean)
return Descriptor(`[${descriptor.components.join(', ')}]`, Object.assign(descriptor, {
var include = descriptor.components.map(function (c) { return c.include; }, this).filter(Boolean)
return Descriptor(`new Float32Array([${descriptor.components.join(', ')}])`, Object.assign(descriptor, {
include: include,
complexity: complexity
}))
Expand Down Expand Up @@ -327,7 +327,7 @@ GLSL.prototype.transforms = {

// { vec3 data[2]; }
if (node.type === 'quantifier') {
console.log(node)
// console.log(node)
}

throw Error('Struct statement contains something strange.')
Expand All @@ -342,7 +342,7 @@ GLSL.prototype.transforms = {
})
}).flat()

var struct = function struct () {
var struct = function struct() {
var args = arguments

var includes = []
Expand Down Expand Up @@ -372,11 +372,11 @@ GLSL.prototype.transforms = {
}.bind(this)

//we should set length to be a compatible type constructor
Object.defineProperty(struct, 'length', {value: argTypes.length})
Object.defineProperty(struct, 'length', { value: argTypes.length })

//register struct constructor, in a fashion of type constructors
this.structs[structName] =
this.types[structName] = struct
this.types[structName] = struct

return Descriptor(null)
},
Expand Down Expand Up @@ -514,7 +514,7 @@ GLSL.prototype.transforms = {
decllist.type === 'decllist' ||
decllist.type === 'function' ||
decllist.type === 'struct',
'Decl structure is malicious')
'Decl structure is malicious')


//declare function as hoisting one
Expand Down Expand Up @@ -603,7 +603,7 @@ GLSL.prototype.transforms = {
//dimensions might be undefined, so we have to specify them here
var dimensions = this.variable(ids[lastId - 1]).dimensions
dimensions.push(parseInt(child.children[0].children[0].data))
this.variable(ids[lastId - 1], {dimensions: dimensions})
this.variable(ids[lastId - 1], { dimensions: dimensions })
}
else if (child.type === 'expr') {
var ident = ids[lastId - 1]
Expand All @@ -612,7 +612,7 @@ GLSL.prototype.transforms = {
var value = this.process(child)

//save identifier initial value
this.variable(ident, {value: value})
this.variable(ident, { value: value })
}
else {
throw Error('Undefined type in decllist: ' + child.type)
Expand Down Expand Up @@ -644,7 +644,7 @@ GLSL.prototype.transforms = {
}

//if result is false/null/empty string - ignore variable definition
if (!(result+'') && result !== 0) return ident
if (!(result + '') && result !== 0) return ident

return `${ident} = ${result}`
}, this).filter(Boolean)
Expand All @@ -664,7 +664,7 @@ GLSL.prototype.transforms = {
//i++, --i etc
suffix: function (node) {
var str = this.process(node.children[0])
return Descriptor(str + node.data, {type: str.type})
return Descriptor(str + node.data, { type: str.type })
},

//loops are the same as in js
Expand Down Expand Up @@ -718,7 +718,7 @@ GLSL.prototype.transforms = {
return res
}, this).join('')

result = Descriptor(result, {complexity: complexity})
result = Descriptor(result, { complexity: complexity })

return result
},
Expand Down Expand Up @@ -803,14 +803,14 @@ GLSL.prototype.transforms = {
// return <expression>;
result = 'return' + (expr.visible ? ' ' + expr : '')
}
return Descriptor(result, {type: expr.type})
return Descriptor(result, { type: expr.type })
},

continue: function () {return Descriptor('continue')},
continue: function () { return Descriptor('continue') },

break: function () {return Descriptor('break')},
break: function () { return Descriptor('break') },

discard: function () {return Descriptor('discard()')},
discard: function () { return Descriptor('discard()') },

'do-while': function (node) {
var exprs = this.process(node.children[0])
Expand Down Expand Up @@ -847,12 +847,12 @@ GLSL.prototype.transforms = {
var matSize = this.types[matType].length
var outerRight = this.process(leftNode.children[1])

var idx = parseFloat(outerRight)|0
var offset = parseFloat(right)|0
var idx = parseFloat(outerRight) | 0
var offset = parseFloat(right) | 0

//if number - try to access component
if (!isNaN(idx) && !isNaN(offset)) {
return Descriptor(matDesc.components[vecSize*idx + offset], {
return Descriptor(matDesc.components[vecSize * idx + offset], {
type: 'float',
complexity: matDesc.complexity + right.complexity + 1
})
Expand All @@ -873,7 +873,7 @@ GLSL.prototype.transforms = {
var start = this.processOperation(right, Descriptor(size), '*')
var end = this.processOperation(start, Descriptor(size), '+')
var comps = floatRE.test(start) && floatRE.test(end) ? left.components.slice(start, end) : undefined
var res = Descriptor(`${left}.slice(${start}, ${end})`, {
var res = Descriptor(`${left}.subarray(${start}, ${end})`, {
type: this.types[leftType].type,
complexity: left.complexity + size,
components: comps
Expand All @@ -899,18 +899,17 @@ GLSL.prototype.transforms = {
},

assign: function (node) {
var result = ''
var operator = node.data
var right = this.process(node.children[1])
var operator = node.data, right = this.process(node.children[1]), left

if (node.children[0].type === 'identifier') {
var left = Descriptor(node.children[0].data, {
left = Descriptor(node.children[0].data, {
type: right.type,
optimize: false,
complexity: 0
})
}
else {
var left = this.process(node.children[0])
left = this.process(node.children[0])
}

var target = left
Expand All @@ -920,15 +919,42 @@ GLSL.prototype.transforms = {
var isSwizzle = node.children[0].type === 'operator' &&
swizzleRE.test(node.children[0].children[1].data)

//a *= b.x
//a *= b.x (single-operand)
if (!isSwizzle && this.types[right.type].length == 1 && this.types[target.type].length == 1) {
return Descriptor(`${target} ${operator} ${right}`, {
type: right.type,
complexity: target.complexity + 1 + right.complexity
})
}

//FIXME: left can be a structure property set a.prop
//mat3[0] *= vec3; - left can be a structure property set a.prop
if (!isSwizzle && this.types[right.type].length > 1 && this.types[target.type].length > 1) {
let rcomp = right.components,
compComplexity = right.components.reduce((total, comp) => (
comp.complexity + total
), 0),
reduceComplexity = 3 + target.complexity + this.types[right.type].length + right.complexity,
components

if (rcomp?.length == target.components?.length) {
components = target.components.map((comp, i) => (
Descriptor(`${comp} ${operator} ${rcomp[i]}`, { type: rcomp[i].type, complexity: rcomp[i].complexity + 1 })
))

// optimize for individual components
if (compComplexity < reduceComplexity) return Descriptor(`(${components.join(', ')}, ${target})`, {
type: right.type,
complexity: compComplexity,
components
})
}

return Descriptor(`${right}.reduce((res,el,i)=>(res[i] ${operator} el, res), ${target})`, {
type: right.type,
complexity: reduceComplexity,
components
})
}

//in cases of setting swizzle - we have to place left unswizzle to the right
if (isSwizzle) {
Expand Down Expand Up @@ -975,10 +1001,10 @@ GLSL.prototype.transforms = {

right = Descriptor(
`[${ids.join(', ')}].map(function (idx, i) { return idx == null ? ${target}[i] : this[idx]; }, ${right})`, {
type: right.type,
complexity: len*4 + right.complexity,
include: right.include,
components: comps
type: right.type,
complexity: len * 4 + right.complexity,
include: right.include,
components: comps
})
right = this.optimizeDescriptor(right)

Expand Down Expand Up @@ -1024,7 +1050,7 @@ GLSL.prototype.transforms = {
var a = this.process(node.children[1])
var b = this.process(node.children[2])

return Descriptor(`${cond} ? ${a} : ${b}`, {type: a.type})
return Descriptor(`${cond} ? ${a} : ${b}`, { type: a.type })
},

unary: function (node) {
Expand All @@ -1036,10 +1062,10 @@ GLSL.prototype.transforms = {
if (node.data === '+') {
//++x
if (node.children[0].type === 'unary') {
return Descriptor(node.data + str, {type: str.type, complexity: complexity})
return Descriptor(node.data + str, { type: str.type, complexity: complexity })
}
else if (node.children[0].parent.type === 'unary') {
return Descriptor(node.data + str, {type: str.type, complexity: complexity})
return Descriptor(node.data + str, { type: str.type, complexity: complexity })
}

//+x
Expand Down Expand Up @@ -1124,7 +1150,7 @@ GLSL.prototype.transforms = {
if (this.debug) {
if (callName == 'print') {
var args = argValues.map(function (a) {
return a+':'+a.type
return a + ':' + a.type
})
console.log.apply(console, args)
return Descriptor(null)
Expand Down Expand Up @@ -1227,7 +1253,7 @@ GLSL.prototype.transforms = {
if (/true|false/i.test(node.data)) type = 'bool'
else if (/^[0-9]+$/.test(node.data) > 0) type = 'int'
else if (floatRE.test(node.data)) type = 'float'
return Descriptor(result, {type: type, complexity: 0})
return Descriptor(result, { type: type, complexity: 0 })
},

//ifs are the same as js
Expand Down Expand Up @@ -1258,7 +1284,7 @@ GLSL.prototype.transforms = {
var last = children[children.length - 1]

//each component therefore should be wrapped to group as well
//FIXME: single-multiplocation ops like (x*34.) + 1. are possible to be unwrapped, providing that they are of the most precedence.
//FIXME: single-multip location ops like (x*34.) + 1. are possible to be unwrapped, providing that they are of the most precedence.
if (last.components) {
last.components = last.components.map(function (comp) {
//if component contains no operations (we not smartly guess that each op adds to complexity) - keep component as is.
Expand All @@ -1272,7 +1298,7 @@ GLSL.prototype.transforms = {
return Descriptor(result, {
type: last.type,
components: last.components,
complexity: children.reduce(function (prev, curr) {return prev+curr.complexity||0}, 0)
complexity: children.reduce(function (prev, curr) { return prev + curr.complexity || 0 }, 0)
})
}

Expand Down Expand Up @@ -1319,7 +1345,7 @@ GLSL.prototype.unswizzle = function (node) {
// unknown identifiers or calls often have undefined components
// a.z → a[2]
if (typeof args[0] === 'number') {
result = Descriptor(`${ident}[${args[0]}]`, {type: null, complexity: 999})
result = Descriptor(`${ident}[${args[0]}]`, { type: null, complexity: 999 })
}
else {
if (args[0] == null) console.warn(`Cannot unswizzle '${ident.type}(${ident}).${prop}': ${prop} is outside the type range.`)
Expand All @@ -1334,15 +1360,15 @@ GLSL.prototype.unswizzle = function (node) {
}

//vec2 a.xy → a
if (type && args.length === this.types[type].length && positions.every(function (position, i) { return position === i})) {
if (type && args.length === this.types[type].length && positions.every(function (position, i) { return position === i })) {
return ident
}

var complexity = args.length * ident.complexity

//a.yz → [1, 2].map(function(x) { return this[x]; }, a)
var result = Descriptor(`[${positions.join(', ')}].map(function (x, i) { return this[x]}, ${ident})`, {
complexity: ident.components ? args.length*2 : 999,
var result = Descriptor(`new Float32Array([${positions.join(', ')}].map(function (x, i) { return this[x]}, ${ident}))`, {
complexity: ident.components ? args.length * 2 : 999,
type: `vec${args.length}`,
components: ident.components && args
})
Expand Down
Loading