JBForth2

 
+
-
edit
 

Balancer

администратор
★★★★★
Ковырялся сегодня, наконец, на тему Java-байткода. Т.е. по поводу возможности компиляции JBForth в байткод JVM.

Пробные примеры получатся.

Огорчение - у каждого метода свой стек. Ограничиться им теоретически можно, но это не оставит от Форта ничего, кроме синтаксиса :) А оно нам нафиг не надо...

Похоже, придётся делать таки отдельный глобальный стек.

Таким образом от нативной производительности остаются опять рожки да ножки.

Хотя, естественно, будет возможность генерации нативных для JVM классов и методов. Так что критические куски кода можно будет писать на JVM-функционале.

...

В общем, перспективы интересные, но работы предстоит чудовищное количество :)
 

Murkt

Pythoneer

Меня это давно интересует - генерация кода на лету, или же трансляция (форт -> джава). Дай ссылок, пожалуйста :)
[team Їжачки - сумні падлюки]  

Murkt

Pythoneer

Или сам расскажи :)
[team Їжачки - сумні падлюки]  
+
-
edit
 

Balancer

администратор
★★★★★
Буду базироваться на ASM - Home Page

Но проблем ожидается масса. Как технологических, так и идеологических.
 
+
-
edit
 

Balancer

администратор
★★★★★
Murkt> Или сам расскажи :)

В двух словах там, действительно, всё просто. Есть байткод (типично Фортовский, кстати, стековый - DUP/SWAP/ADD и т.д.). Каждому методу при вызове формируется отдельный стек и область локальных переменных. И то и другое - заказанного размера. Аргументы метода - тоже локальные переменные. Соответственно, в байткоде есть операции чтения такой переменной. Или field'а какого-либо класса. Или вызова статического или виртуального метода. И т.п.

Проблемы в том, что нет общего стека на всю систему. JVM сама снимает для вызываемого метода со стека аргументы. Соответственно, и число аргументов всегда фиксированное. Возвращаться может только одно значение. Хотя прописаться может с любого места.

Сейчас вижу три (выше писал - два) выхода:

- Делать глобальный стек в виде отдельного класса, как сейчас в JBForth. Но тогда, во-первых, сильно снизится скорость (грубо говоря вместо байтоперации SWAP будем вызывать метод чужого класса, который будет работать с чужими данными). Во-вторых (впрочем, это тоже самое) пропадёт возможность использования массы байткода. Промежуточное решение - делать Форт не кодогенерирующий, а классический. А низкоуровневые слова определять через CODE, как в классическом Форт-ассемблере. Уже внутри этих слов использовать как глобальный, так и локальный стеки в зависимости от требуемой задачи.

- Делать 100% "Java-форт" со всеми ограничениями JVM. Т.е. для каждого слова будет определён фиксированный тип аргументов. Теряем капитально совместимость с классическим Фортом (скажем, слова, типа ?dup будут принципиально невозможны), но приобретаем скорость и "нативный" байткод.

- Делаем весь Форт со всеми словарями одним классом. Практически классическое решение, когда весь словарь лежит в одном кодофайле. Высокая скорость, совместимость с Фортом и... все ограничения одного класса. А их дофига. ЕМНИП, это только 256 локальных переменных, 65536 методов и ограничение на размер в байтах. Также теряется интересная фишка нынешнего JBForth, когда отдельное слово можно переопределять и удалять независимо от всей системы. Точные цифры следует, конечно ещё уточнить. Но ограничения мне не нравятся :)
 

Murkt

Pythoneer

ИМХО, лучше медленнее, но с полными возможностями.

Насчёт входящих-выходящих параметров (точно заданное количество, один на выходе) - может есть смысл их просто заворачивать во что-то, как это в Питоне делается? Если хочешь, расскажу как заворачивается.
[team Їжачки - сумні падлюки]  
+
-
edit
 

Balancer

администратор
★★★★★
Расскажи вкратце, но... Вариант с "внешним" стеком будет не сильно быстрее нынешнего, увы :-/ Разве что только бонус будет в написании именно полноценных .class и генерации .jar

...

В принципе, возможно, это будет самый компактный JDK :D Форт-система размером под несколько сот килобайт сможет генерировать полноценные .jar :)

...

А так - конечно, можно будет сделать дуальную систему. Когда можно будет определять два вида Форт-слов. С фиксированным числом аргументов в нативном коде и с внешним стеком.
 

Murkt

Pythoneer

Я имел в виду, что ты в метод передаёшь вроде как ограниченное и чёткое количество аргументов, но на самом деле столько, сколько тебе надо. То есть, положить на стек вызываемой функции массив (это ведь не полноценный объект, по идее должно быть быстро) со стопкой параметров, а на выходе отдавать тоже массив, и его ты тоже можешь варьировать так как тебе надо - хочешь, без элементов вообще, хочешь - десяток.

Я себе слегка так представил - в принципе, сделать можно, и работать должно быстрее, чем с действително внешним стеком. Хоть это и будет небольшой rocket science.

Я бы посоветовал сначала сделать с полноценным внешним стеком, а потом попробовать сделать с фейковым (как я вот сказал), так как преждевременная оптимизация :)

В Питоне все входящие параметры сворачиваются в кортеж и словарь. По мере надобности, я думаю - если я не передаю именованных параметров, то словарь по идее не должен создаваться (во внутренних механизмах не силён, не ковырялся - сужу только по внешним проявлениям), и с кортежом так же (он хендлит неименованные параметры). На выходе стопка параметров заворачивается в тот же кортеж.

code python
  1. def myfunc():
  2.     return 1, 2, 'a'
  3.  
  4. first, second, third = myfunc()
[team Їжачки - сумні падлюки]  

Murkt

Pythoneer

Насчёт входных параметров:
code python
  1. def myfunc(a, b, c=5, *args, **kwargs):
  2.     print (a, b, c, args, kwargs)


*<название кортежа> - это неименованные параметры, **<название словаря> - именованные.

code python
  1. # с - значение по умолчанию, "лишних" нет
  2. >>> myfunc(1, 2)
  3. (1, 2, 5, (), {})
  4.  
  5. # с - значение по умолчанию, d - "лишнее"
  6. >>> myfunc(1, 2, d=3)
  7. (1, 2, 5, (), {'d': 3})
  8.  
  9. >>> myfunc(1, 2, d=3, *(2,4))
  10. (1, 2, 2, (4,), {'d': 3})
  11.  
  12. >>> myfunc(1, 2, 3, 4, 5, 6, d=7, e=8, f=9)
  13. (1, 2, 3, (4, 5, 6), {'e': 8, 'd': 7, 'f': 9})
  14.  
  15. # аналогично предыдущему
  16. >>> myfunc(*(1, 2, 3, 4, 5, 6), **{'d': 7, 'e': 8, 'f': 9})
  17. (1, 2, 3, (4, 5, 6), {'e': 8, 'd': 7, 'f': 9})
  18.  
  19. # можно комбинировать
  20. >>> myfunc(1, 2, 3, 4, x=10, y=11, *(5, 6), **{'d': 7, 'e': 8, 'f': 9})
  21. (1, 2, 3, (4, 5, 6), {'y': 11, 'x': 10, 'e': 8, 'd': 7, 'f': 9})


Использование в повседневной жизни на каждом шагу, особенно **kwargs. Вот пример из рабочего проекта, можно сказать функция-прокси:
code python
  1. @login_required
  2. @user_in_groups('Modellers')
  3. def modeller_bundles(request, **kwargs):
  4.     """ Show paginated list of bundles.
  5.    """
  6.     kwargs['template_name'] = 'modeller_bundles.html'
  7.     kwargs['queryset'] = sort_query(Bundle.objects.filter(modeller=request.user.username), request)
  8.     kwargs['extra_context'] = {'sorts': request.GET.getlist('sort')}
  9.     kwargs['paginate_by'] = settings.PAGINATE_BY
  10.     kwargs['template_object_name'] = 'bundle'
  11.     return object_list(request, **kwargs)


Но и *args не остаётся незамеченным :)
code python
  1. def sort_query(base_query, request):
  2.     """ Order base_query by parameters from request.GET['sort'].
  3.    """
  4.     if 'sort' in request.GET and request.GET['sort']:
  5.         return base_query.order_by(*tuple(request.GET.getlist('sort')))
  6.     return base_query
[team Їжачки - сумні падлюки]  
Это сообщение редактировалось 15.06.2007 в 19:49

Murkt

Pythoneer

статус
[team Їжачки - сумні падлюки]  
+
-
edit
 
DE Кирилл #17.08.2007 09:37
+
-
edit
 

Кирилл

втянувшийся

- Делать 100% "Java-форт" со всеми ограничениями JVM. Т.е. для каждого слова будет определён фиксированный тип аргументов. Теряем капитально совместимость с классическим Фортом (скажем, слова, типа ?dup будут принципиально невозможны), но приобретаем скорость и "нативный" байткод.
 

ИМХО самый интересный вариант.
Ибо не противоречит Форт-идеологии с одной стороны (меньше "умных" слов) и позволяет контроль стека при компиляции ("стековые комментарии" в середине слова помогут отловить ошибку ДО выполнения). И лаконичности не мешает - типы и количество аргументов высокоуровневого слова однозначно вычисляются по его определению.
Кстати, с точки зрения дисциплинирующих ограничений такой Форт будет ближе к массам, чем классический.
- Сами понимаете, вселенная-то на моей стороне.
- Вот это мне таким вульгарным и кажется.
 
RU Balancer #17.08.2007 10:21  @Кирилл#17.08.2007 09:37
+
-
edit
 

Balancer

администратор
★★★★★
Кирилл> Кстати, с точки зрения дисциплинирующих ограничений такой Форт будет ближе к массам, чем классический.

Да, массам нужна жёсткость :)

...

Кстати, ещё мысль. Нормальную работу со стеком внутри определений можно реализовать в CODE-словах, которые будут просто инлайниться в компилируемое слово. Вернее, CODE-слова надо оставить как есть, а реализовать, скажем, INLINE.

code forth
  1. : word1 ( arg1:type1 arg2:type -- result:type3 )
  2. \ код высокоуровневого слова
  3. ;
  4.  
  5. CODE word2 ( arg:type -- result:type )
  6.    \ низкоуровневый код JVM
  7.    NEXT
  8. END-CODE
  9.  
  10. INLINE word3
  11.    \ низкоуровневый код JVM
  12. END-INLINE
  13.  
  14. : word4 ( -- )
  15. \ ...
  16.     word1 \ тут вызывается внешний метод со всей бодягой в виде передачи аргументов и возврата значения
  17.  
  18.     word2 \ тут - тоже самое, с точки зрения Форт-системы разницы в вызове word1 и word2 нет.
  19.  
  20.     word3 \ а тут - будет заинлайнен код, работающий внутри текущего слова. Соответственно, использует текущее состояние стека.
  21. ;


Правда, надо придумать ещё механизмы обращения к переменным метода из INLINE-слов. Обращаться по их номерам - это как-то старО :)
 
DE Кирилл #26.08.2007 17:05
+
-
edit
 

Кирилл

втянувшийся

А как насчет решения проблемы дороговизны вызовов через макрооптимизацию, как в SPF?
Заодно и специальных INLINE-слов не понадобится...

Еще в Ява-форте можно ввести модули, эквивалентные Ява-классам. Тогда вызовы внутри модуля будут быстрыми, а "наружу" - гибкими.
- Сами понимаете, вселенная-то на моей стороне.
- Вот это мне таким вульгарным и кажется.
 
RU Balancer #27.08.2007 10:25  @Кирилл#26.08.2007 17:05
+
-
edit
 

Balancer

администратор
★★★★★
Кирилл> А как насчет решения проблемы дороговизны вызовов через макрооптимизацию, как в SPF?

Это уже на практике можно будет подумать. Ибо там это не так гладко будет, как в SPF. У JVM свои ограничения.

Кирилл> Еще в Ява-форте можно ввести модули, эквивалентные Ява-классам. Тогда вызовы внутри модуля будут быстрыми, а "наружу" - гибкими.

Да, где-то так и задумывается.
 
DE Кирилл #04.09.2007 07:57
+
-
edit
 

Кирилл

втянувшийся

Еще один довод в пользу Форта со статической типизацией: большинство слов с переменным числом аргументов на стеке (тот же ?DUP) делают двойную работу по принятию решения и ухудшают читабельность текстов программ.
Слова же, возвращающие флаг - бледное подобие исключений... костыль неполной реализации конструкций структурного программирования.
А если замечтаться, в воображении появляется Форт с системой типов Хиндли-Милнера ;)
- Сами понимаете, вселенная-то на моей стороне.
- Вот это мне таким вульгарным и кажется.
 
RU Balancer #04.09.2007 11:01  @Кирилл#04.09.2007 07:57
+
-
edit
 

Balancer

администратор
★★★★★
Кирилл> с системой типов Хиндли-Милнера ;)

Вкратце распиши, а то гуглить некогда :)

...

А на счёт исключений - их реализовывать придётся, полагаю, в любом случае.

И надо думать над красивым синтаксисом аргументов слов. Первое, что в голову приходит - это использовать комментарий с параметрам, заданный де факто, но теперь сделать его обязательным по стандарту:
code forth
  1. public static : str_repeat ( String:arg1 Integer:arg2 -- String )
  2. \ ...
  3. ;


Нужен набор модификаторов - public, private, static, final. По умолчанию, полагаю, нужно делать просто private.

Непонятно, что делать с режимом исполнения. Ибо делать два набора слов, для режима компиляции и для режима исполнения, ИМХО, бред. Как вариант - комиплировать введёную строку в анонимное слово и исполнять потом. Какие могут быть подводные камни?

Кстати, от Форта не так уж много остаётся... Например, мы не можем оперировать стеком вызывающего слова. Что, с одной стороны, нам больше не нужно, так как число аргументов фиксированное и в слово передаётся всё, что ему надо, с другой - это уже не совсем Форт :)

Даже синтаксис. В приведёном примере двоеточие выглядит уже не в тему... Так и напрашивается "static function str_repeat ..." :)
 
DE Кирилл #04.09.2007 11:58
+
-
edit
 

Кирилл

втянувшийся

Вкратце распиши, а то гуглить некогда
 

Вкратце - типы переменных выводятся из выражения, а значит "стековая нотация" в большинстве случаев необязательна! В ОСАML, Haskell и т.д. именно так ;)
Например : AVERAGE + 2 / ; автоматически протипируется как ( int int — int)
просто исходя из типов + и /
Если не баловаться с полиморфизмом на нижнем уровне (а Форт-идеология как раз такая!) - то все просто.
Потом можно и побаловаться - будет куда сложнее (или эквивалент шаблонов или передача неявного аргумента с указателем таблицы операций), зато получится выразительность типизированных функциональных языков реализованная в компактном императивном.
"Стековая нотация" однако полезна - для самодокументирования, усиления контроля компиляции, а также определения локальных переменных.
А ведь мы так даже Хаскель кое в чем уделаем - необязательным окажется указание не только типа, но и имен и даже количества аргументов: все выводится при компиляции.
А на счёт исключений - их реализовывать придётся, полагаю, в любом случае.
 

При наличии в языке исключений стеко-статичность слов сама по себе не является недостатком, а значит с ней можно спокойно смириться.
Нужен набор модификаторов - public, private, static, final. По умолчанию, полагаю, нужно делать просто private.
 

С точки зрения отделения интерфейса от реализации а также Форт-идеологии лучше будут словари public, static, final.
Кстати, static можно выкинуть - в Форте между явным и неявным self особой разницы нет.
Как вариант - комиплировать введёную строку в анонимное слово и исполнять потом. Какие могут быть подводные камни?
 

Куски между определениями компилируются в безымянные слова, которые потом выбрасываются. JIT однако... ;) На SPF кто-то так получил возможность использовать IF, THEN и т.п. в режиме исполнения.
Даже синтаксис. В приведёном примере двоеточие выглядит уже не в тему... Так и напрашивается "static function str_repeat ..."
 

А не надо из Форта Яву делать ;)
- Сами понимаете, вселенная-то на моей стороне.
- Вот это мне таким вульгарным и кажется.
 
RU Balancer #04.09.2007 12:31  @Кирилл#04.09.2007 11:58
+
-
edit
 

Balancer

администратор
★★★★★
Кирилл> С точки зрения отделения интерфейса от реализации а также Форт-идеологии лучше будут словари public, static, final.

Не покатит. Это модификаторы Java-методов :)

Кирилл> Кстати, static можно выкинуть - в Форте между явным и неявным self особой разницы нет.

Опять же, это принципиальный для Java вопрос.

Мы же собираемся генерировать нативные Java-классы.

Кирилл> А не надо из Форта Яву делать ;)

А тогда у нас уже есть JBForth-1 :) Он форт как форт, совершенно типичный, хотя и не очень стандартный.
 
DE Кирилл #04.09.2007 13:34
+
-
edit
 

Кирилл

втянувшийся

Не покатит. Это модификаторы Java-методов
 

Почему же? Если главное, чтобы для JVM генерились корректные методы и классы, то это возможно при любом синтаксисе, необязательно Явовском. Т.е. при помещении слова в словарь final - оно может быть точно так же скомпилировано в байт-код как final-метод, как и при указании java-модификатора.
Опять же, это принципиальный для Java вопрос.
Мы же собираемся генерировать нативные Java-классы.
 

Собственно генерировать ничто не мешает :) А static или нет - видно по первому же параметру слова.
Он форт как форт, совершенно типичный, хотя и не очень стандартный.
 

А хочется Форт быстрый и на JVM ;)
- Сами понимаете, вселенная-то на моей стороне.
- Вот это мне таким вульгарным и кажется.
 

в начало страницы | новое
 
Поиск
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru