1111 * @module cli/asc
1212 */
1313
14+ // Use "." instead of "/" as cwd in browsers
15+ if ( process . browser ) process . cwd = function ( ) { return "." ; } ;
16+
1417const fs = require ( "fs" ) ;
1518const path = require ( "path" ) ;
1619const utf8 = require ( "@protobufjs/utf8" ) ;
17- const colors = require ( "./util/colors" ) ;
20+ const colorsUtil = require ( "./util/colors" ) ;
21+ const optionsUtil = require ( "./util/options" ) ;
1822const EOL = process . platform === "win32" ? "\r\n" : "\n" ;
1923
2024// Use distribution files if present, otherwise run the sources directly
21- var assemblyscript , isDev ;
25+ var assemblyscript , isDev = false ;
2226( ( ) => {
2327 try {
2428 assemblyscript = require ( "../dist/assemblyscript.js" ) ;
25- isDev = false ;
2629 } catch ( e ) {
2730 try {
28- require ( "ts-node" ) . register ( {
29- project : path . join ( __dirname , ".." , "src" , "tsconfig.json" ) ,
30- files : [ // see: https://github.com/TypeStrong/ts-node/issues/620
31- path . join ( __dirname , ".." , "std" , "portable.d.ts" ) ,
32- path . join ( __dirname , ".." , "src" , "glue" , "binaryen.d.ts" )
33- ]
34- } ) ;
31+ require ( "ts-node" ) . register ( { project : path . join ( __dirname , ".." , "src" , "tsconfig.json" ) } ) ;
3532 require ( "../src/glue/js" ) ;
3633 assemblyscript = require ( "../src" ) ;
3734 isDev = true ;
3835 } catch ( e ) {
3936 // last resort: same directory CommonJS
4037 assemblyscript = eval ( "require('./assemblyscript')" ) ;
41- isDev = false ;
4238 }
4339 }
4440} ) ( ) ;
@@ -70,7 +66,7 @@ exports.defaultShrinkLevel = 1;
7066/** Bundled library files. */
7167exports . libraryFiles = exports . isBundle ? BUNDLE_LIBRARY : ( ( ) => { // set up if not a bundle
7268 const libDir = path . join ( __dirname , ".." , "std" , "assembly" ) ;
73- const libFiles = require ( "glob" ) . sync ( "**/* .ts" , { cwd : libDir } ) ;
69+ const libFiles = require ( "glob" ) . sync ( "**/!(*.d) .ts" , { cwd : libDir } ) ;
7470 const bundled = { } ;
7571 libFiles . forEach ( file => bundled [ file . replace ( / \. t s $ / , "" ) ] = fs . readFileSync ( path . join ( libDir , file ) , "utf8" ) ) ;
7672 return bundled ;
@@ -80,8 +76,8 @@ exports.libraryFiles = exports.isBundle ? BUNDLE_LIBRARY : (() => { // set up if
8076exports . definitionFiles = exports . isBundle ? BUNDLE_DEFINITIONS : ( ( ) => { // set up if not a bundle
8177 const stdDir = path . join ( __dirname , ".." , "std" ) ;
8278 return {
83- "assembly" : fs . readFileSync ( path . join ( stdDir , "assembly.d.ts" ) , "utf8" ) ,
84- "portable" : fs . readFileSync ( path . join ( stdDir , "portable.d.ts" ) , "utf8" )
79+ "assembly" : fs . readFileSync ( path . join ( stdDir , "assembly" , "index .d.ts") , "utf8" ) ,
80+ "portable" : fs . readFileSync ( path . join ( stdDir , "portable" , "index .d.ts") , "utf8" )
8581 } ;
8682} ) ( ) ;
8783
@@ -94,12 +90,16 @@ exports.compileString = (sources, options) => {
9490 binary : null ,
9591 text : null
9692 } ) ;
97- exports . main ( [
93+ var argv = [
9894 "--binaryFile" , "binary" ,
9995 "--textFile" , "text" ,
100- ...Object . keys ( options || { } ) . map ( arg => `--${ arg } =${ options [ arg ] } ` ) ,
101- ...Object . keys ( sources ) ,
102- ] , {
96+ ] ;
97+ Object . keys ( options || { } ) . forEach ( key => {
98+ var val = options [ key ] ;
99+ if ( Array . isArray ( val ) ) val . forEach ( val => argv . push ( "--" + key , String ( val ) ) ) ;
100+ else argv . push ( "--" + key , String ( val ) ) ;
101+ } ) ;
102+ exports . main ( argv . concat ( Object . keys ( sources ) ) , {
103103 stdout : output . stdout ,
104104 stderr : output . stderr ,
105105 readFile : name => sources . hasOwnProperty ( name ) ? sources [ name ] : null ,
@@ -129,22 +129,34 @@ exports.main = function main(argv, options, callback) {
129129 if ( ! stdout ) throw Error ( "'options.stdout' must be specified" ) ;
130130 if ( ! stderr ) throw Error ( "'options.stderr' must be specified" ) ;
131131
132- const args = parseArguments ( argv ) ;
133- const indent = 24 ;
134-
132+ const opts = optionsUtil . parse ( argv , exports . options ) ;
133+ const args = opts . options ;
134+ argv = opts . arguments ;
135135 if ( args . noColors ) {
136- colors . stdout . supported =
137- colors . stderr . supported = false ;
136+ colorsUtil . stdout . supported =
137+ colorsUtil . stderr . supported = false ;
138138 } else {
139- colors . stdout = colors . from ( stdout ) ;
140- colors . stderr = colors . from ( stderr ) ;
139+ colorsUtil . stdout = colorsUtil . from ( stdout ) ;
140+ colorsUtil . stderr = colorsUtil . from ( stderr ) ;
141+ }
142+
143+ // Check for unknown arguments
144+ if ( opts . unknown . length ) {
145+ opts . unknown . forEach ( arg => {
146+ stderr . write ( colorsUtil . stderr . yellow ( "WARN: " ) + "Unknown option '" + arg + "'" + EOL ) ;
147+ } ) ;
148+ }
149+
150+ // Check for trailing arguments
151+ if ( opts . trailing . length ) {
152+ stderr . write ( colorsUtil . stderr . yellow ( "WARN: " ) + "Unsupported trailing arguments: " + opts . trailing . join ( " " ) + EOL ) ;
141153 }
142154
143155 // Use default callback if none is provided
144156 if ( ! callback ) callback = function defaultCallback ( err ) {
145157 var code = 0 ;
146158 if ( err ) {
147- stderr . write ( colors . stderr . red ( "ERROR: " ) + err . stack . replace ( / ^ E R R O R : / i, "" ) + EOL ) ;
159+ stderr . write ( colorsUtil . stderr . red ( "ERROR: " ) + err . stack . replace ( / ^ E R R O R : / i, "" ) + EOL ) ;
148160 code = 1 ;
149161 }
150162 return code ;
@@ -156,43 +168,22 @@ exports.main = function main(argv, options, callback) {
156168 return callback ( null ) ;
157169 }
158170 // Print the help message if requested or no source files are provided
159- if ( args . help || args . _ . length < 1 ) {
160- const opts = [ ] ;
161- Object . keys ( exports . options ) . forEach ( name => {
162- var option = exports . options [ name ] ;
163- var text = " " ;
164- text += "--" + name ;
165- if ( option . aliases && option . aliases [ 0 ] . length === 1 ) {
166- text += ", -" + option . aliases [ 0 ] ;
167- }
168- while ( text . length < indent ) {
169- text += " " ;
170- }
171- if ( Array . isArray ( option . description ) ) {
172- opts . push ( text + option . description [ 0 ] + option . description . slice ( 1 ) . map ( line => {
173- for ( let i = 0 ; i < indent ; ++ i ) {
174- line = " " + line ;
175- }
176- return EOL + line ;
177- } ) . join ( "" ) ) ;
178- } else {
179- opts . push ( text + option . description ) ;
180- }
181- } ) ;
182-
171+ if ( args . help || ! argv . length ) {
183172 var out = args . help ? stdout : stderr ;
184- var color = args . help ? colors . stdout : colors . stderr ;
173+ var color = args . help ? colorsUtil . stdout : colorsUtil . stderr ;
185174 out . write ( [
186- color . white ( "Syntax " ) ,
175+ color . white ( "SYNTAX " ) ,
187176 " " + color . cyan ( "asc" ) + " [entryFile ...] [options]" ,
188177 "" ,
189- color . white ( "Examples " ) ,
178+ color . white ( "EXAMPLES " ) ,
190179 " " + color . cyan ( "asc" ) + " hello.ts" ,
191180 " " + color . cyan ( "asc" ) + " hello.ts -b hello.wasm -t hello.wat" ,
192181 " " + color . cyan ( "asc" ) + " hello1.ts hello2.ts -b -O > hello.wasm" ,
193182 "" ,
194- color . white ( "Options" ) ,
195- ] . concat ( opts ) . join ( EOL ) + EOL ) ;
183+ color . white ( "OPTIONS" ) ,
184+ ] . concat (
185+ optionsUtil . help ( exports . options , 24 , EOL )
186+ ) . join ( EOL ) + EOL ) ;
196187 return callback ( null ) ;
197188 }
198189
@@ -209,7 +200,6 @@ exports.main = function main(argv, options, callback) {
209200 // Set up transforms
210201 const transforms = [ ] ;
211202 if ( args . transform ) {
212- if ( typeof args . transform === "string" ) args . transform = args . transform . split ( "," ) ;
213203 args . transform . forEach ( transform =>
214204 transforms . push (
215205 require (
@@ -246,8 +236,9 @@ exports.main = function main(argv, options, callback) {
246236 }
247237 const customLibDirs = [ ] ;
248238 if ( args . lib ) {
249- if ( typeof args . lib === "string" ) args . lib = args . lib . split ( "," ) ;
250- Array . prototype . push . apply ( customLibDirs , args . lib . map ( lib => lib . trim ( ) ) ) ;
239+ let lib = args . lib ;
240+ if ( typeof lib === "string" ) lib = lib . split ( "," ) ;
241+ Array . prototype . push . apply ( customLibDirs , lib . map ( lib => lib . trim ( ) ) ) ;
251242 for ( let i = 0 , k = customLibDirs . length ; i < k ; ++ i ) { // custom
252243 let libDir = customLibDirs [ i ] ;
253244 let libFiles ;
@@ -275,10 +266,10 @@ exports.main = function main(argv, options, callback) {
275266 }
276267
277268 // Include entry files
278- for ( let i = 0 , k = args . _ . length ; i < k ; ++ i ) {
279- const filename = args . _ [ i ] ;
269+ for ( let i = 0 , k = argv . length ; i < k ; ++ i ) {
270+ const filename = argv [ i ] ;
280271
281- let sourcePath = filename . replace ( / \\ / g, "/" ) . replace ( / ( \. t s | \/ ) $ / , "" ) ;
272+ let sourcePath = String ( filename ) . replace ( / \\ / g, "/" ) . replace ( / ( \. t s | \/ ) $ / , "" ) ;
282273
283274 // Try entryPath.ts, then entryPath/index.ts
284275 let sourceText = readFile ( path . join ( baseDir , sourcePath ) + ".ts" ) ;
@@ -385,51 +376,28 @@ exports.main = function main(argv, options, callback) {
385376 const program = assemblyscript . finishParsing ( parser ) ;
386377
387378 // Set up optimization levels
388- var optimizeLevel = - 1 ;
379+ var optimizeLevel = 0 ;
389380 var shrinkLevel = 0 ;
390- var debugInfo = ! args . noDebug ;
391- if ( args . optimize !== false ) {
392- if ( typeof args . optimize === "number" ) {
393- optimizeLevel = args . optimize ;
394- } else if ( args [ "0" ] ) {
395- optimizeLevel = 0 ;
396- } else if ( args [ "1" ] ) {
397- optimizeLevel = 1 ;
398- } else if ( args [ "2" ] ) {
399- optimizeLevel = 2 ;
400- } else if ( args [ "3" ] ) {
401- optimizeLevel = 3 ;
402- } else if ( args . optimize === true ) {
403- optimizeLevel = exports . defaultOptimizeLevel ;
404- shrinkLevel = exports . defaultShrinkLevel ;
405- } else
406- optimizeLevel = 0 ;
407- }
408- if ( args [ "s" ] ) {
409- shrinkLevel = 1 ;
410- } else if ( args [ "z" ] ) {
411- shrinkLevel = 2 ;
381+ if ( args . optimize ) {
382+ optimizeLevel = exports . defaultOptimizeLevel ;
383+ shrinkLevel = exports . defaultShrinkLevel ;
412384 }
413385 if ( typeof args . optimizeLevel === "number" ) {
414386 optimizeLevel = args . optimizeLevel ;
415387 }
416388 if ( typeof args . shrinkLevel === "number" ) {
417389 shrinkLevel = args . shrinkLevel ;
418- } else if ( args . shrinkLevel === "s" ) {
419- shrinkLevel = 1 ;
420- } else if ( args . shrinkLevel === "z" ) {
421- shrinkLevel = 2 ;
422390 }
423- optimizeLevel = Math . max ( optimizeLevel , 0 ) ;
424- shrinkLevel = Math . max ( shrinkLevel , 0 ) ;
391+ optimizeLevel = Math . min ( Math . max ( optimizeLevel , 0 ) , 3 ) ;
392+ shrinkLevel = Math . min ( Math . max ( shrinkLevel , 0 ) , 2 ) ;
425393
426394 // Begin compilation
427395 const compilerOptions = assemblyscript . createOptions ( ) ;
428396 assemblyscript . setTarget ( compilerOptions , 0 ) ;
429- assemblyscript . setNoTreeShaking ( compilerOptions , ! ! args . noTreeShaking ) ;
430- assemblyscript . setNoAssert ( compilerOptions , ! ! args . noAssert ) ;
431- assemblyscript . setImportMemory ( compilerOptions , ! ! args . importMemory ) ;
432- assemblyscript . setImportTable ( compilerOptions , ! ! args . importTable ) ;
397+ assemblyscript . setNoTreeShaking ( compilerOptions , args . noTreeShaking ) ;
398+ assemblyscript . setNoAssert ( compilerOptions , args . noAssert ) ;
399+ assemblyscript . setImportMemory ( compilerOptions , args . importMemory ) ;
400+ assemblyscript . setImportTable ( compilerOptions , args . importTable ) ;
433401 assemblyscript . setMemoryBase ( compilerOptions , args . memoryBase >>> 0 ) ;
434402 assemblyscript . setSourceMap ( compilerOptions , args . sourceMap != null ) ;
435403 assemblyscript . setOptimizeLevelHints ( compilerOptions , optimizeLevel , shrinkLevel ) ;
@@ -515,7 +483,7 @@ exports.main = function main(argv, options, callback) {
515483
516484 module . setOptimizeLevel ( optimizeLevel ) ;
517485 module . setShrinkLevel ( shrinkLevel ) ;
518- module . setDebugInfo ( debugInfo ) ;
486+ module . setDebugInfo ( ! args . noDebug ) ;
519487
520488 var runPasses = [ ] ;
521489 if ( args . runPasses ) {
@@ -741,7 +709,7 @@ exports.main = function main(argv, options, callback) {
741709 var files ;
742710 try {
743711 stats . readTime += measure ( ( ) => {
744- files = require ( "glob" ) . sync ( "* .ts" , { cwd : dirname } ) ;
712+ files = require ( "glob" ) . sync ( "!(*.d) .ts" , { cwd : dirname } ) ;
745713 } ) ;
746714 return files ;
747715 } catch ( e ) {
@@ -764,25 +732,23 @@ exports.main = function main(argv, options, callback) {
764732 }
765733}
766734
767- /** Parses the specified command line arguments. */
768- function parseArguments ( argv ) {
769- const opts = { } ;
770- Object . keys ( exports . options ) . forEach ( key => {
771- const opt = exports . options [ key ] ;
772- if ( opt . aliases ) {
773- ( opts . alias || ( opts . alias = { } ) ) [ key ] = opt . aliases ;
774- }
775- if ( opt . default !== undefined ) {
776- ( opts . default || ( opts . default = { } ) ) [ key ] = opt . default ;
777- }
778- if ( opt . type === "string" ) {
779- ( opts . string || ( opts . string = [ ] ) ) . push ( key ) ;
780- } else if ( opt . type === "boolean" ) {
781- ( opts . boolean || ( opts . boolean = [ ] ) ) . push ( key ) ;
782- }
783- } ) ;
784- return require ( "minimist" ) ( argv , opts ) ;
785- }
735+ var argumentSubstitutions = {
736+ "-O" : [ "--optimize" ] ,
737+ "-Os" : [ "--optimize" , "--shrinkLevel" , "1" ] ,
738+ "-Oz" : [ "--optimize" , "--shrinkLevel" , "2" ] ,
739+ "-O0" : [ "--optimizeLevel" , "0" , "--shrinkLevel" , "0" ] ,
740+ "-O0s" : [ "--optimizeLevel" , "0" , "--shrinkLevel" , "1" ] ,
741+ "-O0z" : [ "--optimizeLevel" , "0" , "--shrinkLevel" , "2" ] ,
742+ "-O1" : [ "--optimizeLevel" , "1" , "--shrinkLevel" , "0" ] ,
743+ "-O1s" : [ "--optimizeLevel" , "1" , "--shrinkLevel" , "1" ] ,
744+ "-O1z" : [ "--optimizeLevel" , "1" , "--shrinkLevel" , "2" ] ,
745+ "-O2" : [ "--optimizeLevel" , "2" , "--shrinkLevel" , "0" ] ,
746+ "-O2s" : [ "--optimizeLevel" , "2" , "--shrinkLevel" , "1" ] ,
747+ "-O2z" : [ "--optimizeLevel" , "2" , "--shrinkLevel" , "2" ] ,
748+ "-O3" : [ "--optimizeLevel" , "3" , "--shrinkLevel" , "0" ] ,
749+ "-O3s" : [ "--optimizeLevel" , "3" , "--shrinkLevel" , "1" ] ,
750+ "-O3z" : [ "--optimizeLevel" , "3" , "--shrinkLevel" , "2" ] ,
751+ } ;
786752
787753/** Checks diagnostics emitted so far for errors. */
788754function checkDiagnostics ( emitter , stderr ) {
0 commit comments