This commits makes effort towards tolerating some of javascript's quirks
when it comes to its type system, note that the interpreter's way of
handling type coercion is still not mature at all, for example, we still
have to implement NaN instead of just crashing when trying to parse a
string and failing.
Instead of every NativeFunction callback having to ask the Interpreter
for the current "this" value and then converting it to an Object etc,
just pass "this" as an Object* directly.
This patch adds NativeProperty, which can be used to implement object
properties that have C++ getters and/or setters.
Use this to move String.prototype.length to its correct place. :^)
To make sure that everyone has the same instance of StringPrototype,
hang a global prototype off of the Interpreter that can be fetched
when constructing new StringObjects.
This patch adds String.prototype.charAt() to demonstrate that prototype
property lookup works, and that you can call a prototype function on an
object, and it will do what you expect. :^)
Object will now traverse up the prototype chain when doing a get().
When a function is called on an object, that object will now also be
the "this" value inside the function. This stuff is probably not very
correct, but we will improve things as we go! :^)
We now evaluate for loops in their own scope if their init statement is
a lexical declaration.
Evaluating for loops in their own scope allow us to obtain expected
behaviour, which means for example, that the block-scoped variables
declared in a for statement will be limited to the scope of the for
loop's body and statement and not to that of the current scope (i.e the
one where the for statement was made)
Previously, we were allowing the redeclaration of a variable with `let`
or `const` if it was declared initially using `var`, we should not
tolerate any form of variable redeclaration using let/const.
This patch makes all HeapBlock allocations aligned to their block size,
enabling us to find the HeapBlock* for a given Cell* by simply masking
bits off of the cell address.
Use this to make a simple Heap& getter for Cell, which lets us avoid
plumbing the Heap& everywhere.
Both types of functions are now Function and implement calling via:
virtual Value call(Interpreter&, Vector<Value> arguments);
This removes the need for CallExpression::execute() to care about which
kind of function it's calling. :^)
This can be used to implement arbitrary functionality, callable from
JavaScript.
To make this work, I had to change the way CallExpression passes
arguments to the callee. Instead of a HashMap<String, Value>, we now
pass an ordered list of Argument { String name; Value value; }.
This patch includes a native "print(argument)" function. :^)
This also tightens the means of redeclaration of a variable by proxy,
since we now have a way of knowing how a variable was initially
declared, we can check if it was declared using `let` or `const` and
not tolerate redeclaration like we did previously.