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
26namespace tvm {
27namespace parser {
28
29TVM_REGISTER_NODE_TYPE(SourceNode);
30
31/*! \brief Construct a source from a string. */
32Source::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
62tvm::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
79TVM_REGISTER_NODE_TYPE(SourceMapNode);
80
81SourceMap::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
87void SourceMap::Add(const Source& source) { (*this)->source_map.Set(source->source_name, source); }
88
89TVM_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