Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: runtime/vm/object.cc

Issue 219993004: Fix line number table generation for multiline strings with interpolation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/scanner.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 7555 matching lines...) Expand 10 before | Expand all | Expand 10 after
7566 return raw_ptr()->source_; 7566 return raw_ptr()->source_;
7567 } 7567 }
7568 7568
7569 7569
7570 RawString* Script::GenerateSource() const { 7570 RawString* Script::GenerateSource() const {
7571 const TokenStream& token_stream = TokenStream::Handle(tokens()); 7571 const TokenStream& token_stream = TokenStream::Handle(tokens());
7572 return token_stream.GenerateSource(); 7572 return token_stream.GenerateSource();
7573 } 7573 }
7574 7574
7575 7575
7576 RawGrowableObjectArray* Script::GenerateLineNumberArray() const {
7577 const GrowableObjectArray& info =
7578 GrowableObjectArray::Handle(GrowableObjectArray::New());
7579 const String& source = String::Handle(Source());
7580 const String& key = Symbols::Empty();
7581 const Object& line_separator = Object::Handle();
7582 const TokenStream& tkns = TokenStream::Handle(tokens());
7583 ASSERT(!tkns.IsNull());
7584 TokenStream::Iterator tkit(tkns, 0, TokenStream::Iterator::kAllTokens);
7585 int current_line = -1;
7586 Scanner s(source, key);
7587 s.Scan();
7588 bool skippedNewline = false;
7589 while (tkit.CurrentTokenKind() != Token::kEOS) {
7590 if (tkit.CurrentTokenKind() == Token::kNEWLINE) {
7591 // Skip newlines from the token stream.
7592 skippedNewline = true;
7593 tkit.Advance();
7594 continue;
7595 }
7596 if (s.current_token().kind != tkit.CurrentTokenKind()) {
7597 // Suppose we have a multiline string with interpolation:
7598 //
7599 // 10 '''
7600 // 11 bar
7601 // 12 baz
7602 // 13 foo is $foo
7603 // 14 '''
7604 //
7605 // In the token stream, this becomes something like:
7606 //
7607 // 10 string('bar\nbaz\nfoo is\n')
7608 // 11 newline
7609 // 12 newline
7610 // 13 string('') interpol_var(foo)
hausner 2014/03/31 23:11:32 interpol_var is followed at the end by a string co
turnidge 2014/04/01 18:06:05 Done.
7611 // 14
7612 //
7613 // In order to keep the token iterator and the scanner in sync,
7614 // we need to skip the extra empty string before the
7615 // interpolation.
7616 if (skippedNewline &&
7617 (s.current_token().kind == Token::kINTERPOL_VAR ||
7618 s.current_token().kind == Token::kINTERPOL_START) &&
7619 tkit.CurrentTokenKind() == Token::kSTRING) {
7620 const String& tokenValue = String::Handle(tkit.CurrentLiteral());
7621 if (tokenValue.Length() == 0) {
7622 tkit.Advance();
7623 }
7624 }
7625 }
7626 skippedNewline = false;
7627 ASSERT(s.current_token().kind == tkit.CurrentTokenKind());
7628 int token_line = s.current_token().position.line;
7629 if (token_line != current_line) {
7630 // emit line
7631 info.Add(line_separator);
7632 info.Add(Smi::Handle(Smi::New(token_line + line_offset())));
7633 current_line = token_line;
7634 }
7635 // TODO(hausner): Could optimize here by not reporting tokens
7636 // that will never be a location used by the debugger, e.g.
7637 // braces, semicolons, most keywords etc.
7638 info.Add(Smi::Handle(Smi::New(tkit.CurrentPosition())));
7639 int column = s.current_token().position.column;
7640 // On the first line of the script we must add the column offset.
7641 if (token_line == 1) {
7642 column += col_offset();
7643 }
7644 info.Add(Smi::Handle(Smi::New(column)));
7645 tkit.Advance();
7646 s.Scan();
7647 }
7648 return info.raw();
7649 }
7650
7651
7576 const char* Script::GetKindAsCString() const { 7652 const char* Script::GetKindAsCString() const {
7577 switch (kind()) { 7653 switch (kind()) {
7578 case RawScript::kScriptTag: 7654 case RawScript::kScriptTag:
7579 return "script"; 7655 return "script";
7580 case RawScript::kLibraryTag: 7656 case RawScript::kLibraryTag:
7581 return "library"; 7657 return "library";
7582 case RawScript::kSourceTag: 7658 case RawScript::kSourceTag:
7583 return "source"; 7659 return "source";
7584 case RawScript::kPatchTag: 7660 case RawScript::kPatchTag:
7585 return "patch"; 7661 return "patch";
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
7855 if (ref) { 7931 if (ref) {
7856 return; 7932 return;
7857 } 7933 }
7858 const String& source = String::Handle(Source()); 7934 const String& source = String::Handle(Source());
7859 jsobj.AddProperty("source", source.ToCString()); 7935 jsobj.AddProperty("source", source.ToCString());
7860 7936
7861 // Print the line number table 7937 // Print the line number table
7862 { 7938 {
7863 JSONArray tokenPosTable(&jsobj, "tokenPosTable"); 7939 JSONArray tokenPosTable(&jsobj, "tokenPosTable");
7864 7940
7865 const TokenStream& tokenStream = TokenStream::Handle(tokens()); 7941 const GrowableObjectArray& lineNumberArray =
7866 ASSERT(!tokenStream.IsNull()); 7942 GrowableObjectArray::Handle(GenerateLineNumberArray());
7867 TokenStream::Iterator tokens(tokenStream, 0); 7943 Object& value = Object::Handle();
7944 intptr_t pos = 0;
7868 7945
7869 const String& key = Symbols::Empty(); 7946 // Skip leading null.
7870 Scanner scanner(source, key); 7947 ASSERT(lineNumberArray.Length() > 0);
7871 scanner.Scan(); 7948 value = lineNumberArray.At(pos);
7872 while (scanner.current_token().kind != Token::kEOS) { 7949 ASSERT(value.IsNull());
7873 ASSERT(tokens.IsValid()); 7950 pos++;
7874 ASSERT(scanner.current_token().kind == tokens.CurrentTokenKind());
7875 int current_line = scanner.current_token().position.line;
7876 7951
7877 // Each entry begins with a line number... 7952 while (pos < lineNumberArray.Length()) {
7878 JSONArray lineInfo(&tokenPosTable); 7953 JSONArray lineInfo(&tokenPosTable);
7879 lineInfo.AddValue(current_line + line_offset()); 7954 while (pos < lineNumberArray.Length()) {
7880 7955 value = lineNumberArray.At(pos);
7881 // ...and is followed by (token offset, col number) pairs. 7956 pos++;
7882 // 7957 if (value.IsNull()) {
7883 // TODO(hausner): Could optimize here by not reporting tokens
7884 // that will never be a location used by the debugger, e.g.
7885 // braces, semicolons, most keywords etc.
7886 while (scanner.current_token().kind != Token::kEOS) {
7887 ASSERT(tokens.IsValid());
7888 ASSERT(scanner.current_token().kind == tokens.CurrentTokenKind());
7889
7890 int token_line = scanner.current_token().position.line;
7891 if (token_line != current_line) {
7892 // We have hit a new line. Break to the outer loop.
7893 break; 7958 break;
7894 } 7959 }
7895 lineInfo.AddValue(tokens.CurrentPosition()); 7960 const Smi& smi = Smi::Cast(value);
7896 7961 lineInfo.AddValue(smi.Value());
7897 intptr_t column = scanner.current_token().position.column;
7898 if (token_line == 1) {
7899 // On the first line of the script we must add the column offset.
7900 column += col_offset();
7901 }
7902 lineInfo.AddValue(column);
7903 scanner.Scan();
7904 tokens.Advance();
7905 } 7962 }
7906 } 7963 }
7907 } 7964 }
7908 } 7965 }
7909 7966
7910 7967
7911 DictionaryIterator::DictionaryIterator(const Library& library) 7968 DictionaryIterator::DictionaryIterator(const Library& library)
7912 : array_(Array::Handle(library.dictionary())), 7969 : array_(Array::Handle(library.dictionary())),
7913 // Last element in array is a Smi indicating the number of entries used. 7970 // Last element in array is a Smi indicating the number of entries used.
7914 size_(Array::Handle(library.dictionary()).Length() - 1), 7971 size_(Array::Handle(library.dictionary()).Length() - 1),
(...skipping 10347 matching lines...) Expand 10 before | Expand all | Expand 10 after
18262 return "_MirrorReference"; 18319 return "_MirrorReference";
18263 } 18320 }
18264 18321
18265 18322
18266 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { 18323 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const {
18267 Instance::PrintToJSONStream(stream, ref); 18324 Instance::PrintToJSONStream(stream, ref);
18268 } 18325 }
18269 18326
18270 18327
18271 } // namespace dart 18328 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/scanner.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698