summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Libraries/LibJS/AST.cpp30
-rw-r--r--Libraries/LibJS/AST.h10
-rw-r--r--Libraries/LibJS/Function.cpp3
-rw-r--r--Libraries/LibJS/Function.h4
-rw-r--r--Libraries/LibJS/Interpreter.cpp8
-rw-r--r--Libraries/LibJS/Interpreter.h4
-rw-r--r--Userland/js.cpp1
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;
}
-