Ticket #35: compDirOpts2.patch

File compDirOpts2.patch, 45.8 kB (added by hopscc, 3 months ago)
  • Source/Compiler.cobra

     
    5656 
    5757        var _globalNS as NameSpace 
    5858        var _modules as List<of Module> 
     59        var _parsedModules as List<of Module>? # accumulated as files parsed 
    5960        var _firstFileName as String? 
    6061 
    6162        var _curModule as Module?  # set during bindInt and bindImp 
    … …  
    232233                Related resources such as CobraLang.cs reside there. 
    233234                """ 
    234235                return Path.getDirectoryName(Assembly.getEntryAssembly.location) to !  # actually could be nil: if you stuck Cobra in the root dir, the .getDirectoryName docs say it will return nil 
    235  
     236                 
    236237        def compileFilesNamed(paths as IList<of String>) 
    237238                .compileFilesNamed(paths) 
    238239 
    … …  
    293294                .options = options 
    294295                bar = '----------------------------------------------------------------------------------------------------' 
    295296                .parseFilesNamed(fileNames) 
     297 
    296298                assert .modules.count 
    297299                if verbose 
    298300                        .dumpModulesForTestify(resultsWriter, 'Modules after parsing') 
    … …  
    326328                .printMessages 
    327329                print bar 
    328330 
     331        def     _addRuntimeRef(opts as Options) 
     332                if not opts.containsKey('reference') 
     333                        opts['reference'] = List<of String>() 
     334                refs = opts['reference'] to List<of String> 
     335                libName = 'Cobra.Lang.dll' 
     336                if libName not in refs 
     337                        if .verbosity, print 'Adding reference to [libName]' 
     338                        refs.add(libName) 
     339 
    329340        def parseFilesNamed(filenames as IList<of String>) as List<of Module> 
    330341                """ 
    331342                Returns the modules for the newly parsed files. 
    … …  
    341352                        embedRunTime = .options.boolValue('embed-run-time') 
    342353 
    343354                        if not embedRunTime 
    344                                 # then reference it 
    345                                 if not .options.containsKey('reference') 
    346                                         .options['reference'] = List<of String>() 
    347                                 refs = .options['reference'] to List<of String> 
    348                                 libName = 'Cobra.Lang.dll' 
    349                                 if libName not in refs 
    350                                         if .verbosity, print 'Adding reference to [libName]' 
    351                                         refs.add(libName) 
     355                                _addRuntimeRef(.options) # then reference runtime dll 
    352356 
    353357                        Node.setCompiler(this) 
    354358                        try 
    355359                                if _modules.count == 0  # attempt at caching modules during testify. incomplete. 
    356360                                        .writeSharpInfoClass 
    357361                                        .readSystemTypes 
    358                                         .readAssemblyTypes 
     362                                        .readAssemblyTypes(.options) 
    359363 
    360364                                if true # _modules.count == 0 
    361365                                        path = Path.combine(.cobraExeDir, 'CobraInfo.cs') 
    … …  
    376380                                                filenames.insert(3, path) 
    377381 
    378382                                modules = List<of Module>() 
     383                                _parsedModules = modules 
    379384                                for filename in filenames 
    380385                                        if filename.endsWith('.cs') 
    381386                                                if _verbosity 
    … …  
    404409                        else 
    405410                                assert modules.count 
    406411                                _modules.addRange(modules) 
     412                                _parsedModules = nil 
    407413                        return modules 
    408414 
     415        def augmentOptions(opts as Options) 
     416                """ 
     417                Update Options and accumulator lists generated from it with additional options settings. 
     418                  Used from inside parseFiles for args compilerDirective handling 
     419                """ 
     420                if .verbosity 
     421                        print 'preAugment Options Dictionary' 
     422                        .options.print 
     423 
     424                # special cases  
     425                _fixupLibRefs(opts) 
     426                _fixupEmbedRunTime(opts) # need this after fixup libs 
     427 
     428                .options.combineNew(opts) 
     429                v = .options.getDefault('verbosity', 0) to int 
     430                if v > _verbosity, _verbosity = v 
     431                if .verbosity 
     432                        print 'postAugment Options Dictionary' 
     433                        .options.print 
     434                         
     435 
     436        def _fixupEmbedRunTime(opts as Options) 
     437                #print 'before', _parsedModules 
     438                if opts.boolValue('embed-run-time') <> .options.boolValue('embed-run-time') 
     439                        if not opts.boolValue('embed-run-time') # changed True to false 
     440                                # remove parsed rtSrc modules 
     441                                rl = for m in _parsedModules where m.isCobraLibrary and not m.fileName.endsWith('.dll') 
     442                                for m in rl 
     443                                        _parsedModules.remove(m) 
     444                                _addRuntimeRef(opts)  # add ref to runtime dll 
     445                        else 
     446                                opts['embed-run-time'] = .options['embed-run-time'] 
     447                                #errchannel.throwError('Cannot switch -ert:no to -ert:yes in compilerDirective') 
     448                                # To support this need to determine where/what recorded for Cobra.dll  
     449                                # ref,clear it out and insert rtl src to be parsed AFTER finish current file 
     450                #print 'after fixup', _parsedModules 
     451                 
     452        def _fixupLibRefs(opts as Options) 
     453                haveRefs = false 
     454                for key in ['library-directory', 'pkg', 'reference'] 
     455                        if opts.containsKey(key) 
     456                                if key == 'reference' 
     457                                        references = opts.getDefaultLOStr('reference') 
     458                                        _fixupLibSuffix(references) 
     459                                if not .options.containsKey(key) 
     460                                        .options[key] = List<of String>() 
     461                                existList = .options[key] to List<of String> 
     462                                augList   = opts[key]  to List<of String> 
     463                                dupCount = 0 
     464                                for item in augList 
     465                                        if item not in existList 
     466                                                if .verbosity, print 'Adding [key] "[item]"' 
     467                                                existList.add(item) 
     468                                        else 
     469                                                if .verbosity, print '[key] "[item]" already in options.[key]' 
     470                                                dupCount += 1 # augList.remove(item)             
     471                                if not haveRefs 
     472                                        haveRefs = key <> 'library-directory' and augList.count - dupCount >0 
     473                                .options.didSpecify(key) # so not overwrite when combine 
     474                                                         
     475                if haveRefs 
     476                        .readAssemblyTypes(opts) 
     477                        if .verbosity > 1 
     478                                references = .options.getDefaultLOStr('reference') 
     479                                _printRefs(references) 
     480                 
     481                         
    409482        def runProcess as Process 
    410483                """ 
    411484                Returns a new Process with startInfo.fileName and p.startInfo.arguments set appropriately 
    … …  
    598671                t = System.Diagnostics.Process.getType 
    599672                .readAssembly(t.assembly) # System.dll 
    600673 
    601         def readAssemblyTypes 
    602                 references = .options.getDefault('reference', List<of String>()) to List<of String> 
    603  
    604                 # Excluding the extension can be problematic 
     674        def _fixupLibSuffix(references as List<of String>) 
    605675                i = 0 
    606676                for reference in List<of String>(references) 
    607677                        if not reference.endsWith('.dll') and not reference.endsWith('.exe') 
    608678                                reference += '.dll' 
    609679                                references[i] = reference 
    610680                        i += 1 
     681                         
     682        def _printRefs(references as List<of String>) 
     683                if references.count == 0 
     684                        print 'No additional assembly references.' 
     685                else 
     686                        print 'Final assembly reference list:' 
     687                        i = 0 
     688                        for refPath in references 
     689                                print '[i]. [refPath]' 
     690                                i += 1 
     691                         
     692        def readAssemblyTypes(options as Options) 
     693                references = options.getDefaultLOStr('reference') 
    611694 
     695                # Excluding the extension can be problematic 
     696                _fixupLibSuffix(references) 
     697 
    612698                # now that references are fixed, make a copy so that .options['references'] is not modified further 
    613699                references = List<of String>(references) 
    614700 
    615                 if .options.containsKey('pkg') 
    616                         for pkgName in .options['pkg'] to List<of String> 
     701                if options.containsKey('pkg') 
     702                        for pkgName in options['pkg'] to List<of String> 
    617703                                references.addRange(.refsForPackage(pkgName)) 
    618704 
    619                 if .verbosity > 1 
    620                         if references.count == 0 
    621                                 print 'No additional assembly references.' 
    622                         else 
    623                                 print 'Final assembly reference list:' 
    624                                 i = 0 
    625                                 for refPath in references 
    626                                         print '[i]. [refPath]' 
    627                                         i += 1 
     705                if .verbosity > 1  
     706                        _printRefs(references) 
    628707 
    629708                # Here be "reflectionOnlyLoad" code... which does not work on Mono 1.2.4 
    630709                # The run-time error message says: 
  • Source/CommandLine.cobra

     
    3232                # not the current Source directory. And Snapshot can be a final release such as '0.7.4' for a 
    3333                # period of time where this Cobra source represents an svn-post-RELEASE. 
    3434                return '0.8.0 post-release' 
    35  
    36         var _optionSpecs as List<of Dictionary<of String, Object>> 
    37  
     35                 
    3836        var _rawOptionSpecs = [ 
    3937                { 
    4038                        'name': 'about', 
    … …  
    201199                }, 
    202200                { 
    203201                        'name': 'reference', 
    204                         'synonyms': ['r'], 
     202                        'synonyms': ['r'], # TODO: lose 'r' ->'Ref', 'R', something else 
    205203                        'isAccumulator': true, 
    206204                        'description': 'Add a DLL reference.', 
    207205                        'args': 'Some.dll', 
    … …  
    220218#                       'args': ':Qualified.Type.Name', 
    221219#               }, 
    222220                { 
    223                         'name': 'run', 
     221                        'name': 'run',  # TODO: Synonym 'r' after change 'reference' switch 
    224222                        'description': 'Runs the Cobra program. This is the default behavior if specify any Cobra source files.', 
    225223                        'type': 'main', 
    226224                }, 
    … …  
    281279                        'type': 'main', 
    282280                }, 
    283281        ] 
     282                 
    284283 
    285284        var _startTime as DateTime 
    286285        var _verbosity = 0 
    … …  
    290289        var _htmlWriter as HtmlWriter? 
    291290 
    292291        var _compiler as Compiler? 
    293  
     292        var _argParser as ArgParser 
     293         
    294294        def init 
    295295                _startTime = DateTime.now 
    296                 # prep the option specs 
    297                 _optionSpecs = List<of Dictionary<of String, Object>>() 
    298                 for specObj in _rawOptionSpecs 
    299                         # since some _optionSpecs are Dictionary<of String, Object> and others are 
    300                         # Dictionary<of String, String> then _optionSpecs ends up being 
    301                         # Dictionary<of String, Object> 
     296                _argParser = ArgParser(.versionString, _rawOptionSpecs) 
    302297 
    303                         if specObj inherits Dictionary<of String, Object> 
    304                                 d = specObj 
    305                         else if specObj inherits Dictionary<of String, String> 
    306                                 d = Dictionary<of String, Object>() 
    307                                 for key in specObj.keys 
    308                                         d[key] = specObj[key] 
    309                         else 
    310                                 throw FallThroughException(specObj.getType) 
    311                         _optionSpecs.add(d) 
    312  
    313298        get compiler from var 
    314299 
    315300        get options from var 
    … …  
    324309        get verbosity as int 
    325310                return _verbosity 
    326311 
     312        def parseArgs(args as IList<of String>, options as out Options?, paths as out List<of String>?) 
     313                _argParser.parseArgs(args, out options, out paths) 
     314                _verbosity = _argParser.verbosity 
     315                CobraMain.willTimeIt = _argParser.willTimeIt 
     316                 
    327317        def run 
    328318                """ 
    329319                Run the command line using the command line arguments. 
    … …  
    339329                        .doAbout 
    340330                        return 
    341331                .parseArgs(args, out _options, out _pathList) 
     332         
    342333                if _options.boolValue('output-html') 
    343334                        _htmlWriter = HtmlWriter(Console.out) 
    344335                        dest = _htmlWriter to TextWriter 
    … …  
    389380                if _htmlWriter 
    390381                        _htmlWriter.writeHtml('</body></html>[_htmlWriter.newLine]') 
    391382 
    392         def isOptionSpecRestrictionViolated(optionSpec as Dictionary<of String, Object>) as bool 
    393                 """ 
    394                 Returns true if the option spec has a 'restriction' key and the check against that restriction is true. 
    395                 """ 
    396                 if optionSpec.containsKey('restriction') 
    397                         branch optionSpec['restriction'] to String 
    398                                 on 'mono-only' 
    399                                         return not CobraCore.isRunningOnMono 
    400                 return false 
    401  
    402         def parseArgs(args as IList<of String>, options as out Options?, paths as out List<of String>?) 
    403                 """ 
    404                 Parse command line arguments. 
    405                 The `args` should include only the arguments and not the executable/program name. 
    406                 """ 
    407                 ensure 
    408                         options 
    409                         paths 
    410                 body 
    411                         optionPrefix = '-' 
    412                         valuePrefix = c':' 
    413                         if not args.count 
    414                                 options = Options() 
    415                                 options.add('help', true) 
    416                                 paths = List<of String>() 
    417                                 return 
    418  
    419                         specDict = Dictionary<of String, Dictionary<of String, Object>>() 
    420                                 # ^ will contain keys for all spec names and their synonyms 
    421                         synToName = Dictionary<of String, String>() 
    422                                 # ^ maps synonyms to their full names 
    423                         synList = List<of String>() 
    424                         for d in _optionSpecs 
    425                                 if .isOptionSpecRestrictionViolated(d) 
    426                                         continue 
    427                                 specDict[d['name'] to String] = d 
    428                                 if d.containsKey('synonyms') 
    429                                         syns = d['synonyms'] to System.Collections.IList 
    430                                         for syn as String in syns 
    431                                                 assert not specDict.containsKey(syn) 
    432                                                 specDict[syn] = d 
    433                                                 synToName[syn] = d['name'] to String 
    434                                                 synList.add(syn) 
    435                                 if not d.containsKey('type') 
    436                                         d.add('type', 'string') 
    437  
    438                         # set up initial valueDict 
    439                         valueDict = Dictionary<of String, Object>() 
    440                         if Utils.isDevMachine 
    441                                 valueDict['reveal-internal-exceptions'] = true  # this is a specially computed default, but can still be overridden on the command line 
    442  
    443                         fileList = List<of String>() 
    444                         value = 'no-value' to dynamic 
    445                         mainOptions = List<of String>() 
    446                         didSpecify = Dictionary<of String, bool>()  # CC: could just be a Set 
    447                         for arg in args 
    448                                 if arg.trim.length == 0 
    449                                         continue 
    450                                 if arg.startsWith(optionPrefix) 
    451                                         isOption = true 
    452                                         while arg.startsWith(optionPrefix) 
    453                                                 arg = arg[1:] 
    454                                 else 
    455                                         isOption = false 
    456                                 if isOption 
    457                                         parts = arg.split(@[valuePrefix], 2) 
    458                                         if parts.length == 1 
    459                                                 name = parts[0] 
    460                                                 if name.endsWith('+') 
    461                                                         name = name[:-1] 
    462                                                         valueStr = 'on' 
    463                                                 else if name.endsWith('-') 
    464                                                         name = name[:-1] 
    465                                                         valueStr = 'off' 
    466                                                 else 
    467                                                         valueStr = 'on' 
    468                                         else 
    469                                                 assert parts.length == 2 
    470                                                 name = parts[0] 
    471                                                 valueStr = parts[1] 
    472                                         assert name.length, parts 
    473                                         name = Utils.getSS(synToName to passthrough, name, name) to ! 
    474                                         if not specDict.containsKey(name) 
    475                                                 msg = 'No such option "[name]".' 
    476                                                 if name.contains('=') 
    477                                                         msg += ' If you meant to specify an option value, use colon (:) instead of equals (=).' 
    478                                                 .error(msg) 
    479                                         spec = specDict[name] 
    480                                         if Utils.getSB(spec to passthrough, 'isAccumulator', false) 
    481                                                 # accumulators are always treated as strings. TODO: assert that 
    482                                                 if valueDict.containsKey(name) 
    483                                                         (valueDict[name] to System.Collections.IList).add(valueStr to passthrough) 
    484                                                 else 
    485                                                         valueDict[name] = [valueStr] 
    486                                                         didSpecify[name] = true 
    487                                         else 
    488                                                 cannotProcess = false 
    489                                                 if name=='debug' 
    490                                                         # special case 
    491                                                         if valueStr=='pdbonly' or valueStr=='full' 
    492                                                                 value = valueStr 
    493                                                         else 
    494                                                                 try 
    495                                                                         value = .boolForString(valueStr) 
    496                                                                 catch FormatException 
    497                                                                         cannotProcess = true 
    498                                                                 success 
    499                                                                         value = if(value, '+', '-') 
    500                                                 else 
    501                                                         if spec['type'] == 'main' 
    502                                                                 mainOptions.add(name) 
    503                                                                 value = true 
    504                                                         else 
    505                                                                 possible = .interpretValue(valueStr, spec) 
    506                                                                 if possible is not nil 
    507                                                                         value = possible 
    508                                                                 else 
    509                                                                         cannotProcess = true 
    510                                                 if cannotProcess 
    511                                                         .error('Cannot process value "[valueStr]" for option "[name]".') 
    512                                                 valueDict[name] = value 
    513                                                 didSpecify[name] = true 
    514                                 else # not isOption 
    515                                         if File.exists(arg) 
    516                                                 fileList.add(arg) 
    517                                         else if File.exists(arg+'.cobra') 
    518                                                 fileList.add(arg+'.cobra') 
    519                                         else if Directory.exists(arg) 
    520                                                 fileList.add(arg) 
    521                                         else 
    522                                                 msg = 'Cannot find "[arg]" as a file.' 
    523                                                 if arg.startsWith('/') 
    524                                                         msg += ' If you meant to specify an option, use dash (-) instead of slash (/).' 
    525                                                 .error(msg) 
    526  
    527                         # handle synonyms 
    528                         for syn in synList 
    529                                 if valueDict.containsKey(syn) 
    530                                         valueDict[synToName[syn]] = valueDict[syn] 
    531                                         valueDict.remove(syn) 
    532  
    533                         # add in defaults 
    534                         for d in _optionSpecs 
    535                                 defaultName = d['name'] to String 
    536                                 if not valueDict.containsKey(defaultName) and d.containsKey('default') 
    537                                         defaultValue = .interpretValue(d['default'] to String, d) to ! 
    538                                         if .verbosity 
    539                                                 print 'Setting option "[defaultName]" to default value [defaultValue].' 
    540                                         valueDict[defaultName] = defaultValue 
    541  
    542                         # TODO: make the option names case-insensitive 
    543  
    544                         # check for more than one main option 
    545                         if mainOptions.count > 1 
    546                                 .error('Cannot have these main options at the same time: [Utils.join(", ", mainOptions)]') 
    547  
    548                         # unpack certain options into specific class fields 
    549                         if valueDict.containsKey('verbosity') 
    550                                 _verbosity = valueDict['verbosity'] to int 
    551                         if not valueDict.containsKey('timeit') and valueDict.containsKey('testify') 
    552                                 valueDict['timeit'] = true 
    553                         if valueDict.containsKey('timeit') 
    554                                 CobraMain.willTimeIt = valueDict['timeit'] to bool 
    555                         if valueDict.containsKey('files') 
    556                                 for fileName as String in valueDict['files'] to System.Collections.IList 
    557                                         try 
    558                                                 for line in File.readAllLines(fileName) 
    559                                                         line = line.trim 
    560                                                         if line.length==0 or line.startsWith('#') 
    561                                                                 continue 
    562                                                         # TODO: dup'ed above 
    563                                                         arg = line 
    564                                                         if File.exists(arg) 
    565                                                                 fileList.add(arg) 
    566                                                         else if File.exists(arg+'.cobra') 
    567                                                                 fileList.add(arg+'.cobra') 
    568                                                         else if Directory.exists(arg) 
    569                                                                 fileList.add(arg) 
    570                                                         else 
    571                                                                 msg = 'Cannot find "[arg]" as a file.' 
    572                                                                 #if arg.startsWith('/') 
    573                                                                 #       msg += ' If you meant to specify an option, use dash (-) instead of slash (/).' 
    574                                                                 .error(msg) 
    575                                                         # end dup 
    576                                         catch IOException 
    577                                                 .error('Cannot open file "[fileName]".') 
    578  
    579                         # set the out parameters 
    580                         options = Options(valueDict) 
    581                         for name in didSpecify.keys 
    582                                 options.didSpecify(name) 
    583                         paths = fileList 
    584  
    585                         .computeArgImplications(options to !) 
    586  
    587  
    588         def computeArgImplications(options as Options) 
    589                 if options.getDefault('target', '') == 'lib' and not options.isSpecified('compile') 
    590                         options['compile'] = true 
    591                 if options.getDefault('debug', '') not in ['', '0', '-'] and not options.isSpecified('debugging-tips') 
    592                         options['debugging-tips'] = false 
    593                 if options.boolValue('turbo') 
    594                         options['contracts'] = 'none' 
    595                         options['include-asserts'] = false 
    596                         options['include-nil-checks'] = false 
    597                         options['include-tests'] = false 
    598                         options['optimize'] = true 
    599  
    600         def interpretValue(valueStr as String, spec as Dictionary<of String, Object>) as dynamic? 
    601                 value as dynamic? 
    602                 branch spec['type'] to String 
    603                         on 'main' 
    604                                 throw InvalidOperationException('This method does not handle the main type.') 
    605                         on 'bool' 
    606                                 try 
    607                                         value = .boolForString(valueStr) 
    608                                 catch FormatException 
    609                                         cannotProcess = true 
    610Â