1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one |
3 | * or more contributor license agreements. See the NOTICE file |
4 | * distributed with this work for additional information |
5 | * regarding copyright ownership. The ASF licenses this file |
6 | * to you under the Apache License, Version 2.0 (the |
7 | * "License"); you may not use this file except in compliance |
8 | * with the License. You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, |
13 | * software distributed under the License is distributed on an |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | * KIND, either express or implied. See the License for the |
16 | * specific language governing permissions and limitations |
17 | * under the License. |
18 | */ |
19 | /*! |
20 | * \file source_map.cc |
21 | * \brief The implementation of the source map data structure. |
22 | */ |
23 | #include <tvm/parser/source_map.h> |
24 | #include <tvm/runtime/registry.h> |
25 | |
26 | namespace tvm { |
27 | namespace parser { |
28 | |
29 | TVM_REGISTER_NODE_TYPE(SourceNode); |
30 | |
31 | /*! \brief Construct a source from a string. */ |
32 | Source::Source(SourceName src_name, std::string source) { |
33 | auto n = make_object<SourceNode>(); |
34 | n->source_name = std::move(src_name); |
35 | n->source = std::move(source); |
36 | |
37 | int index = 0; |
38 | int length = 0; |
39 | n->line_map.push_back({index, length}); |
40 | // NB(@jroesch): |
41 | std::string source_str = n->source; |
42 | for (auto c : source_str) { |
43 | if (c == '\n') { |
44 | // Record the length of the line. |
45 | n->line_map.back().second = length; |
46 | // Bump past the newline. |
47 | index += 1; |
48 | // Record the start of the next line, and put placeholder for length. |
49 | n->line_map.push_back({index, 0}); |
50 | // Reset length to zero. |
51 | length = 0; |
52 | } else { |
53 | length += 1; |
54 | index += 1; |
55 | } |
56 | } |
57 | n->line_map.back().second = length; |
58 | |
59 | data_ = n; |
60 | } |
61 | |
62 | tvm::String Source::GetLine(int line) { |
63 | VLOG(1) << "Source::GetLine: line=" << line; |
64 | ICHECK(line - 1 < static_cast<int64_t>((*this)->line_map.size())) |
65 | << "requested line: " << line << "at index: " << (line - 1) |
66 | << "line_map size: " << (*this)->line_map.size() << "source: " << (*this)->source; |
67 | |
68 | // Adjust for zero indexing, now have (line_start, line_length); |
69 | auto range = (*this)->line_map.at(line - 1); |
70 | int line_start = range.first; |
71 | int line_length = range.second; |
72 | VLOG(1) << "Source::GetLine: line_start=" << line_start << " line_length=" << line_length; |
73 | // TODO(@jroesch): expose substring on tvm::String. |
74 | auto line_text = std::string((*this)->source).substr(line_start, line_length); |
75 | VLOG(1) << "Source::GetLine: line_text=" << line_text; |
76 | return line_text; |
77 | } |
78 | |
79 | TVM_REGISTER_NODE_TYPE(SourceMapNode); |
80 | |
81 | SourceMap::SourceMap(Map<SourceName, Source> source_map) { |
82 | auto n = make_object<SourceMapNode>(); |
83 | n->source_map = std::move(source_map); |
84 | data_ = std::move(n); |
85 | } |
86 | |
87 | void SourceMap::Add(const Source& source) { (*this)->source_map.Set(source->source_name, source); } |
88 | |
89 | TVM_REGISTER_GLOBAL("SourceMapAdd" ).set_body_typed([](SourceMap map, String name, String content) { |
90 | auto src_name = SourceName::Get(name); |
91 | Source source(src_name, content); |
92 | map.Add(source); |
93 | return src_name; |
94 | }); |
95 | |
96 | } // namespace parser |
97 | } // namespace tvm |
98 | |