mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:12:43 +00:00 
			
		
		
		
	LibJS: Parse ArrayExpression and start implementing Array objects
Note that property lookup is not functional yet.
This commit is contained in:
		
							parent
							
								
									0891f860f7
								
							
						
					
					
						commit
						a82f64d3d6
					
				
					 9 changed files with 176 additions and 0 deletions
				
			
		
							
								
								
									
										8
									
								
								Base/home/anon/js/array.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Base/home/anon/js/array.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | var a = [1, 2, 3]; | ||||||
|  | console.log(a); | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | for (var i = 0; i < 3; ++i) { | ||||||
|  |     console.log(a[i]); | ||||||
|  | } | ||||||
|  | */ | ||||||
|  | @ -29,6 +29,7 @@ | ||||||
| #include <AK/StringBuilder.h> | #include <AK/StringBuilder.h> | ||||||
| #include <LibJS/AST.h> | #include <LibJS/AST.h> | ||||||
| #include <LibJS/Interpreter.h> | #include <LibJS/Interpreter.h> | ||||||
|  | #include <LibJS/Runtime/Array.h> | ||||||
| #include <LibJS/Runtime/PrimitiveString.h> | #include <LibJS/Runtime/PrimitiveString.h> | ||||||
| #include <LibJS/Runtime/ScriptFunction.h> | #include <LibJS/Runtime/ScriptFunction.h> | ||||||
| #include <LibJS/Runtime/Value.h> | #include <LibJS/Runtime/Value.h> | ||||||
|  | @ -682,4 +683,21 @@ Value NullLiteral::execute(Interpreter&) const | ||||||
|     return js_null(); |     return js_null(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ArrayExpression::dump(int indent) const | ||||||
|  | { | ||||||
|  |     ASTNode::dump(indent); | ||||||
|  |     for (auto& element : m_elements) { | ||||||
|  |         element.dump(indent + 1); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Value ArrayExpression::execute(Interpreter& interpreter) const | ||||||
|  | { | ||||||
|  |     auto* array = interpreter.heap().allocate<Array>(); | ||||||
|  |     for (auto& element : m_elements) { | ||||||
|  |         array->append(element.execute(interpreter)); | ||||||
|  |     } | ||||||
|  |     return array; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -581,6 +581,24 @@ private: | ||||||
|     virtual const char* class_name() const override { return "ObjectExpression"; } |     virtual const char* class_name() const override { return "ObjectExpression"; } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | class ArrayExpression : public Expression { | ||||||
|  | public: | ||||||
|  |     ArrayExpression(NonnullRefPtrVector<Expression> elements) | ||||||
|  |         : m_elements(move(elements)) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const NonnullRefPtrVector<Expression>& elements() const { return m_elements; } | ||||||
|  | 
 | ||||||
|  |     virtual Value execute(Interpreter&) const override; | ||||||
|  |     virtual void dump(int indent) const override; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     virtual const char* class_name() const override { return "ArrayExpression"; } | ||||||
|  | 
 | ||||||
|  |     NonnullRefPtrVector<Expression> m_elements; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class MemberExpression final : public Expression { | class MemberExpression final : public Expression { | ||||||
| public: | public: | ||||||
|     MemberExpression(NonnullRefPtr<Expression> object, NonnullRefPtr<Expression> property) |     MemberExpression(NonnullRefPtr<Expression> object, NonnullRefPtr<Expression> property) | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ OBJS = \ | ||||||
|     Interpreter.o \
 |     Interpreter.o \
 | ||||||
|     Lexer.o \
 |     Lexer.o \
 | ||||||
|     Parser.o \
 |     Parser.o \
 | ||||||
|  |     Runtime/Array.o \
 | ||||||
|     Runtime/Cell.o \
 |     Runtime/Cell.o \
 | ||||||
|     Runtime/ConsoleObject.o \
 |     Runtime/ConsoleObject.o \
 | ||||||
|     Runtime/Function.o \
 |     Runtime/Function.o \
 | ||||||
|  |  | ||||||
|  | @ -231,6 +231,8 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression() | ||||||
|         return parse_object_expression(); |         return parse_object_expression(); | ||||||
|     case TokenType::Function: |     case TokenType::Function: | ||||||
|         return parse_function_node<FunctionExpression>(); |         return parse_function_node<FunctionExpression>(); | ||||||
|  |     case TokenType::BracketOpen: | ||||||
|  |         return parse_array_expression(); | ||||||
|     default: |     default: | ||||||
|         m_has_errors = true; |         m_has_errors = true; | ||||||
|         expected("primary expression (missing switch case)"); |         expected("primary expression (missing switch case)"); | ||||||
|  | @ -273,6 +275,22 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression() | ||||||
|     return create_ast_node<ObjectExpression>(); |     return create_ast_node<ObjectExpression>(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | NonnullRefPtr<ArrayExpression> Parser::parse_array_expression() | ||||||
|  | { | ||||||
|  |     consume(TokenType::BracketOpen); | ||||||
|  | 
 | ||||||
|  |     NonnullRefPtrVector<Expression> elements; | ||||||
|  |     while (match_expression()) { | ||||||
|  |         elements.append(parse_expression(0)); | ||||||
|  |         if (!match(TokenType::Comma)) | ||||||
|  |             break; | ||||||
|  |         consume(TokenType::Comma); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     consume(TokenType::BracketClose); | ||||||
|  |     return create_ast_node<ArrayExpression>(move(elements)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| NonnullRefPtr<Expression> Parser::parse_expression(int min_precedence, Associativity associativity) | NonnullRefPtr<Expression> Parser::parse_expression(int min_precedence, Associativity associativity) | ||||||
| { | { | ||||||
|     if (match_unary_prefixed_expression()) |     if (match_unary_prefixed_expression()) | ||||||
|  |  | ||||||
|  | @ -56,6 +56,7 @@ public: | ||||||
|     NonnullRefPtr<Expression> parse_primary_expression(); |     NonnullRefPtr<Expression> parse_primary_expression(); | ||||||
|     NonnullRefPtr<Expression> parse_unary_prefixed_expression(); |     NonnullRefPtr<Expression> parse_unary_prefixed_expression(); | ||||||
|     NonnullRefPtr<ObjectExpression> parse_object_expression(); |     NonnullRefPtr<ObjectExpression> parse_object_expression(); | ||||||
|  |     NonnullRefPtr<ArrayExpression> parse_array_expression(); | ||||||
|     NonnullRefPtr<Expression> parse_secondary_expression(NonnullRefPtr<Expression>, int min_precedence, Associativity associate = Associativity::Right); |     NonnullRefPtr<Expression> parse_secondary_expression(NonnullRefPtr<Expression>, int min_precedence, Associativity associate = Associativity::Right); | ||||||
|     NonnullRefPtr<CallExpression> parse_call_expression(NonnullRefPtr<Expression>); |     NonnullRefPtr<CallExpression> parse_call_expression(NonnullRefPtr<Expression>); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										60
									
								
								Libraries/LibJS/Runtime/Array.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								Libraries/LibJS/Runtime/Array.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  * | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright notice, this | ||||||
|  |  *    list of conditions and the following disclaimer. | ||||||
|  |  * | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||||
|  |  *    this list of conditions and the following disclaimer in the documentation | ||||||
|  |  *    and/or other materials provided with the distribution. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||||
|  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||||
|  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||||
|  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||||
|  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||||
|  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <AK/Function.h> | ||||||
|  | #include <LibJS/Runtime/Array.h> | ||||||
|  | 
 | ||||||
|  | namespace JS { | ||||||
|  | 
 | ||||||
|  | Array::Array() | ||||||
|  | { | ||||||
|  |     put_native_property( | ||||||
|  |         "length", | ||||||
|  |         [this](Object*) { | ||||||
|  |             return Value(length()); | ||||||
|  |         }, | ||||||
|  |         [](Object*, Value) { | ||||||
|  |             ASSERT_NOT_REACHED(); | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Array::~Array() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Array::append(Value value) | ||||||
|  | { | ||||||
|  |     m_elements.append(value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Array::visit_children(Cell::Visitor& visitor) | ||||||
|  | { | ||||||
|  |     Object::visit_children(visitor); | ||||||
|  |     for (auto& element : m_elements) | ||||||
|  |         visitor.visit(element); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								Libraries/LibJS/Runtime/Array.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								Libraries/LibJS/Runtime/Array.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  * | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright notice, this | ||||||
|  |  *    list of conditions and the following disclaimer. | ||||||
|  |  * | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||||
|  |  *    this list of conditions and the following disclaimer in the documentation | ||||||
|  |  *    and/or other materials provided with the distribution. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||||
|  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||||
|  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||||
|  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||||
|  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||||
|  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <LibJS/Runtime/Object.h> | ||||||
|  | 
 | ||||||
|  | namespace JS { | ||||||
|  | 
 | ||||||
|  | class Array final : public Object { | ||||||
|  | public: | ||||||
|  |     Array(); | ||||||
|  |     virtual ~Array() override; | ||||||
|  | 
 | ||||||
|  |     i32 length() const { return static_cast<i32>(m_elements.size()); } | ||||||
|  |     const Vector<Value>& elements() const { return m_elements; } | ||||||
|  | 
 | ||||||
|  |     void append(Value); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     virtual const char* class_name() const override { return "Array"; } | ||||||
|  |     virtual void visit_children(Cell::Visitor&) override; | ||||||
|  |     virtual bool is_array() const override { return true; } | ||||||
|  | 
 | ||||||
|  |     Vector<Value> m_elements; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -46,6 +46,7 @@ public: | ||||||
|     void put_native_function(String property_name, AK::Function<Value(Object*, Vector<Value>)>); |     void put_native_function(String property_name, AK::Function<Value(Object*, Vector<Value>)>); | ||||||
|     void put_native_property(String property_name, AK::Function<Value(Object*)> getter, AK::Function<void(Object*, Value)> setter); |     void put_native_property(String property_name, AK::Function<Value(Object*)> getter, AK::Function<void(Object*, Value)> setter); | ||||||
| 
 | 
 | ||||||
|  |     virtual bool is_array() const { return false; } | ||||||
|     virtual bool is_function() const { return false; } |     virtual bool is_function() const { return false; } | ||||||
|     virtual bool is_native_function() const { return false; } |     virtual bool is_native_function() const { return false; } | ||||||
|     virtual bool is_string_object() const { return false; } |     virtual bool is_string_object() const { return false; } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling