Ticket #35: compDirArgOpts.patch
File compDirArgOpts.patch, 50.3 KB (added by hopscc, 16 years ago) |
---|
-
Source/Compiler.cobra
55 55 56 56 var _globalNS as NameSpace 57 57 var _modules as List<of Module> 58 var _parsedModules as List<of Module>? # accumulated as files parsed 58 59 var _firstFileName as String? 59 60 60 61 var _curModule as Module? # set during bindInt and bindImp … … 224 225 Related resources such as CobraLang.cs reside there. 225 226 """ 226 227 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 228 229 def compileFilesNamed(paths as IList<of String>) 229 230 .compileFilesNamed(paths) 230 231 … … 285 286 .options = options 286 287 bar = '----------------------------------------------------------------------------------------------------' 287 288 .parseFilesNamed(fileNames) 289 288 290 assert .modules.count 289 291 if verbose 290 292 .dumpModulesForTestify(resultsWriter, 'Modules after parsing') … … 318 320 .printMessages 319 321 print bar 320 322 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 321 332 def parseFilesNamed(filenames as IList<of String>) as List<of Module> 322 333 """ 323 334 Returns the modules for the newly parsed files. … … 333 344 embedRunTime = .options.boolValue('embed-run-time') 334 345 335 346 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 344 348 345 349 Node.setCompiler(this) 346 350 try 347 351 if _modules.count == 0 # attempt at caching modules during testify. incomplete. 348 352 .writeSharpInfoClass 349 353 .readSystemTypes 350 .readAssemblyTypes 354 .readAssemblyTypes(.options) 351 355 352 356 if true # _modules.count == 0 353 357 path = Path.combine(.cobraExeDir, 'CobraInfo.cs') … … 368 372 filenames.insert(3, path) 369 373 370 374 modules = List<of Module>() 375 _parsedModules = modules 371 376 for filename in filenames 372 377 if filename.endsWith('.cs') 373 378 if _verbosity … … 396 401 else 397 402 assert modules.count 398 403 _modules.addRange(modules) 404 _parsedModules = nil 399 405 return modules 400 406 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 401 474 def runProcess as Process 402 475 """ 403 476 Returns a new Process with startInfo.fileName and p.startInfo.arguments set appropriately … … 587 660 t = System.Diagnostics.Process.getType 588 661 .readAssembly(t.assembly) # System.dll 589 662 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>) 594 664 i = 0 595 665 for reference in List<of String>(references) 596 666 if not reference.endsWith('.dll') and not reference.endsWith('.exe') 597 667 reference += '.dll' 598 668 references[i] = reference 599 669 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') 600 683 684 # Excluding the extension can be problematic 685 _fixupLibSuffix(references) 686 601 687 # now that references are fixed, make a copy so that .options['references'] is not modified further 602 688 references = List<of String>(references) 603 689 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> 606 692 references.addRange(.refsForPackage(pkgName)) 607 693 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) 617 696 618 697 # Here be "reflectionOnlyLoad" code... which does not work on Mono 1.2.4 619 698 # The run-time error message says: … … 634 713 # $sharp('curDomain.ReflectionOnlyAssemblyResolve += _resolveEvent') 635 714 636 715 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) 643 729 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 673 754 def refsForPackage(pkgName as String) as List<of String> 674 755 """ 675 756 Returns the library/DLL refs for the give package name. … … 1414 1495 if optimize 1415 1496 backEndOptions += ' [optChar]optimize+' 1416 1497 1417 thing = options.getDefault ('reference', List<of String>()) to List<of String>1498 thing = options.getDefaultLOStr('reference') 1418 1499 for refer in thing 1419 1500 backEndOptions += ' "[optChar]r:[refer]"' 1420 1501 … … 1448 1529 sharpArgs = sharpArgs[1:-1] 1449 1530 backEndOptions += ' ' + sharpArgs 1450 1531 1451 for libPath in .options.getDefault ('library-directory', [])1532 for libPath in .options.getDefaultLOStr('library-directory') 1452 1533 backEndOptions += ' ' + '-lib:"[libPath]"' 1453 1534 1454 for pkgName in .options.getDefault ('pkg', [])1535 for pkgName in .options.getDefaultLOStr('pkg') 1455 1536 backEndOptions += ' ' + '-pkg:[pkgName]' 1456 1537 1457 1538 # .cs files … … 1482 1563 cp.generateExecutable = options.getDefault('target', 'exe') in ['exe', 'winexe'] 1483 1564 cp.outputAssembly = _fullExeFileName 1484 1565 cp.compilerOptions = backEndOptions 1566 if _verbosity > 2 1567 print 'CodeProvider [backEndOptions] [cp.referencedAssemblies]' 1485 1568 #trace backEndOptions 1486 1569 #trace sharpFileNameList 1487 1570 cr = provider.compileAssemblyFromFile(cp, sharpFileNameList.toArray) -
Source/CommandLine.cobra
32 32 # not the current Source directory. And Snapshot can be a final release such as '0.7.4' for a 33 33 # period of time where this Cobra source represents an svn-post-RELEASE. 34 34 return '0.8.0 post-release' 35 36 var _optionSpecs as List<of Dictionary<of String, Object>> 37 35 38 36 var _rawOptionSpecs = [ 39 37 { 40 38 'name': 'about', … … 201 199 }, 202 200 { 203 201 'name': 'reference', 204 'synonyms': ['r'], 202 'synonyms': ['r'], # TODO: lose 'r' ->'Ref', 'R', something else 205 203 'isAccumulator': true, 206 204 'description': 'Add a DLL reference.', 207 205 'args': 'Some.dll', … … 220 218 # 'args': ':Qualified.Type.Name', 221 219 # }, 222 220 { 223 'name': 'run', 221 'name': 'run', # TODO: Synonym 'r' after change 'reference' switch 224 222 'description': 'Runs the Cobra program. This is the default behavior if specify any Cobra source files.', 225 223 'type': 'main', 226 224 }, … … 281 279 'type': 'main', 282 280 }, 283 281 ] 282 284 283 285 284 var _startTime as DateTime 286 285 var _verbosity = 0 … … 290 289 var _htmlWriter as HtmlWriter? 291 290 292 291 var _compiler as Compiler? 293 292 var _argParser as ArgParser 293 294 294 def init 295 295 _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) 302 297 303 if specObj inherits Dictionary<of String, Object>304 d = specObj305 else if specObj inherits Dictionary<of String, String>306 d = Dictionary<of String, Object>()307 for key in specObj.keys308 d[key] = specObj[key]309 else310 throw FallThroughException(specObj.getType)311 _optionSpecs.add(d)312 313 298 get compiler from var 314 299 315 300 get options from var … … 324 309 get verbosity as int 325 310 return _verbosity 326 311 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 327 317 def run 328 318 """ 329 319 Run the command line using the command line arguments. … … 339 329 .doAbout 340 330 return 341 331 .parseArgs(args, out _options, out _pathList) 332 342 333 if _options.boolValue('output-html') 343 334 _htmlWriter = HtmlWriter(Console.out) 344 335 dest = _htmlWriter to TextWriter … … 389 380 if _htmlWriter 390 381 _htmlWriter.writeHtml('</body></html>[_htmlWriter.newLine]') 391 382 392 def isOptionSpecRestrictionViolated(optionSpec as Dictionary<of String, Object>) as bool393 """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 String398 on 'mono-only'399 return not CobraCore.isRunningOnMono400 return false401 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 ensure408 options409 paths410 body411 optionPrefix = '-'412 valuePrefix = c':'413 if not args.count414 options = Options()415 options.add('help', true)416 paths = List<of String>()417 return418 419 specDict = Dictionary<of String, Dictionary<of String, Object>>()420 # ^ will contain keys for all spec names and their synonyms421 synToName = Dictionary<of String, String>()422 # ^ maps synonyms to their full names423 synList = List<of String>()424 for d in _optionSpecs425 if .isOptionSpecRestrictionViolated(d)426 continue427 specDict[d['name'] to String] = d428 if d.containsKey('synonyms')429 syns = d['synonyms'] to System.Collections.IList430 for syn as String in syns431 assert not specDict.containsKey(syn)432 specDict[syn] = d433 synToName[syn] = d['name'] to String434 synList.add(syn)435 if not d.containsKey('type')436 d.add('type', 'string')437 438 # set up initial valueDict439 valueDict = Dictionary<of String, Object>()440 if Utils.isDevMachine441 valueDict['reveal-internal-exceptions'] = true # this is a specially computed default, but can still be overridden on the command line442 443 fileList = List<of String>()444 value = 'no-value' to dynamic445 mainOptions = List<of String>()446 didSpecify = Dictionary<of String, bool>() # CC: could just be a Set447 for arg in args448 if arg.trim.length == 0449 continue450 if arg.startsWith(optionPrefix)451 isOption = true452 while arg.startsWith(optionPrefix)453 arg = arg[1:]454 else455 isOption = false456 if isOption457 parts = arg.split(@[valuePrefix], 2)458 if parts.length == 1459 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 else467 valueStr = 'on'468 else469 assert parts.length == 2470 name = parts[0]471 valueStr = parts[1]472 assert name.length, parts473 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 that482 if valueDict.containsKey(name)483 (valueDict[name] to System.Collections.IList).add(valueStr to passthrough)484 else485 valueDict[name] = [valueStr]486 didSpecify[name] = true487 else488 cannotProcess = false489 if name=='debug'490 # special case491 if valueStr=='pdbonly' or valueStr=='full'492 value = valueStr493 else494 try495 value = .boolForString(valueStr)496 catch FormatException497 cannotProcess = true498 success499 value = if(value, '+', '-')500 else501 if spec['type'] == 'main'502 mainOptions.add(name)503 value = true504 else505 possible = .interpretValue(valueStr, spec)506 if possible is not nil507 value = possible508 else509 cannotProcess = true510 if cannotProcess511 .error('Cannot process value "[valueStr]" for option "[name]".')512 valueDict[name] = value513 didSpecify[name] = true514 else # not isOption515 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 else522 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 synonyms528 for syn in synList529 if valueDict.containsKey(syn)530 valueDict[synToName[syn]] = valueDict[syn]531 valueDict.remove(syn)532 533 # add in defaults534 for d in _optionSpecs535 defaultName = d['name'] to String536 if not valueDict.containsKey(defaultName) and d.containsKey('default')537 defaultValue = .interpretValue(d['default'] to String, d) to !538 if .verbosity539 print 'Setting option "[defaultName]" to default value [defaultValue].'540 valueDict[defaultName] = defaultValue541 542 # TODO: make the option names case-insensitive543 544 # check for more than one main option545 if mainOptions.count > 1546 .error('Cannot have these main options at the same time: [Utils.join(", ", mainOptions)]')547 548 # unpack certain options into specific class fields549 if valueDict.containsKey('verbosity')550 _verbosity = valueDict['verbosity'] to int551 if not valueDict.containsKey('timeit') and valueDict.containsKey('testify')552 valueDict['timeit'] = true553 if valueDict.containsKey('timeit')554 CobraMain.willTimeIt = valueDict['timeit'] to bool555 if valueDict.containsKey('files')556 for fileName as String in valueDict['files'] to System.Collections.IList557 try558 for line in File.readAllLines(fileName)559 line = line.trim560 if line.length==0 or line.startsWith('#')561 continue562 # TODO: dup'ed above563 arg = line564 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 else571 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 dup576 catch IOException577 .error('Cannot open file "[fileName]".')578 579 # set the out parameters580 options = Options(valueDict)581 for name in didSpecify.keys582 options.didSpecify(name)583 paths = fileList584 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'] = true591 if options.getDefault('debug', '') not in ['', '0', '-'] and not options.isSpecified('debugging-tips')592 options['debugging-tips'] = false593 if options.boolValue('turbo')594 options['contracts'] = 'none'595 options['include-asserts'] = false596 options['include-nil-checks'] = false597 options['include-tests'] = false598 options['optimize'] = true599 600 def interpretValue(valueStr as String, spec as Dictionary<of String, Object>) as dynamic?601 value as dynamic?602 branch spec['type'] to String603 on 'main'604 throw InvalidOperationException('This method does not handle the main type.')605 on 'bool'606 try607 value = .boolForString(valueStr)608 catch FormatException609 cannotProcess = true610 on 'int'611 if valueStr == 'on' # set internally when there is no value612 valueStr = '1'613 try614 value = int.parse(valueStr)615 catch FormatException616 cannotProcess = true617 catch OverflowException618 cannotProcess = true619 # TODO: check min and max620 on 'string'621 value = valueStr622 on 'menu'623 if valueStr.length==0624 cannotProcess = true625 if not (spec['choices'] to System.Collections.IList).contains(valueStr)626 cannotProcess = true627 else628 value = valueStr629 r = if(cannotProcess, nil, value)630 return r631 632 383 def doCompile(paths as List<of String>) as Compiler 633 384 return .doCompile(paths, true, false, false) 634 385 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 636 388 oldPaths = List<of String>(paths) 637 389 paths.clear 638 390 for path in oldPaths … … 650 402 c.htmlWriter = _htmlWriter 651 403 try 652 404 c.compileFilesNamed(paths, writeTestInvocation, stopAfterBindInt) 405 if _verbosity <> c.verbosity, _verbosity = c.verbosity 653 406 catch StopCompilation 654 407 # Each phase of the compiler may throw an exception to stop compilation. 655 408 # Before doing so, it prints its errors. … … 728 481 c = .doCompile(paths, false, false, false) 729 482 if c.errors.count 730 483 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 543 class 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' 731 715 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 739 809 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 740 946 def doHelp 741 # CC: multiline string742 947 .doAbout 743 948 print '' 744 949 print 'Usage:' … … 764 969 print ' <options> can be:' 765 970 766 971 # print options from their specs (but not the main ones which are covered above) 767 leftMargin = 8768 972 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() 789 974 for spec in _optionSpecs 790 975 if spec.containsKey('type') and spec['type']=='main' # CC: spec.get('main', '') 791 976 continue … … 841 1026 first = false 842 1027 else 843 1028 print ' Example: -[spec["name"]]:[spec["example"]]' 1029 if spec.containsKey('eg') #Verbatim example line 1030 print ' e.g. [spec["eg"]]' 844 1031 845 1032 def doAbout 846 1033 # CC: multiline string … … 852 1039 # TODO: print ' http://Cobra-Language.com/Docs/License.text' 853 1040 print 'Usage: cobra -h' 854 1041 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) 869 1043 if msg.length 870 1044 print 'cobra: error: [msg]' 871 1045 print 'Run Cobra without options to get full usage information.' 872 1046 Environment.exit(1) 1047 1048 873 1049 874 875 ## Build Standard Library876 877 def doBuildStandardLibrary878 v = .verbosity879 if v880 print 'Building standard library'881 dllInfo = FileInfo('Cobra.Lang.dll')882 if dllInfo.exists883 if v884 print 'Renaming Cobra.Lang.dll to Cobra.Lang-previous.dll'885 prevInfo = FileInfo('Cobra.Lang-previous.dll')886 if prevInfo.exists887 prevInfo.delete888 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 investigation891 _options['embed-run-time'] = true # because the runtime is what we're building!892 .doCompile(List<of String>(), true, false, false)893 894 895 ## Testify896 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).run903 904 905 1050 class HtmlWriter 906 1051 inherits TextWriter 907 1052 """ … … 929 1074 finally 930 1075 _isWritingHtml = false 931 1076 932 933 1077 class Options 934 1078 inherits Dictionary<of String, Object> 935 1079 … … 951 1095 def didSpecify(name as String) 952 1096 _isSpecified[name] = true 953 1097 1098 def setSpecified(specify as Dictionary<of String,bool>) 1099 for name in specify.keys 1100 .didSpecify(name) 1101 954 1102 def boolValue(key as String) as bool 955 1103 if .containsKey(key) 956 1104 return this[key] to bool … … 963 1111 else 964 1112 return default 965 1113 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 966 1120 # CC: def getDefault<of T>(key as String, value as T) as T ... 967 1121 968 1122 def combine(options as Options) … … 970 1124 for key in options.keys 971 1125 this[key] = options[key] 972 1126 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 973 1133 def print 974 1134 for key in .keys 975 1135 print ' [key]: [CobraCore.toTechString(this[key])]' -
Source/CobraParser.cobra
40 40 interface IErrorRecorder 41 41 42 42 def recordError(error as SourceException) 43 44 43 44 45 45 class Parser 46 46 """ 47 47 Notes: … … 543 543 .expect('EOL') 544 544 # TODO: throw AssertException(SourceSite sourceSite, object[] expressions, object thiss, object info) 545 545 assert false, IdentifierExpr(token, 'throw') 546 on 'number' 546 on 'number' # deprecatable for %% args -number: 547 547 # number 'decimal' | 'float' | 'float32' | 'float64' 548 548 typeName = .grab 549 549 if typeName.text not in ['decimal', 'float', 'float32', 'float64'] … … 551 551 .expect('EOL') 552 552 comp = .typeProvider to? Compiler 553 553 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) 554 577 else 555 578 .throwError('Unknown compiler directive.') 556 579 -
Source/TestifyRunner.cobra
508 508 .failed 509 509 return 0 510 510 511 if willRunExe and options.boolValue('compile') # Maybe changed by compiler directive 512 willRunExe = false 511 513 if c.messages.count 512 514 # can't be errors or StopCompilation would have been caught above 513 515 print 'Unexpected warnings in test.' -
Source/CobraTokenizer.cobra
929 929 if reMatch.success 930 930 name = reMatch.groups[1].value 931 931 branch name 932 on 'no-warnings' , .addNoWarning(tok)932 on 'no-warnings' or 'no-warn', .addNoWarning(tok) 933 933 # for testify 934 934 on 'args', pass # TODO: actually this could be worth implementing outside of testify 935 935 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 4 class 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 4 class 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 4 class 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 4 use System.Xml 5 6 class 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 4 class 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 4 class 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 7 class 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
1 1 Post 0.8 2 2 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 3 9 * Added support for "extended initializers" which allow you to set properties of the object in the same call being used to create the object: 4 10 .code 5 11 r = Rectangle(p1=Point(x=0, y=1), p2=Point(x=2, y=3))