blob: c3692247443b1a4caca6261699dde5570d1f1690 [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 TOOLS_FIDL_FIDLC_SRC_VALUES_H_
#define TOOLS_FIDL_FIDLC_SRC_VALUES_H_
#include <iostream>
#include <limits>
#include <type_traits>
#include "tools/fidl/fidlc/src/properties.h"
#include "tools/fidl/fidlc/src/raw_ast.h"
#include "tools/fidl/fidlc/src/reference.h"
#include "tools/fidl/fidlc/src/source_span.h"
namespace fidlc {
struct Type;
// ConstantValue represents the concrete _value_ of a constant. (For the
// _declaration_, see Const. For the _use_, see Constant.) ConstantValue has
// derived classes for all the different kinds of constants.
struct ConstantValue {
virtual ~ConstantValue() = default;
enum class Kind : uint8_t {
kInt8,
kInt16,
kInt32,
kInt64,
kUint8,
kZxUchar,
kUint16,
kUint32,
kUint64,
kZxUsize64,
kZxUintptr64,
kFloat32,
kFloat64,
kBool,
kString,
kDocComment,
};
virtual bool Convert(Kind kind, std::unique_ptr<ConstantValue>* out_value) const = 0;
virtual std::unique_ptr<ConstantValue> Clone() const = 0;
const Kind kind;
protected:
explicit ConstantValue(Kind kind) : kind(kind) {}
};
template <typename ValueType>
struct NumericConstantValue final : ConstantValue {
static_assert(std::is_arithmetic<ValueType>::value && !std::is_same<ValueType, bool>::value,
"NumericConstantValue can only be used with a numeric ValueType");
explicit NumericConstantValue(ValueType value) : ConstantValue(GetKind()), value(value) {}
friend bool operator==(const NumericConstantValue<ValueType>& l,
const NumericConstantValue<ValueType>& r) {
return l.value == r.value;
}
friend bool operator<(const NumericConstantValue<ValueType>& l,
const NumericConstantValue<ValueType>& r) {
return l.value < r.value;
}
friend bool operator>(const NumericConstantValue<ValueType>& l,
const NumericConstantValue<ValueType>& r) {
return l.value > r.value;
}
friend bool operator!=(const NumericConstantValue<ValueType>& l,
const NumericConstantValue<ValueType>& r) {
return l.value != r.value;
}
friend bool operator<=(const NumericConstantValue<ValueType>& l,
const NumericConstantValue<ValueType>& r) {
return l.value <= r.value;
}
friend bool operator>=(const NumericConstantValue<ValueType>& l,
const NumericConstantValue<ValueType>& r) {
return l.value >= r.value;
}
friend NumericConstantValue<ValueType> operator|(const NumericConstantValue<ValueType>& l,
const NumericConstantValue<ValueType>& r) {
static_assert(!std::is_same_v<ValueType, float> && !std::is_same_v<ValueType, double>);
return NumericConstantValue<ValueType>(l.value | r.value);
}
friend std::ostream& operator<<(std::ostream& os, const NumericConstantValue<ValueType>& v) {
if constexpr (GetKind() == Kind::kInt8)
return os << static_cast<int>(v.value);
if constexpr (GetKind() == Kind::kUint8)
return os << static_cast<unsigned>(v.value);
return os << v.value;
}
bool Convert(Kind kind, std::unique_ptr<ConstantValue>* out_value) const override;
std::unique_ptr<ConstantValue> Clone() const override {
return std::make_unique<NumericConstantValue<ValueType>>(value);
}
static NumericConstantValue<ValueType> Min() {
return NumericConstantValue<ValueType>(std::numeric_limits<ValueType>::lowest());
}
static NumericConstantValue<ValueType> Max() {
return NumericConstantValue<ValueType>(std::numeric_limits<ValueType>::max());
}
ValueType value;
private:
constexpr static Kind GetKind() {
if constexpr (std::is_same_v<ValueType, uint64_t>)
return Kind::kUint64;
if constexpr (std::is_same_v<ValueType, int64_t>)
return Kind::kInt64;
if constexpr (std::is_same_v<ValueType, uint32_t>)
return Kind::kUint32;
if constexpr (std::is_same_v<ValueType, int32_t>)
return Kind::kInt32;
if constexpr (std::is_same_v<ValueType, uint16_t>)
return Kind::kUint16;
if constexpr (std::is_same_v<ValueType, int16_t>)
return Kind::kInt16;
if constexpr (std::is_same_v<ValueType, uint8_t>)
return Kind::kUint8;
if constexpr (std::is_same_v<ValueType, int8_t>)
return Kind::kInt8;
if constexpr (std::is_same_v<ValueType, double>)
return Kind::kFloat64;
if constexpr (std::is_same_v<ValueType, float>)
return Kind::kFloat32;
}
template <typename TargetType>
bool ConvertTo(std::unique_ptr<ConstantValue>* out_value) const;
};
using SizeValue = NumericConstantValue<uint32_t>;
using HandleSubtypeValue = NumericConstantValue<uint32_t>;
using HandleRightsValue = NumericConstantValue<RightsWrappedType>;
struct BoolConstantValue final : ConstantValue {
explicit BoolConstantValue(bool value)
: ConstantValue(ConstantValue::Kind::kBool), value(value) {}
explicit operator bool() const { return value; }
friend bool operator==(const BoolConstantValue& l, const BoolConstantValue& r) {
return l.value == r.value;
}
friend bool operator!=(const BoolConstantValue& l, const BoolConstantValue& r) {
return l.value != r.value;
}
friend std::ostream& operator<<(std::ostream& os, const BoolConstantValue& v) {
return os << v.value;
}
bool Convert(Kind kind, std::unique_ptr<ConstantValue>* out_value) const override;
std::unique_ptr<ConstantValue> Clone() const override {
return std::make_unique<BoolConstantValue>(value);
}
bool value;
};
struct DocCommentConstantValue final : ConstantValue {
explicit DocCommentConstantValue(std::string_view value)
: ConstantValue(ConstantValue::Kind::kDocComment), value(value) {}
friend std::ostream& operator<<(std::ostream& os, const DocCommentConstantValue& v) {
return os << v.value;
}
bool Convert(Kind kind, std::unique_ptr<ConstantValue>* out_value) const override;
std::unique_ptr<ConstantValue> Clone() const override {
return std::make_unique<DocCommentConstantValue>(value);
}
// Refers to the std::string owned by the RawDocCommentLiteral.
std::string_view value;
};
struct StringConstantValue final : ConstantValue {
explicit StringConstantValue(std::string_view value)
: ConstantValue(ConstantValue::Kind::kString), value(value) {}
friend std::ostream& operator<<(std::ostream& os, const StringConstantValue& v) {
return os << v.value;
}
bool Convert(Kind kind, std::unique_ptr<ConstantValue>* out_value) const override;
std::unique_ptr<ConstantValue> Clone() const override {
return std::make_unique<StringConstantValue>(value);
}
// Refers to the std::string owned by the RawStringLiteral.
std::string_view value;
};
// Constant represents the _use_ of a constant. (For the _declaration_, see
// Const. For the _value_, see ConstantValue.) A Constant can either be a
// reference to another constant (IdentifierConstant), a literal value
// (LiteralConstant). Every Constant resolves to a concrete ConstantValue.
struct Constant {
virtual ~Constant() = default;
enum class Kind : uint8_t { kIdentifier, kLiteral, kBinaryOperator };
Constant(Kind kind, SourceSpan span) : kind(kind), span(span), value_(nullptr) {}
bool IsResolved() const { return value_ != nullptr; }
void ResolveTo(std::unique_ptr<ConstantValue> value, const Type* type);
const ConstantValue& Value() const;
std::unique_ptr<Constant> Clone() const;
const Kind kind;
const SourceSpan span;
// compiled tracks whether we attempted to resolve this constant, to avoid
// resolving twice a constant which cannot be resolved.
bool compiled = false;
// set when resolved to
const Type* type = nullptr;
protected:
std::unique_ptr<ConstantValue> value_;
private:
// Helper to implement Clone(). Clones without including compilation state.
virtual std::unique_ptr<Constant> CloneImpl() const = 0;
};
struct IdentifierConstant final : Constant {
IdentifierConstant(const RawCompoundIdentifier& name, SourceSpan span)
: Constant(Kind::kIdentifier, span), reference(name) {}
// This constructor is needed for IdentifierLayoutParameter::Disambiguate().
IdentifierConstant(Reference reference, SourceSpan span)
: Constant(Kind::kIdentifier, span), reference(std::move(reference)) {}
Reference reference;
private:
std::unique_ptr<Constant> CloneImpl() const override {
return std::make_unique<IdentifierConstant>(reference, span);
}
};
struct LiteralConstant final : Constant {
explicit LiteralConstant(const RawLiteral* literal)
: Constant(Kind::kLiteral, literal->span()), literal(literal) {}
std::unique_ptr<LiteralConstant> CloneLiteralConstant() const {
return std::make_unique<LiteralConstant>(literal);
}
// Owned by Library::raw_literals.
const RawLiteral* literal;
private:
std::unique_ptr<Constant> CloneImpl() const override { return CloneLiteralConstant(); }
};
struct BinaryOperatorConstant final : Constant {
enum class Operator : uint8_t { kOr };
BinaryOperatorConstant(std::unique_ptr<Constant> left_operand,
std::unique_ptr<Constant> right_operand, Operator op, SourceSpan span)
: Constant(Kind::kBinaryOperator, span),
left_operand(std::move(left_operand)),
right_operand(std::move(right_operand)),
op(op) {}
const std::unique_ptr<Constant> left_operand;
const std::unique_ptr<Constant> right_operand;
const Operator op;
private:
std::unique_ptr<Constant> CloneImpl() const override {
return std::make_unique<BinaryOperatorConstant>(left_operand->Clone(), right_operand->Clone(),
op, span);
}
};
} // namespace fidlc
#endif // TOOLS_FIDL_FIDLC_SRC_VALUES_H_