set:function(props){ if(!this.hasOwnProperty('_props')){ this._props = this._props?Object.create(this._props):{} } for(var key in props){ var config = props[key] if(typeof config !== 'object' || Object.getPrototypeOf(config) !== Object.prototype){ config = {value:config} } this._props[key] = config if(config.value !== undefined) this[key] = config.value if(!config.type) config.type = types.typeFromValue(config.value) if(!config.kind) config.kind = 'instance' } }
proto.MemberExpression = function(node){ // just chuck This //if(node.object.type === 'ThisExpression' || node.object.type === 'Identifier' && ignore_objects[node.object.name]){ // var ret = this.walk(node.property) // node.infer = node.property.infer // return ret //} var objectstr = this.walk(node.object, node) if(node.computed){ var objinfer = node.object.infer if(objinfer.kind !== 'value'){ console.log(objinfer) throw this.InferErr(node, 'cannot use index[] on non value type') } var objtype = objinfer.type if(objtype.slots <= 1){ throw this.InferErr(node, 'cannot use index[] on item with size 1') } var argstr = this.walk(node.property, node) var primtype = objtype.primary if(objtype.name === 'mat4'){ primtype = types.vec4 } else if(objtype.name === 'mat3'){ primtype = types.vec3 } else if(objtype.name === 'mat2'){ primtype = types.vec2 } node.infer = { kind:'value', type:primtype } return objectstr + '[' + argstr + ']' } else{ var objectinfer = node.object.infer var propname = node.property.name if(objectinfer.kind === 'value'){ var type = objectinfer.type if(!type.fields){ throw this.InferErr(node, 'Object not a struct '+objectstr+'.'+propname) } var proptype = type.fields[propname] if(!proptype){ // do more complicated bits // check swizzling or aliases var proplen = propname.length if(proplen < 1 || proplen > 4) throw this.InferErr(node, 'Invalid property '+objectstr+'.'+propname) var typename = type.name proptype = types[proplen === 1? swizone[typename]: (swiztype[typename] + proplen)] var swiz = swizlut[typename] if(!swiz) throw this.InferErr(node, 'Invalid swizzle '+objectstr+'.'+propname) for(var i = 0, set = swiz.set[swiz.pick[propname.charCodeAt(0)]]; i < proplen; i++){ if(!set || !set[propname.charCodeAt(i)]) throw this.InferErr(node, 'Invalid swizzle '+objectstr+'.'+propname) } } // look up property propname node.infer = { kind:'value', lvalue:objectinfer.lvalue, // propagate lvalue-ness type:proptype } return objectstr + '.' + propname } else if(objectinfer.kind === 'this'){ var value = this.root[propname] var fullname = 'this_DOT_' + propname // its a function if(typeof value === 'function'){ node.infer = { kind: 'function', name: propname, fullname: fullname, callee: value } return fullname } var props = this.root._props var config = props[propname] if(config !== undefined ){ // we found a prop! // check kind if(config.kind === 'instance'){ var value = config.value this.instanceProps[fullname] = { type:config.type, name:propname, config:config } node.infer = { kind:'value', lvalue:true, type:config.type } return fullname } else if(config.kind === 'uniform'){ if(this.uniforms[fullname]){ this.uniforms[fullname].refcount++ } else{ this.uniforms[fullname] = { type:config.type, config:config, name:propname, refcount:1 } } node.infer = { kind:'value', type:config.type } return fullname } else if(config.kind === 'sampler'){ var sampler = config.sampler this.samplers[fullname] = { name:propname, sampler:sampler } node.infer = { kind:'value', name:propname, sampler:sampler, type:sampler.type } return fullname } else if(config.kind === 'geometry'){ proptype = config.type this.geometryProps[fullname] = { type:proptype, name:propname } node.infer = { kind:'value', lvalue:true, type:proptype } return fullname } else if(config.kind === 'output'){ // its already defined var type = config.type if(prev){ node.infer = { kind: 'value', lvalue:true, type: prev } } else{ node.infer = { kind: 'outundef', lvalue:true, name: name } } return fullname } } // use of unconfigured sampler if(value instanceof painter.Texture){ this.samplers[fullname] = { name:ret, sampler:sampler } var sampler = value.sampler || painter.SAMPLER2DNEAREST node.infer = { kind:'value', name:ret, sampler:sampler, type:sampler.type } return fullname } // check if its a mesh attribute if(value instanceof painter.Mesh){ proptype = value.type this.geometryProps[fullname] = { type:proptype, name:propname } node.infer = { kind:'value', lvalue:true, type:proptype } return fullname } if(value === undefined){ // something undefined // its already defined var prev = this.varyOut[fullname] || this.varyIn && this.varyIn[fullname] if(prev){ this.varyOut[fullname] = prev node.infer = { kind: 'value', lvalue:true, type: prev.type } } else{ if(this.varyIn){ var out = this.outputs[fullname] if(out){ node.infer = { kind: 'value', lvalue:true, type:out } } else{ node.infer = { kind: 'outundef', lvalue:true, name: propname } } } else{ node.infer = { kind: 'varyundef', lvalue:true, name: propname } } } // lets check if node.infer holds property return fullname } // default to instanced property var type = types.typeFromValue(value) if(type){ this.instanceProps[fullname] = { type:type, name:propname, config:{type:type} } node.infer = { kind:'value', lvalue:true, type:type } return fullname } } throw this.InferErr(node, 'Cant determine type for this.'+propname) } }