Serenity Operating System
at hosted 209 lines 5.4 kB view raw
1/* 2 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#pragma once 28 29#include <AK/Assertions.h> 30#include <AK/Forward.h> 31#include <AK/LogStream.h> 32#include <LibJS/Forward.h> 33 34namespace JS { 35 36class Value { 37public: 38 enum class Type { 39 Empty, 40 Undefined, 41 Null, 42 Number, 43 String, 44 Object, 45 Boolean, 46 }; 47 48 bool is_empty() const { return m_type == Type::Empty; } 49 bool is_undefined() const { return m_type == Type::Undefined; } 50 bool is_null() const { return m_type == Type::Null; } 51 bool is_number() const { return m_type == Type::Number; } 52 bool is_string() const { return m_type == Type::String; } 53 bool is_object() const { return m_type == Type::Object; } 54 bool is_boolean() const { return m_type == Type::Boolean; } 55 bool is_cell() const { return is_string() || is_object(); } 56 bool is_array() const; 57 58 bool is_nan() const { return is_number() && __builtin_isnan(as_double()); } 59 bool is_infinity() const { return is_number() && __builtin_isinf(as_double()); } 60 61 Value() 62 : m_type(Type::Empty) 63 { 64 } 65 66 explicit Value(bool value) 67 : m_type(Type::Boolean) 68 { 69 m_value.as_bool = value; 70 } 71 72 explicit Value(double value) 73 : m_type(Type::Number) 74 { 75 m_value.as_double = value; 76 } 77 78 explicit Value(i32 value) 79 : m_type(Type::Number) 80 { 81 m_value.as_double = value; 82 } 83 84 Value(Object* object) 85 : m_type(object ? Type::Object : Type::Null) 86 { 87 m_value.as_object = object; 88 } 89 90 Value(PrimitiveString* string) 91 : m_type(Type::String) 92 { 93 m_value.as_string = string; 94 } 95 96 explicit Value(Type type) 97 : m_type(type) 98 { 99 } 100 101 Type type() const { return m_type; } 102 103 double as_double() const 104 { 105 ASSERT(type() == Type::Number); 106 return m_value.as_double; 107 } 108 109 bool as_bool() const 110 { 111 ASSERT(type() == Type::Boolean); 112 return m_value.as_bool; 113 } 114 115 Object& as_object() 116 { 117 ASSERT(type() == Type::Object); 118 return *m_value.as_object; 119 } 120 121 const Object& as_object() const 122 { 123 ASSERT(type() == Type::Object); 124 return *m_value.as_object; 125 } 126 127 PrimitiveString* as_string() 128 { 129 ASSERT(is_string()); 130 return m_value.as_string; 131 } 132 133 const PrimitiveString* as_string() const 134 { 135 ASSERT(is_string()); 136 return m_value.as_string; 137 } 138 139 Cell* as_cell() 140 { 141 ASSERT(is_cell()); 142 return m_value.as_cell; 143 } 144 145 String to_string() const; 146 bool to_boolean() const; 147 Value to_number() const; 148 i32 to_i32() const; 149 double to_double() const; 150 151 Object* to_object(Heap&) const; 152 153private: 154 Type m_type { Type::Undefined }; 155 156 union { 157 bool as_bool; 158 double as_double; 159 PrimitiveString* as_string; 160 Object* as_object; 161 Cell* as_cell; 162 } m_value; 163}; 164 165inline Value js_undefined() 166{ 167 return Value(Value::Type::Undefined); 168} 169 170inline Value js_null() 171{ 172 return Value(Value::Type::Null); 173} 174 175inline Value js_nan() 176{ 177 return Value(__builtin_nan("")); 178} 179 180inline Value js_infinity() 181{ 182 return Value(__builtin_huge_val()); 183} 184 185Value greater_than(Value lhs, Value rhs); 186Value greater_than_equals(Value lhs, Value rhs); 187Value less_than(Value lhs, Value rhs); 188Value less_than_equals(Value lhs, Value rhs); 189Value bitwise_and(Value lhs, Value rhs); 190Value bitwise_or(Value lhs, Value rhs); 191Value bitwise_xor(Value lhs, Value rhs); 192Value bitwise_not(Value); 193Value unary_plus(Value); 194Value unary_minus(Value); 195Value left_shift(Value lhs, Value rhs); 196Value right_shift(Value lhs, Value rhs); 197Value add(Value lhs, Value rhs); 198Value sub(Value lhs, Value rhs); 199Value mul(Value lhs, Value rhs); 200Value div(Value lhs, Value rhs); 201Value mod(Value lhs, Value rhs); 202Value exp(Value lhs, Value rhs); 203Value eq(Value lhs, Value rhs); 204Value typed_eq(Value lhs, Value rhs); 205Value instance_of(Value lhs, Value rhs); 206 207const LogStream& operator<<(const LogStream&, const Value&); 208 209}