diff --git a/Base/home/anon/js/forced-gc.js b/Base/home/anon/js/forced-gc.js new file mode 100644 index 00000000000..70a1da3a438 --- /dev/null +++ b/Base/home/anon/js/forced-gc.js @@ -0,0 +1,5 @@ +function foo() { + var x = {}; + $gc(); +} +foo(); diff --git a/Base/home/anon/js/simple-function.js b/Base/home/anon/js/simple-function.js new file mode 100644 index 00000000000..801e58841f5 --- /dev/null +++ b/Base/home/anon/js/simple-function.js @@ -0,0 +1,2 @@ +function foo() { return (1 + 2) + 3; } +foo(); diff --git a/Base/home/anon/js/simple-parse.js b/Base/home/anon/js/simple-parse.js new file mode 100644 index 00000000000..0bac548acbc --- /dev/null +++ b/Base/home/anon/js/simple-parse.js @@ -0,0 +1,7 @@ +var foo = 1; +function bar() { + return 38; +} +foo = {}; +foo = bar() + 4; +foo; diff --git a/Base/home/anon/js/simple-scopes.js b/Base/home/anon/js/simple-scopes.js new file mode 100644 index 00000000000..dcea148c258 --- /dev/null +++ b/Base/home/anon/js/simple-scopes.js @@ -0,0 +1,9 @@ +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() diff --git a/Base/home/anon/js/simple-variables.js b/Base/home/anon/js/simple-variables.js new file mode 100644 index 00000000000..dfecdab09c3 --- /dev/null +++ b/Base/home/anon/js/simple-variables.js @@ -0,0 +1,7 @@ +c = 1; +function foo() { + var a = 5; + var b = 7; + return a + b + c; +} +foo(); diff --git a/Base/home/anon/js/string-length.js b/Base/home/anon/js/string-length.js new file mode 100644 index 00000000000..db20e7c955c --- /dev/null +++ b/Base/home/anon/js/string-length.js @@ -0,0 +1,3 @@ +function foo() { + "hello friends".length +} diff --git a/Userland/js.cpp b/Userland/js.cpp index 6c919fdb6b3..d8875d97751 100644 --- a/Userland/js.cpp +++ b/Userland/js.cpp @@ -24,7 +24,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include +#include +#include #include #include #include @@ -35,14 +38,29 @@ #define PROGRAM 6 -static NonnullOwnPtr build_program(JS::Heap&); - -int main() +int main(int argc, char** argv) { + bool dump_ast = false; + const char* script_path = nullptr; + + Core::ArgsParser args_parser; + args_parser.add_option(dump_ast, "Dump the AST", "ast-dump", 'A'); + args_parser.add_positional_argument(script_path, "Path to script file", "script"); + args_parser.parse(argc, argv); + + auto file = Core::File::construct(script_path); + if (!file->open(Core::IODevice::ReadOnly)) { + fprintf(stderr, "Failed to open %s: %s\n", script_path, file->error_string()); + return 1; + } + auto file_contents = file->read_all(); + JS::Interpreter interpreter; - auto program = build_program(interpreter.heap()); - program->dump(0); + auto program = JS::Parser(JS::Lexer(file_contents)).parse_program(); + + if (dump_ast) + program->dump(0); auto result = interpreter.run(*program); dbg() << "Interpreter returned " << result; @@ -54,139 +72,3 @@ int main() return 0; } -#if PROGRAM == 1 -NonnullOwnPtr build_program(JS::Heap&) -{ - // function foo() { return (1 + 2) + 3; } - // foo(); - - auto block = make(); - block->append( - make( - JS::BinaryOp::Plus, - make( - JS::BinaryOp::Plus, - make(JS::Value(1)), - make(JS::Value(2))), - make(JS::Value(3)))); - - auto program = make(); - program->append("foo", move(block)); - program->append(make("foo")); - return program; -} -#elif PROGRAM == 2 -NonnullOwnPtr build_program(JS::Heap&) -{ - // c = 1; - // function foo() { - // var a = 5; - // var b = 7; - // return a + b + c; - // } - // foo(); - - auto program = make(); - program->append(make( - JS::AssignmentOp::Assign, - make("c"), - make(JS::Value(1)))); - - auto block = make(); - block->append( - make("a"), - make(JS::Value(5)), - JS::DeclarationType::Var); - block->append( - make("b"), - make(JS::Value(7)), - JS::DeclarationType::Var); - - block->append( - make( - JS::BinaryOp::Plus, - make( - JS::BinaryOp::Plus, - make("a"), - make("b")), - make("c"))); - - program->append("foo", move(block)); - program->append(make("foo")); - - return program; -} -#elif PROGRAM == 3 -NonnullOwnPtr build_program(JS::Heap&) -{ - // function foo() { - // var x = {}; - // $gc(); - // } - // foo(); - - auto block = make(); - block->append( - make("x"), - make(), - JS::DeclarationType::Var); - block->append(make("$gc")); - - auto program = make(); - program->append("foo", move(block)); - program->append(make("foo")); - return program; -} -#elif PROGRAM == 4 -NonnullOwnPtr build_program(JS::Heap&) -{ - // 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(); - block_bar->append(make("y"), make(JS::Value(6)), JS::DeclarationType::Var); - - auto block_foo = make(); - block_foo->append("bar", move(block_bar)); - block_foo->append(make("bar")); - block_foo->append(make("y")); - - auto program = make(); - program->append("foo", move(block_foo)); - program->append(make("foo")); - return program; -} -#elif PROGRAM == 5 -NonnullOwnPtr build_program(JS::Heap& heap) -{ - // "hello friends".length - - auto program = make(); - program->append(make( - make(JS::Value(js_string(heap, "hello friends"))), - make("length"))); - - return program; -} -#elif PROGRAM == 6 -NonnullOwnPtr 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(); -} -#endif