Skip to content

Commit

Permalink
Merge branch 'master' of ~/rvs_get/test/git-dir
Browse files Browse the repository at this point in the history
Conflicts:
	js_pp/js_pp.js
  • Loading branch information
azatoth committed Oct 5, 2010
2 parents 1a12167 + cb41020 commit 463cc28
Show file tree
Hide file tree
Showing 4 changed files with 293 additions and 228 deletions.
2 changes: 1 addition & 1 deletion js_pp/js_ast.js
Expand Up @@ -3,7 +3,7 @@
// - no 'loc' property on nodes (may add separate start, end integers later)
// - Function body is always BlockStatement, never Expression (which is moz-specific)
// - no generators (also moz-specific)
// - no multiple catch clauses (also moz-specific)
// - no multiple catch clauses (also moz-specific)
// - no 'meta' property on FunctionDeclaration or FunctionExpression
// - no "for each ... in" support (moz-specific)
// - formal parameters must be identifiers, not destructuring patterns (which again is moz-specific)
Expand Down
84 changes: 84 additions & 0 deletions js_pp/js_compose.js
@@ -0,0 +1,84 @@
// compose :: Context, [String] → String

// Each compose function takes a Context c carrying information about
// the surrounding context in which the node appears, and an array of
// strings ss which it must combine and return into the final result.

var compose=

{Program:compose_program_elements
,Block:compose_program_elements

,IfStatement:function(c,ss){var ret
return 'if'
+ (c.space_before_if_test?' ':'')
+ (c.space_inside_if_test_parens?'( ':'(')
+ ss[0]
+ (c.space_inside_if_test_parens?' )':')')
+ ' ' // TODO: handle blocks and single statements here
+ ss[1]
+ (ss[2] // is there an alternative branch?
?'else'+ss[2]
:'')}

,ExpressionStatement:function(c,ss){return ss[0]}

,CallExpression:function(c,ss){return ss[0]+ss[1]} // TODO: add options for whitespace between callee and arguments

,Arguments:function(c,ss){
return '('
+ ss.join(c.space_after_comma?', ':',')
+ ')'}

,BinaryExpression:function(op,prec,assoc){return function(c,ss){var parenthesize,parens
parenthesize=prec>c.min_prec || prec==c.min_prec && assoc!=c.assoc
parens=c.spaces_inside_parens?['( ',' )']:['(',')']
return (parenthesize?parens[0]:'')
+ ss[0]
+ (c.space_around_operators?(' '+op+' '):op)
+ ss[1]
+ (parenthesize?parens[1]:'')}}

,ArrayExpression:function(c,ss){
return '['
+ ss.join(',') // TODO: add options for spaces
+ ']'}

,Literal:function(kind,value){return function(c,ss){
switch(kind){
case 'string':return compose_string(c,value)
case 'number':return compose_number(c,value)
case 'regexp':
default: throw new Error('unhandled literal kind: '+kind)}}}

}

function compose_program_elements(c,ss){var line_sep
line_sep='\n'+c.indentation
// this actually isn't correct either, because some "program elements" are function declarations, they are not all statements, and should not all have semicolons even in semicolons=all mode
// The semicolons should be added in the statements' individual compose functions.
if(c.semicolons=='all')return ss.map(function(s){return s+';'}).join(line_sep)
throw new Error('XXX TODO: implement other semicolon styles')}

function compose_string(c,val){var quote_char
quote_char=c.string_quote_char||c.string_quote_char_preference
assert(quote_char=='single'||quote_char=='double','known string quote preference')
// quote_string_* are declared in ../deps/util.js
return {single:quote_string_single,double:quote_string_double}[quote_char](val)}

function compose_number(c,n){var str,ret,sign,radix
radix=c.number_radix||c.number_radix_preference
sign=n<0?'-':''
n=Math.abs(n)
str=n.toString(radix)
switch(radix){
case 8: ret='0'+str;break
case 10: ret=(str.slice(-6)=='000000') ? exp_notation() : str;break
case 16: ret='0x'+str;break
default: throw new Error('unhandled number radix: '+radix)}
ret=sign+ret
assert(+ret == n,"number formatting preserves value")
return ret}

function compose_regexp(c,val){
}
135 changes: 135 additions & 0 deletions js_pp/js_generate_sub_contexts.js
@@ -0,0 +1,135 @@
// create_initial_context :: Options → Context

function create_initial_context(opts){var ctx,copied
ctx={min_prec:19
,indentation:''
,number_radix_preference:opts.number_radix_preference
}
switch(opts.string_quote_style){
case 'single': ctx.string_quote_char='single';break
case 'double': ctx.string_quote_char='double';break
case 'shorter-or-single': ctx.string_quote_char_preference='single';break
case 'shorter-or-double': ctx.string_quote_char_preference='double';break
default: throw new Error('bad option string_quote_style: '+opts.string_quote_style)}
switch(opts.semicolons){
case 'all': ctx.semicolons='all';break
default: throw new Error('unimplemented semicolon option: '+opts.semicolons)}
copied=['space_before_if_test'
,'space_inside_if_test_parens'
,'space_after_single_line_if_test'
,'spaces_inside_parens'
,'space_around_operators'
]
copied.forEach(function(p){ctx[p]=opts[p]})
return ctx}

// JavaScript operator precedence:

// 1 bracket accessors, dot accessors
// 2 new with arguments, function call
// 3 new without arguments
// 4 postincrement, postdecrement
// 5 delete, void, typeof, preincrement, predecrement, unary plus, unary minus, bitwise not, logical not
// Binary operators:
// 6 Multiplicative (*, /)
// 7 Additive (+, -)
// 8 Shift
// 9 Relational (<, >, <=, >=, instanceof, in)
// 10 Equality
// 11 BitwiseAnd
// 12 BitwiseXOr
// 13 BitwiseOr
// 14 LogicalAnd
// 15 LogicalOr
// 16 ternary ≔ OrExpr ? AssignExpr : AssignExpr
// 17 assignment operators
// 18 comma operator
// Other
// 19 statement separators (newlines, semicolons)

// generate_sub_contexts :: Formattable × Context → [Context]

// Most of these use a helper function h(), declared below, which
// copies the input context and modifies the copies. The arguments
// to h() are: the initial context, the number of copies to create,
// and up to n modification objects which will overwrite properties
// in the corresponding copies. If n is greater than the number of
// provided objects, the last object will be used repeatedly.

var generate_sub_contexts=

{Program:gsc_program_elements

,Block:gsc_program_elements

,IfStatement:function(f,c){
// IfStatement children: test, consequent, (opt) alternate
return h(c,f.cn.length
,{min_prec:18}
,{min_prec:20}
,{min_prec:20})}

,ExpressionStatement:function(f,c){
return h(c,1
,{min_prec:18})}

,CallExpression:function(f,c){
return h(c,2
,{min_prec:2}
,{min_prec:17})}

,Arguments:function(f,c){
return h(c,f.cn.length
,{min_prec:17})}

,BinaryExpression:function(f,c){
assert(f.assoc=='left','all binary ops left-associative')
return h(c,f.cn.length
,{min_prec:f.prec,assoc:'left'}
,{min_prec:f.prec })}

,ArrayExpression:function(f,c){var string_quote_char,i,l,dbl_penalty,sgl_penalty,update
dbl_penalty=sgl_penalty=0
if(c.homogenize_arrays && !c.string_quote_char){
// testing some ideas by homogenizing string quote characters in arrays, see doc/overview
for(i=0,l=f.cn.length;i<l;i++){
if(f.cn[i].quote_char_preference=='double') sgl_penalty+=f.cn[i].quote_char_penalty
if(f.cn[i].quote_char_preference=='single') dbl_penalty+=f.cn[i].quote_char_penalty}
string_quote_char = dbl_penalty > sgl_penalty ? 'single'
: sgl_penalty < dbl_penalty ? 'double'
: c.string_quote_char_preference}
update={min_prec:17}
if(string_quote_char)update.string_quote_char=string_quote_char
return h(c,f.cn.length,update)}

}

// this is intended to be in a module (like the other js_pp files), so the 'h' helper will not be in the global scope.
// h :: Context, Integer, [update_object] → [Context]
// The provided context is copied as many times as necessary.
// Each update or diff object provided is used to replace properties of the context at the corresponding position.
// If there are more context objects requested than diff objects provided, the last diff object is reused.
// This is convenient for expressions with a variable number of sub-expressions that should be formatted alike.
// When a context is updated it is shallow-copied first.
// Thus it is safe to include multiple references to the same context object in the output array.
function h(c,n,diff /* ... */){var i,p,c2,ret
ret=[]
for(i=0;i<n;i++){
c2=null
diff=arguments[2+i]||diff
if(diff) for(p in diff){
c2=c2||copy(c)
c2[p]=diff[p]}
ret[i]=c2||c}
return ret}

function copy(o){var r={},p;for(p in o)r[p]=o[p];return r}

// handles programs, blocks, function bodies
// all are sequences of statements and/or function declarations
function gsc_program_elements(f,c){var c1,i,l,ret
ret=[]
c1=copy(c)
c1.min_prec=20
for(i=0,l=f.cn.length;i<l;i++) ret.push(c1)
return ret}

0 comments on commit 463cc28

Please sign in to comment.