ast-source-ranges.h 11.5 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 31 32 33 34 35 36 37 38 39

  static constexpr int kFunctionLiteralSourcePosition = -2;
  STATIC_ASSERT(kFunctionLiteralSourcePosition == kNoSourcePosition - 1);

  // Source ranges associated with a function literal do not contain real
  // source positions; instead, they are created with special marker values.
  // These are later recognized and rewritten during processing in
  // Coverage::Collect().
  static SourceRange FunctionLiteralMarkerRange() {
    return {kFunctionLiteralSourcePosition, kFunctionLiteralSourcePosition};
  }

40 41 42
  int32_t start, end;
};

43 44
// The list of ast node kinds that have associated source ranges. Note that this
// macro is not undefined at the end of this file.
45
#define AST_SOURCE_RANGE_LIST(V) \
46
  V(BinaryOperation)             \
47
  V(Block)                       \
48
  V(CaseClause)                  \
49
  V(Conditional)                 \
50
  V(FunctionLiteral)             \
51 52 53
  V(IfStatement)                 \
  V(IterationStatement)          \
  V(JumpStatement)               \
54
  V(NaryOperation)               \
55
  V(Suspend)                     \
56 57 58 59 60 61 62 63 64 65 66
  V(SwitchStatement)             \
  V(Throw)                       \
  V(TryCatchStatement)           \
  V(TryFinallyStatement)

enum class SourceRangeKind {
  kBody,
  kCatch,
  kContinuation,
  kElse,
  kFinally,
67
  kRight,
68 69 70 71 72
  kThen,
};

class AstNodeSourceRanges : public ZoneObject {
 public:
73
  virtual ~AstNodeSourceRanges() = default;
74
  virtual SourceRange GetRange(SourceRangeKind kind) = 0;
75 76
  virtual bool HasRange(SourceRangeKind kind) = 0;
  virtual void RemoveContinuationRange() { UNREACHABLE(); }
77 78
};

79 80 81 82 83
class BinaryOperationSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit BinaryOperationSourceRanges(const SourceRange& right_range)
      : right_range_(right_range) {}

84
  SourceRange GetRange(SourceRangeKind kind) override {
85
    DCHECK(HasRange(kind));
86 87 88
    return right_range_;
  }

89 90 91 92
  bool HasRange(SourceRangeKind kind) override {
    return kind == SourceRangeKind::kRight;
  }

93 94 95 96
 private:
  SourceRange right_range_;
};

97 98 99 100 101
class ContinuationSourceRanges : public AstNodeSourceRanges {
 public:
  explicit ContinuationSourceRanges(int32_t continuation_position)
      : continuation_position_(continuation_position) {}

102
  SourceRange GetRange(SourceRangeKind kind) override {
103
    DCHECK(HasRange(kind));
104 105 106
    return SourceRange::OpenEnded(continuation_position_);
  }

107 108 109 110 111 112 113 114 115
  bool HasRange(SourceRangeKind kind) override {
    return kind == SourceRangeKind::kContinuation;
  }

  void RemoveContinuationRange() override {
    DCHECK(HasRange(SourceRangeKind::kContinuation));
    continuation_position_ = kNoSourcePosition;
  }

116 117 118 119
 private:
  int32_t continuation_position_;
};

120 121 122 123 124 125
class BlockSourceRanges final : public ContinuationSourceRanges {
 public:
  explicit BlockSourceRanges(int32_t continuation_position)
      : ContinuationSourceRanges(continuation_position) {}
};

126 127 128 129 130
class CaseClauseSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit CaseClauseSourceRanges(const SourceRange& body_range)
      : body_range_(body_range) {}

131
  SourceRange GetRange(SourceRangeKind kind) override {
132
    DCHECK(HasRange(kind));
133 134 135
    return body_range_;
  }

136 137 138 139
  bool HasRange(SourceRangeKind kind) override {
    return kind == SourceRangeKind::kBody;
  }

140 141 142 143
 private:
  SourceRange body_range_;
};

144 145 146 147 148 149
class ConditionalSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit ConditionalSourceRanges(const SourceRange& then_range,
                                   const SourceRange& else_range)
      : then_range_(then_range), else_range_(else_range) {}

150
  SourceRange GetRange(SourceRangeKind kind) override {
151
    DCHECK(HasRange(kind));
152 153 154 155 156 157 158 159 160 161
    switch (kind) {
      case SourceRangeKind::kThen:
        return then_range_;
      case SourceRangeKind::kElse:
        return else_range_;
      default:
        UNREACHABLE();
    }
  }

162 163 164 165
  bool HasRange(SourceRangeKind kind) override {
    return kind == SourceRangeKind::kThen || kind == SourceRangeKind::kElse;
  }

166 167 168 169 170
 private:
  SourceRange then_range_;
  SourceRange else_range_;
};

171 172 173 174 175 176 177 178 179 180 181 182
class FunctionLiteralSourceRanges final : public AstNodeSourceRanges {
 public:
  SourceRange GetRange(SourceRangeKind kind) override {
    DCHECK(HasRange(kind));
    return SourceRange::FunctionLiteralMarkerRange();
  }

  bool HasRange(SourceRangeKind kind) override {
    return kind == SourceRangeKind::kBody;
  }
};

183 184 185 186 187 188
class IfStatementSourceRanges final : public AstNodeSourceRanges {
 public:
  explicit IfStatementSourceRanges(const SourceRange& then_range,
                                   const SourceRange& else_range)
      : then_range_(then_range), else_range_(else_range) {}

189
  SourceRange GetRange(SourceRangeKind kind) override {
190
    DCHECK(HasRange(kind));
191 192 193 194 195 196
    switch (kind) {
      case SourceRangeKind::kElse:
        return else_range_;
      case SourceRangeKind::kThen:
        return then_range_;
      case SourceRangeKind::kContinuation: {
197
        if (!has_continuation_) return SourceRange::Empty();
198 199 200 201 202 203 204 205 206
        const SourceRange& trailing_range =
            else_range_.IsEmpty() ? then_range_ : else_range_;
        return SourceRange::ContinuationOf(trailing_range);
      }
      default:
        UNREACHABLE();
    }
  }

207 208 209 210 211 212 213 214 215 216
  bool HasRange(SourceRangeKind kind) override {
    return kind == SourceRangeKind::kThen || kind == SourceRangeKind::kElse ||
           kind == SourceRangeKind::kContinuation;
  }

  void RemoveContinuationRange() override {
    DCHECK(HasRange(SourceRangeKind::kContinuation));
    has_continuation_ = false;
  }

217 218 219
 private:
  SourceRange then_range_;
  SourceRange else_range_;
220
  bool has_continuation_ = true;
221 222 223 224 225 226 227
};

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

228
  SourceRange GetRange(SourceRangeKind kind) override {
229
    DCHECK(HasRange(kind));
230 231 232 233
    switch (kind) {
      case SourceRangeKind::kBody:
        return body_range_;
      case SourceRangeKind::kContinuation:
234
        if (!has_continuation_) return SourceRange::Empty();
235 236 237 238 239 240
        return SourceRange::ContinuationOf(body_range_);
      default:
        UNREACHABLE();
    }
  }

241 242 243 244 245 246 247 248 249 250
  bool HasRange(SourceRangeKind kind) override {
    return kind == SourceRangeKind::kBody ||
           kind == SourceRangeKind::kContinuation;
  }

  void RemoveContinuationRange() override {
    DCHECK(HasRange(SourceRangeKind::kContinuation));
    has_continuation_ = false;
  }

251 252
 private:
  SourceRange body_range_;
253
  bool has_continuation_ = true;
254 255 256 257 258 259 260 261
};

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

262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
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(); }

277
  SourceRange GetRange(SourceRangeKind kind) override { UNREACHABLE(); }
278
  bool HasRange(SourceRangeKind kind) override { return false; }
279 280 281 282 283

 private:
  ZoneVector<SourceRange> ranges_;
};

284 285 286 287 288 289
class SuspendSourceRanges final : public ContinuationSourceRanges {
 public:
  explicit SuspendSourceRanges(int32_t continuation_position)
      : ContinuationSourceRanges(continuation_position) {}
};

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
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) {}

307
  SourceRange GetRange(SourceRangeKind kind) override {
308
    DCHECK(HasRange(kind));
309 310 311 312
    switch (kind) {
      case SourceRangeKind::kCatch:
        return catch_range_;
      case SourceRangeKind::kContinuation:
313
        if (!has_continuation_) return SourceRange::Empty();
314 315 316 317
        return SourceRange::ContinuationOf(catch_range_);
      default:
        UNREACHABLE();
    }
318 319
  }

320 321 322 323 324 325 326 327 328 329
  bool HasRange(SourceRangeKind kind) override {
    return kind == SourceRangeKind::kCatch ||
           kind == SourceRangeKind::kContinuation;
  }

  void RemoveContinuationRange() override {
    DCHECK(HasRange(SourceRangeKind::kContinuation));
    has_continuation_ = false;
  }

330 331
 private:
  SourceRange catch_range_;
332
  bool has_continuation_ = true;
333 334 335 336 337 338 339
};

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

340
  SourceRange GetRange(SourceRangeKind kind) override {
341
    DCHECK(HasRange(kind));
342 343 344 345
    switch (kind) {
      case SourceRangeKind::kFinally:
        return finally_range_;
      case SourceRangeKind::kContinuation:
346
        if (!has_continuation_) return SourceRange::Empty();
347 348 349 350
        return SourceRange::ContinuationOf(finally_range_);
      default:
        UNREACHABLE();
    }
351 352
  }

353 354 355 356 357 358 359 360 361 362
  bool HasRange(SourceRangeKind kind) override {
    return kind == SourceRangeKind::kFinally ||
           kind == SourceRangeKind::kContinuation;
  }

  void RemoveContinuationRange() override {
    DCHECK(HasRange(SourceRangeKind::kContinuation));
    has_continuation_ = false;
  }

363 364
 private:
  SourceRange finally_range_;
365
  bool has_continuation_ = true;
366 367 368 369 370 371 372 373
};

// 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) {}

374
  AstNodeSourceRanges* Find(ZoneObject* node) {
375 376 377 378 379 380 381 382
    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) { \
383
    DCHECK_NOT_NULL(node);                              \
384 385 386 387 388 389
    map_.emplace(node, ranges);                         \
  }
  AST_SOURCE_RANGE_LIST(DEFINE_MAP_INSERT)
#undef DEFINE_MAP_INSERT

 private:
390
  ZoneMap<ZoneObject*, AstNodeSourceRanges*> map_;
391 392 393 394 395 396
};

}  // namespace internal
}  // namespace v8

#endif  // V8_AST_AST_SOURCE_RANGES_H_