| 59 | } |
| 60 | |
| 61 | SourceLocation Ast::ComputeSourceLocation(int64_t expr_id) const { |
| 62 | const auto& source_info = this->source_info(); |
| 63 | auto iter = source_info.positions().find(expr_id); |
| 64 | if (iter == source_info.positions().end()) { |
| 65 | return SourceLocation{}; |
| 66 | } |
| 67 | int32_t absolute_position = iter->second; |
| 68 | if (absolute_position < 0) { |
| 69 | return SourceLocation{}; |
| 70 | } |
| 71 | |
| 72 | // Find the first line offset that is greater than the absolute position. |
| 73 | int32_t line_idx = -1; |
| 74 | int32_t offset = 0; |
| 75 | for (int32_t i = 0; i < source_info.line_offsets().size(); ++i) { |
| 76 | int32_t next_offset = source_info.line_offsets()[i]; |
| 77 | if (next_offset <= offset) { |
| 78 | // Line offset is not monotonically increasing, so line information is |
| 79 | // invalid. |
| 80 | return SourceLocation{}; |
| 81 | } |
| 82 | if (absolute_position < next_offset) { |
| 83 | line_idx = i; |
| 84 | break; |
| 85 | } |
| 86 | offset = next_offset; |
| 87 | } |
| 88 | |
| 89 | if (line_idx < 0 || line_idx >= source_info.line_offsets().size()) { |
| 90 | return SourceLocation{}; |
| 91 | } |
| 92 | |
| 93 | int32_t rel_position = absolute_position - offset; |
| 94 | |
| 95 | return SourceLocation{line_idx + 1, rel_position}; |
| 96 | } |
| 97 | |
| 98 | } // namespace cel |