1. Как в рантайме правильнее разграничить вызов нативных (реализованных на Java) функций и вызов функций на JavaScript (это весьма разные сущности)?
Ну сделай разные классы для разных функций. JS динамически типизированный, так что в основном ты все равно будешь работать с каким-нибудь базовым абстрактным JsValue, от него и унаследуй классы функций. У класса JsValue сделай метод
JsValue call(scope: JsScope, context: JsValue, args: ArrayList<JsValue>)
который кидает
TypeError: бла-бла-бла is not a function
, а в классах функций (
JsNativeFunction
и
JsFunction
) переопредели его чтобы возвращал что-то.
2. Как оптимальнее хранить scopes? Через Hashtable/HashMap в виде вектора (имитация стека) - нормальное решение?
Я не эксперт, но я делал скоуп в виде хешмапа со ссылкой на родительский скоуп (и так по ссылкам можно было соответственно дойти до глобального скоупа), вроде нормальный вариант.
3. Как правильно организовать поиск функций в цепочке прототипов объекта? Например, мы ищем функцию; она находится в прототипе, ссылку на который мы храним. Но при вызове такая функция должна работать с полями данных исходного объекта, а не прототипа, или прототипа прототипа и т.д. В JavaScript всё будет в такой ситуации работать корректно, а как такое грамотно эмулировать?
Не вижу проблемы.
x.foo(42)
разворачивается во что-то типа этого:
JsObject xVar = scope.getVar("x");
xVar
.attr("foo") // ищет атрибут в объекте или в прототипе
.call(scope, xVar, Arrays.asList(JsInt(42)));
Второй параметр метода
call
- это и есть контекст, то есть объект у которого вызывается метод.
4. Эффективный алгоритм разбора выражений тоже не помешал бы. Как быстро разобрать строку, зная приоритеты операторов, корректно выделить все круглые скобки, которые могут быть вложены друг в друга, и т.д. Ссылки на любую литературу, в том числе англоязычную, приветствуются.
Тут вряд ли что-то толковое подскажу, кроме как посмотреть в сторону ANTLR и аналогов.
P. S.Немного литературы по теме