srctree

Robin Linden parent 4d71ad40 de902650
js: Add a simple object value-kind

inlinesplit
js/ast.h added: 40, removed: 4, total 36
@@ -6,6 +6,7 @@
#define JS_AST_H_
 
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <string>
@@ -51,6 +52,8 @@ struct NativeFunction {
[[nodiscard]] bool operator==(NativeFunction const &) const { return false; }
};
 
using Object = std::map<std::string, Value, std::less<>>;
 
// TODO(robinlinden): This needs to support more values.
class Value {
public:
@@ -59,6 +62,7 @@ public:
explicit Value(std::string value) : value_{std::move(value)} {}
explicit Value(std::shared_ptr<Function> value) : value_{std::move(value)} {}
explicit Value(std::vector<Value> value) : value_{std::move(value)} {}
explicit Value(Object value) : value_{std::move(value)} {}
explicit Value(NativeFunction value) : value_{std::move(value)} {}
 
bool is_undefined() const { return std::holds_alternative<Undefined>(value_); }
@@ -66,12 +70,14 @@ public:
bool is_string() const { return std::holds_alternative<std::string>(value_); }
bool is_function() const { return std::holds_alternative<std::shared_ptr<Function>>(value_); }
bool is_vector() const { return std::holds_alternative<std::vector<Value>>(value_); }
bool is_object() const { return std::holds_alternative<Object>(value_); }
bool is_native_function() const { return std::holds_alternative<NativeFunction>(value_); }
 
double as_number() const { return std::get<double>(value_); }
std::string const &as_string() const { return std::get<std::string>(value_); }
std::shared_ptr<Function const> as_function() const { return std::get<std::shared_ptr<Function>>(value_); }
std::vector<Value> const &as_vector() const { return std::get<std::vector<Value>>(value_); }
Object const &as_object() const { return std::get<Object>(value_); }
NativeFunction const &as_native_function() const { return std::get<NativeFunction>(value_); }
 
bool as_bool() const {
@@ -90,7 +96,16 @@ private:
struct Undefined {
[[nodiscard]] bool operator==(Undefined const &) const = default;
};
std::variant<Undefined, std::string, double, std::shared_ptr<Function>, std::vector<Value>, NativeFunction> value_;
 
std::variant<Undefined,
std::string,
double,
std::shared_ptr<Function>,
std::vector<Value>,
Object,
NativeFunction //
>
value_;
};
 
struct NumericLiteral {
 
js/ast_test.cpp added: 40, removed: 4, total 36
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022 Robin Lindén <dev@robinlinden.eu>
// SPDX-FileCopyrightText: 2022-2023 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
@@ -22,5 +22,26 @@ int main() {
expect_eq(Value{std::vector<Value>{}}.as_bool(), true);
});
 
etest::test("Value: object", [] {
Object o{
{"hello", Value{5.}}, //
{"f", Value{NativeFunction{[](std::vector<Value> const &v) {
return Value{v.at(0).as_number() * 2};
}}}}, //
};
 
auto val = Value{std::move(o)};
etest::require(val.is_object());
 
auto const &obj = val.as_object();
etest::expect(obj.contains("hello"));
etest::expect(obj.contains("f"));
etest::expect(!obj.contains("e"));
etest::expect(!obj.contains("henlo"));
 
expect_eq(obj.at("hello").as_number(), 5.);
expect_eq(obj.at("f").as_native_function().f({Value{5.}}).as_number(), 5. * 2);
});
 
return etest::run_all_tests();
}