ast-source-ranges.h 8.32 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_AST_AST_SOURCE_RANGES_H_
#define V8_AST_AST_SOURCE_RANGES_H_

#include "src/ast/ast.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {

// Specifies a range within the source code. {start} is 0-based and inclusive,
// {end} is 0-based and exclusive.
struct SourceRange {
  SourceRange() : SourceRange(kNoSourcePosition, kNoSourcePosition) {}
  SourceRange(int start, int end) : start(start), end(end) {}
  bool IsEmpty() const { return start == kNoSourcePosition; }
  static SourceRange Empty() { return SourceRange(); }
  static SourceRange OpenEnded(int32_t start) {
    return SourceRange(start, kNoSourcePosition);
  }
24 25 26
  static SourceRange ContinuationOf(const SourceRange& that,
                                    int end = kNoSourcePosition) {
    return that.IsEmpty() ? Empty() : SourceRange(that.end, end);
27 28 29 30
  }
  int32_t start, end;
};

31 32
// The list of ast node kinds that have associated source ranges. Note that this
// macro is not undefined at the end of this file.
33
#define AST_SOURCE_RANGE_LIST(V) \
34
  V(BinaryOperation)             \
35
  V(Block)                       \
36
  V(CaseClause)                  \
37
  V(Conditional)                 \
38 39 40
  V(IfStatement)                 \
  V(IterationStatement)          \
  V(JumpStatement)               \
41
  V(NaryOperation)               \
42
  V(Suspend)                     \
43 44 45 46 47 48 49 50 51 52 53
  V(SwitchStatement)             \
  V(Throw)                       \
  V(TryCatchStatement)           \
  V(TryFinallyStatement)

enum class SourceRangeKind {
  kBody,
  kCatch,
  kContinuation,
  kElse,
  kFinally,
54
  kRight,
55 56 57 58 59
  kThen,
};

class AstNodeSourceRanges : public ZoneObject {
 public:
60
  virtual ~AstNodeSourceRanges() = default;
61 62 63
  virtual SourceRange GetRange(SourceRangeKind kind) = 0;
};

64 65 66 67 68
class BinaryOperationSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit BinaryOperationSourceRanges(const SourceRange& right_range)
      : right_range_(right_range) {}

69
  SourceRange GetRange(SourceRangeKind kind) override {
70 71 72 73 74 75 76 77
    DCHECK_EQ(kind, SourceRangeKind::kRight);
    return right_range_;
  }

 private:
  SourceRange right_range_;
};

78 79 80 81 82
class ContinuationSourceRanges : public AstNodeSourceRanges {
 public:
  explicit ContinuationSourceRanges(int32_t continuation_position)
      : continuation_position_(continuation_position) {}

83
  SourceRange GetRange(SourceRangeKind kind) override {
84
    DCHECK_EQ(kind, SourceRangeKind::kContinuation);
85 86 87 88 89 90 91
    return SourceRange::OpenEnded(continuation_position_);
  }

 private:
  int32_t continuation_position_;
};

92 93 94 95 96 97
class BlockSourceRanges final : public ContinuationSourceRanges {
 public:
  explicit BlockSourceRanges(int32_t continuation_position)
      : ContinuationSourceRanges(continuation_position) {}
};

98 99 100 101 102
class CaseClauseSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit CaseClauseSourceRanges(const SourceRange& body_range)
      : body_range_(body_range) {}

103
  SourceRange GetRange(SourceRangeKind kind) override {
104
    DCHECK_EQ(kind, SourceRangeKind::kBody);
105 106 107 108 109 110 111
    return body_range_;
  }

 private:
  SourceRange body_range_;
};

112 113 114 115 116 117
class ConditionalSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit ConditionalSourceRanges(const SourceRange& then_range,
                                   const SourceRange& else_range)
      : then_range_(then_range), else_range_(else_range) {}

118
  SourceRange GetRange(SourceRangeKind kind) override {
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
    switch (kind) {
      case SourceRangeKind::kThen:
        return then_range_;
      case SourceRangeKind::kElse:
        return else_range_;
      default:
        UNREACHABLE();
    }
  }

 private:
  SourceRange then_range_;
  SourceRange else_range_;
};

134 135 136 137 138 139
class IfStatementSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit IfStatementSourceRanges(const SourceRange& then_range,
                                   const SourceRange& else_range)
      : then_range_(then_range), else_range_(else_range) {}

140
  SourceRange GetRange(SourceRangeKind kind) override {
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    switch (kind) {
      case SourceRangeKind::kElse:
        return else_range_;
      case SourceRangeKind::kThen:
        return then_range_;
      case SourceRangeKind::kContinuation: {
        const SourceRange& trailing_range =
            else_range_.IsEmpty() ? then_range_ : else_range_;
        return SourceRange::ContinuationOf(trailing_range);
      }
      default:
        UNREACHABLE();
    }
  }

 private:
  SourceRange then_range_;
  SourceRange else_range_;
};

class IterationStatementSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit IterationStatementSourceRanges(const SourceRange& body_range)
      : body_range_(body_range) {}

166
  SourceRange GetRange(SourceRangeKind kind) override {
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
    switch (kind) {
      case SourceRangeKind::kBody:
        return body_range_;
      case SourceRangeKind::kContinuation:
        return SourceRange::ContinuationOf(body_range_);
      default:
        UNREACHABLE();
    }
  }

 private:
  SourceRange body_range_;
};

class JumpStatementSourceRanges final : public ContinuationSourceRanges {
 public:
  explicit JumpStatementSourceRanges(int32_t continuation_position)
      : ContinuationSourceRanges(continuation_position) {}
};

187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
class NaryOperationSourceRanges final : public AstNodeSourceRanges {
 public:
  NaryOperationSourceRanges(Zone* zone, const SourceRange& range)
      : ranges_(zone) {
    AddRange(range);
  }

  SourceRange GetRangeAtIndex(size_t index) {
    DCHECK(index < ranges_.size());
    return ranges_[index];
  }

  void AddRange(const SourceRange& range) { ranges_.push_back(range); }
  size_t RangeCount() const { return ranges_.size(); }

202
  SourceRange GetRange(SourceRangeKind kind) override { UNREACHABLE(); }
203 204 205 206 207

 private:
  ZoneVector<SourceRange> ranges_;
};

208 209 210 211 212 213
class SuspendSourceRanges final : public ContinuationSourceRanges {
 public:
  explicit SuspendSourceRanges(int32_t continuation_position)
      : ContinuationSourceRanges(continuation_position) {}
};

214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
class SwitchStatementSourceRanges final : public ContinuationSourceRanges {
 public:
  explicit SwitchStatementSourceRanges(int32_t continuation_position)
      : ContinuationSourceRanges(continuation_position) {}
};

class ThrowSourceRanges final : public ContinuationSourceRanges {
 public:
  explicit ThrowSourceRanges(int32_t continuation_position)
      : ContinuationSourceRanges(continuation_position) {}
};

class TryCatchStatementSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit TryCatchStatementSourceRanges(const SourceRange& catch_range)
      : catch_range_(catch_range) {}

231
  SourceRange GetRange(SourceRangeKind kind) override {
232 233 234 235 236 237 238 239
    switch (kind) {
      case SourceRangeKind::kCatch:
        return catch_range_;
      case SourceRangeKind::kContinuation:
        return SourceRange::ContinuationOf(catch_range_);
      default:
        UNREACHABLE();
    }
240 241 242 243 244 245 246 247 248 249 250
  }

 private:
  SourceRange catch_range_;
};

class TryFinallyStatementSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit TryFinallyStatementSourceRanges(const SourceRange& finally_range)
      : finally_range_(finally_range) {}

251
  SourceRange GetRange(SourceRangeKind kind) override {
252 253 254 255 256 257 258 259
    switch (kind) {
      case SourceRangeKind::kFinally:
        return finally_range_;
      case SourceRangeKind::kContinuation:
        return SourceRange::ContinuationOf(finally_range_);
      default:
        UNREACHABLE();
    }
260 261 262 263 264 265 266 267 268 269 270 271
  }

 private:
  SourceRange finally_range_;
};

// Maps ast node pointers to associated source ranges. The parser creates these
// mappings and the bytecode generator consumes them.
class SourceRangeMap final : public ZoneObject {
 public:
  explicit SourceRangeMap(Zone* zone) : map_(zone) {}

272
  AstNodeSourceRanges* Find(ZoneObject* node) {
273 274 275 276 277 278 279 280
    auto it = map_.find(node);
    if (it == map_.end()) return nullptr;
    return it->second;
  }

// Type-checked insertion.
#define DEFINE_MAP_INSERT(type)                         \
  void Insert(type* node, type##SourceRanges* ranges) { \
281
    DCHECK_NOT_NULL(node);                              \
282 283 284 285 286 287
    map_.emplace(node, ranges);                         \
  }
  AST_SOURCE_RANGE_LIST(DEFINE_MAP_INSERT)
#undef DEFINE_MAP_INSERT

 private:
288
  ZoneMap<ZoneObject*, AstNodeSourceRanges*> map_;
289 290 291 292 293 294
};

}  // namespace internal
}  // namespace v8

#endif  // V8_AST_AST_SOURCE_RANGES_H_