11cb0ef41Sopenharmony_ci// Copyright 2021 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_TORQUE_CPP_BUILDER_H_
61cb0ef41Sopenharmony_ci#define V8_TORQUE_CPP_BUILDER_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <stack>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/torque/ast.h"
111cb0ef41Sopenharmony_ci#include "src/torque/types.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace v8 {
141cb0ef41Sopenharmony_cinamespace internal {
151cb0ef41Sopenharmony_cinamespace torque {
161cb0ef41Sopenharmony_cinamespace cpp {
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cistruct TemplateParameter {
191cb0ef41Sopenharmony_ci  explicit TemplateParameter(std::string name) : name(std::move(name)) {}
201cb0ef41Sopenharmony_ci  TemplateParameter(std::string type, std::string name)
211cb0ef41Sopenharmony_ci      : name(std::move(name)), type(std::move(type)) {}
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  std::string name;
241cb0ef41Sopenharmony_ci  std::string type;
251cb0ef41Sopenharmony_ci};
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciclass Class {
281cb0ef41Sopenharmony_ci public:
291cb0ef41Sopenharmony_ci  explicit Class(std::string name) : name_(std::move(name)) {}
301cb0ef41Sopenharmony_ci  Class(std::vector<TemplateParameter> template_parameters, std::string name)
311cb0ef41Sopenharmony_ci      : template_parameters_(std::move(template_parameters)),
321cb0ef41Sopenharmony_ci        name_(std::move(name)) {}
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  std::string GetName() const { return name_; }
351cb0ef41Sopenharmony_ci  std::vector<TemplateParameter> GetTemplateParameters() const {
361cb0ef41Sopenharmony_ci    return template_parameters_;
371cb0ef41Sopenharmony_ci  }
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci private:
401cb0ef41Sopenharmony_ci  std::vector<TemplateParameter> template_parameters_;
411cb0ef41Sopenharmony_ci  std::string name_;
421cb0ef41Sopenharmony_ci};
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci#define FUNCTION_FLAG_LIST(V) \
451cb0ef41Sopenharmony_ci  V(Inline, 0x01)             \
461cb0ef41Sopenharmony_ci  V(V8Inline, 0x03)           \
471cb0ef41Sopenharmony_ci  V(Const, 0x04)              \
481cb0ef41Sopenharmony_ci  V(Constexpr, 0x08)          \
491cb0ef41Sopenharmony_ci  V(Export, 0x10)             \
501cb0ef41Sopenharmony_ci  V(Static, 0x20)             \
511cb0ef41Sopenharmony_ci  V(Override, 0x40)
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciclass Function {
541cb0ef41Sopenharmony_ci public:
551cb0ef41Sopenharmony_ci  enum FunctionFlag {
561cb0ef41Sopenharmony_ci#define ENTRY(name, value) k##name = value,
571cb0ef41Sopenharmony_ci    FUNCTION_FLAG_LIST(ENTRY)
581cb0ef41Sopenharmony_ci#undef ENTRY
591cb0ef41Sopenharmony_ci  };
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  struct Parameter {
621cb0ef41Sopenharmony_ci    std::string type;
631cb0ef41Sopenharmony_ci    std::string name;
641cb0ef41Sopenharmony_ci    std::string default_value;
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci    Parameter(std::string type, std::string name,
671cb0ef41Sopenharmony_ci              std::string default_value = {})
681cb0ef41Sopenharmony_ci        : type(std::move(type)),
691cb0ef41Sopenharmony_ci          name(std::move(name)),
701cb0ef41Sopenharmony_ci          default_value(std::move(default_value)) {}
711cb0ef41Sopenharmony_ci  };
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  explicit Function(std::string name)
741cb0ef41Sopenharmony_ci      : pos_(CurrentSourcePosition::Get()),
751cb0ef41Sopenharmony_ci        owning_class_(nullptr),
761cb0ef41Sopenharmony_ci        name_(std::move(name)) {}
771cb0ef41Sopenharmony_ci  Function(Class* owning_class, std::string name)
781cb0ef41Sopenharmony_ci      : pos_(CurrentSourcePosition::Get()),
791cb0ef41Sopenharmony_ci        owning_class_(owning_class),
801cb0ef41Sopenharmony_ci        name_(std::move(name)) {}
811cb0ef41Sopenharmony_ci  ~Function() = default;
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  static Function DefaultGetter(std::string return_type, Class* owner,
841cb0ef41Sopenharmony_ci                                std::string name) {
851cb0ef41Sopenharmony_ci    Function getter(owner, std::move(name));
861cb0ef41Sopenharmony_ci    getter.SetReturnType(std::move(return_type));
871cb0ef41Sopenharmony_ci    getter.SetInline();
881cb0ef41Sopenharmony_ci    getter.SetConst();
891cb0ef41Sopenharmony_ci    return getter;
901cb0ef41Sopenharmony_ci  }
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  static Function DefaultSetter(Class* owner, std::string name,
931cb0ef41Sopenharmony_ci                                std::string parameter_type,
941cb0ef41Sopenharmony_ci                                std::string parameter_name) {
951cb0ef41Sopenharmony_ci    Function setter(owner, std::move(name));
961cb0ef41Sopenharmony_ci    setter.SetReturnType("void");
971cb0ef41Sopenharmony_ci    setter.AddParameter(std::move(parameter_type), std::move(parameter_name));
981cb0ef41Sopenharmony_ci    setter.SetInline();
991cb0ef41Sopenharmony_ci    return setter;
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  void SetFlag(FunctionFlag flag, bool value = true) {
1031cb0ef41Sopenharmony_ci    if (value) {
1041cb0ef41Sopenharmony_ci      flags_ = flags_ | flag;
1051cb0ef41Sopenharmony_ci    } else {
1061cb0ef41Sopenharmony_ci      flags_ = flags_.without(flag);
1071cb0ef41Sopenharmony_ci    }
1081cb0ef41Sopenharmony_ci  }
1091cb0ef41Sopenharmony_ci  void SetFlags(base::Flags<FunctionFlag> flags, bool value = true) {
1101cb0ef41Sopenharmony_ci    if (value) {
1111cb0ef41Sopenharmony_ci      flags_ |= flags;
1121cb0ef41Sopenharmony_ci    } else {
1131cb0ef41Sopenharmony_ci      flags_ &= ~flags;
1141cb0ef41Sopenharmony_ci    }
1151cb0ef41Sopenharmony_ci  }
1161cb0ef41Sopenharmony_ci  bool HasFlag(FunctionFlag flag) const { return (flags_ & flag) == flag; }
1171cb0ef41Sopenharmony_ci#define ACCESSOR(name, value)                            \
1181cb0ef41Sopenharmony_ci  void Set##name(bool v = true) { SetFlag(k##name, v); } \
1191cb0ef41Sopenharmony_ci  bool Is##name() const { return HasFlag(k##name); }
1201cb0ef41Sopenharmony_ci  FUNCTION_FLAG_LIST(ACCESSOR)
1211cb0ef41Sopenharmony_ci#undef ACCESSOR
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  void SetDescription(std::string description) {
1241cb0ef41Sopenharmony_ci    description_ = std::move(description);
1251cb0ef41Sopenharmony_ci  }
1261cb0ef41Sopenharmony_ci  void SetName(std::string name) { name_ = std::move(name); }
1271cb0ef41Sopenharmony_ci  void SetReturnType(std::string return_type) {
1281cb0ef41Sopenharmony_ci    return_type_ = std::move(return_type);
1291cb0ef41Sopenharmony_ci  }
1301cb0ef41Sopenharmony_ci  void AddParameter(std::string type, std::string name = {},
1311cb0ef41Sopenharmony_ci                    std::string default_value = {}) {
1321cb0ef41Sopenharmony_ci    parameters_.emplace_back(std::move(type), std::move(name),
1331cb0ef41Sopenharmony_ci                             std::move(default_value));
1341cb0ef41Sopenharmony_ci  }
1351cb0ef41Sopenharmony_ci  void InsertParameter(int index, std::string type, std::string name = {},
1361cb0ef41Sopenharmony_ci                       std::string default_value = {}) {
1371cb0ef41Sopenharmony_ci    DCHECK_GE(index, 0);
1381cb0ef41Sopenharmony_ci    DCHECK_LE(index, parameters_.size());
1391cb0ef41Sopenharmony_ci    parameters_.insert(
1401cb0ef41Sopenharmony_ci        parameters_.begin() + index,
1411cb0ef41Sopenharmony_ci        Parameter(std::move(type), std::move(name), std::move(default_value)));
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci  std::vector<Parameter> GetParameters() const { return parameters_; }
1441cb0ef41Sopenharmony_ci  std::vector<std::string> GetParameterNames() const {
1451cb0ef41Sopenharmony_ci    std::vector<std::string> names;
1461cb0ef41Sopenharmony_ci    std::transform(parameters_.begin(), parameters_.end(),
1471cb0ef41Sopenharmony_ci                   std::back_inserter(names),
1481cb0ef41Sopenharmony_ci                   [](const Parameter& p) { return p.name; });
1491cb0ef41Sopenharmony_ci    return names;
1501cb0ef41Sopenharmony_ci  }
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  static constexpr int kAutomaticIndentation = -1;
1531cb0ef41Sopenharmony_ci  void PrintDeclaration(std::ostream& stream,
1541cb0ef41Sopenharmony_ci                        int indentation = kAutomaticIndentation) const;
1551cb0ef41Sopenharmony_ci  void PrintDefinition(std::ostream& stream,
1561cb0ef41Sopenharmony_ci                       const std::function<void(std::ostream&)>& builder,
1571cb0ef41Sopenharmony_ci                       int indentation = 0) const;
1581cb0ef41Sopenharmony_ci  void PrintInlineDefinition(std::ostream& stream,
1591cb0ef41Sopenharmony_ci                             const std::function<void(std::ostream&)>& builder,
1601cb0ef41Sopenharmony_ci                             int indentation = 2) const;
1611cb0ef41Sopenharmony_ci  void PrintBeginDefinition(std::ostream& stream, int indentation = 0) const;
1621cb0ef41Sopenharmony_ci  void PrintEndDefinition(std::ostream& stream, int indentation = 0) const;
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci protected:
1651cb0ef41Sopenharmony_ci  void PrintDeclarationHeader(std::ostream& stream, int indentation) const;
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci private:
1681cb0ef41Sopenharmony_ci  SourcePosition pos_;
1691cb0ef41Sopenharmony_ci  Class* owning_class_;
1701cb0ef41Sopenharmony_ci  std::string description_;
1711cb0ef41Sopenharmony_ci  std::string name_;
1721cb0ef41Sopenharmony_ci  std::string return_type_;
1731cb0ef41Sopenharmony_ci  std::vector<Parameter> parameters_;
1741cb0ef41Sopenharmony_ci  base::Flags<FunctionFlag> flags_;
1751cb0ef41Sopenharmony_ci};
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ciDEFINE_OPERATORS_FOR_FLAGS(base::Flags<Function::FunctionFlag>)
1781cb0ef41Sopenharmony_ci#undef FUNCTION_FLAG_LIST
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ciclass File {
1811cb0ef41Sopenharmony_ci public:
1821cb0ef41Sopenharmony_ci  explicit File(std::ostream& stream) : stream_(&stream) {}
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  void BeginIncludeGuard(const std::string& name);
1851cb0ef41Sopenharmony_ci  void EndIncludeGuard(const std::string& name);
1861cb0ef41Sopenharmony_ci  void BeginNamespace(std::string name);
1871cb0ef41Sopenharmony_ci  void BeginNamespace(std::string name0, std::string name1);
1881cb0ef41Sopenharmony_ci  void EndNamespace(const std::string& name);
1891cb0ef41Sopenharmony_ci  void EndNamespace(const std::string& name0, const std::string& name1);
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  void AddInclude(std::string include) { includes_.insert(std::move(include)); }
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci  template <typename T>
1941cb0ef41Sopenharmony_ci  File& operator<<(const T& value) {
1951cb0ef41Sopenharmony_ci    s() << value;
1961cb0ef41Sopenharmony_ci    return *this;
1971cb0ef41Sopenharmony_ci  }
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci protected:
2001cb0ef41Sopenharmony_ci  std::ostream& s() { return *stream_; }
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci private:
2031cb0ef41Sopenharmony_ci  std::ostream* stream_;
2041cb0ef41Sopenharmony_ci  std::set<std::string> includes_;
2051cb0ef41Sopenharmony_ci  std::stack<std::string> namespaces_;
2061cb0ef41Sopenharmony_ci};
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ciclass IncludeGuardScope {
2091cb0ef41Sopenharmony_ci public:
2101cb0ef41Sopenharmony_ci  explicit IncludeGuardScope(File* file, std::string name)
2111cb0ef41Sopenharmony_ci      : file_(file), name_(std::move(name)) {
2121cb0ef41Sopenharmony_ci    file_->BeginIncludeGuard(name_);
2131cb0ef41Sopenharmony_ci  }
2141cb0ef41Sopenharmony_ci  IncludeGuardScope(const IncludeGuardScope&) = delete;
2151cb0ef41Sopenharmony_ci  IncludeGuardScope(IncludeGuardScope&& other) V8_NOEXCEPT : file_(nullptr),
2161cb0ef41Sopenharmony_ci                                                             name_() {
2171cb0ef41Sopenharmony_ci    std::swap(file_, other.file_);
2181cb0ef41Sopenharmony_ci    std::swap(name_, other.name_);
2191cb0ef41Sopenharmony_ci  }
2201cb0ef41Sopenharmony_ci  ~IncludeGuardScope() {
2211cb0ef41Sopenharmony_ci    if (file_) {
2221cb0ef41Sopenharmony_ci      file_->EndIncludeGuard(name_);
2231cb0ef41Sopenharmony_ci    }
2241cb0ef41Sopenharmony_ci  }
2251cb0ef41Sopenharmony_ci  IncludeGuardScope& operator=(const IncludeGuardScope&) = delete;
2261cb0ef41Sopenharmony_ci  IncludeGuardScope& operator=(IncludeGuardScope&& other) V8_NOEXCEPT {
2271cb0ef41Sopenharmony_ci    if (this != &other) {
2281cb0ef41Sopenharmony_ci      DCHECK_NULL(file_);
2291cb0ef41Sopenharmony_ci      DCHECK(name_.empty());
2301cb0ef41Sopenharmony_ci      std::swap(file_, other.file_);
2311cb0ef41Sopenharmony_ci      std::swap(name_, other.name_);
2321cb0ef41Sopenharmony_ci    }
2331cb0ef41Sopenharmony_ci    return *this;
2341cb0ef41Sopenharmony_ci  }
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci private:
2371cb0ef41Sopenharmony_ci  File* file_;
2381cb0ef41Sopenharmony_ci  std::string name_;
2391cb0ef41Sopenharmony_ci};
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci}  // namespace cpp
2421cb0ef41Sopenharmony_ci}  // namespace torque
2431cb0ef41Sopenharmony_ci}  // namespace internal
2441cb0ef41Sopenharmony_ci}  // namespace v8
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci#endif  // V8_TORQUE_CPP_BUILDER_H_
247