Changeset 1771

Show
Ignore:
Timestamp:
11/20/08 03:16:46 (7 weeks ago)
Author:
Chuck.Esterbrook
Message:

Code cleanup.
More migration to the Cobra.Lang subdirectory.

Location:
cobra/trunk/Source
Files:
6 added
2 modified

Legend:

Unmodified
Added
Removed
  • cobra/trunk/Source/Cobra.Lang/files.text

    r1770 r1771  
     1CobraCore.cobra 
     2CobraFrame.cobra 
     3HtmlExceptionReportWriter.cobra 
     4Exceptions.cobra 
     5Extensions.cobra 
     6Set.cobra 
     7SourceSite.cobra 
     8StringMaker.cobra 
    19Tracer.cobra 
    210Visitor.cobra 
    3 HtmlExceptionReportWriter.cobra 
    4 Exceptions.cobra 
  • cobra/trunk/Source/CobraLang.cobra

    r1770 r1771  
    11use System.Reflection 
    2 use System.Runtime.CompilerServices 
    32 
    43 
     
    1413                inherits Attribute 
    1514                pass 
    16  
    17         class CobraCore 
    18  
    19                 shared 
    20                  
    21                         ## Release info 
    22  
    23                         get versionDescription as String 
    24                                 """ 
    25                                 Returns a textual description of the version such as "X.Y.Z" or "svn-post-X.Y.Z". 
    26                                 """ 
    27                                 return 'svn-post-[.version]' 
    28                                 # return .version.toString 
    29                          
    30                         get isOfficialRelease 
    31                                 return false 
    32  
    33                         get version as Version 
    34                                 return Version(0, 8, 0) 
    35  
    36                         get releaseNum as int 
    37                                 return 25 
    38  
    39  
    40                         ## String Makers 
    41                          
    42                         pro printStringMaker as StringMaker 
    43                                 """ 
    44                                 Used by `print` statements, string substitutions and .toPrintString methods. 
    45                                 """ 
    46                                 get 
    47                                         return CobraImp._printStringMaker 
    48                                 set 
    49                                         CobraImp._printStringMaker = value 
    50                          
    51                         pro techStringMaker as StringMaker 
    52                                 """ 
    53                                 Used by `assert` failures, `trace` statements and .toTechString methods. 
    54                                 """ 
    55                                 get 
    56                                         return CobraImp._techStringMaker 
    57                                 set 
    58                                         CobraImp._techStringMaker = value 
    59  
    60  
    61                         ## Program stuff 
    62  
    63                         get commandLineArgs as List<of String> 
    64                                 return List<of String>(Environment.getCommandLineArgs) 
    65  
    66                         get exePath as String 
    67                                 """ 
    68                                 Returns the full path of the currently executing exe including directory, file name and extension. 
    69                                 Use `Path.getDirectoryName()` on this to get the directory containing the current exe. 
    70                                 """ 
    71                                 test 
    72                                         assert '.exe' in CobraCore.exePath 
    73                                 body 
    74                                         return Assembly.getEntryAssembly.location 
    75  
    76                         get printDestination as TextWriter 
    77                                 """ 
    78                                 Returns the TextWriter that print statements currently print to. 
    79                                 This can change via the block version of the `print to` statement. 
    80                                 """ 
    81                                 return CobraImp.printDestination 
    82  
    83                         def printDebuggingTips 
    84                                 print 'An unhandled exception has occurred.' 
    85                                 print 
    86                                 print 'Cobra debugging tips:' 
    87                                 print '    To get file name and line number information for the stack frames, use:' 
    88                                 print '        cobra -debug foo.cobra' 
    89                                 if CobraCore.isRunningOnMono 
    90                                         print '    If running the executable through "mono" then also use --debug (double dash):' 
    91                                         print '        mono --debug foo.exe ...' 
    92                                 print '    To get a post-mortem, HTML-formatted report with more details about your objects:' 
    93                                 print '        cobra -debug -exception-report foo.cobra' 
    94                                 print '    For even more information, try:' 
    95                                 print '        cobra -debug -exception-report -detailed-stack-trace foo.cobra' 
    96                                 print '    Or use the abbreviations:' 
    97                                 print '        cobra -d -er -dst foo.cobra' 
    98                                 # TODO: print '    See also: http://cobra-language.com/docs/debugging' 
    99                                 print 
    100                          
    101  
    102                         ## Reset 
    103                          
    104                         def reset(printDestination as TextWriter) 
    105                                 """ 
    106                                 Resets the Cobra run-time support using the argument as the initial print destination on the "print to" stack. 
    107                                 This is occasionally needed in special circumstances such as running with Pex (http://research.microsoft.com/pex/). 
    108                                 """ 
    109                                 CobraImp.reset(printDestination) 
    110  
    111                         def reset 
    112                                 """ 
    113                                 Resets the Cobra run-time support using Console.out. 
    114                                 """ 
    115                                 .reset(Console.out) 
    116                          
    117  
    118                         ## Tracer 
    119  
    120                         var _tracer as Tracer? 
    121  
    122                         pro tracer as Tracer 
    123                                 """ 
    124                                 The global Tracer object used by `trace` statements. 
    125                                 Via this property, you can set this to your own instance, 
    126                                 or access the tracer to read or write its properties. 
    127                                 To turn off tracing, for example, you can write `CobraCore.tracer.isActive = false`. 
    128                                 """ 
    129                                 get 
    130                                         if _tracer is nil 
    131                                                 _tracer = Tracer() 
    132                                         return _tracer to ! 
    133                                 set 
    134                                         _tracer = Tracer() 
    135  
    136  
    137                         ## Run Tests 
    138  
    139                         def runAllTests 
    140                                 """ 
    141                                 Run all Cobra `test` sections in all assemblies using reflection to locate them. 
    142                                 """ 
    143                                 # start = DateTime.now 
    144                                 _runAllTests(Assembly.getEntryAssembly, Dictionary<of String, String>()) 
    145                                 # duration = DateTime.now.subtract(start) 
    146                                 # trace duration 
    147  
    148                         def _runAllTests(ass as Assembly, found as Dictionary<of String, String>)  # CC: found should be Set<of String> 
    149                                 name = ass.getName.toString 
    150                                 if found.containsKey(name) 
    151                                         return 
    152                                 found.add(name, name) 
    153                                 if _skipAssemblyNameForTesting(name)  # saves some time 
    154                                         return 
    155  
    156                                 # print 'Testing assembly:', ass 
    157                                 for type in ass.getExportedTypes 
    158                                         members = type.getMember('RunTestsIfNeeded') 
    159                                         if members and members.length and members[0] inherits MethodInfo 
    160                                                 method = members[0] to MethodInfo 
    161                                                 # trace type, method 
    162                                                 if type.containsGenericParameters 
    163                                                         # TODO: this is quite awful. tests in generic types are being skipped! 
    164                                                         # potential solution 1: move type test out of the type into a "sister" type: private __FooTest 
    165                                                         # potential solution 2: require a constructed type in Cobra: `test Foo<of int> ...` and then put that in a method attribute in the gen C# and use that type 
    166                                                         continue 
    167                                                 method.invoke(type, nil) 
    168  
    169                                 # traverse further assemblies 
    170                                 for assName in ass.getReferencedAssemblies 
    171                                         subAss = Assembly.load(assName) 
    172                                         _runAllTests(subAss to !, found) 
    173  
    174                         var _skipPrefixes = @['System.', 'Mono.', 'mscorlib,', 'System,'] 
    175  
    176                         def _skipAssemblyNameForTesting(name as String) as bool 
    177                                 for prefix in _skipPrefixes 
    178                                         if name.startsWith(prefix) 
    179                                                 return true 
    180                                 return false 
    181  
    182  
    183                         ## Detailed stack trace 
    184  
    185                         pro maxStackFrames as int 
    186                                 """ 
    187                                 When detailed stack trace is on, this value limits the maximum stack depth before 
    188                                 Cobra will exit with a stack overflow error including a listing of the most 
    189                                 recent stack frames. The default value is 250. You can set to 0 to disable 
    190                                 stack overflow detection. 
    191                                 """ 
    192                                 get 
    193                                         return CobraImp._maxStackFrames 
    194                                 set 
    195                                         require value == 0 or value > 9 
    196                                         CobraImp._maxStackFrames = value 
    197  
    198                         pro numLastMaxStackFrames as int 
    199                                 """ 
    200                                 When stack overflow is detected, this value gives the number of most recent stack frames that will be printed. 
    201                                 """ 
    202                                 get 
    203                                         return CobraImp._numLastMaxStackFrames 
    204                                 set 
    205                                         require value >= 2 
    206                                         CobraImp._numLastMaxStackFrames = value 
    207                                          
    208                         var _maxDumpObjectCount = 250 
    209          
    210                         pro maxDumpObjectCount from var 
    211                                 """ 
    212                                 Controls the maximum number of objects dumped  in the exception report. 
    213                                 Defaults to 250 which can easily result in a 5MB exception report. 
    214                                 """ 
    215  
    216                         get hasDetailedStackTrace 
    217                                 return CobraImp.hasDetailedStackTrace 
    218  
    219                         def handleUnhandledException(ex as Exception) 
    220                                 print 
    221                                 try 
    222                                         print 'Unhandled Exception: [ex]' 
    223                                 catch exc as Exception 
    224                                         print 'Unhandled Exception: CAUGHT EXCEPTION FOR [ex.getType.name].toString: [exc]' 
    225                                 fileName = 'cobra-exception-report.html' 
    226                                 print 'Writing exception report to [fileName]...' 
    227                                 using tw = File.createText(fileName) 
    228                                         HtmlExceptionReportWriter().writeReport(tw, ex) 
    229                                 print 'Wrote [fileName]' 
    230                                 envVarName = 'COBRA_OPEN_HTML_SST_COMMAND' 
    231                                 cmd = Environment.getEnvironmentVariable(envVarName) 
    232                                 if cmd 
    233                                         if cmd.trim.length 
    234                                                 p = System.Diagnostics.Process() 
    235                                                 p.startInfo.fileName = cmd 
    236                                                 p.startInfo.arguments = fileName 
    237                                                 p.startInfo.useShellExecute = false 
    238                                                 p.start 
    239                                                 print '[cmd] [fileName]' 
    240                                 else 
    241                                         print 'You can set the environment variable [envVarName]' 
    242                                         print 'to automatically open the exception report.' 
    243  
    244          
    245                         ## Type names and tech strings 
    246  
    247                         def typeName(t as Type) as String 
    248                                 return CobraImp.typeName(t) 
    249  
    250                         def toTechString(x as Object?) as String 
    251                                 return CobraImp.toTechString(x) 
    252  
    253  
    254                         ## Will check control flags 
    255  
    256                         # CC: make a public section/block here 
    257                         var _willCheckInvariant = true 
    258                                 is public 
    259                         var _willCheckRequire = true 
    260                                 is public 
    261                         var _willCheckEnsure = true 
    262                                 is public 
    263                         var _willCheckAssert = true 
    264                                 is public 
    265                         var _willCheckNil = true 
    266                                 is public 
    267  
    268                         pro willCheckInvariant from var 
    269                         pro willCheckRequire from var 
    270                         pro willCheckEnsure from var 
    271                         pro willCheckAssert from var 
    272                         pro willCheckNil from var 
    273  
    274                         set willCheckAll as bool 
    275                                 .willCheckInvariant = value 
    276                                 .willCheckRequire = value 
    277                                 .willCheckEnsure = value 
    278                                 .willCheckAssert = value 
    279                                 .willCheckNil = value 
    280  
    281  
    282                         ## Finding cobra command line program 
    283  
    284                         def runCobraExe(args as String, process as out System.Diagnostics.Process?) as String 
    285                                 """ 
    286                                 Runs cobra.exe with the given args, sets the process to the one created for cobra.exe and returns all output including stdio and stderr. 
    287                                 In addition to examining the output, you should be interested in process.exitCode which will be zero if there was no problems. 
    288                                 Uses CobraCore.findCobraExe and raises IOException if it cannot be found. 
    289                                 Uses CobraCore.runAndCaptureAllOutput(p) to run the process. 
    290                                 """ 
    291                                 cobraExePath = CobraCore.findCobraExe 
    292                                 if cobraExePath is nil or cobraExePath == '' 
    293                                         throw IOException('Cannot locate cobra.exe using CobraCore.findCobraExe. Consider invoking .findCobraExe with additional search paths and passing the result to .runCobraExe.') 
    294                                 return .runCobraExe(cobraExePath, args, out process) 
    295  
    296                         def runCobraExe(cobraExePath as String, args as String, process as out System.Diagnostics.Process?) as String 
    297                                 require cobraExePath.length 
    298                                 p = System.Diagnostics.Process() 
    299                                 if CobraCore.isRunningOnMono 
    300                                         p.startInfo.fileName = 'mono' 
    301                                         p.startInfo.arguments = cobraExePath + ' ' + args 
    302                                 else 
    303                                         p.startInfo.fileName = cobraExePath 
    304                                         p.startInfo.arguments = args 
    305                                 # print '[p.startInfo.fileName] [p.startInfo.arguments]' 
    306                                 process = p 
    307                                 return CobraCore.runAndCaptureAllOutput(p) 
    308  
    309                         def findCobraExe as String? 
    310                                 return .findCobraExe(nil) 
    311  
    312                         def findCobraExe(extraPaths as IList<of String>?) as String? 
    313                                 """ 
    314                                 Finds cobra.exe on the current system by looking in various places: 
    315                                         * the current directory 
    316                                         * the directory where the current executable resides 
    317                                         * the path of the cobra.exe that produced the current executable 
    318                                         * the path of the COBRA environment variable 
    319                                         * the system PATH 
    320                                         * educated guesses like \WINDOWS\Program Files\Cobra\bin and /usr/local/bin 
    321                                         * the extraPaths argument 
    322                                 """ 
    323                                 # check previous cached result first 
    324                                 if _findCobraCache 
    325                                         return _findCobraCache 
    326                                 # check the current directory 
    327                                 path = _findCobraExe(Environment.currentDirectory) 
    328                                 if path 
    329                                         return path 
    330                                 # check the directory where the current executable resides 
    331                                 path = _findCobraExe(CobraCore.exePath) 
    332                                 if path 
    333                                         return path 
    334                                 # check for the cobra that created the current executable 
    335                                 if File.exists(CobraInfo.cobraPath) 
    336                                         return CobraInfo.cobraPath 
    337                                 # check COBRA environment variable 
    338                                 path = Environment.getEnvironmentVariable('COBRA') ? '' 
    339                                 if path <> '' 
    340                                         path = _findCobraExe(path) 
    341                                         if path 
    342                                                 return path 
    343                                 # check the PATH 
    344                                 paths = (Environment.getEnvironmentVariable('PATH') ? '').split(Path.pathSeparator) 
    345                                 for sysPath in paths 
    346                                         path = _findCobraExe(sysPath) 
    347                                         if path 
    348                                                 return path 
    349                                 # check common locations and extraPaths 
    350                                 morePaths = [ 
    351                                         r'\WINDOWS\Program Files\Cobra\bin', 
    352                                         r'\Cobra\bin', 
    353                                         r'/usr/local/bin', 
    354                                         r'/usr/bin', 
    355                                         r'/bin', 
    356                                 ] 
    357                                 if extraPaths 
    358                                         morePaths.addRange(extraPaths) 
    359                                 for path in morePaths 
    360                                         path = _findCobraExe(path) 
    361                                         if path 
    362                                                 return path 
    363                                 # cannot find cobra.exe 
    364                                 return nil 
    365  
    366                         def clearCobraExeCache 
    367                                 """ 
    368                                 The `findCobraExe` method caches its results for subsequent speed. 
    369                                 This method clears the cache in the event you need to do so. 
    370                                 """ 
    371                                 _findCobraCache = nil 
    372  
    373                         var _findCobraCache as String? 
    374  
    375                         def _findCobraExe(path as String) as String? 
    376                                 _findCobraCache = _findCobraExe(path, true) 
    377                                 return _findCobraCache 
    378  
    379                         def _findCobraExe(path as String, firstTime as bool) as String? 
    380                                 if path <> CobraCore.exePath and path.endsWith('cobra.exe') 
    381                                         # ^ first condition guards against test cases like "invoke-cobra.exe" from endlessly invoking themselves 
    382                                         if File.exists(path) 
    383                                                 return path 
    384                                         else 
    385                                                 return nil 
    386                                 else if Directory.exists(path) 
    387                                         exe = Path.combine(path, 'cobra.exe') 
    388                                         if File.exists(exe) 
    389                                                 return exe 
    390                                         exe = Path.combine(Path.combine(path, 'bin'), 'cobra.exe') 
    391                                         if File.exists(exe) 
    392                                                 return exe 
    393                                         if firstTime 
    394                                                 # check for a 'Cobra' subdirectory 
    395                                                 return _findCobraExe(Path.combine(path, 'Cobra'), false) 
    396                                         else 
    397                                                 return nil 
    398                                 else 
    399                                         return nil 
    400  
    401  
    402                         ## Other util 
    403                          
    404                         var _isRunningOnMono as bool? 
    405                          
    406                         get isRunningOnMono as bool 
    407                                 if _isRunningOnMono is nil 
    408                                         _isRunningOnMono = $sharp('Type.GetType("Mono.Runtime")') is not nil 
    409                                 return _isRunningOnMono to ! 
    410                                  
    411                         def runAndCaptureAllOutput(process as System.Diagnostics.Process) as String 
    412                                 """ 
    413                                 Example: 
    414                                         p = System.Diagnostics.Process() 
    415                                         p.startInfo.fileName = 'some-program' 
    416                                         p.startInfo.arguments = 'foo bar baz' 
    417                                         output = CobraCore.runAndCaptureAllOutput(p) 
    418                                         trace p, p.exitCode, output 
    419                                 TODO: change to extension method on Process 
    420                                 """ 
    421                                 return CobraImp.runAndCaptureAllOutput(process) 
    422  
    423                         def noOp(args as vari dynamic?) as dynamic? 
    424                                 """ 
    425                                 No operation. Primarily used in Cobra's own test suite to consume a local variable to avoid undesired warnings. 
    426                                 Takes any number of values and returns an undefined value of type `dynamic?` for maximum flexibility. 
    427                                 """ 
    428                                 return 0 
    429  
    430                         var _htmlEncodes = @[['&', '&amp;'], ['<', '&lt;'], ['>', '&gt;'], ['"', '&quot;']] 
    431  
    432                         def htmlEncode(obj as Object) as String 
    433                                 """ 
    434                                 Return the HTML encoded version of the given object. 
    435                                 Returns the contents of the object if it is an instance of Html. 
    436                                 This is useful to display a plain ASCII text string on a web page. 
    437                                 """ 
    438                                 if obj inherits Html 
    439                                         return obj.contents 
    440                                 else 
    441                                         return .htmlEncode(obj.toString) 
    442                          
    443                         def htmlEncode(s as String) as String 
    444                                 """ 
    445                                 Return the HTML encoded version of the given string. 
    446                                 This is useful to display a plain ASCII text string on a web page. 
    447                                 """ 
    448                                 test 
    449                                         rw = HtmlExceptionReportWriter() 
    450                                         assert rw.htmlEncode('foo') == 'foo' 
    451                                         assert rw.htmlEncode('3 < 5') == '3 &lt; 5' 
    452                                 body 
    453                                         for code in _htmlEncodes 
    454                                                 s = s.replace(code[0], code[1]) 
    455                                         return s 
    456  
    45715 
    45816        class CobraDirectString 
     
    555113                get sourceSite as SourceSite 
    556114 
    557         class SourceSite 
    558                 """ 
    559                 A SourceSite instance captures the source location of a statement or expression, as in the 
    560                 filename, line number, declaring class name, method name and run-time object. The Cobra 
    561                 compiler generates SourceSite instances in various circumstances; for example, the `trace` 
    562                 statement. 
    563                 """ 
    564  
    565                 var _fileName as String 
    566                 var _lineNum as int 
    567                 var _className as String 
    568                 var _memberName as String 
    569                 var _object as Object 
    570  
    571                 def init(fileName as String, lineNum as int, className as String, memberName as String, obj as Object) 
    572                         _fileName = fileName 
    573                         _lineNum = lineNum 
    574                         _className = className 
    575                         _memberName = memberName 
    576                         _object = obj 
    577  
    578                 def toString as String is override 
    579                         #fileName = CobraCore.toTechString(_fileName) 
    580                         #className = CobraCore.toTechString(_className) 
    581                         #memberName = CobraCore.toTechString(_memberName) 
    582                         #obj = CobraCore.toTechString(_object) 
    583                         #return '[.getType.name]([fileName], [_lineNum], [className], [memberName], [obj])' 
    584                         return '[_fileName]:[_lineNum] in [_className].[_memberName] for object [CobraCore.toTechString(_object)]' 
    585  
    586                 get fileName from var 
    587  
    588                 get lineNum from var 
    589  
    590                 get className from var 
    591  
    592                 get memberName from var 
    593  
    594                 get object from var 
    595  
    596                 get runTimeClassName as String 
    597                         return _object.getType.name 
    598  
    599                 def oneLiner(sep as String) as String 
    600                         return .oneLiner(sep, true) 
    601  
    602                 def oneLiner(sep as String, willOutputDirectoryNames as bool) as String 
    603                         test 
    604                                 si = SourceSite('Foo.cobra', 10, 'Object', 'bar', Object()) 
    605                     &