#ifndef SASS_AST_VALUES_H #define SASS_AST_VALUES_H // sass.hpp must go before all system headers to get the // __EXTENSIONS__ fix on Solaris. #include "sass.hpp" #include "ast.hpp" namespace Sass { ////////////////////////////////////////////////////////////////////// // Still just an expression, but with a to_string method ////////////////////////////////////////////////////////////////////// class PreValue : public Expression { public: PreValue(SourceSpan pstate, bool d = false, bool e = false, bool i = false, Type ct = NONE); ATTACH_VIRTUAL_AST_OPERATIONS(PreValue); virtual ~PreValue() { } }; ////////////////////////////////////////////////////////////////////// // base class for values that support operations ////////////////////////////////////////////////////////////////////// class Value : public PreValue { public: Value(SourceSpan pstate, bool d = false, bool e = false, bool i = false, Type ct = NONE); // Some obects are not meant to be compared // ToDo: maybe fallback to pointer comparison? virtual bool operator< (const Expression& rhs) const override = 0; virtual bool operator== (const Expression& rhs) const override = 0; // We can give some reasonable implementations by using // inverst operators on the specialized implementations virtual bool operator> (const Expression& rhs) const { return rhs < *this; } virtual bool operator!= (const Expression& rhs) const { return !(*this == rhs); } ATTACH_VIRTUAL_AST_OPERATIONS(Value); }; /////////////////////////////////////////////////////////////////////// // Lists of values, both comma- and space-separated (distinguished by a // type-tag.) Also used to represent variable-length argument lists. /////////////////////////////////////////////////////////////////////// class List : public Value, public Vectorized { void adjust_after_pushing(ExpressionObj e) override { is_expanded(false); } private: ADD_PROPERTY(enum Sass_Separator, separator) ADD_PROPERTY(bool, is_arglist) ADD_PROPERTY(bool, is_bracketed) ADD_PROPERTY(bool, from_selector) public: List(SourceSpan pstate, size_t size = 0, enum Sass_Separator sep = SASS_SPACE, bool argl = false, bool bracket = false); sass::string type() const override { return is_arglist_ ? "arglist" : "list"; } static sass::string type_name() { return "list"; } const char* sep_string(bool compressed = false) const { return separator() == SASS_SPACE ? " " : (compressed ? "," : ", "); } bool is_invisible() const override { return empty() && !is_bracketed(); } ExpressionObj value_at_index(size_t i); virtual size_t hash() const override; virtual size_t size() const; virtual void set_delayed(bool delayed) override; virtual bool operator< (const Expression& rhs) const override; virtual bool operator== (const Expression& rhs) const override; ATTACH_AST_OPERATIONS(List) ATTACH_CRTP_PERFORM_METHODS() }; /////////////////////////////////////////////////////////////////////// // Key value paris. /////////////////////////////////////////////////////////////////////// class Map : public Value, public Hashed { void adjust_after_pushing(std::pair p) override { is_expanded(false); } public: Map(SourceSpan pstate, size_t size = 0); sass::string type() const override { return "map"; } static sass::string type_name() { return "map"; } bool is_invisible() const override { return empty(); } List_Obj to_list(SourceSpan& pstate); virtual size_t hash() const override; virtual bool operator< (const Expression& rhs) const override; virtual bool operator== (const Expression& rhs) const override; ATTACH_AST_OPERATIONS(Map) ATTACH_CRTP_PERFORM_METHODS() }; ////////////////////////////////////////////////////////////////////////// // Binary expressions. Represents logical, relational, and arithmetic // operations. Templatized to avoid large switch statements and repetitive // subclassing. ////////////////////////////////////////////////////////////////////////// class Binary_Expression : public PreValue { private: HASH_PROPERTY(Operand, op) HASH_PROPERTY(ExpressionObj, left) HASH_PROPERTY(ExpressionObj, right) mutable size_t hash_; public: Binary_Expression(SourceSpan pstate, Operand op, ExpressionObj lhs, ExpressionObj rhs); const sass::string type_name(); const sass::string separator(); bool is_left_interpolant(void) const override; bool is_right_interpolant(void) const override; bool has_interpolant() const override; virtual void set_delayed(bool delayed) override; virtual bool operator< (const Expression& rhs) const override; virtual bool operator==(const Expression& rhs) const override; virtual size_t hash() const override; enum Sass_OP optype() const { return op_.operand; } ATTACH_AST_OPERATIONS(Binary_Expression) ATTACH_CRTP_PERFORM_METHODS() }; //////////////////////////////////////////////////// // Function reference. //////////////////////////////////////////////////// class Function final : public Value { public: ADD_PROPERTY(Definition_Obj, definition) ADD_PROPERTY(bool, is_css) public: Function(SourceSpan pstate, Definition_Obj def, bool css); sass::string type() const override { return "function"; } static sass::string type_name() { return "function"; } bool is_invisible() const override { return true; } sass::string name(); bool operator< (const Expression& rhs) const override; bool operator== (const Expression& rhs) const override; ATTACH_AST_OPERATIONS(Function) ATTACH_CRTP_PERFORM_METHODS() }; ////////////////// // Function calls. ////////////////// class Function_Call final : public PreValue { HASH_CONSTREF(String_Obj, sname) HASH_PROPERTY(Arguments_Obj, arguments) HASH_PROPERTY(Function_Obj, func) ADD_PROPERTY(bool, via_call) ADD_PROPERTY(void*, cookie) mutable size_t hash_; public: Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, void* cookie); Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, Function_Obj func); Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args); Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args, void* cookie); Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args, Function_Obj func); Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args); sass::string name() const; bool is_css(); bool operator==(const Expression& rhs) const override; size_t hash() const override; ATTACH_AST_OPERATIONS(Function_Call) ATTACH_CRTP_PERFORM_METHODS() }; /////////////////////// // Variable references. /////////////////////// class Variable final : public PreValue { ADD_CONSTREF(sass::string, name) public: Variable(SourceSpan pstate, sass::string n); virtual bool operator==(const Expression& rhs) const override; virtual size_t hash() const override; ATTACH_AST_OPERATIONS(Variable) ATTACH_CRTP_PERFORM_METHODS() }; //////////////////////////////////////////////// // Numbers, percentages, dimensions, and colors. //////////////////////////////////////////////// class Number final : public Value, public Units { HASH_PROPERTY(double, value) ADD_PROPERTY(bool, zero) mutable size_t hash_; public: Number(SourceSpan pstate, double val, sass::string u = "", bool zero = true); bool zero() { return zero_; } sass::string type() const override { return "number"; } static sass::string type_name() { return "number"; } // cancel out unnecessary units // result will be in input units void reduce(); // normalize units to defaults // needed to compare two numbers void normalize(); size_t hash() const override; bool operator< (const Number& rhs) const; bool operator== (const Number& rhs) const; bool operator< (const Expression& rhs) const override; bool operator== (const Expression& rhs) const override; ATTACH_AST_OPERATIONS(Number) ATTACH_CRTP_PERFORM_METHODS() }; ////////// // Colors. ////////// class Color : public Value { ADD_CONSTREF(sass::string, disp) HASH_PROPERTY(double, a) protected: mutable size_t hash_; public: Color(SourceSpan pstate, double a = 1, const sass::string disp = ""); sass::string type() const override { return "color"; } static sass::string type_name() { return "color"; } virtual size_t hash() const override = 0; bool operator< (const Expression& rhs) const override; bool operator== (const Expression& rhs) const override; virtual Color_RGBA* copyAsRGBA() const = 0; virtual Color_RGBA* toRGBA() = 0; virtual Color_HSLA* copyAsHSLA() const = 0; virtual Color_HSLA* toHSLA() = 0; ATTACH_VIRTUAL_AST_OPERATIONS(Color) }; ////////// // Colors. ////////// class Color_RGBA final : public Color { HASH_PROPERTY(double, r) HASH_PROPERTY(double, g) HASH_PROPERTY(double, b) public: Color_RGBA(SourceSpan pstate, double r, double g, double b, double a = 1, const sass::string disp = ""); sass::string type() const override { return "color"; } static sass::string type_name() { return "color"; } size_t hash() const override; Color_RGBA* copyAsRGBA() const override; Color_RGBA* toRGBA() override { return this; } Color_HSLA* copyAsHSLA() const override; Color_HSLA* toHSLA() override { return copyAsHSLA(); } bool operator< (const Expression& rhs) const override; bool operator== (const Expression& rhs) const override; ATTACH_AST_OPERATIONS(Color_RGBA) ATTACH_CRTP_PERFORM_METHODS() }; ////////// // Colors. ////////// class Color_HSLA final : public Color { HASH_PROPERTY(double, h) HASH_PROPERTY(double, s) HASH_PROPERTY(double, l) public: Color_HSLA(SourceSpan pstate, double h, double s, double l, double a = 1, const sass::string disp = ""); sass::string type() const override { return "color"; } static sass::string type_name() { return "color"; } size_t hash() const override; Color_RGBA* copyAsRGBA() const override; Color_RGBA* toRGBA() override { return copyAsRGBA(); } Color_HSLA* copyAsHSLA() const override; Color_HSLA* toHSLA() override { return this; } bool operator< (const Expression& rhs) const override; bool operator== (const Expression& rhs) const override; ATTACH_AST_OPERATIONS(Color_HSLA) ATTACH_CRTP_PERFORM_METHODS() }; ////////////////////////////// // Errors from Sass_Values. ////////////////////////////// class Custom_Error final : public Value { ADD_CONSTREF(sass::string, message) public: Custom_Error(SourceSpan pstate, sass::string msg); bool operator< (const Expression& rhs) const override; bool operator== (const Expression& rhs) const override; ATTACH_AST_OPERATIONS(Custom_Error) ATTACH_CRTP_PERFORM_METHODS() }; ////////////////////////////// // Warnings from Sass_Values. ////////////////////////////// class Custom_Warning final : public Value { ADD_CONSTREF(sass::string, message) public: Custom_Warning(SourceSpan pstate, sass::string msg); bool operator< (const Expression& rhs) const override; bool operator== (const Expression& rhs) const override; ATTACH_AST_OPERATIONS(Custom_Warning) ATTACH_CRTP_PERFORM_METHODS() }; //////////// // Booleans. //////////// class Boolean final : public Value { HASH_PROPERTY(bool, value) mutable size_t hash_; public: Boolean(SourceSpan pstate, bool val); operator bool() override { return value_; } sass::string type() const override { return "bool"; } static sass::string type_name() { return "bool"; } size_t hash() const override; bool is_false() override { return !value_; } bool operator< (const Expression& rhs) const override; bool operator== (const Expression& rhs) const override; ATTACH_AST_OPERATIONS(Boolean) ATTACH_CRTP_PERFORM_METHODS() }; //////////////////////////////////////////////////////////////////////// // Abstract base class for Sass string values. Includes interpolated and // "flat" strings. //////////////////////////////////////////////////////////////////////// class String : public Value { public: String(SourceSpan pstate, bool delayed = false); static sass::string type_name() { return "string"; } virtual ~String() = 0; virtual void rtrim() = 0; virtual bool operator<(const Expression& rhs) const override { return this->to_string() < rhs.to_string(); }; virtual bool operator==(const Expression& rhs) const override { return this->to_string() == rhs.to_string(); }; ATTACH_VIRTUAL_AST_OPERATIONS(String); ATTACH_CRTP_PERFORM_METHODS() }; inline String::~String() { }; /////////////////////////////////////////////////////////////////////// // Interpolated strings. Meant to be reduced to flat strings during the // evaluation phase. /////////////////////////////////////////////////////////////////////// class String_Schema final : public String, public Vectorized { ADD_PROPERTY(bool, css) mutable size_t hash_; public: String_Schema(SourceSpan pstate, size_t size = 0, bool css = true); sass::string type() const override { return "string"; } static sass::string type_name() { return "string"; } bool is_left_interpolant(void) const override; bool is_right_interpolant(void) const override; bool has_interpolants(); void rtrim() override; size_t hash() const override; virtual void set_delayed(bool delayed) override; bool operator< (const Expression& rhs) const override; bool operator==(const Expression& rhs) const override; ATTACH_AST_OPERATIONS(String_Schema) ATTACH_CRTP_PERFORM_METHODS() }; //////////////////////////////////////////////////////// // Flat strings -- the lowest level of raw textual data. //////////////////////////////////////////////////////// class String_Constant : public String { ADD_PROPERTY(char, quote_mark) HASH_CONSTREF(sass::string, value) protected: mutable size_t hash_; public: String_Constant(SourceSpan pstate, sass::string val, bool css = true); String_Constant(SourceSpan pstate, const char* beg, bool css = true); String_Constant(SourceSpan pstate, const char* beg, const char* end, bool css = true); String_Constant(SourceSpan pstate, const Token& tok, bool css = true); sass::string type() const override { return "string"; } static sass::string type_name() { return "string"; } bool is_invisible() const override; virtual void rtrim() override; size_t hash() const override; bool operator< (const Expression& rhs) const override; bool operator==(const Expression& rhs) const override; // quotes are forced on inspection virtual sass::string inspect() const override; ATTACH_AST_OPERATIONS(String_Constant) ATTACH_CRTP_PERFORM_METHODS() }; //////////////////////////////////////////////////////// // Possibly quoted string (unquote on instantiation) //////////////////////////////////////////////////////// class String_Quoted final : public String_Constant { public: String_Quoted(SourceSpan pstate, sass::string val, char q = 0, bool keep_utf8_escapes = false, bool skip_unquoting = false, bool strict_unquoting = true, bool css = true); bool operator< (const Expression& rhs) const override; bool operator==(const Expression& rhs) const override; // quotes are forced on inspection sass::string inspect() const override; ATTACH_AST_OPERATIONS(String_Quoted) ATTACH_CRTP_PERFORM_METHODS() }; ////////////////// // The null value. ////////////////// class Null final : public Value { public: Null(SourceSpan pstate); sass::string type() const override { return "null"; } static sass::string type_name() { return "null"; } bool is_invisible() const override { return true; } operator bool() override { return false; } bool is_false() override { return true; } size_t hash() const override; bool operator< (const Expression& rhs) const override; bool operator== (const Expression& rhs) const override; ATTACH_AST_OPERATIONS(Null) ATTACH_CRTP_PERFORM_METHODS() }; ////////////////////////////////// // The Parent Reference Expression. ////////////////////////////////// class Parent_Reference final : public Value { public: Parent_Reference(SourceSpan pstate); sass::string type() const override { return "parent"; } static sass::string type_name() { return "parent"; } bool operator< (const Expression& rhs) const override { return false; // they are always equal } bool operator==(const Expression& rhs) const override { return true; // they are always equal }; ATTACH_AST_OPERATIONS(Parent_Reference) ATTACH_CRTP_PERFORM_METHODS() }; } #endif