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 <LibJS/AST.h> | ||||
| #include <LibJS/Interpreter.h> | ||||
| #include <LibJS/Runtime/Array.h> | ||||
| #include <LibJS/Runtime/PrimitiveString.h> | ||||
| #include <LibJS/Runtime/ScriptFunction.h> | ||||
| #include <LibJS/Runtime/Value.h> | ||||
|  | @ -682,4 +683,21 @@ Value NullLiteral::execute(Interpreter&) const | |||
|     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"; } | ||||
| }; | ||||
| 
 | ||||
| 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 { | ||||
| public: | ||||
|     MemberExpression(NonnullRefPtr<Expression> object, NonnullRefPtr<Expression> property) | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ OBJS = \ | |||
|     Interpreter.o \
 | ||||
|     Lexer.o \
 | ||||
|     Parser.o \
 | ||||
|     Runtime/Array.o \
 | ||||
|     Runtime/Cell.o \
 | ||||
|     Runtime/ConsoleObject.o \
 | ||||
|     Runtime/Function.o \
 | ||||
|  |  | |||
|  | @ -231,6 +231,8 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression() | |||
|         return parse_object_expression(); | ||||
|     case TokenType::Function: | ||||
|         return parse_function_node<FunctionExpression>(); | ||||
|     case TokenType::BracketOpen: | ||||
|         return parse_array_expression(); | ||||
|     default: | ||||
|         m_has_errors = true; | ||||
|         expected("primary expression (missing switch case)"); | ||||
|  | @ -273,6 +275,22 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression() | |||
|     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) | ||||
| { | ||||
|     if (match_unary_prefixed_expression()) | ||||
|  |  | |||
|  | @ -56,6 +56,7 @@ public: | |||
|     NonnullRefPtr<Expression> parse_primary_expression(); | ||||
|     NonnullRefPtr<Expression> parse_unary_prefixed_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<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_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_native_function() 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