Changeset 1574
- Timestamp:
- 08/12/08 23:46:19 (3 months ago)
- Location:
- cobra/trunk
- Files:
-
- 1 added
- 5 modified
-
Developer/IntermediateReleaseNotes.text (modified) (1 diff)
-
Source/CobraParser.cobra (modified) (2 diffs)
-
Source/CobraTokenizer.cobra (modified) (3 diffs)
-
Source/Compiler.cobra (modified) (4 diffs)
-
Source/Tokenizer.cobra (modified) (9 diffs)
-
Tests/800-warnings/400-no-warnings.cobra (added)
Legend:
- Unmodified
- Added
- Removed
-
cobra/trunk/Developer/IntermediateReleaseNotes.text
r1573 r1574 35 35 print 'bar' 36 36 #/ 37 38 * Added support for warning suppression on arbitrary lines by placing a trailing comment containing `.no-warnings.` after the `#` 39 .code 40 this.call() # .no-warnings. 37 41 38 42 * Added support for a Cobra compiler directive to specify the type for `number` -
cobra/trunk/Source/CobraParser.cobra
r1573 r1574 220 220 .throwError(te.token, msg) 221 221 222 # TODO: fold all occcurrences of this lookup to a helper 223 compiler = .typeProvider to? Compiler 224 if compiler, compiler.noWarningLines = tokenizer.noWarningLines 225 222 226 if tokenizer.errors.count 223 227 for error in tokenizer.errors 224 228 .recordError(error.token, error.message) 225 229 226 230 _nextTokenIndex = 0 227 231 … … 549 553 .throwError('Compiler directive "number": unrecognized type "[typeName.text]". Must be one of "decimal", "float", "float32" or "float64".') 550 554 .expect('EOL') 551 comp = .typeProvider to Compiler?555 comp = .typeProvider to? Compiler 552 556 if comp, comp.numberTypeName = typeName.text 553 557 else -
cobra/trunk/Source/CobraTokenizer.cobra
r1572 r1574 1 use System.Text.RegularExpressions 2 3 1 4 class CobraTokenizer 2 5 inherits Tokenizer … … 392 395 #print '<> onWHITESPACE_COMMENT_2' 393 396 return nil 394 397 395 398 ## 396 399 ## Comment out block … … 507 510 return tok 508 511 512 var _directiveRE = Regex(r'#\s*\.([\w\-]+)\.', RegexOptions.Compiled) 513 509 514 def onSINGLE_LINE_COMMENT(tok as IToken) as IToken? 510 515 # eat these 516 517 # check for .no-warnings. 518 reMatch = _directiveRE.match(tok.text) 519 if reMatch.success 520 name = reMatch.groups[1].value 521 branch name 522 on 'no-warnings', .addNoWarning(tok) 523 # for testify 524 on 'args', pass # TODO: actually this could be worth implementing outside of testify 525 on 'compile-only', pass 526 on 'error', pass 527 on 'multi', pass 528 on 'multipart', pass 529 on 'skip', pass 530 on 'warning', pass 531 else, .throwError('Unrecognized compiler directive "[name]".') 532 511 533 return nil 512 534 -
cobra/trunk/Source/Compiler.cobra
r1569 r1574 75 75 var _messages as List<of SourceException> # all errors and warnings 76 76 var _messagesPerSourceLine as IDictionary<of String, List<of SourceException>> # key is 'filename:lineNum' 77 var _noWarningLines as ISet<of String> # key is 'filename:lineNum' 77 78 78 79 var _intermediateFileNames as List<of String> … … 105 106 _messages = List<of SourceException>() 106 107 _messagesPerSourceLine = Dictionary<of String, List<of SourceException>>() 108 _noWarningLines = Set<of String>() 107 109 _errors = List<of SourceException>() 108 110 _warnings = List<of SourceException>() … … 182 184 183 185 get messages from var 186 187 pro noWarningLines from var 184 188 185 189 pro htmlWriter from var … … 1154 1158 def warning(cw as CobraWarning) 1155 1159 require not cw.isError 1160 if _suppressWarning(cw), return 1156 1161 _addMessage(cw) 1157 1162 1163 def _suppressWarning(cw as CobraWarning) as bool 1164 # TODO: add suppress all warnings (cmdline sw) - maybe? 1165 # TODO: add suppress by error tag - maybe? 1166 entry = if(cw.hasSourceSite, '[cw.fileName]:[cw.lineNum]', '') 1167 return _noWarningLines.contains(entry) 1168 1158 1169 def augmentWarning(node as ISyntaxNode, lookFor as String, search as String, augment as String) as bool 1159 1170 require -
cobra/trunk/Source/Tokenizer.cobra
r1571 r1574 301 301 var _tokenDefsByFirstChar as Dictionary<of char, List<of TokenDef>>? 302 302 var _tokenDefsByWhich as Dictionary<of String, TokenDef>? 303 var _noWarningLines as ISet<of String> 303 304 var _curTokenDef as TokenDef? 304 305 var _lastTokenDef as TokenDef? … … 315 316 316 317 def init 318 # before adding code here, consider if it should go in _reset or _reuse instead 317 319 _didReset = false 318 320 _reset() … … 369 371 get tokenDefsByWhich from var 370 372 373 get noWarningLines from var 371 374 372 375 ## Other … … 385 388 """ 386 389 _errors = List<of TokenizerError>() 390 _noWarningLines = Set<of String>() 387 391 _curToken = nil 388 392 _lastToken = nil … … 437 441 """ 438 442 tokens = List<of IToken>() 443 start = DateTime.now 439 444 while true 440 445 t = .nextToken 441 if t 442 tokens.add(t) 443 else 444 break 446 if t, tokens.add(t) 447 else, break 448 # determine timings for various Tokenizer lexing changes 449 if false # CC: can use /# ... #/ in the future 450 duration = DateTime.now.subtract(start) 451 if tokens.count > 100 and duration > TimeSpan(0) 452 ticksPerToken = (duration.ticks to int) / tokens.count 453 ticksPerTokenMS = ticksPerToken / 10_000 454 fileName = _fileName 455 if fileName.startsWith('('), fileName = '(None)' 456 else, fileName = Path.getFileName(fileName) 457 print '[fileName.padRight(20)]\t[duration]\t[tokens.count]\t' stop 458 print ' [ticksPerTokenMS:N3] ms/Token av ([ticksPerTokenMS/1000:N3]sec)' 445 459 return tokens 446 460 … … 592 606 try 593 607 assert _tokenDefs 594 if _narrowTokenDefs and _tokenDefs.count >= _minNumTokenDefsToNarrow 595 assert _tokenDefsByFirstChar 596 assert _sourceLine.length 597 if _tokenDefsByFirstChar.containsKey(_sourceLine[0]) 598 # print 'Using short list for char: [_sourceLine[0]], [_sourceLine[0] to int]' 599 tokenDefs = _tokenDefsByFirstChar[_sourceLine[0]] 600 else 601 tokenDefs = _tokenDefs to ! 602 else 603 tokenDefs = _tokenDefs to ! 608 tokenDefs = _getCandidateTokenDefs(_sourceLine) 604 609 for tokenDef in tokenDefs 605 610 count += 1 606 if tokenDef.ignoreCount 607 tokenDef.ignoreCount -= 1 608 continue 609 if not tokenDef.isActive 610 continue 611 if _sourceLineIndex>0 and tokenDef.requiresBOL 612 continue 613 if not .isActiveCall(tokenDef) 611 if _skipMatchAttempt(tokenDef, _sourceLineIndex) 614 612 continue 615 613 #print '<> Trying to match [tokenDef]' … … 635 633 # enable methods to customize handling of tokens 636 634 reinvoke = false 637 638 which = tok.which 639 if _onTokenTypeCache.containsKey(which) 640 meth = _onTokenTypeCache[which] 641 else 642 methName = 'On' + which 643 meth = .getType.getMethod(methName) 644 _onTokenTypeCache[which] = meth 645 635 meth = _getTokenMethod(tok.which) 646 636 if meth 647 try 648 tok = meth.invoke(this, @[tok]) to IToken? 649 catch tie as TargetInvocationException 650 throw tie.innerException 651 if tok is nil 652 # skip token, so go to the next one 653 reinvoke = true 654 else 655 # TODO: could probably make this more efficient by axing the queue and just checking for nextToken in this method 656 while tok 657 _tokenQueue.enqueue(tok) 658 tok = tok.nextToken 659 reinvoke = true # to pick up the queue 637 tok = _tokenPostProcess(meth, tok) 638 # nil indicates skipped token - will re call this method 639 if not tok 640 reinvoke = true # to pick up next token after skipped 660 641 661 642 # finished with current line? … … 689 670 _avgCount += count 690 671 _avgCountNum += 1 672 673 def _getCandidateTokenDefs(sourceLine as String?) as List<of TokenDef> 674 if _narrowTokenDefs and _tokenDefs.count >= _minNumTokenDefsToNarrow 675 assert _tokenDefsByFirstChar 676 assert _sourceLine.length 677 if _tokenDefsByFirstChar.containsKey(_sourceLine[0]) 678 # print 'Using short list for char: [_sourceLine[0]], [_sourceLine[0] to int]' 679 return _tokenDefsByFirstChar[_sourceLine[0]] 680 return _tokenDefs to ! 681 682 def _skipMatchAttempt(tokenDef as TokenDef, sourceLineIndex as int) as bool 683 if tokenDef.ignoreCount 684 tokenDef.ignoreCount -= 1 685 return true 686 if not tokenDef.isActive 687 return true 688 if sourceLineIndex>0 and tokenDef.requiresBOL 689 return true 690 if not .isActiveCall(tokenDef) 691 return true 692 return false 693 694 def _getTokenMethod(which as String) as MethodInfo? 695 """ 696 Get method for token (On<WHICH>) using reflection. 697 Caching is used to boost performance. 698 """ 699 if not _onTokenTypeCache.containsKey(which) # not already in methods cache 700 methName = 'On' + which 701 meth = .getType.getMethod(methName) 702 _onTokenTypeCache[which] = meth 703 else 704 meth = _onTokenTypeCache[which] 705 return meth 706 707 def _tokenPostProcess(meth as MethodInfo, tok as IToken?) as IToken? 708 """ 709 Invoke any tokenMethod and return the result which could the same token, a replacement 710 token or nil to skip the token. Any token returned could be the start of a token chain 711 via token.nextToken. 712 """ 713 try 714 tok = meth.invoke(this, @[tok]) to IToken? 715 catch tie as TargetInvocationException 716 throw tie.innerException 717 if not tok 718 return nil # token is to be skipped 719 retTok = tok 720 tok = tok.nextToken 721 while tok 722 # TODO: could probably make this more efficient by axing the queue and just checking for nextToken in this method 723 _tokenQueue.enqueue(tok) # store any token chain returned by method call 724 tok = tok.nextToken 725 return retTok 691 726 692 727 def pushTokenDefs(defs as List<of TokenDef>) … … 763 798 throw .recordError(msg) 764 799 800 def addNoWarning(token as IToken) 801 _noWarningLines.add('[token.fileName]:[token.lineNum]') 802 765 803 def checkTokens(tokens as List<of IToken>, expected as String) 766 804 is shared
