diff options
-rw-r--r-- | Libraries/LibJS/AST.cpp | 30 | ||||
-rw-r--r-- | Libraries/LibJS/AST.h | 10 | ||||
-rw-r--r-- | Libraries/LibJS/Function.cpp | 3 | ||||
-rw-r--r-- | Libraries/LibJS/Function.h | 4 | ||||
-rw-r--r-- | Libraries/LibJS/Interpreter.cpp | 8 | ||||
-rw-r--r-- | Libraries/LibJS/Interpreter.h | 4 | ||||
-rw-r--r-- | Userland/js.cpp | 1 |
7 files changed, 46 insertions, 14 deletions
diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 2d36cbfe8e..007a7d9e74 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -24,6 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <AK/HashMap.h> +#include <AK/StringBuilder.h> #include <LibJS/AST.h> #include <LibJS/Function.h> #include <LibJS/Interpreter.h> @@ -40,7 +42,7 @@ Value ScopeNode::execute(Interpreter& interpreter) const Value FunctionDeclaration::execute(Interpreter& interpreter) const { - auto* function = interpreter.heap().allocate<Function>(name(), body()); + auto* function = interpreter.heap().allocate<Function>(name(), body(), parameters()); interpreter.set_variable(m_name, Value(function)); return Value(function); } @@ -62,7 +64,18 @@ Value CallExpression::execute(Interpreter& interpreter) const auto* callee_object = callee.as_object(); ASSERT(callee_object->is_function()); auto& function = static_cast<Function&>(*callee_object); - return interpreter.run(function.body(), ScopeType::Function); + + const size_t arguments_size = m_arguments.size(); + ASSERT(function.parameters().size() == arguments_size); + HashMap<String, Value> passed_parameters; + for (size_t i = 0; i < arguments_size; ++i) { + auto name = function.parameters()[i]; + auto value = m_arguments[i].execute(interpreter); + dbg() << name << ": " << value; + passed_parameters.set(move(name), move(value)); + } + + return interpreter.run(function.body(), move(passed_parameters), ScopeType::Function); } Value ReturnStatement::execute(Interpreter& interpreter) const @@ -283,8 +296,19 @@ void BooleanLiteral::dump(int indent) const void FunctionDeclaration::dump(int indent) const { + bool first_time = true; + StringBuilder parameters_builder; + for (const auto& parameter : m_parameters) { + if (first_time) + first_time = false; + else + parameters_builder.append(','); + + parameters_builder.append(parameter); + } + print_indent(indent); - printf("%s '%s'\n", class_name(), name().characters()); + printf("%s '%s(%s)'\n", class_name(), name().characters(), parameters_builder.build().characters()); body().dump(indent + 1); } diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index 8a01f4659c..772d168f49 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -29,6 +29,7 @@ #include <AK/NonnullOwnPtrVector.h> #include <AK/OwnPtr.h> #include <AK/String.h> +#include <AK/Vector.h> #include <LibJS/Forward.h> #include <LibJS/Value.h> @@ -115,14 +116,16 @@ private: class FunctionDeclaration : public Statement { public: - FunctionDeclaration(String name, NonnullOwnPtr<ScopeNode> body) + FunctionDeclaration(String name, NonnullOwnPtr<ScopeNode> body, Vector<String> parameters = {}) : m_name(move(name)) , m_body(move(body)) + , m_parameters(move(parameters)) { } String name() const { return m_name; } const ScopeNode& body() const { return *m_body; } + const Vector<String>& parameters() const { return m_parameters; }; virtual Value execute(Interpreter&) const override; virtual void dump(int indent) const override; @@ -132,6 +135,7 @@ private: String m_name; NonnullOwnPtr<ScopeNode> m_body; + const Vector<String> m_parameters; }; class Expression : public ASTNode { @@ -363,8 +367,9 @@ private: class CallExpression : public Expression { public: - explicit CallExpression(String name) + explicit CallExpression(String name, NonnullOwnPtrVector<Expression> arguments = {}) : m_name(move(name)) + , m_arguments(move(arguments)) { } @@ -377,6 +382,7 @@ private: virtual const char* class_name() const override { return "CallExpression"; } String m_name; + const NonnullOwnPtrVector<Expression> m_arguments; }; enum class AssignmentOp { diff --git a/Libraries/LibJS/Function.cpp b/Libraries/LibJS/Function.cpp index d0d26b1514..665e0d4218 100644 --- a/Libraries/LibJS/Function.cpp +++ b/Libraries/LibJS/Function.cpp @@ -29,9 +29,10 @@ namespace JS { -Function::Function(String name, const ScopeNode& body) +Function::Function(String name, const ScopeNode& body, Vector<String> parameters) : m_name(move(name)) , m_body(body) + , m_parameters(move(parameters)) { } diff --git a/Libraries/LibJS/Function.h b/Libraries/LibJS/Function.h index 5e119bc98a..0a1cdfa55c 100644 --- a/Libraries/LibJS/Function.h +++ b/Libraries/LibJS/Function.h @@ -33,11 +33,12 @@ namespace JS { class Function : public Object { public: - Function(String name, const ScopeNode& body); + Function(String name, const ScopeNode& body, Vector<String> parameters = {}); virtual ~Function(); const String& name() const { return m_name; } const ScopeNode& body() const { return m_body; } + const Vector<String>& parameters() const { return m_parameters; }; protected: virtual const char* class_name() const override { return "Function"; } @@ -47,6 +48,7 @@ private: String m_name; const ScopeNode& m_body; + const Vector<String> m_parameters; }; } diff --git a/Libraries/LibJS/Interpreter.cpp b/Libraries/LibJS/Interpreter.cpp index 6c3ab98dfe..2f0b20d87b 100644 --- a/Libraries/LibJS/Interpreter.cpp +++ b/Libraries/LibJS/Interpreter.cpp @@ -42,9 +42,9 @@ Interpreter::~Interpreter() { } -Value Interpreter::run(const ScopeNode& scope_node, ScopeType scope_type) +Value Interpreter::run(const ScopeNode& scope_node, HashMap<String, Value> scope_variables, ScopeType scope_type) { - enter_scope(scope_node, scope_type); + enter_scope(scope_node, move(scope_variables), scope_type); Value last_value = js_undefined(); for (auto& node : scope_node.children()) { @@ -55,9 +55,9 @@ Value Interpreter::run(const ScopeNode& scope_node, ScopeType scope_type) return last_value; } -void Interpreter::enter_scope(const ScopeNode& scope_node, ScopeType scope_type) +void Interpreter::enter_scope(const ScopeNode& scope_node, HashMap<String, Value> scope_variables, ScopeType scope_type) { - m_scope_stack.append({ scope_type, scope_node, {} }); + m_scope_stack.append({ scope_type, scope_node, move(scope_variables) }); } void Interpreter::exit_scope(const ScopeNode& scope_node) diff --git a/Libraries/LibJS/Interpreter.h b/Libraries/LibJS/Interpreter.h index 7f3f4f76d7..6e590f3a3d 100644 --- a/Libraries/LibJS/Interpreter.h +++ b/Libraries/LibJS/Interpreter.h @@ -49,7 +49,7 @@ public: Interpreter(); ~Interpreter(); - Value run(const ScopeNode&, ScopeType = ScopeType::Block); + Value run(const ScopeNode&, HashMap<String, Value> scope_variables = {}, ScopeType = ScopeType::Block); Object& global_object() { return *m_global_object; } const Object& global_object() const { return *m_global_object; } @@ -65,7 +65,7 @@ public: void collect_roots(Badge<Heap>, HashTable<Cell*>&); private: - void enter_scope(const ScopeNode&, ScopeType); + void enter_scope(const ScopeNode&, HashMap<String, Value> scope_variables, ScopeType); void exit_scope(const ScopeNode&); Heap m_heap; diff --git a/Userland/js.cpp b/Userland/js.cpp index d8875d9775..4194d7db64 100644 --- a/Userland/js.cpp +++ b/Userland/js.cpp @@ -71,4 +71,3 @@ int main(int argc, char** argv) interpreter.heap().collect_garbage(); return 0; } - |