UNPKG

dreemgl

Version:

DreemGL is an open-source multi-screen prototyping framework for mediated environments, with a visual editor and shader styling for webGL and DALi runtimes written in JavaScript. As a toolkit for gpu-accelerated multiscreen development, DreemGL includes

967 lines (823 loc) 23 kB
/* DreemGL is a collaboration between Teeming Society & Samsung Electronics, sponsored by Samsung and others. Copyright 2015-2016 Teeming Society. Licensed under the Apache License, Version 2.0 (the "License"); You may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.*/ define.class(function(require, exports){ var Parser = require('$system/parse/onejsparser') exports.walk = function(ast, textbuf, opts, add){ var glwalker = new this() if(opts) for(var key in opts){ glwalker[key] = opts[key] } glwalker.line = 0 glwalker.textbuf = textbuf glwalker.add = add glwalker.expand(ast) } this.post_comma = 1 this.post_colon = 1 this.around_operator = 1 this.actual_indent = 0 this.actual_line = 0 this.force_newlines_array = false this.force_newlines_object = false this.atConstructor = function(){ this.indent = 0 } // helper functions this.dColon = function(type, padding){ this.add('::', padding, type, exports._DColon) } this.dot = function(type, padding){ this.add('.', padding, type, exports._Dot) } this.colon = function(type, padding){ this.add(':', padding, type, exports._Colon) } this.semiColon = function(type, padding){ this.add(';', padding, type, exports._SemiColon) } this.comma = function(type, padding){ this.add(',', padding, type, exports._Comma) } this.parenL = function(type, padding){ this.add('(', padding, type, exports._Paren, exports._ParenL) } this.parenR = function(type, padding){ this.add(')', padding, type, exports._Paren, exports._ParenL) } this.braceL = function(type, padding){ this.add('{', padding, type, exports._Brace, exports._BraceL) } this.braceR = function(type, padding){ this.add('}', padding, type, exports._Brace, exports._BraceR) } this.bracketL = function(type, padding){ this.add('[', padding, type, exports._Bracket, exports._BracketL) } this.bracketR = function(type, padding){ this.add(']', padding, type, exports._Bracket, exports._BracketR) } this.operator = function(op, type, padding){ this.add(op, padding, type, exports._Operator, exports.ops[op]) } this.keyword = function(value, type, padding){ this.add(value, padding || 0, type, exports._Keyword) } this.tab = function(indent){ // lets add a tab this.actual_indent = indent // alright lets write it on the previous newline. this.add('\t', 4*256 + indent) //this.add(Array(indent+1).join('\t') ) } this.space = function(){ this.add(' ') } this.newline = function(){ this.actual_line++ this.add('\n') } this.comment = function(text, pre){ if(this.lastIsNewline()) this.tab(this.indent), pre = '' this.add((pre||'') + '//' + text, 0, exports._Comment) } this.comments = function(comments, prefix){ var has_newline = false if(!comments) return false for(var i = 0; i < comments.length; i++){ var comment = comments[i] if(comment === 1){ if(this.lastIsNewline()) this.tab(this.indent) this.newline() has_newline = true } else this.comment(comment, prefix) } return has_newline } this.commentHasNewline = function(comments, prefix){ var has_newline = false if(!comments) return false for(var i = 0; i < comments.length; i++){ var comment = comments[i] if(comment === 1){ has_newline = true } } return has_newline } this.lastIsNewline = function(){ return this.last_is_newline //return this.textbuf.charCodeAt(this.textbuf.char_count - 1) === 10 } this.lastCharCode = function(){ return this.textbuf.charCodeAt(this.textbuf.char_count - 1) } // expand ast node this.expand = function(n, arg){ if(n){ if(!this[n.type]) throw new Error('type '+n.type+' not in codeview') else return this[n.type](n, arg) } } // AST nodes this.Program = function(n){ this.Block(n, true) } this.Empty = function(n){} this.Id = function(n){ this.add(n.name, 0, exports._Id) } this.Property = function(n, secondary){ this.add(n.name, 0, exports._Property, secondary ||0) } var tempcolor = vec4() this.Value = function(n){//: { value:0, raw:0, kind:0, multi:0 }, if(n.kind === undefined){ var str if(typeof n.value === 'string'){ if(n.value.indexOf('"')!==-1) str = "'" + n.value + "'" else str = '"' + n.value + '"' } else str = '' + n.value this.add(str, 0, exports._Value, exports._Number) } else if(n.kind == 'num') this.add(n.raw!==undefined?n.raw:''+n.value, 0, exports._Value, exports._Number) else if(n.kind == 'string'){ var subtype = exports._String var col = 0 vec4.parse(n.value, tempcolor, true) if(tempcolor[0] !== -1){ subtype = exports._Color col = -(parseInt(tempcolor[0]*255)*65536+parseInt(tempcolor[1]*255)*256+parseInt(tempcolor[2]*255)) this.add("'", 0 , exports._Value, exports._String) this.add(n.value, 0 , col) this.add("'", 0 , exports._Value, exports._String) } else{ this.add(n.raw!==undefined?n.raw:'"'+n.value+'"', 0 , exports._Value, subtype) } } else if(n.kind === 'boolean'){ this.add(n.raw!==undefined?n.raw:''+n.value, 0, exports._Value, exports._Boolean, n.value?1:0) } else { this.add(n.raw!==undefined?n.raw:''+n.value, 0, exports._Value) } } this.This = function(n){//: { }, this.add('this', 0, exports._This, exports._Keyword) } this.Array = function(n){//: { elems:2 }, this.bracketL(exports._Array, 0) var has_newlines = this.force_newlines_array if(this.comments(n.cm1)) has_newlines = true else if(this.force_newlines_array) this.newline() var old_indent = this.indent if(has_newlines) this.indent++ for(var i = 0; i < n.elems.length; i++){ var elem = n.elems[i] if(!elem) continue //if(!has_newlines && i) this.comma(exports._Array, 0) this.comments(elem.cmu) if(this.lastIsNewline()) this.tab(this.indent) this.expand(elem) //var do_newline = has_newlines || this.commentHasNewline(elem.cmr) if(i < n.elems.length - 1) this.comma(exports._Array, has_newlines?0:2*256+this.post_comma) if(has_newlines && !this.comments(elem.cmr)) this.newline() } if(has_newlines && this.comments(n.cm2)) this.tab(this.indent - 1) if(this.lastIsNewline()) this.tab(old_indent) this.indent = old_indent this.bracketR(exports._Array, 0) return has_newlines } this.Object = function(n, indent){//: { keys:3 }, this.braceL(exports._Object, 0) // allright so var has_newlines = this.force_newlines_object if(this.comments(n.cm1)) has_newlines = true else if(this.force_newlines_object) this.newline() //console.log(has_newlines, n) var old_indent = this.indent if(has_newlines) this.indent++ var maxlen = 0 for(var i = 0; i < n.keys.length; i ++){ var prop = n.keys[i] var name = prop.key.name if (!name) { name = prop.key.value } var len = name.length if(len>maxlen) maxlen = len } for(var i = 0; i < n.keys.length; i ++){ var prop = n.keys[i] //if(!has_newlines && i){ // this.comma(exports._Object, 0) // this.space() //} if(this.lastIsNewline()) this.tab(this.indent) if(has_newlines) this.comments(prop.cmu) if(this.lastIsNewline()) this.tab(this.indent) //var do_newline = has_newlines //|| this.commentHasNewline(prop.cmr) this.expand(prop.key, exports._Object) if(prop.value){ var name = prop.key.name if (!name) { name = prop.key.value } var diff = maxlen + 1 - name.length this.colon(exports._Object, has_newlines?1*256+diff:0) this.expand(prop.value) } if(i < n.keys.length - 1){ this.comma(exports._Object, has_newlines?0:2*256+this.post_comma) //this.space() } if(has_newlines && !this.comments(prop.cmr)){ this.newline() } } if(has_newlines){ //this.comments(n.cm2) // check if we are in an argument list if(this.lastIsNewline()) this.tab(indent?old_indent+1:old_indent) } this.indent = old_indent this.braceR(exports._Object, 0) return has_newlines } this.Index = function(n){//: { object:1, index:1 }, this.expand(n.object) this.bracketL(exports._Index, 0) if(n.index) this.expand(n.index) this.bracketR(exports._Index, 0) } this.Key = function(n){//: { object:1, key:1, exist:0 }, this.expand(n.object) if(n.cm1 && this.comments(n.cm1,' ')){ this.tab(this.indent + 1) } this.dot(exports._Key) if(n.cm2 && this.comments(n.cm2,' ')){ this.tab(this.indent + 1) } this.expand(n.key) } this.Block = function(n, skipbrace){//:{ steps:2 }, var old_indent = 0 if(!skipbrace){ this.braceL(exports._Block, 0) old_indent = this.indent this.indent++ // lets output our immediate follow comments } this.comments(n.cm1, ' ') if(!skipbrace){ if(!this.lastIsNewline()) this.newline() } for(var i = 0; i < n.steps.length; i++){ var step = n.steps[i] // if we have comments above, insert them this.comments(step.cmu) if(this.lastIsNewline()) this.tab(this.indent) this.expand(step) this.comments(step.cmr, ' ') if(!this.lastIsNewline()) this.newline() } this.comments(n.cm2) if(!skipbrace){ // lets add our tail comments this.indent = old_indent if(!this.lastIsNewline()){ this.newline() } this.tab(old_indent) this.braceR(exports._Block, 0) } } this.List = function(n){//: { items:2 }, for(var i = 0; i < n.items.length; i++){ var item = n.items[i] if(i) this.comma(exports._List) this.expand(item) } } this.Break = function(n){//: { label:1 }, this.keyword('break', exports._Break) } this.Continue = function(n){//: { label:1 }, this.keyword('continue', exports._Continue) } this.Label = function(n){//: { label:1, body:1 }, this.expand(n.label) this.expand(n.body) } this.If = function(n){//: { test:1, then:1, else:1, postfix:0, compr:0 }, this.keyword('if', exports._If) //this.space() this.parenL(exports._If, 1*256+1) this.indent++ this.expand(n.test) this.indent-- this.parenR(exports._If, 2*256+1) //this.space() // if our n.then has wsu, lets do it if(n.then.cmu){ if(this.comments(n.then.cmu)) this.tab(this.indent+1) } this.expand(n.then) if(n.else){ // we have to end the if expression properly if(!this.comments(n.cm1,' ')) this.newline() if(this.lastIsNewline()) this.tab(this.indent) this.keyword('else', exports._If) //this.space() if(n.else.cmu){ if(this.comments(n.else.cmu)) this.tab(this.indent+1) } this.expand(n.else) //debug() } } this.Switch = function(n){//: { on:1, cases:2 }, this.keyword('switch', _Switch) //this.space() this.parenL(_Switch, 0) this.expand(n.on) this.parenR(_Switch, 0) //this.space() this.braceL(_Switch, 0) //var old_indent = indent //indent++ if(!this.comments(n.cm1)){ this.newline() this.tab(indent) } for(var i = 0; i < n.cases.length; i++){ this.expand(n.cases[i]) } this.comments(n.cm2) //indent = old_indent if(this.lastIsNewline()) this.tab(indent) this.braceR(exports._Switch, 0) } this.Case = function(n){//: { test:1, then:2 }, this.comments(n.cmu) if(!this.lastIsNewline()) this.newline() this.tab(indent) this.keyword('case', exports._Case) //this.space() this.expand(n.test) this.colon(exports._Case) this.comments(n.cmr) if(n.steps && n.steps.length){ if(!this.lastIsNewline()) this.newline() var old_indent = this.indent this.indent++ this.tab(this.indent) this.Block(n, true) this.indent = old_indent } //expand(n.then) } this.Throw = function(n){//: { arg:1 }, this.keyword('throw', exports._Throw) //this.space() this.expand(n.arg) } this.Try = function(n){//: { try:1, arg:1, catch:1, finally:1 }, this.Keyword('try', exports._Try) this.expand(n.try) this.Keyword('catch', exports._Try) this.parenL(exports._Try, 0) this.expand(n.arg) this.parenR(exports._Try, 0) this.expand(n.catch) if(n.finally){ this.keyword('finally', exports._Try) this.expand(n.finally) } } this.While = function(n){//: { test:1, loop:1 }, this.keyword('while', exports._While) this.parenL(exports._While, 0) this.expand(n.test) this.parenR(exports._While, 0) this.expand(n.loop) } this.DoWhile = function(n){//: { loop:1, test:1 }, this.keyword('do', exports._Do) this.expand(n.loop) this.keyword('while', exports._Do) this.parenL(exports._Do, 0) this.expand(n.test) this.parenR(exports._Do, 0) } this.For = function(n){//: { init:1, test:1, update:1, loop:1, compr:0 }, this.keyword('for', exports._For) //this.space() this.parenL(exports._For, 0) this.expand(n.init) this.semiColon(exports._For) //this.space() this.expand(n.test) this.semiColon(exports._For) //this.space() this.expand(n.update) this.parenR(exports._For, 0) if(n.loop.cmu){ if(this.comments(n.loop.cmu)) this.tab(this.indent + 1) } //else if(n.loop.type != 'Block') this.space() this.expand(n.loop) } this.ForIn = function(n){//: { left:1, right:1, loop:1, compr:0 }, this.keyword('for', exports._For) //this.space() this.parenL(exports._For, 0) this.expand(n.left) //this.space() this.keyword('in', exports._For) //this.space() this.expand(n.right) this.parenR(exports._For, 0) if(n.loop.cmu){ if(this.comments(n.loop.cmu)) this.tab(this.indent + 1) } //else if(n.loop.type != 'Block') this.space() this.expand(n.loop) } this.ForOf = function(n){//: { left:1, right:1, loop:1, compr:0 }, this.keyword('for', exports._For) //this.space() this.parenL(exports._For, 0) this.expand(n.left) //this.space() this.keyword('of', exports._For) //this.space() this.expand(n.right) this.parenR(exports._For, 0) if(n.loop.cmu){ if(this.comments(n.loop.cmu)) this.tab(this.indent + 1) } //else if(n.loop.type != 'Block') this.space() this.expand(n.loop) } this.Var = function(n){//: { defs:2, const:0 }, this.keyword('var', exports._Var) if(n.defs && n.defs.length){ this.space() for(var i = 0; i < n.defs.length; i++){ if(i) this.comma(exports._Var, 2*256+this.after_comma) this.expand(n.defs[i]) } } } this.Def = function(n){//: { id:1, init:1, dim:1 }, this.expand(n.id) if(n.init){ //this.space() this.operator('=', exports._Def, 3*256+1) //this.space() this.expand(n.init) } } this.Function = function(n){//: { id:1, name:1, params:2, rest:1, body:1, arrow:0, gen:0, def:0 }, if(!n.arrow){ if(n.name) this.expand(n.name) else if(n.id){ this.keyword('function', exports._Function) this.space() this.expand(n.id) } else this.keyword('function', exports._Function) } //else Keyword('function', _Function) this.parenL(exports._Function, 0) if(n.params) for(var i = 0; i < n.params.length; i++){ if(i){ this.comma(exports._Function, 2*256+1)//, this.space() } this.expand(n.params[i]) } if(n.rest){ if(i) this.comma(exports._Function)//, this.space() this.expand(n.rest) } this.parenR(exports._Function, 0) if(n.arrow=='=>') this.operator('=>', exports._Function) //else this.space() this.expand(n.body) } this.Return = function(n){//: { arg:1 }, this.keyword('return', exports._Return) if(n.arg) this.space(), this.expand(n.arg) } this.Yield = function(n){//: { arg:1 }, this.keyword('yield', exports._Yield) if(n.arg) this.space(), this.expand(n.arg) } this.Await = function(n){//: { arg:1 }, this.keyword('await', exports._Await) if(n.arg) this.space(), this.expand(n.arg) } this.Unary = function(n){//: { op:0, prefix:0, arg:1 }, if(n.prefix){ if(n.op.length!=1) this.keyword(n.op, exports._Unary), this.space() else this.operator(n.op, exports._Unary) this.expand(n.arg) } else{ this.expand(n.arg) this.operator(n.op, exports._Unary) } } this.Binary = function(n){//: { op:0, prio:0, left:1, right:1 }, var paren_l = Parser.needsParens(n, n.left, true) var paren_r = Parser.needsParens(n, n.right) if(paren_l) this.parenL(exports._Binary, 0) this.expand(n.left) if(paren_l) this.parenR(exports._Binary, 0) var old_indent = this.indent this.indent++ if(n.cm1 && this.comments(n.cm1,' ')){ this.tab(this.indent) } //else this.space() this.operator(n.op, exports._Binary, 3*256+this.around_operator) if(n.cm2 && this.comments(n.cm2,' ')){ this.tab(this.indent) } //else this.space() if(paren_r) this.parenL(exports._Binary, 0) this.expand(n.right) if(paren_r) this.parenR(exports._Binary, 0) this.indent = old_indent } this.Logic = function(n){//: { op:0, prio:0, left:1, right:1 }, var paren_l = Parser.needsParens(n, n.left, true) var paren_r = Parser.needsParens(n, n.right) if(paren_l) this.parenL(exports._Logic, 0) this.expand(n.left) if(paren_l) this.parenR(exports._Logic, 0) var old_indent = this.indent this.indent++ if(n.cm1 && this.comments(n.cm1,' ')){ this.tab(this.indent) } //else this.space() if(n.op.length > 1){ if(n.op.length == 2){ this.operator(n.op[0], exports._Logic, 1*256+this.around_operator) this.operator(n.op[1], exports._Logic, 2*256+this.around_operator) } else{ this.operator(n.op, exports._Logic,0) } } else{ this.operator(n.op, exports._Logic, 3*256+this.around_operator) } if(n.cm2 && this.comments(n.cm2,' ')){ this.tab(this.indent) } //else this.space() if(paren_r) this.parenL(exports._Logic,0) this.expand(n.right) if(paren_r) this.parenR(exports._Logic,0) this.indent = old_indent } this.Assign = function(n){//: { op:0, prio:0, left:1, right:1 }, this.expand(n.left) var old_indent = this.indent this.indent++ if(n.cm1 && this.comments(n.cm1,' ')){ this.tab(this.indent) } //else this.space() //this.operator(n.op, exports._Assign, 0) if(n.op.length > 1){ if(n.op.length == 2){ this.operator(n.op[0], exports._Assign, 1*256+this.around_operator) this.operator(n.op[1], exports._Assign, 2*256+this.around_operator) } else{ this.operator(n.op, exports._Assign,0) } } else{ this.operator(n.op, exports._Assign, 3*256+this.around_operator) } if(n.cm2 && this.comments(n.cm2,' ')){ this.tab(this.indent) } //else this.space() if(n.right.type === 'Function' || n.right.type === 'Object'){ this.indent-- } this.expand(n.right) this.indent = old_indent } this.Update = function(n){//: { op:0, prio:0, arg:1, prefix:0 }, if(n.prefix){ this.operator(n.op, exports._Update), this.expand(n.arg) } else{ this.expand(n.arg) this.operator(n.op, exports._Update) } } this.Condition = function(n){//: { test:1, then:1, else:1 }, this.expand(n.test) this.operator('?', exports._Condition) this.expand(n.then) this.operator(':', exports._Condition) this.expand(n.else) } this.New = function(n){//: { fn:1, args:2 }, this.keyword('new', exports._New) this.space() this.expand(n.fn) this.parenL(exports._New) for(var i = 0; i < n.args.length; i++){ if(i) this.comma(exports._New)//, this.space() this.expand(n.args[i]) } this.parenR(exports._New) } this.Call = function(n){//: { fn:1, args:2 }, var fn_t = n.fn.type if(fn_t == 'Function' || fn_t == 'List' || fn_t == 'Logic' || fn_t == 'Condition') { this.parenL(exports._Call, 0) this.expand(n.fn) this.parenR(exports._Call, 0) } else this.expand(n.fn) this.parenL(exports._Call, 0) var has_newlines = false if(this.comments(n.cm1)) has_newlines = true var old_indent = this.indent //if(has_newlines) this.indent++ // cleanup hack // lets check if it has a newline //var first_is_obj if(!has_newlines && n.args.length>0 && (n.args[0].type === 'Object' || n.args[0].type === 'Array' || n.args[0].type === 'Function')){ first_is_obj = true if(n.args.length === 1) this.indent-- } for(var i = 0; i < n.args.length; i++){ var arg = n.args[i] if(!arg)continue this.comments(arg.cmu) if(this.lastIsNewline()) this.tab(this.indent) var has_nl = this.expand(arg) // check wether to switch to has_newlines if(i === 0 && !has_newlines){ has_newlines = has_nl } var do_newline = has_newlines || this.commentHasNewline(arg.cmr) if(i < n.args.length - 1) this.comma(exports._Call, do_newline?0:2*256+this.post_comma) if(n.args.length > 1 && has_newlines && !this.comments(arg.cmr)) this.newline() //else this.space() } if(has_newlines && this.comments(n.cm2)) this.tab(this.indent - 1) if(this.lastIsNewline()) this.tab(old_indent) this.indent = old_indent this.parenR(exports._Call, 0) return has_newlines } exports.types = { // Base node markers _Id:1, _Property:2, _Value:3, _This:4, _Array:5, _Object:6, _Index:7, _Key:8, _ThisCall: 9, _Block:10, _List: 11, _Comprehension:12, _Template: 13, _Break:14, _Continue:15, _Label:16, _If:17, _Switch:18, _Case:19, _Throw:20, _Try:21, _While:22, _DoWhile:23, _For:24, _ForIn:25, _ForOf:26, _Var:27, _Def:28, _Function:29, _Return:30, _Yield:31, _Await:32, _Unary:33, _Binary:34, _Logic:35, _Assign:36, _Update:37, _Condition:38, _New:39, _Call:40, _Nest:41, _Class:42, _Rest:43, _Comment:44, // second level markers _Id:1, _Paren:2, _ParenL:1, _ParenR:2, _Brace:3, _BraceL:1, _BraceR:2, _Bracket:4, _BracketL:1, _BracketR:2, _Comma:5, _Colon:6, _DColon:7, _Dot:8, _SemiColon:9, _Operator:10, _Plus:1, _Min:2, _Div:3, _Mul:4, _Pow:5, _Shl:6, _Shr:7, _EQ:8, _NEQ:9, _GT:10, _LT:11, _GTE:12, _LTE:13, _Plusplus:14, _Minmin:15, _Assign:16, _PlusAssign:17, _MinAssign:18, _MulAssign:19, _DivAssign:20, _ShlAssign:21, _ShrAssign:22, _TerniaryQ:23, _TerniaryC:24, _Signal:25, _String:11, _Number:12, _Boolean:13, _Tab:14, _Keyword:15, _Color:16 } for(var key in exports.types) exports[key] = exports.types[key] exports.ops ={ '++':exports._Plusplus, '--':exports._Minmin, '+':exports._Plus, '-':exports._Min, '/':exports._Div, '*':exports._Mul, '**':exports._Pow, '==':exports._EQ, '!=':exports._NEQ, '>':exports._GT, '<':exports._LT, '=>':exports._GTE, '<=':exports._LTE, '<<':exports._Shl, '>>':exports._Shr, '=':exports._Assign, ':=':exports._Signal, '+=':exports._PlusAssign, '-=':exports._MinAssign, '/=':exports._DivAssign, '*=':exports._MulAssign, '<<=':exports._ShlAssign, '>>=':exports._ShrAssign, '?':exports._TerniaryQ, ':':exports._TerniaryC } })