Wiki

Ticket #35: compDirArgOpts.patch

File compDirArgOpts.patch, 50.3 KB (added by hopscc, 16 years ago)
  • Source/Compiler.cobra

     
    5555 
    5656    var _globalNS as NameSpace 
    5757    var _modules as List<of Module> 
     58    var _parsedModules as List<of Module>? # accumulated as files parsed 
    5859    var _firstFileName as String? 
    5960 
    6061    var _curModule as Module?  # set during bindInt and bindImp 
     
    224225        Related resources such as CobraLang.cs reside there. 
    225226        """ 
    226227        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 
    227  
     228         
    228229    def compileFilesNamed(paths as IList<of String>) 
    229230        .compileFilesNamed(paths) 
    230231 
     
    285286        .options = options 
    286287        bar = '----------------------------------------------------------------------------------------------------' 
    287288        .parseFilesNamed(fileNames) 
     289 
    288290        assert .modules.count 
    289291        if verbose 
    290292            .dumpModulesForTestify(resultsWriter, 'Modules after parsing') 
     
    318320        .printMessages 
    319321        print bar 
    320322 
     323    def _addRuntimeRef(opts as Options) 
     324        if not opts.containsKey('reference') 
     325            opts['reference'] = List<of String>() 
     326        refs = opts['reference'] to List<of String> 
     327        libName = 'Cobra.Lang.dll' 
     328        if libName not in refs 
     329            if .verbosity, print 'Adding reference to [libName]' 
     330            refs.add(libName) 
     331 
    321332    def parseFilesNamed(filenames as IList<of String>) as List<of Module> 
    322333        """ 
    323334        Returns the modules for the newly parsed files. 
     
    333344            embedRunTime = .options.boolValue('embed-run-time') 
    334345 
    335346            if not embedRunTime 
    336                 # then reference it 
    337                 if not .options.containsKey('reference') 
    338                     .options['reference'] = List<of String>() 
    339                 refs = .options['reference'] to List<of String> 
    340                 libName = 'Cobra.Lang.dll' 
    341                 if libName not in refs 
    342                     if .verbosity, print 'Adding reference to [libName]' 
    343                     refs.add(libName) 
     347                _addRuntimeRef(.options) # then reference runtime dll 
    344348 
    345349            Node.setCompiler(this) 
    346350            try 
    347351                if _modules.count == 0  # attempt at caching modules during testify. incomplete. 
    348352                    .writeSharpInfoClass 
    349353                    .readSystemTypes 
    350                     .readAssemblyTypes 
     354                    .readAssemblyTypes(.options) 
    351355 
    352356                if true # _modules.count == 0 
    353357                    path = Path.combine(.cobraExeDir, 'CobraInfo.cs') 
     
    368372                        filenames.insert(3, path) 
    369373 
    370374                modules = List<of Module>() 
     375                _parsedModules = modules 
    371376                for filename in filenames 
    372377                    if filename.endsWith('.cs') 
    373378                        if _verbosity 
     
    396401            else 
    397402                assert modules.count 
    398403                _modules.addRange(modules) 
     404                _parsedModules = nil 
    399405            return modules 
    400406 
     407    def augmentOptions(opts as Options) 
     408        """ 
     409        Update Options and accumulator lists generated from it with additional options settings. 
     410          Used from inside parseFiles for args compilerDirective handling 
     411        """ 
     412        if .verbosity 
     413            print 'preAugment Options Dictionary' 
     414            .options.print 
     415 
     416        # special cases  
     417        _fixupLibRefs(opts) 
     418        _fixupEmbedRunTime(opts) # need this after fixup libs 
     419 
     420        .options.combineNew(opts) 
     421        v = .options.getDefault('verbosity', 0) to int 
     422        if v > _verbosity, _verbosity = v 
     423        if .verbosity 
     424            print 'postAugment Options Dictionary' 
     425            .options.print 
     426             
     427 
     428    def _fixupEmbedRunTime(opts as Options) 
     429        #print 'before', _parsedModules 
     430        if opts.boolValue('embed-run-time') <> .options.boolValue('embed-run-time') 
     431            if not opts.boolValue('embed-run-time') # changed True to false 
     432                # remove parsed rtSrc modules 
     433                rl = for m in _parsedModules where m.isCobraLibrary and not m.fileName.endsWith('.dll') 
     434                for m in rl 
     435                    _parsedModules.remove(m) 
     436                _addRuntimeRef(opts)  # add ref to runtime dll 
     437            else 
     438                opts['embed-run-time'] = .options['embed-run-time'] 
     439                #errchannel.throwError('Cannot switch -ert:no to -ert:yes in compilerDirective') 
     440                # To support this need to determine where/what recorded for Cobra.dll  
     441                # ref,clear it out and insert rtl src to be parsed AFTER finish current file 
     442        #print 'after fixup', _parsedModules 
     443         
     444    def _fixupLibRefs(opts as Options) 
     445        haveRefs = false 
     446        for key in ['library-directory', 'pkg', 'reference'] 
     447            if opts.containsKey(key) 
     448                if key == 'reference' 
     449                    references = opts.getDefaultLOStr('reference') 
     450                    _fixupLibSuffix(references) 
     451                if not .options.containsKey(key) 
     452                    .options[key] = List<of String>() 
     453                existList = .options[key] to List<of String> 
     454                augList   = opts[key]  to List<of String> 
     455                dupCount = 0 
     456                for item in augList 
     457                    if item not in existList 
     458                        if .verbosity, print 'Adding [key] "[item]"' 
     459                        existList.add(item) 
     460                    else 
     461                        if .verbosity, print '[key] "[item]" already in options.[key]' 
     462                        dupCount += 1 # augList.remove(item)         
     463                if not haveRefs 
     464                    haveRefs = key <> 'library-directory' and augList.count - dupCount >0 
     465                .options.didSpecify(key) # so not overwrite when combine 
     466                             
     467        if haveRefs 
     468            .readAssemblyTypes(opts) 
     469            if .verbosity > 1 
     470                references = .options.getDefaultLOStr('reference') 
     471                _printRefs(references) 
     472         
     473             
    401474    def runProcess as Process 
    402475        """ 
    403476        Returns a new Process with startInfo.fileName and p.startInfo.arguments set appropriately 
     
    587660        t = System.Diagnostics.Process.getType 
    588661        .readAssembly(t.assembly) # System.dll 
    589662 
    590     def readAssemblyTypes 
    591         references = .options.getDefault('reference', List<of String>()) to List<of String> 
    592  
    593         # Excluding the extension can be problematic 
     663    def _fixupLibSuffix(references as List<of String>) 
    594664        i = 0 
    595665        for reference in List<of String>(references) 
    596666            if not reference.endsWith('.dll') and not reference.endsWith('.exe') 
    597667                reference += '.dll' 
    598668                references[i] = reference 
    599669            i += 1 
     670             
     671    def _printRefs(references as List<of String>) 
     672        if references.count == 0 
     673            print 'No additional assembly references.' 
     674        else 
     675            print 'Final assembly reference list:' 
     676            i = 0 
     677            for refPath in references 
     678                print '[i]. [refPath]' 
     679                i += 1 
     680             
     681    def readAssemblyTypes(options as Options) 
     682        references = options.getDefaultLOStr('reference') 
    600683 
     684        # Excluding the extension can be problematic 
     685        _fixupLibSuffix(references) 
     686 
    601687        # now that references are fixed, make a copy so that .options['references'] is not modified further 
    602688        references = List<of String>(references) 
    603689 
    604         if .options.containsKey('pkg') 
    605             for pkgName in .options['pkg'] to List<of String> 
     690        if options.containsKey('pkg') 
     691            for pkgName in options['pkg'] to List<of String> 
    606692                references.addRange(.refsForPackage(pkgName)) 
    607693 
    608         if .verbosity > 1 
    609             if references.count == 0 
    610                 print 'No additional assembly references.' 
    611             else 
    612                 print 'Final assembly reference list:' 
    613                 i = 0 
    614                 for refPath in references 
    615                     print '[i]. [refPath]' 
    616                     i += 1 
     694        if .verbosity > 1  
     695            _printRefs(references) 
    617696 
    618697        # Here be "reflectionOnlyLoad" code... which does not work on Mono 1.2.4 
    619698        # The run-time error message says: 
     
    634713        # $sharp('curDomain.ReflectionOnlyAssemblyResolve += _resolveEvent') 
    635714 
    636715        for reference in references 
    637             if .verbosity > 0 
    638                 print 'Loading reference:', reference 
    639             if false 
    640                 # Does not work on Novell Mono. See notes above. 
    641                 referredAss = Assembly.reflectionOnlyLoadFrom(reference) 
    642                 # TODO: handle all the exceptions from Assembly.loadFrom 
     716            _loadAssemblyForRef(reference) 
     717 
     718    def _loadAssemblyForRef(reference as String) 
     719        if .verbosity > 0 
     720            print 'Loading reference:', reference 
     721        if false 
     722            # Does not work on Novell Mono. See notes above. 
     723            referredAss = Assembly.reflectionOnlyLoadFrom(reference) 
     724            # TODO: handle all the exceptions from Assembly.loadFrom 
     725        else 
     726            if File.exists(reference) 
     727                # try current directory 
     728                referredAss = Assembly.loadFrom(reference) 
    643729            else 
    644                 if File.exists(reference) 
    645                     # try current directory 
    646                     referredAss = Assembly.loadFrom(reference) 
    647                 else 
    648                     # TODO: the problem with -lib: in both Cobra and C# is that it has no effect on runtime, 
    649                     # you must still register the DLLs in the GAC or copy them into the same dir as the .exe 
    650                     # because the -lib: paths are not passed into executable. 
    651                     # So should Cobra copy the .dll's into the target directory (if their paths are not in MONO_PATH)? 
    652                     searchPaths = .options.getDefault('library-directory', List<of String>()) to List<of String> 
    653                     # TODO: ?: searchPaths.add(Path.getDirectoryName(Assembly.getExecutingAssembly.location))  # try Cobra's directory - also should be added to .options.'library-directory' not to a local var 
    654                     found = false 
    655                     for searchPath in searchPaths 
    656                         combinedPath = Path.combine(searchPath, reference) 
    657                         if File.exists(combinedPath) 
    658                             referredAss = Assembly.loadFrom(combinedPath) 
    659                             found = true 
    660                             break 
    661                     if not found 
    662                         # try system wide (GAC) 
    663                         if reference.endsWith('.dll') 
    664                             reference = reference[:-4] 
    665                         referredAss = Utils.loadWithPartialName(reference) 
    666                 # TODO: handle all the exceptions from Assembly.loadFrom 
    667             if referredAss 
    668                 .readAssembly(referredAss, reference <> 'Cobra.Lang.dll') 
    669             else 
    670                 _addMessage(SourceException('Cannot locate assembly reference "[reference]".')) 
    671             i += 1 
    672  
     730                # TODO: the problem with -lib: in both Cobra and C# is that it has no effect on runtime, 
     731                # you must still register the DLLs in the GAC or copy them into the same dir as the .exe 
     732                # because the -lib: paths are not passed into executable. 
     733                # So should Cobra copy the .dll's into the target directory (if their paths are not in MONO_PATH)? 
     734                searchPaths = .options.getDefaultLOStr('library-directory') 
     735                # TODO: ?: searchPaths.add(Path.getDirectoryName(Assembly.getExecutingAssembly.location))  # try Cobra's directory - also should be added to .options.'library-directory' not to a local var 
     736                found = false 
     737                for searchPath in searchPaths 
     738                    combinedPath = Path.combine(searchPath, reference) 
     739                    if File.exists(combinedPath) 
     740                        referredAss = Assembly.loadFrom(combinedPath) 
     741                        found = true 
     742                        break 
     743                if not found 
     744                    # try system wide (GAC) 
     745                    if reference.endsWith('.dll') 
     746                        reference = reference[:-4] 
     747                    referredAss = Utils.loadWithPartialName(reference) 
     748            # TODO: handle all the exceptions from Assembly.loadFrom 
     749        if referredAss 
     750            .readAssembly(referredAss, reference <> 'Cobra.Lang.dll') 
     751        else 
     752            _addMessage(SourceException('Cannot locate assembly reference "[reference]".')) 
     753                 
    673754    def refsForPackage(pkgName as String) as List<of String> 
    674755        """ 
    675756        Returns the library/DLL refs for the give package name. 
     
    14141495            if optimize 
    14151496                backEndOptions += ' [optChar]optimize+' 
    14161497 
    1417             thing = options.getDefault('reference', List<of String>()) to List<of String> 
     1498            thing = options.getDefaultLOStr('reference') 
    14181499            for refer in thing 
    14191500                backEndOptions += ' "[optChar]r:[refer]"' 
    14201501 
     
    14481529                    sharpArgs = sharpArgs[1:-1] 
    14491530                backEndOptions += ' ' + sharpArgs 
    14501531 
    1451             for libPath in .options.getDefault('library-directory', []) 
     1532            for libPath in .options.getDefaultLOStr('library-directory') 
    14521533                backEndOptions += ' ' + '-lib:"[libPath]"' 
    14531534 
    1454             for pkgName in .options.getDefault('pkg', []) 
     1535            for pkgName in .options.getDefaultLOStr('pkg') 
    14551536                backEndOptions += ' ' + '-pkg:[pkgName]' 
    14561537 
    14571538            # .cs files 
     
    14821563                cp.generateExecutable = options.getDefault('target', 'exe') in ['exe', 'winexe'] 
    14831564                cp.outputAssembly = _fullExeFileName 
    14841565                cp.compilerOptions = backEndOptions 
     1566                if _verbosity > 2 
     1567                    print 'CodeProvider [backEndOptions] [cp.referencedAssemblies]' 
    14851568                #trace backEndOptions 
    14861569                #trace sharpFileNameList 
    14871570                cr = provider.compileAssemblyFromFile(cp, sharpFileNameList.toArray) 
  • 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             on 'int' 
    611                 if valueStr == 'on'  # set internally when there is no value 
    612                     valueStr = '1' 
    613                 try 
    614                     value = int.parse(valueStr) 
    615                 catch FormatException 
    616                     cannotProcess = true 
    617                 catch OverflowException 
    618                     cannotProcess = true 
    619                 # TODO: check min and max 
    620             on 'string' 
    621                 value = valueStr 
    622             on 'menu' 
    623                 if valueStr.length==0 
    624                     cannotProcess = true 
    625                 if not (spec['choices'] to System.Collections.IList).contains(valueStr) 
    626                     cannotProcess = true 
    627                 else 
    628                     value = valueStr 
    629         r = if(cannotProcess, nil, value) 
    630         return r 
    631  
    632383    def doCompile(paths as List<of String>) as Compiler 
    633384        return .doCompile(paths, true, false, false) 
    634385 
    635     def doCompile(paths as List<of String>, willPrintSuccessMsg as bool, writeTestInvocation as bool, stopAfterBindInt as bool) as Compiler 
     386    def doCompile(paths as List<of String>, willPrintSuccessMsg as bool,  
     387            writeTestInvocation as bool, stopAfterBindInt as bool) as Compiler 
    636388        oldPaths = List<of String>(paths) 
    637389        paths.clear 
    638390        for path in oldPaths 
     
    650402        c.htmlWriter = _htmlWriter 
    651403        try 
    652404            c.compileFilesNamed(paths, writeTestInvocation, stopAfterBindInt) 
     405            if _verbosity <> c.verbosity, _verbosity = c.verbosity 
    653406        catch StopCompilation 
    654407            # Each phase of the compiler may throw an exception to stop compilation. 
    655408            # Before doing so, it prints its errors. 
     
    728481        c = .doCompile(paths, false, false, false) 
    729482        if c.errors.count 
    730483            print 'Not running due to errors above.' 
     484            return 
     485        if .options.boolValue('compile')  # Maybe changed by compiler directive 
     486            return 
     487 
     488        p = c.runProcess 
     489        if _verbosity >= 1 
     490            print 'Running: [p.startInfo.fileName] [p.startInfo.arguments]' 
     491            print .verboseLineSeparator 
     492        p.startInfo.useShellExecute = false 
     493        p.start 
     494        p.waitForExit  # TODO: is this necessary? 
     495 
     496    def doHelp 
     497        _argParser.doHelp   # CC: multiline string 
     498 
     499    def doAbout 
     500        _argParser.doAbout 
     501 
     502    def doVersion 
     503        print .versionString 
     504 
     505    def error(msg as String) 
     506        if msg.length 
     507            print 'cobra: error: [msg]' 
     508            print 'Run Cobra without options to get full usage information.' 
     509        Environment.exit(1) 
     510 
     511 
     512    ## Build Standard Library 
     513 
     514    def doBuildStandardLibrary 
     515        v = .verbosity 
     516        if v 
     517            print 'Building standard library' 
     518        dllInfo = FileInfo('Cobra.Lang.dll') 
     519        if dllInfo.exists 
     520            if v 
     521                print 'Renaming Cobra.Lang.dll to Cobra.Lang-previous.dll' 
     522            prevInfo = FileInfo('Cobra.Lang-previous.dll') 
     523            if prevInfo.exists 
     524                prevInfo.delete 
     525            FileInfo('Cobra.Lang.dll').moveTo('Cobra.Lang-previous.dll') 
     526        _options['target'] = 'lib' 
     527        _options['include-tests'] = false  # TODO: including tests in a DLL tends to cause problems. it might be because tests are triggered by type initializers. this needs investigation 
     528        _options['embed-run-time'] = true  # because the runtime is what we're building! 
     529        .doCompile(List<of String>(), true, false, false) 
     530 
     531 
     532    ## Testify 
     533 
     534    def doTestify(paths as List<of String>) 
     535        """ 
     536        Used internally for testing cobra during development. 
     537        Why not just 'test'? because that is reserved for regular developers to run true unit tests. 
     538        """ 
     539        TestifyRunner(_startTime, this, paths).run 
     540         
     541     
     542 
     543class ArgParser 
     544    """ 
     545    Class for handling parsing of cmdline string arguments into a set of recognised  
     546    Options and a list of paths. 
     547    Provides documentation display (help, about) printed output as well 
     548    """ 
     549    var _self as ArgParser? is shared 
     550    var _versionString as String 
     551    var _verbosity = 0 
     552    var _willTimeIt = false 
     553    var _optsOnly = false 
     554     
     555    get versionString from var 
     556    get verbosity from var 
     557    get willTimeIt from var 
     558 
     559    var _optionSpecs as List<of Dictionary<of String, Object>> 
     560 
     561    var _specDict as Dictionary<of String, Dictionary<of String, Object>> 
     562    #   ^ will contain keys for all spec names and their synonyms 
     563    var _synToName as Dictionary<of String, String> 
     564    #   ^ maps synonyms to their full names 
     565    var _synList as List<of String> 
     566 
     567    def init(version as String, rawOptionSpecs) 
     568        _versionString = version 
     569        # prep the option specs 
     570        _optionSpecs = List<of Dictionary<of String, Object>>() 
     571        for specObj in rawOptionSpecs 
     572            # since some _optionSpecs are Dictionary<of String, Object> and others are 
     573            # Dictionary<of String, String> then _optionSpecs ends up being 
     574            # Dictionary<of String, Object> 
     575 
     576            if specObj inherits Dictionary<of String, Object> 
     577                d = specObj 
     578            else if specObj inherits Dictionary<of String, String> 
     579                d = Dictionary<of String, Object>() 
     580                for key in specObj.keys 
     581                    d[key] = specObj[key] 
     582            else 
     583                throw FallThroughException(specObj.getType) 
     584            _optionSpecs.add(d) 
     585 
     586        _specDict = Dictionary<of String, Dictionary<of String, Object>>() 
     587        _synToName = Dictionary<of String, String>() 
     588        _synList = List<of String>() 
     589        _initSynonyms 
     590        _self = this 
     591         
     592    def parseToOptions(args as IList<of String>) as Options is shared 
     593        """ 
     594        Reuse ArgParser to parse some additional string option args. Files are not allowed  
     595        Can be used only after ArgParser has already been constructed providing OptionSpecs 
     596        Return new set of Options from given args list 
     597        """ 
     598        assert _self , 'ArgParser.init must have been called sometime before using ArgParse.parseToOptions()' 
     599        opts = Options() 
     600        paths = List<of String>() 
     601        #TODO: mark which opts as unusable in this context and filter out 
     602        _self._optsOnly = true 
     603        _self.parseArgs(args, out opts, out paths) 
     604        if _self.verbosity or opts.getDefault('verbosity', 0) to int 
     605            print 'parseToOptions Option Dictionary:' 
     606            opts.print 
     607        return opts 
     608         
     609    def parseArgs(args as IList<of String>, options as out Options?, paths as out List<of String>?) 
     610        """ 
     611        Parse command line arguments: options and files. 
     612        The `args` should include only the arguments and not the executable/program name. 
     613        """ 
     614        _optsOnly = false 
     615        _parseArgs(args, out options, out paths) 
     616         
     617    def _parseArgs(args as IList<of String>, options as out Options?, paths as out List<of String>?) 
     618        ensure 
     619            options 
     620            paths 
     621        body 
     622            optionPrefix = '-' 
     623            if not args.count 
     624                options = Options() 
     625                options.add('help', true) 
     626                paths = List<of String>() 
     627                return 
     628 
     629            # set up initial valueDict 
     630            valueDict = Dictionary<of String, Object>() 
     631            didSpecify = Dictionary<of String, bool>()  # CC: could just be a Set 
     632            if Utils.isDevMachine 
     633                valueDict['reveal-internal-exceptions'] = true  # this is a specially computed default, but can still be overridden on the command line 
     634 
     635            valueStr = 'no-value' 
     636            fileList = List<of String>() 
     637            mainOptions = List<of String>() 
     638            for arg in args 
     639                if not arg.trim.length 
     640                    continue 
     641                     
     642                isOption = arg.startsWith(optionPrefix) 
     643                if isOption 
     644                    name = _getOptionParts(arg, optionPrefix, out valueStr) 
     645                    spec = _specDict[name] 
     646 
     647                    if _isAccumulatorOpt(spec) 
     648                        _accumulateOptValue(name, valueStr, valueDict, didSpecify) 
     649                        continue 
     650                         
     651                    value = _processToValue(name, valueStr, spec, mainOptions) 
     652                    if value is nil 
     653                        _error('Cannot process value "[valueStr]" for option "[name]".') 
     654                    valueDict[name] = value to ! 
     655                    didSpecify[name] = true 
     656                else # not isOption 
     657                    if _optsOnly 
     658                        _error("Filenames are not allowed here, All the args provided must be '-' prefixed options") 
     659                    if arg.startsWith('/') 
     660                        errHint = ' If you meant to specify an option, use dash (-) instead of slash (/).' 
     661                    _processAsFile(arg, fileList, errHint) 
     662 
     663            _handleSynonyms(valueDict)           
     664            _addInDefaults(valueDict)        
     665 
     666            # TODO: make the option names case-insensitive 
     667 
     668            if mainOptions.count > 1 
     669                _error('Cannot have these main options at the same time: [Utils.join(", ", mainOptions)]') 
     670 
     671            _unpackOptions(valueDict, fileList)  
     672 
     673            # set the out parameters 
     674            options = Options(valueDict) 
     675            options.setSpecified(didSpecify) 
     676            paths = fileList 
     677            _computeArgImplications(options to !) 
     678         
     679    def _getOptionParts(arg as String,  
     680                optionPrefix as String, 
     681                valueStr as out String) as String 
     682        arg = .fixOptionArg(arg, optionPrefix)   
     683        # name, valueStr = .splitOpt(arg) 
     684        l   = .splitOpt(arg)  
     685        name     = l[0] 
     686        valueStr = l[1] 
     687        name = .validateOptionName(name) 
     688        return name          
     689         
     690             
     691    def fixOptionArg(arg as String, optionPrefix as String) as String    
     692        """ 
     693        Strip any leading switch chars                                                                                              ing optionPrefix and adjust remaining option 
     694        """ 
     695        while arg.startsWith(optionPrefix) 
     696            arg = arg[1:] 
     697        return arg 
     698                 
     699    def  splitOpt(arg as String) as IList<of String> 
     700        """ 
     701        Split option into name and valueStr 
     702        """ 
     703        valuePrefix = c':' 
     704        parts = arg.split(@[valuePrefix], 2) 
     705        if parts.length == 1 
     706            name = parts[0] 
     707            if name.endsWith('+') 
     708                name = name[:-1] 
     709                valueStr = 'on' 
     710            else if name.endsWith('-') 
     711                name = name[:-1] 
     712                valueStr = 'off' 
     713            else 
     714                valueStr = 'on' 
    731715        else 
    732             p = c.runProcess 
    733             if _verbosity >= 1 
    734                 print 'Running: [p.startInfo.fileName] [p.startInfo.arguments]' 
    735                 print .verboseLineSeparator 
    736             p.startInfo.useShellExecute = false 
    737             p.start 
    738             p.waitForExit  # TODO: is this necessary? 
     716            assert parts.length == 2 
     717            name = parts[0] 
     718            valueStr = parts[1] 
     719        assert parts, name.length  
     720        assert valueStr.length 
     721        return [name, valueStr]  
     722         
     723    def isOptionSpecRestrictionViolated(optionSpec as Dictionary<of String, Object>) as bool 
     724        """ 
     725        Returns true if the option spec has a 'restriction' key and the check against that restriction is true. 
     726        """ 
     727        if optionSpec.containsKey('restriction') 
     728            branch optionSpec['restriction'] to String 
     729                on 'mono-only' 
     730                    return not CobraCore.isRunningOnMono 
     731        return false 
     732             
     733    def _initSynonyms 
     734        """ 
     735        Init supporting data structures for handling option synonyms         
     736        """      
     737        for d in _optionSpecs 
     738            if .isOptionSpecRestrictionViolated(d) 
     739                continue 
     740            _specDict[d['name'] to String] = d 
     741            if d.containsKey('synonyms') 
     742                syns = d['synonyms'] to System.Collections.IList 
     743                for syn as String in syns 
     744                    assert not _specDict.containsKey(syn) 
     745                    _specDict[syn] = d 
     746                    _synToName[syn] = d['name'] to String 
     747                    _synList.add(syn) 
     748            if not d.containsKey('type') 
     749                d.add('type', 'string') 
     750             
     751    def validateOptionName(name as String)as String 
     752        """ 
     753        Ensure the given name exists as an option name or synonym mappable 
     754        to an option name; return the canonical name for the option/synonym 
     755        """ 
     756        name = Utils.getSS(_synToName to passthrough, name, name) to ! 
     757        if not _specDict.containsKey(name) 
     758            msg = 'No such option "[name]".' 
     759            if name.contains('=') 
     760                msg += ' If you meant to specify an option value, use colon (:) instead of equals (=).' 
     761            _error(msg) 
     762        return name      
     763         
     764    def _isAccumulatorOpt(spec as Dictionary<of String,Object>) as bool 
     765        return  Utils.getSB(spec to passthrough, 'isAccumulator', false) 
     766             
     767    def _accumulateOptValue(name as String, valueStr as String, _ 
     768            valueDict as Dictionary<of String, Object>, _ 
     769            didSpecify as Dictionary<of String, bool>) 
     770        # accumulators are always treated as strings. TODO: assert that 
     771        if valueDict.containsKey(name) 
     772            (valueDict[name] to System.Collections.IList).add(valueStr to passthrough) 
     773        else 
     774            valueDict[name] = [valueStr] 
     775            didSpecify[name] = true 
     776         
     777             
     778    def _fixupDebug(valueStr as String) as String? 
     779        if valueStr == 'pdbonly' or valueStr == 'full' 
     780            return valueStr 
     781             
     782        value as String? = 'no-value'    
     783        try 
     784            b = _boolForString(valueStr) 
     785        catch FormatException 
     786            value = nil 
     787        success 
     788            value = if(b, '+', '-') 
     789        return value 
     790     
     791    def _processToValue(name as String,   
     792                        valueStr as String,  
     793                        spec as Dictionary<of String, Object>, 
     794                        mainOptions as List<of String>) as dynamic? 
     795        value as dynamic? = 'no-value' 
     796     
     797        if name == 'debug'      # special case 
     798            return _fixupDebug(valueStr) 
     799         
     800        t  = spec['type'] to String 
     801        branch t 
     802            on 'main' 
     803                mainOptions.add(name) 
     804                value = true 
     805            else 
     806                value = _interpretValue(valueStr, spec) 
     807        return value 
     808                 
    739809 
     810    def _handleSynonyms(valueDict as Dictionary<of String, Object>) 
     811        for syn in _synList 
     812            if valueDict.containsKey(syn) 
     813                valueDict[_synToName[syn]] = valueDict[syn] 
     814                valueDict.remove(syn) 
     815             
     816    def _addInDefaults(valueDict as Dictionary<of String, Object>) 
     817        for d in _optionSpecs 
     818            defaultName = d['name'] to String 
     819            if not valueDict.containsKey(defaultName) and d.containsKey('default') 
     820                defaultValue = _interpretValue(d['default'] to String, d) to ! 
     821                if .verbosity 
     822                    print 'Setting option "[defaultName]" to default value [defaultValue].' 
     823                valueDict[defaultName] = defaultValue 
     824         
     825    def _unpackOptions(valueDict as Dictionary<of String, Object>, fileList as List<of String>)  
     826        """ 
     827        Unpack certain options (verbosity and timeit) into specific class fields,  
     828            do files option processing 
     829        """ 
     830        if valueDict.containsKey('verbosity') 
     831            _verbosity = valueDict['verbosity'] to int 
     832 
     833        if not valueDict.containsKey('timeit') and valueDict.containsKey('testify') 
     834            valueDict['timeit'] = true 
     835        if valueDict.containsKey('timeit') 
     836            _willTimeIt = valueDict['timeit'] to bool 
     837             
     838        if valueDict.containsKey('files') 
     839            fileNamesList = valueDict['files'] to System.Collections.IList 
     840            _processFilesFile( fileNamesList, fileList) 
     841                 
     842    def _processFilesFile(fileNamesList as IList, fileList as List<of String>) 
     843        """ 
     844        Treat entries in fileNamesList as names of files containing filenames to compile,  
     845        validate names and add into fileList 
     846        """ 
     847        for fileName as String in fileNamesList 
     848            try 
     849                for line in File.readAllLines(fileName) 
     850                    line = line.trim 
     851                    if line.length==0 or line.startsWith('#') 
     852                        continue 
     853                    _processAsFile(line, fileList, nil) 
     854            catch IOException 
     855                _error('Cannot open file "[fileName]".') 
     856             
     857    def  _processAsFile(arg as String, fileList as List<of String>, errHint as String?) 
     858        """ 
     859        Validate arg as filename and on success add into fileList 
     860        """ 
     861        if File.exists(arg) 
     862            fileList.add(arg) 
     863        else if File.exists(arg+'.cobra') 
     864            fileList.add(arg+'.cobra') 
     865        else if Directory.exists(arg) 
     866            fileList.add(arg) 
     867        else  
     868            msg = 'Cannot find "[arg]" as a file.' 
     869            if errHint  
     870                msg += errHint 
     871            _error(msg) 
     872             
     873 
     874    def _computeArgImplications(options as Options) 
     875        if options.getDefault('target', '') == 'lib' and not options.isSpecified('compile') 
     876            options['compile'] = true 
     877        if options.getDefault('debug', '') not in ['', '0', '-'] and not options.isSpecified('debugging-tips') 
     878            options['debugging-tips'] = false 
     879        if options.boolValue('turbo') 
     880            options['contracts'] = 'none' 
     881            options['include-asserts'] = false 
     882            options['include-nil-checks'] = false 
     883            options['include-tests'] = false 
     884            options['optimize'] = true 
     885             
     886    def _interpretValue(valueStr as String, spec as Dictionary<of String, Object>) as dynamic? 
     887        value as dynamic? 
     888        branch spec['type'] to String 
     889            on 'main' 
     890                throw InvalidOperationException('This method does not handle the main type.') 
     891            on 'bool' 
     892                try 
     893                    value = _boolForString(valueStr) 
     894                catch FormatException 
     895                    value = nil  # cannot process 
     896            on 'int' 
     897                if valueStr == 'on'  # set internally when there is no value 
     898                    valueStr = '1' 
     899                try 
     900                    value = int.parse(valueStr) 
     901                catch FormatException 
     902                    value = nil 
     903                catch OverflowException 
     904                    value = nil 
     905                # TODO: check min and max 
     906            on 'string' 
     907                value = valueStr 
     908            on 'menu' 
     909                if valueStr.length==0 
     910                    value = nil 
     911                if not (spec['choices'] to System.Collections.IList).contains(valueStr) 
     912                    value = nil 
     913                else 
     914                    value = valueStr 
     915        return value 
     916         
     917    def _boolForString(s as String) as bool 
     918        if s.toLower in ['', '+', 'on', 'true', 't', 'yes', 'y', '1'] 
     919            return true 
     920        else if s.toLower in ['-', 'off', 'false', 'f', 'no', 'n', '0'] 
     921            return false 
     922        else 
     923            throw FormatException() 
     924         
     925    def _calcWidth as int 
     926        leftMargin = 8 
     927        try 
     928            consoleWidth = Console.windowWidth 
     929        catch IOException 
     930            # 2008-04-11, When redirecting output, MS .NET 2.0 throws IOException while Novell Mono 1.9 returns 0 
     931            consoleWidth = 0 
     932        if consoleWidth < 1 
     933            try 
     934                consoleWidth = Console.bufferWidth 
     935            catch IOException 
     936                consoleWidth = 0 
     937        totalWidth = consoleWidth - 2 
     938        if totalWidth < 0,  totalWidth = 0 
     939        if totalWidth == 0, totalWidth = 78 
     940        else if totalWidth < 20, totalWidth = 20 
     941        assert totalWidth > 0 
     942        width = totalWidth - leftMargin 
     943        assert width > 0 
     944        return width 
     945         
    740946    def doHelp 
    741         # CC: multiline string 
    742947        .doAbout 
    743948        print '' 
    744949        print 'Usage:' 
     
    764969        print '  <options> can be:' 
    765970 
    766971        # print options from their specs (but not the main ones which are covered above) 
    767         leftMargin = 8 
    768972        leftMarginStr = '        ' 
    769         try 
    770             consoleWidth = Console.windowWidth 
    771         catch IOException 
    772             # 2008-04-11, When redirecting output, MS .NET 2.0 throws IOException while Novell Mono 1.9 returns 0 
    773             consoleWidth = 0 
    774         if consoleWidth < 1 
    775             try 
    776                 consoleWidth = Console.bufferWidth 
    777             catch IOException 
    778                 consoleWidth = 0 
    779         totalWidth = consoleWidth - 2 
    780         if totalWidth < 0 
    781             totalWidth = 0 
    782         if totalWidth == 0 
    783             totalWidth = 78 
    784         else if totalWidth < 20 
    785             totalWidth = 20 
    786         assert totalWidth > 0 
    787         width = totalWidth - leftMargin 
    788         assert width > 0 
     973        width = _calcWidth() 
    789974        for spec in _optionSpecs 
    790975            if spec.containsKey('type') and spec['type']=='main' # CC: spec.get('main', '') 
    791976                continue 
     
    8411026                        first = false 
    8421027                else 
    8431028                    print '        Example: -[spec["name"]]:[spec["example"]]' 
     1029            if spec.containsKey('eg') #Verbatim example line 
     1030                print '        e.g. [spec["eg"]]' 
    8441031 
    8451032    def doAbout 
    8461033        # CC: multiline string 
     
    8521039        # TODO: print '             http://Cobra-Language.com/Docs/License.text' 
    8531040        print 'Usage:       cobra -h' 
    8541041 
    855     def doVersion 
    856         print .versionString 
    857  
    858     def boolForString(s as String) as bool 
    859         if s.toLower in ['', '+', 'on', 'true', 't', 'yes', 'y', '1'] 
    860             return true 
    861         else if s.toLower in ['-', 'off', 'false', 'f', 'no', 'n', '0'] 
    862             return false 
    863         else 
    864             throw FormatException() 
    865  
    866     ## Self Services 
    867  
    868     def error(msg as String) 
     1042    def _error(msg as String) 
    8691043        if msg.length 
    8701044            print 'cobra: error: [msg]' 
    8711045            print 'Run Cobra without options to get full usage information.' 
    8721046        Environment.exit(1) 
     1047         
     1048         
    8731049 
    874  
    875     ## Build Standard Library 
    876  
    877     def doBuildStandardLibrary 
    878         v = .verbosity 
    879         if v 
    880             print 'Building standard library' 
    881         dllInfo = FileInfo('Cobra.Lang.dll') 
    882         if dllInfo.exists 
    883             if v 
    884                 print 'Renaming Cobra.Lang.dll to Cobra.Lang-previous.dll' 
    885             prevInfo = FileInfo('Cobra.Lang-previous.dll') 
    886             if prevInfo.exists 
    887                 prevInfo.delete 
    888             FileInfo('Cobra.Lang.dll').moveTo('Cobra.Lang-previous.dll') 
    889         _options['target'] = 'lib' 
    890         _options['include-tests'] = false  # TODO: including tests in a DLL tends to cause problems. it might be because tests are triggered by type initializers. this needs investigation 
    891         _options['embed-run-time'] = true  # because the runtime is what we're building! 
    892         .doCompile(List<of String>(), true, false, false) 
    893  
    894  
    895     ## Testify 
    896  
    897     def doTestify(paths as List<of String>) 
    898         """ 
    899         Used internally for testing cobra during development. 
    900         Why not just 'test'? because that is reserved for regular developers to run true unit tests. 
    901         """ 
    902         TestifyRunner(_startTime, this, paths).run 
    903  
    904  
    9051050class HtmlWriter 
    9061051    inherits TextWriter 
    9071052    """ 
     
    9291074        finally 
    9301075            _isWritingHtml = false 
    9311076 
    932  
    9331077class Options 
    9341078    inherits Dictionary<of String, Object> 
    9351079 
     
    9511095    def didSpecify(name as String) 
    9521096        _isSpecified[name] = true 
    9531097 
     1098    def setSpecified(specify as Dictionary<of String,bool>) 
     1099        for name in specify.keys 
     1100            .didSpecify(name) 
     1101 
    9541102    def boolValue(key as String) as bool 
    9551103        if .containsKey(key) 
    9561104            return this[key] to bool 
     
    9631111        else 
    9641112            return default 
    9651113 
     1114    def getDefaultLOStr(key as String) as List<of String> 
     1115        if .containsKey(key) 
     1116            return this[key] to List<of String> 
     1117        else 
     1118            return List<of String>() 
     1119 
    9661120    # CC: def getDefault<of T>(key as String, value as T) as T ... 
    9671121 
    9681122    def combine(options as Options) 
     
    9701124            for key in options.keys 
    9711125                this[key] = options[key] 
    9721126 
     1127    def combineNew(options as Options) 
     1128        if options is not this 
     1129            for key in options.keys  
     1130                if not .isSpecified(key) 
     1131                    this[key] = options[key] 
     1132 
    9731133    def print 
    9741134        for key in .keys 
    9751135            print '    [key]: [CobraCore.toTechString(this[key])]' 
  • Source/CobraParser.cobra

     
    4040interface IErrorRecorder 
    4141 
    4242    def recordError(error as SourceException) 
    43  
    44  
     43         
     44         
    4545class Parser 
    4646    """ 
    4747    Notes: 
     
    543543                .expect('EOL') 
    544544                # TODO: throw AssertException(SourceSite sourceSite, object[] expressions, object thiss, object info) 
    545545                assert false, IdentifierExpr(token, 'throw') 
    546             on 'number' 
     546            on 'number'   # deprecatable for %% args -number: 
    547547                # number 'decimal' | 'float' | 'float32' | 'float64' 
    548548                typeName = .grab 
    549549                if typeName.text not in ['decimal', 'float', 'float32', 'float64'] 
     
    551551                .expect('EOL') 
    552552                comp = .typeProvider to? Compiler 
    553553                if comp, comp.numberTypeName = typeName.text 
     554            on 'args'   # remaining tokens are cmdline args 
     555                # args -ref:foo.dll -target:exe 
     556                args = List<of String>() 
     557                token = .grab 
     558                argStr = token.text 
     559                endLast = token.colNum + token.length 
     560                while token.which <> 'EOL' 
     561                    token = .grab 
     562                    if endLast < token.colNum or token.which == 'EOL' 
     563                        args.add(argStr) 
     564                        argStr = token.text 
     565                    else 
     566                        argStr += token.text 
     567                    endLast = token.colNum + token.length 
     568                     
     569                if not args.count  
     570                    .throwError('args directive needs at least one arg following.') 
     571                     
     572                comp = .typeProvider to? Compiler 
     573                #trace args 
     574                if comp 
     575                    options = ArgParser.parseToOptions(args) 
     576                    comp.augmentOptions(options) 
    554577            else 
    555578                .throwError('Unknown compiler directive.') 
    556579 
  • Source/TestifyRunner.cobra

     
    508508            .failed 
    509509            return 0 
    510510 
     511        if willRunExe and options.boolValue('compile')  # Maybe changed by compiler directive 
     512            willRunExe = false 
    511513        if c.messages.count 
    512514            # can't be errors or StopCompilation would have been caught above 
    513515            print 'Unexpected warnings in test.' 
  • Source/CobraTokenizer.cobra

     
    929929        if reMatch.success 
    930930            name = reMatch.groups[1].value 
    931931            branch name 
    932                 on 'no-warnings', .addNoWarning(tok) 
     932                on 'no-warnings' or 'no-warn', .addNoWarning(tok) 
    933933                # for testify 
    934934                on 'args', pass  # TODO: actually this could be worth implementing outside of testify 
    935935                on 'compile-only', pass 
  • Tests/700-command-line/800-foolib1.cobra

     
     1# test making a library internally spec with compiler directives 
     2%% args -embed-run-time:no -target:lib 
     3 
     4class Foo 
     5 
     6    get one as int 
     7        return 1 
     8 
     9    get two as int 
     10        return 2 
     11 
     12    get name as String 
     13        return .getType.name 
     14 
     15    def computeString as String 
     16        return 'aoeuaoeu' 
     17 
     18    def checkInts(args as vari int) as int 
     19        for arg in args 
     20            assert arg 
     21        return args.length 
  • Tests/700-command-line/842-turbo.cobra

     
     1# test .args. -turbo from compiler directive 
     2%% args -turbo 
     3 
     4class Program 
     5 
     6    def main is shared 
     7        assert false 
  • Tests/700-command-line/812-lib-option.cobra

     
     1# was .args. -lib:libdir -r:foolib -c 
     2%% args -lib:libdir -r:foolib -c 
     3 
     4class Test 
     5 
     6    def main is shared 
     7        assert Foo().two == 33 
  • Tests/700-command-line/801-reference-gac-lib.cobra

     
     1# Test referencing a library using compiler directive not cmdline 
     2%% args -reference:System.Xml 
     3 
     4use System.Xml 
     5 
     6class Test 
     7 
     8    def main is shared 
     9        xDoc = XmlDocument() 
     10        #xDoc.load('filename.xml') 
     11        xDoc.loadXml('<xml> <name>Cobra</name> <url>http://Cobra-Language.com/</url> </xml>') 
     12        name = xDoc.getElementsByTagName('name') # an XmlNodeList 
     13        url = xDoc.getElementsByTagName('url') 
     14        assert name.item(0).innerText == 'Cobra' 
     15        assert url.item(0).innerText.startsWith('http://') 
  • Tests/700-command-line/840-include-asserts.cobra

     
     1# Test -include-asserts:no from compiler Directive 
     2%% args -include-asserts:no 
     3 
     4class Program 
     5 
     6    def main is shared 
     7        assert false 
  • Tests/700-command-line/802-fooprog.cobra

     
     1# reference a fully specified dll from compiler directive 
     2%% args -reference:800-foolib1.dll 
     3 
     4class Program 
     5 
     6    def main is shared 
     7        f = Foo() 
     8        assert f.one == 1 
     9        assert f.two == 2 
     10        name = f.name 
     11        .checkName(name) 
     12        s = f.computeString 
     13        .checkName(s) 
     14        assert f.checkInts(2, 4, 6) == 3 
     15 
     16    def checkName(name as String) is shared 
     17        assert name.length 
  • Tests/700-command-line/804-fooprog.cobra

     
     1# reference not fully specified library fm compiler directive 
     2%% args -reference:800-foolib1 
     3 
     4# same as other 8??-fooprog, but the %% -reference arg does not include the ".dll" extension 
     5# -- both ways should work 
     6 
     7class Program 
     8 
     9    def main is shared 
     10        f = Foo() 
     11        assert f.one == 1 
     12        assert f.two == 2 
     13        #print f.two 
     14        name = f.name 
     15        .checkName(name) 
     16        s = f.computeString 
     17        .checkName(s) 
     18        assert f.checkInts(2, 4, 6) == 3 
     19 
     20    def checkName(name as String) is shared 
     21        assert name.length 
  • Developer/IntermediateReleaseNotes.text

     
    11Post 0.8 
    22 
     3* Added support for a new compiler Directive 'args' that takes commandline 
     4 options and applies them to the compilation environment from that point on. 
     5.code 
     6    %% args -target:lib -enable-run-time:no 
     7    %% args -compile -reference:System.Windows.Forms -target:winexe 
     8      
    39* Added support for "extended initializers" which allow you to set properties of the object in the same call being used to create the object: 
    410.code 
    511    r = Rectangle(p1=Point(x=0, y=1), p2=Point(x=2, y=3))