2020-03-07 19:42:11 +01:00
/*
* 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/NonnullOwnPtr.h>
# include <LibJS/AST.h>
# include <LibJS/Interpreter.h>
# include <LibJS/Object.h>
2020-03-11 19:27:43 +01:00
# include <LibJS/Parser.h>
2020-03-11 18:58:19 +01:00
# include <LibJS/PrimitiveString.h>
2020-03-07 19:42:11 +01:00
# include <LibJS/Value.h>
# include <stdio.h>
2020-03-11 19:27:43 +01:00
# define PROGRAM 6
2020-03-09 21:58:27 +01:00
2020-03-11 19:27:43 +01:00
static NonnullOwnPtr < JS : : Program > build_program ( JS : : Heap & ) ;
2020-03-09 21:13:55 +01:00
2020-03-07 19:42:11 +01:00
int main ( )
{
2020-03-11 18:58:19 +01:00
JS : : Interpreter interpreter ;
2020-03-07 19:42:11 +01:00
2020-03-11 19:27:43 +01:00
auto program = build_program ( interpreter . heap ( ) ) ;
2020-03-07 19:42:11 +01:00
program - > dump ( 0 ) ;
auto result = interpreter . run ( * program ) ;
dbg ( ) < < " Interpreter returned " < < result ;
printf ( " %s \n " , result . to_string ( ) . characters ( ) ) ;
2020-03-08 19:59:59 +01:00
2020-03-09 21:30:12 +01:00
dbg ( ) < < " Collecting garbage on exit... " ;
2020-03-08 19:59:59 +01:00
interpreter . heap ( ) . collect_garbage ( ) ;
2020-03-07 19:42:11 +01:00
return 0 ;
}
2020-03-09 21:13:55 +01:00
2020-03-09 21:58:27 +01:00
# if PROGRAM == 1
2020-03-11 19:27:43 +01:00
NonnullOwnPtr < JS : : Program > build_program ( JS : : Heap & )
2020-03-09 21:13:55 +01:00
{
// function foo() { return (1 + 2) + 3; }
// foo();
auto block = make < JS : : BlockStatement > ( ) ;
block - > append < JS : : ReturnStatement > (
make < JS : : BinaryExpression > (
JS : : BinaryOp : : Plus ,
make < JS : : BinaryExpression > (
JS : : BinaryOp : : Plus ,
make < JS : : Literal > ( JS : : Value ( 1 ) ) ,
make < JS : : Literal > ( JS : : Value ( 2 ) ) ) ,
make < JS : : Literal > ( JS : : Value ( 3 ) ) ) ) ;
2020-03-11 19:27:43 +01:00
auto program = make < JS : : Program > ( ) ;
program - > append < JS : : FunctionDeclaration > ( " foo " , move ( block ) ) ;
program - > append < JS : : ExpressionStatement > ( make < JS : : CallExpression > ( " foo " ) ) ;
return program ;
2020-03-09 21:13:55 +01:00
}
2020-03-09 21:58:27 +01:00
# elif PROGRAM == 2
2020-03-11 19:27:43 +01:00
NonnullOwnPtr < JS : : Program > build_program ( JS : : Heap & )
2020-03-09 21:13:55 +01:00
{
// c = 1;
// function foo() {
// var a = 5;
// var b = 7;
// return a + b + c;
// }
// foo();
2020-03-11 19:27:43 +01:00
auto program = make < JS : : Program > ( ) ;
program - > append < JS : : ExpressionStatement > ( make < JS : : AssignmentExpression > (
2020-03-09 21:13:55 +01:00
JS : : AssignmentOp : : Assign ,
make < JS : : Identifier > ( " c " ) ,
2020-03-11 19:27:43 +01:00
make < JS : : Literal > ( JS : : Value ( 1 ) ) ) ) ;
2020-03-09 21:13:55 +01:00
auto block = make < JS : : BlockStatement > ( ) ;
block - > append < JS : : VariableDeclaration > (
make < JS : : Identifier > ( " a " ) ,
2020-03-11 21:09:20 +02:00
make < JS : : Literal > ( JS : : Value ( 5 ) ) ,
JS : : DeclarationType : : Var ) ;
2020-03-09 21:13:55 +01:00
block - > append < JS : : VariableDeclaration > (
make < JS : : Identifier > ( " b " ) ,
2020-03-11 21:09:20 +02:00
make < JS : : Literal > ( JS : : Value ( 7 ) ) ,
JS : : DeclarationType : : Var ) ;
2020-03-09 21:13:55 +01:00
block - > append < JS : : ReturnStatement > (
make < JS : : BinaryExpression > (
JS : : BinaryOp : : Plus ,
make < JS : : BinaryExpression > (
JS : : BinaryOp : : Plus ,
make < JS : : Identifier > ( " a " ) ,
make < JS : : Identifier > ( " b " ) ) ,
make < JS : : Identifier > ( " c " ) ) ) ;
2020-03-11 19:27:43 +01:00
program - > append < JS : : FunctionDeclaration > ( " foo " , move ( block ) ) ;
program - > append < JS : : ExpressionStatement > ( make < JS : : CallExpression > ( " foo " ) ) ;
return program ;
2020-03-09 21:13:55 +01:00
}
2020-03-09 21:58:27 +01:00
# elif PROGRAM == 3
2020-03-11 19:27:43 +01:00
NonnullOwnPtr < JS : : Program > build_program ( JS : : Heap & )
2020-03-09 21:30:12 +01:00
{
// function foo() {
// var x = {};
// $gc();
// }
// foo();
auto block = make < JS : : BlockStatement > ( ) ;
block - > append < JS : : VariableDeclaration > (
make < JS : : Identifier > ( " x " ) ,
2020-03-11 21:09:20 +02:00
make < JS : : ObjectExpression > ( ) ,
JS : : DeclarationType : : Var ) ;
2020-03-11 19:27:43 +01:00
block - > append < JS : : ExpressionStatement > ( make < JS : : CallExpression > ( " $gc " ) ) ;
2020-03-09 21:30:12 +01:00
2020-03-11 19:27:43 +01:00
auto program = make < JS : : Program > ( ) ;
program - > append < JS : : FunctionDeclaration > ( " foo " , move ( block ) ) ;
program - > append < JS : : ExpressionStatement > ( make < JS : : CallExpression > ( " foo " ) ) ;
return program ;
2020-03-09 21:30:12 +01:00
}
2020-03-11 18:58:19 +01:00
# elif PROGRAM == 4
2020-03-11 19:27:43 +01:00
NonnullOwnPtr < JS : : Program > build_program ( JS : : Heap & )
2020-03-11 21:09:20 +02:00
{
// function foo() {
// function bar() {
// var y = 6;
// }
//
// bar()
// return y;
// }
// foo(); //I should return `undefined` because y is bound to the inner-most enclosing function, i.e the nested one (bar()), therefore, it's undefined in the scope of foo()
auto block_bar = make < JS : : BlockStatement > ( ) ;
block_bar - > append < JS : : VariableDeclaration > ( make < JS : : Identifier > ( " y " ) , make < JS : : Literal > ( JS : : Value ( 6 ) ) , JS : : DeclarationType : : Var ) ;
auto block_foo = make < JS : : BlockStatement > ( ) ;
block_foo - > append < JS : : FunctionDeclaration > ( " bar " , move ( block_bar ) ) ;
2020-03-11 19:27:43 +01:00
block_foo - > append < JS : : ExpressionStatement > ( make < JS : : CallExpression > ( " bar " ) ) ;
2020-03-11 21:09:20 +02:00
block_foo - > append < JS : : ReturnStatement > ( make < JS : : Identifier > ( " y " ) ) ;
2020-03-11 19:27:43 +01:00
auto program = make < JS : : Program > ( ) ;
program - > append < JS : : FunctionDeclaration > ( " foo " , move ( block_foo ) ) ;
program - > append < JS : : ExpressionStatement > ( make < JS : : CallExpression > ( " foo " ) ) ;
return program ;
2020-03-11 21:09:20 +02:00
}
# elif PROGRAM == 5
2020-03-11 19:27:43 +01:00
NonnullOwnPtr < JS : : Program > build_program ( JS : : Heap & heap )
2020-03-11 18:58:19 +01:00
{
// "hello friends".length
2020-03-11 19:27:43 +01:00
auto program = make < JS : : Program > ( ) ;
program - > append < JS : : ExpressionStatement > ( make < JS : : MemberExpression > (
2020-03-11 18:58:19 +01:00
make < JS : : Literal > ( JS : : Value ( js_string ( heap , " hello friends " ) ) ) ,
2020-03-11 19:27:43 +01:00
make < JS : : Identifier > ( " length " ) ) ) ;
return program ;
}
# elif PROGRAM == 6
NonnullOwnPtr < JS : : Program > build_program ( JS : : Heap & )
{
const char * source = " var foo = 1; \n "
" function bar() { \n "
" return 38; \n "
" } \n "
" foo = {}; \n "
" foo = bar() + 4; \n "
" foo; \n " ;
auto parser = JS : : Parser ( JS : : Lexer ( source ) ) ;
return parser . parse_program ( ) ;
2020-03-11 18:58:19 +01:00
}
2020-03-09 21:58:27 +01:00
# endif