Console util done.

This commit is contained in:
Onoshko Dan 2014-05-20 00:29:01 +07:00
parent 3a8f96a40e
commit 744ecd3a8e
8 changed files with 115 additions and 57 deletions

View File

@ -91,8 +91,9 @@ ColaScript is a language that compiles in JavaScript. This language is similar t
- `@use` - `@use`
@use strict, typing @use strict
@use asmjs @use asmjs
@use closure
- `@if @end_if @else` - `@if @end_if @else`

View File

@ -3,7 +3,7 @@
"use strict"; "use strict";
var UglifyJS = require("../tools/node"); var Cola = require("../tools/node");
var sys = require("util"); var sys = require("util");
var optimist = require("optimist"); var optimist = require("optimist");
var fs = require("fs"); var fs = require("fs");
@ -19,16 +19,18 @@ Without [options] it will simply parse input files and dump the AST\n\
with whitespace and comments discarded. To achieve compression and\n\ with whitespace and comments discarded. To achieve compression and\n\
mangling you need to use `-c` and `-m`.\ mangling you need to use `-c` and `-m`.\
") ")
.describe("j", "Work with JavaScript (by default Cola will expect ColaScript).")
.describe("source-map", "Specify an output file where to generate source map.") .describe("source-map", "Specify an output file where to generate source map.")
.describe("source-map-root", "The path to the original source to be included in the source map.") .describe("source-map-root", "The path to the original source to be included in the source map.")
.describe("source-map-url", "The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map.") .describe("source-map-url", "The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map.")
.describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.") .describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.")
.describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.") .describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
.describe("screw-ie8", "Pass this flag if you don't care about full compliance with Internet Explorer 6-8 quirks (by default UglifyJS will try to be IE-proof).") .describe("screw-ie8", "Pass this flag if you don't care about full compliance with Internet Explorer 6-8 quirks (by default Cola will try to be IE-proof).")
.describe("expr", "Parse a single expression, rather than a program (for parsing JSON)") .describe("expr", "Parse a single expression, rather than a program (for parsing JSON)")
.describe("n", "Disable `main` binding.")
.describe("p", "Skip prefix for original filenames that appear in source maps. \ .describe("p", "Skip prefix for original filenames that appear in source maps. \
For example -p 3 will drop 3 directories from file names and ensure they are relative paths. \ For example -p 3 will drop 3 directories from file names and ensure they are relative paths. \
You can also specify -p relative, which will make UglifyJS figure out itself the relative paths between original sources, \ You can also specify -p relative, which will make Cola figure out itself the relative paths between original sources, \
the source map and the output file.") the source map and the output file.")
.describe("o", "Output file (default STDOUT).") .describe("o", "Output file (default STDOUT).")
.describe("b", "Beautify output/specify output options.") .describe("b", "Beautify output/specify output options.")
@ -56,15 +58,18 @@ parsed, but the source map will adjust for its presence.")
.describe("stats", "Display operations run time on STDERR.") .describe("stats", "Display operations run time on STDERR.")
.describe("acorn", "Use Acorn for parsing.") .describe("acorn", "Use Acorn for parsing.")
.describe("spidermonkey", "Assume input files are SpiderMonkey AST format (as JSON).") .describe("spidermonkey", "Assume input files are SpiderMonkey AST format (as JSON).")
.describe("self", "Build itself (UglifyJS2) as a library (implies --wrap=UglifyJS --export-all)") .describe("self", "Build itself (Cola) as a library (implies --wrap=Cola --export-all)")
.describe("wrap", "Embed everything in a big function, making the “exports” and “global” variables available. \ .describe("wrap", "Embed everything in a big function, making the “exports” and “global” variables available. \
You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser.") You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser.")
.describe("export-all", "Only used when --wrap, this tells UglifyJS to add code to automatically export all globals.") .describe("export-all", "Only used when --wrap, this tells Cola to add code to automatically export all globals.")
.describe("lint", "Display some scope warnings") .describe("lint", "Display some scope warnings")
.describe("v", "Verbose") .describe("v", "Verbose")
.describe("V", "Print version number and exit.") .describe("V", "Print version number and exit.")
.describe("noerr", "Don't throw an error for unknown options in -c, -b or -m.") .describe("noerr", "Don't throw an error for unknown options in -c, -b or -m.")
.alias("j", "js")
.alias("j", "javascript")
.alias("n", "no-main-binding")
.alias("p", "prefix") .alias("p", "prefix")
.alias("o", "output") .alias("o", "output")
.alias("v", "verbose") .alias("v", "verbose")
@ -88,7 +93,9 @@ You need to pass an argument to this option to specify the name that your module
.string("wrap") .string("wrap")
.string("p") .string("p")
.boolean("j")
.boolean("expr") .boolean("expr")
.boolean("n")
.boolean("source-map-include-sources") .boolean("source-map-include-sources")
.boolean("screw-ie8") .boolean("screw-ie8")
.boolean("export-all") .boolean("export-all")
@ -109,7 +116,7 @@ You need to pass an argument to this option to specify the name that your module
normalize(ARGS); normalize(ARGS);
if (ARGS.noerr) { if (ARGS.noerr) {
UglifyJS.DefaultsError.croak = function(msg, defs) { Cola.DefaultsError.croak = function(msg, defs) {
sys.error("WARN: " + msg); sys.error("WARN: " + msg);
}; };
} }
@ -121,7 +128,7 @@ if (ARGS.version || ARGS.V) {
} }
if (ARGS.ast_help) { if (ARGS.ast_help) {
var desc = UglifyJS.describe_ast(); var desc = Cola.describe_ast();
sys.puts(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2)); sys.puts(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
process.exit(0); process.exit(0);
} }
@ -139,6 +146,10 @@ var COMPRESS = getOptions("c", true);
var MANGLE = getOptions("m", true); var MANGLE = getOptions("m", true);
var BEAUTIFY = getOptions("b", true); var BEAUTIFY = getOptions("b", true);
if (ARGS.j) {
if (COMPRESS) COMPRESS.is_js = getOptions("j");
}
if (ARGS.d) { if (ARGS.d) {
if (COMPRESS) COMPRESS.global_defs = getOptions("d"); if (COMPRESS) COMPRESS.global_defs = getOptions("d");
} }
@ -159,7 +170,7 @@ if (ARGS.screw_ie8) {
} }
if (BEAUTIFY) if (BEAUTIFY)
UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY); Cola.merge(OUTPUT_OPTIONS, BEAUTIFY);
if (ARGS.comments) { if (ARGS.comments) {
if (/^\//.test(ARGS.comments)) { if (/^\//.test(ARGS.comments)) {
@ -184,8 +195,8 @@ if (ARGS.self) {
if (files.length > 0) { if (files.length > 0) {
sys.error("WARN: Ignoring input files since --self was passed"); sys.error("WARN: Ignoring input files since --self was passed");
} }
files = UglifyJS.FILES; files = Cola.FILES;
if (!ARGS.wrap) ARGS.wrap = "UglifyJS"; if (!ARGS.wrap) ARGS.wrap = "Cola";
ARGS.export_all = true; ARGS.export_all = true;
} }
@ -222,7 +233,7 @@ var TOPLEVEL = null;
var P_RELATIVE = ARGS.p && ARGS.p == "relative"; var P_RELATIVE = ARGS.p && ARGS.p == "relative";
var SOURCES_CONTENT = {}; var SOURCES_CONTENT = {};
var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({ var SOURCE_MAP = ARGS.source_map ? new Cola.SourceMap({
file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE, file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE,
root: ARGS.source_map_root, root: ARGS.source_map_root,
orig: ORIG_MAP, orig: ORIG_MAP,
@ -231,10 +242,10 @@ var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({
OUTPUT_OPTIONS.source_map = SOURCE_MAP; OUTPUT_OPTIONS.source_map = SOURCE_MAP;
try { try {
var output = UglifyJS.OutputStream(OUTPUT_OPTIONS); var output = new Cola.OutputStream(OUTPUT_OPTIONS);
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS); var compressor = COMPRESS && new Cola.Compressor(COMPRESS);
} catch(ex) { } catch(ex) {
if (ex instanceof UglifyJS.DefaultsError) { if (ex instanceof Cola.DefaultsError) {
sys.error(ex.msg); sys.error(ex.msg);
sys.error("Supported options:"); sys.error("Supported options:");
sys.error(sys.inspect(ex.defs)); sys.error(sys.inspect(ex.defs));
@ -274,13 +285,16 @@ async.eachLimit(files, 1, function (file, cb) {
} }
else { else {
try { try {
TOPLEVEL = UglifyJS.parse(code, { TOPLEVEL = Cola.parse(code, {
filename : file, filename : file,
toplevel : TOPLEVEL, toplevel : TOPLEVEL,
expression : ARGS.expr, expression : ARGS.expr,
is_js : ARGS.j
}); });
if (!ARGS.j) TOPLEVEL = TOPLEVEL.toJavaScript({ main_bindiing: !ARGS.n });
} catch(ex) { } catch(ex) {
if (ex instanceof UglifyJS.JS_Parse_Error) { if (ex instanceof Cola.JS_Parse_Error) {
sys.error("Parse error at " + file + ":" + ex.line + "," + ex.col); sys.error("Parse error at " + file + ":" + ex.line + "," + ex.col);
sys.error(ex.message); sys.error(ex.message);
sys.error(ex.stack); sys.error(ex.stack);
@ -294,7 +308,7 @@ async.eachLimit(files, 1, function (file, cb) {
}); });
}, function () { }, function () {
if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){ if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL); TOPLEVEL = Cola.AST_Node.from_mozilla_ast(TOPLEVEL);
}); });
if (ARGS.wrap) { if (ARGS.wrap) {
@ -373,11 +387,11 @@ async.eachLimit(files, 1, function (file, cb) {
} }
if (ARGS.stats) { if (ARGS.stats) {
sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", { sys.error(Cola.string_template("Timing information (compressed {count} files):", {
count: files.length count: files.length
})); }));
for (var i in STATS) if (STATS.hasOwnProperty(i)) { for (var i in STATS) if (STATS.hasOwnProperty(i)) {
sys.error(UglifyJS.string_template("- {name}: {time}s", { sys.error(Cola.string_template("- {name}: {time}s", {
name: i, name: i,
time: (STATS[i] / 1000).toFixed(3) time: (STATS[i] / 1000).toFixed(3)
})); }));
@ -401,16 +415,17 @@ function getOptions(x, constants) {
if (x !== true) { if (x !== true) {
var ast; var ast;
try { try {
ast = UglifyJS.parse(x, { expression: true }); ast = Cola.parse(x, { expression: true, is_js: ARGS.j });
if (!ARGS.j) ast = ast.toJavaScript({ main_bindiing: !ARGS.n });
} catch(ex) { } catch(ex) {
if (ex instanceof UglifyJS.JS_Parse_Error) { if (ex instanceof Cola.JS_Parse_Error) {
sys.error("Error parsing arguments in: " + x); sys.error("Error parsing arguments in: " + x);
process.exit(1); process.exit(1);
} }
} }
ast.walk(new UglifyJS.TreeWalker(function(node){ ast.walk(new Cola.TreeWalker(function(node){
if (node instanceof UglifyJS.AST_Seq) return; // descend if (node instanceof Cola.AST_Seq) return; // descend
if (node instanceof UglifyJS.AST_Assign) { if (node instanceof Cola.AST_Assign) {
var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_"); var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_");
var value = node.right; var value = node.right;
if (constants) if (constants)
@ -418,7 +433,7 @@ function getOptions(x, constants) {
ret[name] = value; ret[name] = value;
return true; // no descend return true; // no descend
} }
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_Binary) { if (node instanceof Cola.AST_Symbol || node instanceof Cola.AST_Binary) {
var name = node.print_to_string({ beautify: false }).replace(/-/g, "_"); var name = node.print_to_string({ beautify: false }).replace(/-/g, "_");
ret[name] = true; ret[name] = true;
return true; // no descend return true; // no descend

View File

@ -112,4 +112,4 @@ Object Profile(String firstName, String secondName, String country = "Russia", A
}; };
} }
main(); //main();

View File

@ -111,6 +111,14 @@ Cola.AST_Node = Cola.DEFNODE("Node", "start end", {
} }
}, null); }, null);
Cola.AST_Command = Cola.DEFNODE("Command", "name args", {
$documentation: "Compiler-command statement",
$propdoc: {
name: "[string] Name of command",
args: "[AST_Node*] List of arguments"
}
}, Cola.AST_Node);
Cola.AST_Noop = Cola.DEFNODE("Noop", null, null, Cola.AST_Node); Cola.AST_Noop = Cola.DEFNODE("Noop", null, null, Cola.AST_Node);
Cola.AST_Node.warn_function = null; Cola.AST_Node.warn_function = null;

View File

@ -288,6 +288,7 @@ Cola.OutputStream.prototype.add_mapping = function (token, name) {
if(!this.options.source_map) return; if(!this.options.source_map) return;
try { try {
if (token && !token.file) console.log(token);
if (token) this.options.source_map.add( if (token) this.options.source_map.add(
token.file || "?", token.file || "?",
this.current_line, this.current_col, this.current_line, this.current_col,

View File

@ -531,7 +531,7 @@ Cola.Tokenizer.prototype.read_at = function (){
this.S.string.at[this.S.string.level].inside_at = true; this.S.string.at[this.S.string.level].inside_at = true;
this.S.string.at[this.S.string.level].balance = 1; this.S.string.at[this.S.string.level].balance = 1;
return this.token("punc", "@" + this.next()); return this.token("punc", "@" + this.next());
} } else return this.token("punc", "@");
this.parse_error('Unexpected character "@"'); this.parse_error('Unexpected character "@"');
} }
@ -1047,7 +1047,35 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() {
case "punc": case "punc":
switch (this.S.token.value) { switch (this.S.token.value) {
case "@":
if (!this.is_js && this.next_is("name"))
return new Cola.AST_Command({
name : this.next().value,
args : (function(){
var args = [];
while (!this.peek().nlb && !this.next_is('eof')){
if (this.next_is('punc', '{')) {
this.next();
args.push(new Cola.AST_BlockStatement({
start : this.S.token,
body : this.block_(),
end : this.prev()
}));
} else
args.push(this.next());
}
this.next();
return args;
}).call(this)
});
case "{": case "{":
if (this.is_js) return new Cola.AST_BlockStatement({
start : this.S.token,
body : this.block_(),
end : this.prev()
});
this.dumpS(); this.dumpS();
var balance = 0, is_object = false; var balance = 0, is_object = false;
this.next_until(function(){ this.next_until(function(){

View File

@ -34,6 +34,8 @@
***********************************************************************/ ***********************************************************************/
!this.Cola && (this.Cola = {});
Cola.$_cola_is = function $_cola_is(_object, _type){ Cola.$_cola_is = function $_cola_is(_object, _type){
return _object === _type || _type.prototype && (_object instanceof _type || _object.__proto__ === _type.prototype) || isNaN(_object) && isNaN(_type); return _object === _type || _type.prototype && (_object instanceof _type || _object.__proto__ === _type.prototype) || isNaN(_object) && isNaN(_type);
} }

View File

@ -3,17 +3,13 @@ var fs = require("fs");
var vm = require("vm"); var vm = require("vm");
var sys = require("util"); var sys = require("util");
var UglifyJS = vm.createContext({ var MOZ_SourceMap = require("source-map");
sys : sys,
console : console,
MOZ_SourceMap : require("source-map")
});
function load_global(file) { function load_global(file) {
file = path.resolve(path.dirname(module.filename), file); file = path.resolve(path.dirname(module.filename), file);
try { try {
var code = fs.readFileSync(file, "utf8"); var code = fs.readFileSync(file, "utf8");
return vm.runInContext(code, UglifyJS, file); return eval(code);
} catch(ex) { } catch(ex) {
// XXX: in case of a syntax error, the message is kinda // XXX: in case of a syntax error, the message is kinda
// useless. (no location information). // useless. (no location information).
@ -31,26 +27,28 @@ var FILES = exports.FILES = [
"../lib/output.js", "../lib/output.js",
"../lib/compress.js", "../lib/compress.js",
"../lib/sourcemap.js", "../lib/sourcemap.js",
"../lib/mozilla-ast.js" "../lib/mozilla-ast.js",
"../lib/translate.js",
"../lib/std.js"
].map(function(file){ ].map(function(file){
return path.join(path.dirname(fs.realpathSync(__filename)), file); return path.join(path.dirname(fs.realpathSync(__filename)), file);
}); });
FILES.forEach(load_global); FILES.forEach(load_global);
UglifyJS.AST_Node.warn_function = function(txt) { Cola.AST_Node.warn_function = function(txt) {
sys.error("WARN: " + txt); sys.error("WARN: " + txt);
}; };
// XXX: perhaps we shouldn't export everything but heck, I'm lazy. // XXX: perhaps we shouldn't export everything but heck, I'm lazy.
for (var i in UglifyJS) { for (var i in Cola) {
if (UglifyJS.hasOwnProperty(i)) { if (Cola.hasOwnProperty(i)) {
exports[i] = UglifyJS[i]; exports[i] = Cola[i];
} }
} }
exports.minify = function(files, options) { exports.minify = function(files, options) {
options = UglifyJS.defaults(options, { options = Cola.defaults(options, {
spidermonkey : false, spidermonkey : false,
outSourceMap : null, outSourceMap : null,
sourceRoot : null, sourceRoot : null,
@ -59,16 +57,18 @@ exports.minify = function(files, options) {
warnings : false, warnings : false,
mangle : {}, mangle : {},
output : null, output : null,
compress : {} compress : {},
is_js : false,
main_binding : true
}); });
UglifyJS.base54.reset(); Cola.base54.reset();
// 1. parse // 1. parse
var toplevel = null, var toplevel = null,
sourcesContent = {}; sourcesContent = {};
if (options.spidermonkey) { if (options.spidermonkey) {
toplevel = UglifyJS.AST_Node.from_mozilla_ast(files); toplevel = Cola.AST_Node.from_mozilla_ast(files);
} else { } else {
if (typeof files == "string") if (typeof files == "string")
files = [ files ]; files = [ files ];
@ -77,19 +77,22 @@ exports.minify = function(files, options) {
? file ? file
: fs.readFileSync(file, "utf8"); : fs.readFileSync(file, "utf8");
sourcesContent[file] = code; sourcesContent[file] = code;
toplevel = UglifyJS.parse(code, { toplevel = Cola.parse(code, {
filename: options.fromString ? "?" : file, filename: options.fromString ? "?" : file,
toplevel: toplevel toplevel: toplevel,
is_js : options.is_js
}); });
if (!options.is_js) toplevel = toplevel.toJavaScript({ main_binding : options.main_binding });
}); });
} }
// 2. compress // 2. compress
if (options.compress) { if (options.compress) {
var compress = { warnings: options.warnings }; var compress = { warnings: options.warnings, is_js : options.is_js };
UglifyJS.merge(compress, options.compress); Cola.merge(compress, options.compress);
toplevel.figure_out_scope(); toplevel.figure_out_scope();
var sq = UglifyJS.Compressor(compress); var sq = new Cola.Compressor(compress);
toplevel = toplevel.transform(sq); toplevel = toplevel.transform(sq);
} }
@ -107,7 +110,7 @@ exports.minify = function(files, options) {
inMap = fs.readFileSync(options.inSourceMap, "utf8"); inMap = fs.readFileSync(options.inSourceMap, "utf8");
} }
if (options.outSourceMap) { if (options.outSourceMap) {
output.source_map = UglifyJS.SourceMap({ output.source_map = new Cola.SourceMap({
file: options.outSourceMap, file: options.outSourceMap,
orig: inMap, orig: inMap,
root: options.sourceRoot root: options.sourceRoot
@ -122,9 +125,9 @@ exports.minify = function(files, options) {
} }
if (options.output) { if (options.output) {
UglifyJS.merge(output, options.output); Cola.merge(output, options.output);
} }
var stream = UglifyJS.OutputStream(output); var stream = new Cola.OutputStream(output);
toplevel.print(stream); toplevel.print(stream);
return { return {
code : stream + "", code : stream + "",
@ -143,11 +146,11 @@ exports.minify = function(files, options) {
// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; // if (ctor.SUBCLASSES.length > 0) ret.sub = sub;
// return ret; // return ret;
// } // }
// return doitem(UglifyJS.AST_Node).sub; // return doitem(Cola.AST_Node).sub;
// } // }
exports.describe_ast = function() { exports.describe_ast = function() {
var out = UglifyJS.OutputStream({ beautify: true }); var out = new Cola.OutputStream({ beautify: true });
function doitem(ctor) { function doitem(ctor) {
out.print("AST_" + ctor.TYPE); out.print("AST_" + ctor.TYPE);
var props = ctor.SELF_PROPS.filter(function(prop){ var props = ctor.SELF_PROPS.filter(function(prop){
@ -177,6 +180,6 @@ exports.describe_ast = function() {
}); });
} }
}; };
doitem(UglifyJS.AST_Node); doitem(Cola.AST_Node);
return out + ""; return out + "";
}; };