Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/js/src/frontend/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 14 kB image not shown  

Quelle  ParseNode.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "frontend/ParseNode.h"

#include "mozilla/FloatingPoint.h"
#include "mozilla/Try.h"  // MOZ_TRY*

#include "jsnum.h"

#include "frontend/CompilationStencil.h"  // ExtensibleCompilationStencil
#include "frontend/FullParseHandler.h"
#include "frontend/ParseContext.h"
#include "frontend/Parser.h"      // ParserBase
#include "frontend/ParserAtom.h"  // ParserAtomsTable, TaggedParserAtomIndex
#include "frontend/SharedContext.h"
#include "js/Printer.h"
#include "vm/Scope.h"  // GetScopeDataTrailingNames

using namespace js;
using namespace js::frontend;

#ifdef DEBUG
void ListNode::checkConsistency() const {
  ParseNode* const* tailNode;
  uint32_t actualCount = 0;
  if (const ParseNode* last = head()) {
    const ParseNode* pn = last;
    while (pn) {
      last = pn;
      pn = pn->pn_next;
      actualCount++;
    }

    tailNode = &last->pn_next;
  } else {
    tailNode = &head_;
  }
  MOZ_ASSERT(tail() == tailNode);
  MOZ_ASSERT(count() == actualCount);
}
#endif

/*
 * Allocate a ParseNode from parser's node freelist or, failing that, from
 * cx's temporary arena.
 */

void* ParseNodeAllocator::allocNode(size_t size) {
  LifoAlloc::AutoFallibleScope fallibleAllocator(&alloc);
  void* p = alloc.alloc(size);
  if (!p) {
    ReportOutOfMemory(fc);
  }
  return p;
}

ParseNodeResult ParseNode::appendOrCreateList(ParseNodeKind kind,
                                              ParseNode* left, ParseNode* right,
                                              FullParseHandler* handler,
                                              ParseContext* pc) {
  // The asm.js specification is written in ECMAScript grammar terms that
  // specify *only* a binary tree.  It's a royal pain to implement the asm.js
  // spec to act upon n-ary lists as created below.  So for asm.js, form a
  // binary tree of lists exactly as ECMAScript would by skipping the
  // following optimization.
  if (!pc->useAsmOrInsideUseAsm()) {
    // Left-associative trees of a given operator (e.g. |a + b + c|) are
    // binary trees in the spec: (+ (+ a b) c) in Lisp terms.  Recursively
    // processing such a tree, exactly implemented that way, would blow the
    // the stack.  We use a list node that uses O(1) stack to represent
    // such operations: (+ a b c).
    //
    // (**) is right-associative; per spec |a ** b ** c| parses as
    // (** a (** b c)). But we treat this the same way, creating a list
    // node: (** a b c). All consumers must understand that this must be
    // processed with a right fold, whereas the list (+ a b c) must be
    // processed with a left fold because (+) is left-associative.
    //
    if (left->isKind(kind) &&
        (kind == ParseNodeKind::PowExpr ? !left->isInParens()
                                        : left->isBinaryOperation())) {
      ListNode* list = &left->as<ListNode>();

      list->append(right);
      list->pn_pos.end = right->pn_pos.end;

      return list;
    }
  }

  ListNode* list;
  MOZ_TRY_VAR(list, handler->newResult<ListNode>(kind, left));

  list->append(right);
  return list;
}

const ParseNode::TypeCode ParseNode::typeCodeTable[] = {
#define TYPE_CODE(_name, type) type::classTypeCode(),
    FOR_EACH_PARSE_NODE_KIND(TYPE_CODE)
#undef TYPE_CODE
};

#ifdef DEBUG

const size_t ParseNode::sizeTable[] = {
#  define NODE_SIZE(_name, type) sizeof(type),
    FOR_EACH_PARSE_NODE_KIND(NODE_SIZE)
#  undef NODE_SIZE
};

static const charconst parseNodeNames[] = {
#  define STRINGIFY(name, _type) #name,
    FOR_EACH_PARSE_NODE_KIND(STRINGIFY)
#  undef STRINGIFY
};

static void DumpParseTree(const ParserAtomsTable* parserAtoms, ParseNode* pn,
                          GenericPrinter& out, int indent) {
  if (pn == nullptr) {
    out.put("#NULL");
  } else {
    pn->dump(parserAtoms, out, indent);
  }
}

void frontend::DumpParseTree(ParserBase* parser, ParseNode* pn,
                             GenericPrinter& out, int indent) {
  ParserAtomsTable* parserAtoms = parser ? &parser->parserAtoms() : nullptr;
  ::DumpParseTree(parserAtoms, pn, out, indent);
}

static void IndentNewLine(GenericPrinter& out, int indent) {
  out.putChar('\n');
  for (int i = 0; i < indent; ++i) {
    out.putChar(' ');
  }
}

void ParseNode::dump() { dump(nullptr); }

void ParseNode::dump(const ParserAtomsTable* parserAtoms) {
  js::Fprinter out(stderr);
  dump(parserAtoms, out);
}

void ParseNode::dump(const ParserAtomsTable* parserAtoms, GenericPrinter& out) {
  dump(parserAtoms, out, 0);
  out.putChar('\n');
}

void ParseNode::dump(const ParserAtomsTable* parserAtoms, GenericPrinter& out,
                     int indent) {
  switch (getKind()) {
#  define DUMP(K, T)                              \
    case ParseNodeKind::K:                        \
      as<T>().dumpImpl(parserAtoms, out, indent); \
      break;
    FOR_EACH_PARSE_NODE_KIND(DUMP)
#  undef DUMP
    default:
      out.printf("#", (void*)thisunsigned(getKind()));
  }
}

void NullaryNode::dumpImpl(const ParserAtomsTable* parserAtoms,
                           GenericPrinter& out, int indent) {
  switch (getKind()) {
    case ParseNodeKind::TrueExpr:
      out.put("#true");
      break;
    case ParseNodeKind::FalseExpr:
      out.put("#false");
      break;
    case ParseNodeKind::NullExpr:
      out.put("#null");
      break;
    case ParseNodeKind::RawUndefinedExpr:
      out.put("#undefined");
      break;

    default:
      out.printf("(%s)", parseNodeNames[getKindAsIndex()]);
  }
}

void NumericLiteral::dumpImpl(const ParserAtomsTable* parserAtoms,
                              GenericPrinter& out, int indent) {
  ToCStringBuf cbuf;
  const char* cstr = NumberToCString(&cbuf, value());
  MOZ_ASSERT(cstr);
  if (!std::isfinite(value())) {
    out.put("#");
  }
  out.printf("%s", cstr);
}

void BigIntLiteral::dumpImpl(const ParserAtomsTable* parserAtoms,
                             GenericPrinter& out, int indent) {
  out.printf("(%s)", parseNodeNames[getKindAsIndex()]);
}

void RegExpLiteral::dumpImpl(const ParserAtomsTable* parserAtoms,
                             GenericPrinter& out, int indent) {
  out.printf("(%s)", parseNodeNames[getKindAsIndex()]);
}

static void DumpCharsNoNewline(const ParserAtomsTable* parserAtoms,
                               TaggedParserAtomIndex index,
                               GenericPrinter& out) {
  out.put("\"");
  if (parserAtoms) {
    parserAtoms->dumpCharsNoQuote(out, index);
  } else {
    DumpTaggedParserAtomIndexNoQuote(out, index, nullptr);
  }
  out.put("\"");
}

void LoopControlStatement::dumpImpl(const ParserAtomsTable* parserAtoms,
                                    GenericPrinter& out, int indent) {
  const char* name = parseNodeNames[getKindAsIndex()];
  out.printf("(%s", name);
  if (label_) {
    out.printf(" ");
    DumpCharsNoNewline(parserAtoms, label_, out);
  }
  out.printf(")");
}

void UnaryNode::dumpImpl(const ParserAtomsTable* parserAtoms,
                         GenericPrinter& out, int indent) {
  const char* name = parseNodeNames[getKindAsIndex()];
  out.printf("(%s ", name);
  indent += strlen(name) + 2;
  ::DumpParseTree(parserAtoms, kid(), out, indent);
  out.printf(")");
}

void BinaryNode::dumpImpl(const ParserAtomsTable* parserAtoms,
                          GenericPrinter& out, int indent) {
  if (isKind(ParseNodeKind::DotExpr)) {
    out.put("(.");

    ::DumpParseTree(parserAtoms, right(), out, indent + 2);

    out.putChar(' ');
    if (as<PropertyAccess>().isSuper()) {
      out.put("super");
    } else {
      ::DumpParseTree(parserAtoms, left(), out, indent + 2);
    }

    out.printf(")");
    return;
  }

  const char* name = parseNodeNames[getKindAsIndex()];
  out.printf("(%s ", name);
  indent += strlen(name) + 2;
  ::DumpParseTree(parserAtoms, left(), out, indent);
  IndentNewLine(out, indent);
  ::DumpParseTree(parserAtoms, right(), out, indent);
  out.printf(")");
}

void TernaryNode::dumpImpl(const ParserAtomsTable* parserAtoms,
                           GenericPrinter& out, int indent) {
  const char* name = parseNodeNames[getKindAsIndex()];
  out.printf("(%s ", name);
  indent += strlen(name) + 2;
  ::DumpParseTree(parserAtoms, kid1(), out, indent);
  IndentNewLine(out, indent);
  ::DumpParseTree(parserAtoms, kid2(), out, indent);
  IndentNewLine(out, indent);
  ::DumpParseTree(parserAtoms, kid3(), out, indent);
  out.printf(")");
}

void FunctionNode::dumpImpl(const ParserAtomsTable* parserAtoms,
                            GenericPrinter& out, int indent) {
  const char* name = parseNodeNames[getKindAsIndex()];
  out.printf("(%s ", name);
  indent += strlen(name) + 2;
  ::DumpParseTree(parserAtoms, body(), out, indent);
  out.printf(")");
}

void ModuleNode::dumpImpl(const ParserAtomsTable* parserAtoms,
                          GenericPrinter& out, int indent) {
  const char* name = parseNodeNames[getKindAsIndex()];
  out.printf("(%s ", name);
  indent += strlen(name) + 2;
  ::DumpParseTree(parserAtoms, body(), out, indent);
  out.printf(")");
}

void ListNode::dumpImpl(const ParserAtomsTable* parserAtoms,
                        GenericPrinter& out, int indent) {
  const char* name = parseNodeNames[getKindAsIndex()];
  out.printf("(%s [", name);
  if (ParseNode* listHead = head()) {
    indent += strlen(name) + 3;
    ::DumpParseTree(parserAtoms, listHead, out, indent);
    for (ParseNode* item : contentsFrom(listHead->pn_next)) {
      IndentNewLine(out, indent);
      ::DumpParseTree(parserAtoms, item, out, indent);
    }
  }
  out.printf("])");
}

void NameNode::dumpImpl(const ParserAtomsTable* parserAtoms,
                        GenericPrinter& out, int indent) {
  switch (getKind()) {
    case ParseNodeKind::StringExpr:
    case ParseNodeKind::TemplateStringExpr:
    case ParseNodeKind::ObjectPropertyName:
      DumpCharsNoNewline(parserAtoms, atom_, out);
      return;

    case ParseNodeKind::Name:
    case ParseNodeKind::PrivateName:  // atom() already includes the '#', no
                                      // need to specially include it.
    case ParseNodeKind::PropertyNameExpr:
      if (!atom_) {
        out.put("#");
      } else if (parserAtoms) {
        if (atom_ == TaggedParserAtomIndex::WellKnown::empty()) {
          out.put("#");
        } else {
          parserAtoms->dumpCharsNoQuote(out, atom_);
        }
      } else {
        DumpTaggedParserAtomIndexNoQuote(out, atom_, nullptr);
      }
      return;

    case ParseNodeKind::LabelStmt: {
      this->as<LabeledStatement>().dumpImpl(parserAtoms, out, indent);
      return;
    }

    default: {
      const char* name = parseNodeNames[getKindAsIndex()];
      out.printf("(%s)", name);
      return;
    }
  }
}

void LabeledStatement::dumpImpl(const ParserAtomsTable* parserAtoms,
                                GenericPrinter& out, int indent) {
  const char* name = parseNodeNames[getKindAsIndex()];
  out.printf("(%s ", name);
  DumpCharsNoNewline(parserAtoms, label(), out);
  indent += strlen(name) + 2;
  IndentNewLine(out, indent);
  ::DumpParseTree(parserAtoms, statement(), out, indent);
  out.printf(")");
}

template <ParseNodeKind Kind, typename ScopeType>
void BaseScopeNode<Kind, ScopeType>::dumpImpl(
    const ParserAtomsTable* parserAtoms, GenericPrinter& out, int indent) {
  const char* name = parseNodeNames[getKindAsIndex()];
  out.printf("(%s [", name);
  int nameIndent = indent + strlen(name) + 3;
  if (!isEmptyScope()) {
    typename ScopeType::ParserData* bindings = scopeBindings();
    auto names = GetScopeDataTrailingNames(bindings);
    for (uint32_t i = 0; i < names.size(); i++) {
      auto index = names[i].name();
      if (parserAtoms) {
        if (index == TaggedParserAtomIndex::WellKnown::empty()) {
          out.put("#");
        } else {
          parserAtoms->dumpCharsNoQuote(out, index);
        }
      } else {
        DumpTaggedParserAtomIndexNoQuote(out, index, nullptr);
      }
      if (i < names.size() - 1) {
        IndentNewLine(out, nameIndent);
      }
    }
  }
  out.putChar(']');
  indent += 2;
  IndentNewLine(out, indent);
  ::DumpParseTree(parserAtoms, scopeBody(), out, indent);
  out.printf(")");
}

#  ifdef ENABLE_DECORATORS
void ClassMethod::dumpImpl(const ParserAtomsTable* parserAtoms,
                           GenericPrinter& out, int indent) {
  if (decorators_) {
    decorators_->dumpImpl(parserAtoms, out, indent);
  }
  Base::dumpImpl(parserAtoms, out, indent);
}

void ClassField::dumpImpl(const ParserAtomsTable* parserAtoms,
                          GenericPrinter& out, int indent) {
  if (decorators_) {
    decorators_->dumpImpl(parserAtoms, out, indent);
    out.putChar(' ');
  }
  Base::dumpImpl(parserAtoms, out, indent);
  IndentNewLine(out, indent + 2);
  if (accessorGetterNode_) {
    out.printf("getter: ");
    accessorGetterNode_->dumpImpl(parserAtoms, out, indent);
  }
  IndentNewLine(out, indent + 2);
  if (accessorSetterNode_) {
    out.printf("setter: ");
    accessorSetterNode_->dumpImpl(parserAtoms, out, indent);
  }
}

void ClassNode::dumpImpl(const ParserAtomsTable* parserAtoms,
                         GenericPrinter& out, int indent) {
  if (decorators_) {
    decorators_->dumpImpl(parserAtoms, out, indent);
  }
  Base::dumpImpl(parserAtoms, out, indent);
}
#  endif

#endif

TaggedParserAtomIndex NumericLiteral::toAtom(
    FrontendContext* fc, ParserAtomsTable& parserAtoms) const {
  return NumberToParserAtom(fc, parserAtoms, value());
}

RegExpObject* RegExpLiteral::create(
    JSContext* cx, FrontendContext* fc, ParserAtomsTable& parserAtoms,
    CompilationAtomCache& atomCache,
    ExtensibleCompilationStencil& stencil) const {
  return stencil.regExpData[index_].createRegExpAndEnsureAtom(
      cx, fc, parserAtoms, atomCache);
}

bool js::frontend::IsAnonymousFunctionDefinition(ParseNode* pn) {
  // ES 2017 draft
  // 12.15.2 (ArrowFunction, AsyncArrowFunction).
  // 14.1.12 (FunctionExpression).
  // 14.4.8 (Generatoression).
  // 14.6.8 (AsyncFunctionExpression)
  if (pn->is<FunctionNode>() &&
      !pn->as<FunctionNode>().funbox()->explicitName()) {
    return true;
  }

  // 14.5.8 (ClassExpression)
  if (pn->is<ClassNode>() && !pn->as<ClassNode>().names()) {
    return true;
  }

  return false;
}

Messung V0.5
C=93 H=97 G=94

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.