Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of ~/rvs_get/test/git-dir
Conflicts: js_pp/js_pp.js
- Loading branch information
Showing
4 changed files
with
293 additions
and
228 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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){ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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} |
Oops, something went wrong.