* TODO =Symbol= primitive * Statements [7/7] ** DONE [2020-12-21 Mon] BlockStatement ** DONE [2020-12-21 Mon] IfStatement ** DONE [2020-12-22 Tue] ForStatement ** DONE [2021-01-23 Sat] WhileStatement ** DONE [2021-01-23 Sat] DoWhileStatement ** DONE [2021-01-24 Sun] BreakStatement, ContinueStatement *** DONE [2021-01-23 Sat] BreakStatement *** DONE [2021-01-23 Sat] ContinueStatement *** DONE [2021-01-23 Sat] LabeledStatement *** DONE [2021-01-23 Sat] labeled break *** DONE [2021-01-24 Sun] labeled continue ** DONE [2021-02-06 Sat] SwitchStatement ** DONE [2021-01-28 Thu] TryStatement * Expressions [10/10] ** DONE [2020-12-21 Mon] ConditinalExpression ** DONE [2021-02-05 Fri] ForInExpression ** DONE [2021-01-23 Sat] UpdateExpression ** DONE [2021-01-19 Tue] LogicalExpression... *** DONE [2021-01-19 Tue] && *** DONE [2021-01-19 Tue] || ** DONE [2021-01-04 Mon] UnaryExpression *** DONE [2021-01-03 Sun] everything, except... *** DONE [2021-01-04 Mon] =delete= ** DONE [2021-02-06 Sat] SequenceExpression ** DONE [2021-02-07 Sun] BinaryExpression [17/17] *** DONE [2020-12-30 Wed] ~==~ Abstract Equality Comparison *** DONE [2020-12-22 Tue] ~<~ Abstract Relationl Comparison *** DONE [2021-01-13 Wed] ~+~ between all types *** DONE [2021-01-19 Tue] ~===~ *** DONE [2021-01-26 Tue] =<= *** DONE [2021-01-26 Tue] ~<=~ *** DONE [2021-01-26 Tue] ~>~ *** DONE [2021-01-30 Sat] =instanceof= *** DONE [2021-02-07 Sun] =in= *** DONE [2021-02-07 Sun] =/= *** DONE [2021-02-07 Sun] =%= *** DONE [2021-02-07 Sun] =**= *** DONE [2021-02-07 Sun] =|= *** DONE [2021-02-07 Sun] =^= *** DONE [2021-02-07 Sun] =<<= *** DONE [2021-02-07 Sun] =>>= *** DONE [2021-02-07 Sun] =>>>= ** DONE [2021-02-07 Sun] AssignmentExpression [7/7] *** DONE [2020-12-21 Mon] ~=~ *** DONE [2021-01-02 Sat] ~+=~ *** DONE [2021-01-15 Fri] ~-=~ *** DONE [2021-01-14 Thu] ~*=~ *** DONE [2021-02-07 Sun] ~/=~ *** DONE [2021-02-07 Sun] ~&=~ *** DONE [2021-02-07 Sun] ~|=~ ** DONE [2021-01-11 Mon] ArrayExpression * Variables [6/8] ** DONE [2020-12-26 Sat] mutable values and assignment ** DONE [2021-01-11 Mon] array members get/assign ** DONE [2021-02-13 Sat] variable hoisting ** DONE [2021-02-13 Sat] assignment to an outer variable ** DONE [2021-02-13 Sat] free-variables analysis for closures ** DONE [2022-06-15 Sat] a new local scope in =catch {}= ** TODO =let= variables, block scope [1/2] *** DONE [2022-06-19 Sun] initial hack: create an object scope for every block *** TODO proper declarative lexical scope for blocks ** TODO =const= values * Function calls [3/3] ** DONE [2021-01-01 Fri] CallExpression ** DONE [2021-01-16 Sun] immediate calls: ~(function(){})()~ ** DONE [2021-01-23 Sat] array member calls: ~a[0]()~ * Builtin objects ** builtin functions [3/5] *** DONE [2021-04-28 Wed] =parseFloat= *** DONE [2021-01-09 Sat] =parseInt= *** TODO proper =parseInt= *** DONE [2022-07-05 Tue] =eval= *** TODO =isNaN= ** builtin =Object= [10/26] *** DONE [2021-01-05 Tue] create it! *** DONE [2021-01-05 Tue] Object.getOwnPropertyDescriptor *** DONE [2021-01-08 Fri] .constructor *** DONE [2021-01-08 Fri] Object.is() *** DONE [2021-01-18 Mon] Object() constructor *** DONE [2021-01-18 Mon] .valueOf() *** DONE [2021-02-10 Wed] Object.create() *** DONE [2021-02-10 Wed] Object.defineProperties() *** DONE [2021-02-13 Sat] Object.setPrototypeOf() *** DONE [2021-02-13 Sat] .hasOwnProperty() *** TODO Object.getPrototypeOf() *** TODO Object.assign() *** TODO Object.keys() *** TODO Object.values() *** TODO Object.entries() *** TODO Object.fromEntries() *** TODO Object.getOwnPropertyDescriptors() *** TODO Object.getOwnPropertyNames() *** TODO Object.freeze() *** TODO Object.isFrozen() *** TODO Object.preventExtensions() *** TODO Object.isExtensible() *** TODO Object.seal() *** TODO Object.isSealed() *** TODO .isPrototypeOf() *** TODO .propertyIsEnumerable() ** builtin =Function= [4/6] *** DONE [2021-01-06 Wed] =src/builtin/function.rs= *** DONE [2021-01-17 Sun] .constructor *** DONE [2021-01-20 Wed] .call() *** DONE [2021-01-20 Wed] .apply() *** TODO .bind() *** TODO ...everything else ** builtin =Array= [6/10] *** DONE [2021-01-10 Sun] =src/builtin/array.rs= *** DONE [2021-01-15 Fri] (de)serialization *** DONE [2021-01-16 Sat] .toString() *** DONE [2021-05-16 Sun] .length *** DONE [2021-05-16 Sun] .push() *** DONE [2021-05-22 Sat] .pop() *** TODO Array.from *** TODO Array.of *** TODO Array.isArray() *** TODO ...everything else ** builtin =JSON= [/] ** builtin =Boolean= [3/3] *** DONE [2021-01-20 Wed] scaffolding in =src/builtin/boolean.rs= *** DONE [2021-01-20 Wed] Boolean constructor, =Object(true)= *** DONE [2021-01-20 Wed] Boolean.prototype **** DONE [2021-01-20 Wed] .valueOf **** DONE [2021-01-20 Wed] .toString ** builtin =String= [10/20] *** DONE [2021-03-10 Wed] .length *** DONE [2021-04-24 Sat] string indexing *** DONE [2021-04-24 Sat] =src/builtin/string.rs= *** DONE [2021-04-24 Sat] String() constructor; Object("string") *** DONE [2021-04-28 Wed] .charCodeAt() *** DONE [2021-05-01 Sat] .charAt() *** DONE [2021-05-01 Sat] .slice() *** DONE [2021-05-22 Sat] .substr() *** DONE [2021-05-30 Sun] .indexOf() *** DONE [2022-07-09 Sat] .replace() *** TODO =.replace(/regexp/)= *** TODO check escape notation *** TODO String.fromCharCode() *** TODO String.fromCodePoint() *** TODO String.raw() *** TODO .concat() *** TODO .includes() *** TODO .endsWith() *** TODO .lastIndexOf() *** TODO .replace() *** TODO ... ** builtin =Number= [/] ** MAYBE builtin =assert= object ** NOPE =console= in sljs This is I/O and should not live in the interpreter core. * User functions [3/4] ** DONE FunctionExpression *** DONE [2021-01-06 Wed] function scope *** DONE [2021-01-17 Sun] closures *** DONE [2021-01-23 Sat] =arguments= ** DONE [2021-01-06 Wed] ReturnExpression ** DONE [2021-01-23 Sat] FunctionDeclaration ** TODO recursive functions [1/3] *** DONE [2021-01-17 Sun] make them work *** TODO limit call stack, throw StackOverflow *** MAYBE tail call optimization * User objects [4/5] ** DONE [2021-01-09 Sat] prototype chain ** DONE [2021-01-17 Sun] ThisExpression ** DONE [2021-01-18 Mon] NewExpression ** DONE [2021-01-31 Sun] properties lookup on the chain ** TODO properties, =get=, =set= * User exceptions [3/4] ** DONE [2021-01-27 Wed] =throw= ** DONE [2021-01-28 Thu] =try=, =catch=, =finally= ** DONE [2021-01-31 Sun] =Error= objects ** TODO stacktraces with source locations * DONE [2021-01-14 Thu] rewrite the =Heap= to be =Vec= * DONE [2020-12-31 Thu] make it a library * DONE [2021-01-01 Fri] a repl executable * testing [1/3] ** DONE [2022-06-19 Sun] move tests to =tests/= ** WIP split tests into internal =assert_eval= and external =assert_parse= Internal tests (=src/test/interp.rs=) should take an AST constructed via a DSL for AST construction. External tests (=tests/parse.rs=) verify parsing from a string to an AST. ** TODO write a test262 harness in Rust * MAYBE optimizations [1/6] ** DONE Set up microbenchmarks *Why*: because optimization is not possible without metrics. *How*: cargo bench? ** TODO Use a streaming json parser *Why*: copying JSON into a huge String to be immediately discarded is wasteful. Making a complete intermediate JSON structure from it is also wasteful *How*: something like https://docs.rs/qjsonrs reads from a Read, producing JSON tokens, some of which trigger callbacks SAX-style. A bottom-up "parser" assembles pieces into a Program. Some intermediate JSON-like structures may be kept around. ** TODO Bytecode compilation *Why*: AST-based interpretation is dumb. ** MAYBE Intern all property names *Why*: all properties are currently stored by a =String= key. This means that each property key is 24 bytes and contains a pointer to its UTF8 buffer. A comparison of two keys means chasing two pointers and reading unknown extents of memory. *Interning*: all keys will become integer handles for interned strings. Each key lookup will be an int comparison. *Bonus*: =Symbol= will correspond to interned keys naturally. ** MAYBE Track hidden classes, especially after calling constructors *Why*: HashMap is not always the best storage; vector can be better. Abstracting property names into a hidden class can leave each object with a single vector of values and a pointer to the hidden class with the value description vector. Work: need to convert HashMap-based objects into class-based objects and back. ** MAYBE Frozen/sealed objects to store their properties in a vector. *Why*: frozen/sealed objects are by definition non-extensible. Attaching a hidden class looks like a good idea. * TODO garbage collection [1/3] ** DONE [2021-05-31 Mon] SimpleCopyingGC draft It kinda works, but has a fatal flaw: ~JSRef~s are free-floating in the unmanaged code. ** MAYBE Introduce an explicit stack for references in use? ** MAYBE A garbage collector in another thread? * TODO the **endgoal**: be able to run Esprima internally [4/6] ** DONE [2021-02-08 Sun] all of Esprima syntax is understood ** DONE [2021-03-02 Tue] all of Esprima code can be loaded ** DONE [2021-05-22 Sat] there is a binary doing parsing via internal Esprima ** DONE [2022-06-05 Sun] make parsing engines abstract ** TODO interpreter doing parsing with Esprima can parse Esprima. Blocked by: needs GC, 16 GB RAM is not enough. ** MAYBE try treesitter? * DONE =eval= It's buggy, but it's metainterpreted now. #+TODO: BUG TODO MAYBE WIP | DONE NOPE