srctree

Robin Linden parent 07e21f6e 4cb78d4f
js: Implement interpreted execution of MemberExpression

inlinesplit
js/interpreter.h added: 30, removed: 11, total 19
@@ -36,15 +36,6 @@ public:
Value operator()(ExpressionStatement const &v) { return execute(v.expression); }
 
Value operator()(BinaryExpression const &v) {
// TODO(robinlinden): This should be done in a more generic fashion.
auto get_value_resolving_variables = [this](Expression const &expr) {
if (std::holds_alternative<Identifier>(expr)) {
return variables.at(execute(expr).as_string());
}
 
return execute(expr);
};
 
auto lhs = get_value_resolving_variables(*v.lhs);
auto rhs = get_value_resolving_variables(*v.rhs);
 
@@ -97,6 +88,12 @@ public:
return scope.execute(fn.as_native_function());
}
 
Value operator()(MemberExpression const &v) {
auto object = get_value_resolving_variables(*v.object);
auto property = execute(v.property);
return object.as_object().at(property.as_string());
}
 
Value operator()(Function const &v) {
auto const &args = variables.at("arguments").as_vector();
for (std::size_t i = 0; i < v.params.size(); ++i) {
@@ -152,6 +149,16 @@ public:
 
std::map<std::string, Value, std::less<>> variables;
std::optional<Value> returning;
 
private:
// TODO(robinlinden): This should be done in a more generic fashion.
Value get_value_resolving_variables(Expression const &expr) {
if (std::holds_alternative<Identifier>(expr)) {
return variables.at(execute(expr).as_string());
}
 
return execute(expr);
}
};
 
} // namespace js::ast
 
js/interpreter_test.cpp added: 30, removed: 11, total 19
@@ -111,6 +111,18 @@ int main() {
expect_eq(e.variables.size(), std::size_t{1});
});
 
etest::test("member expression", [] {
Interpreter e;
e.variables["obj"] = Value{Object{{"hello", Value{5.}}}};
 
auto member_expr = MemberExpression{
.object = std::make_shared<Expression>(Identifier{"obj"}),
.property = Identifier{"hello"},
};
 
expect_eq(e.execute(member_expr), Value{5.});
});
 
etest::test("return, values are returned", [] {
auto declaration = FunctionDeclaration{
.id = Identifier{"func"},