Существует ли C-подобный мини-синтаксис / язык, который может быть переведен как на родной C / C ++, так и на Java? - PullRequest
3 голосов
/ 07 июля 2011

Я бы хотел, чтобы мое приложение было "скриптовым". Язык сценария должен быть набран и подобен Си. Он должен иметь обычные операторы управления, примитивные типы, массивы и операторы, которые можно найти как в C, так и в Java. Сценарии должны иметь возможность определять функции и вызывать предварительно определенные функции API, такие как sin () ..., которые я предпочитаю предлагать. Если сценарий пройдет проверку синтаксиса, он будет затем переведен приложением в Java, а затем скомпилирован на лету, но также должна быть возможность перевести его на C / C ++ и получить его встроенную компиляцию. Проверка синтаксиса и перевод на Java / C должны выполняться в JVM. Мне не нужен переводчик для него, так как он всегда будет переведен на Java / C. Только проверка синтаксиса и переводчик.

Есть ли такой язык там? Если нет, то какой самый простой способ сделать это в JVM, учитывая, что я не разбираюсь в программировании компилятора / интерпретатора? (Если бы я был, мне не нужно было бы задавать этот вопрос ...)

Если есть решение "Scala", это также будет хорошо, так как я на самом деле перевожу свой Java-код в Scala.

[EDIT] Единственная причина, по которой я хочу перевод на C / C ++ - это производительность. Я ожидаю много «битовых манипуляций» над массивами, для которых Java не очень подходит, в частности из-за проверки диапазона при каждой операции индекса массива. Я также ожидаю много объектов, которые косвенно стоят в циклах GC.

[РЕДАКТИРОВАТЬ # 2] Хорошо, я вижу, я должен получить бетон. Я рассматриваю программирование клона Minecraft в качестве упражнения, чтобы отвлечься от "Business Computing". Я говорю о движке, а не об игровом процессе. И меня больше интересует серверная часть, чем 3D, потому что я «серверный парень». Мы говорим о том, чтобы использовать шаблон веса полета для представления миллионов объектов (блоков / вокселей) и получать к ним доступ много раз в секунду. Это не то, для чего была создана JVM. Посмотрите в этой статье пример того, что я имею в виду: Почему мы выбрали CPP вместо Java

Я не хочу программировать все на C / C ++, но подозреваю, что это единственный способ добиться хорошей производительности. Другой пример того, что я имею в виду, это VoltDB , который, возможно, является самой быстрой базой данных SQL. Они написали это на Java и C / C ++, используя Java для ввода-вывода и сети, а C - для тяжелых манипуляций с памятью и суеты. Пользовательские хранимые процедуры написаны на Java, но я не думаю, что так должно быть. Я думаю, что должна быть возможность компилировать в Java на клиенте и в тестовых сборках, а также компилировать в C на сервере, где можно настроить полную среду разработки.

Ответы [ 9 ]

4 голосов
/ 07 июля 2011

Может быть Haxe подойдет вашим потребностям. Это промежуточный язык высокого уровня, который может быть скомпилирован в исходный код C ++. Цели Java находятся в разработке .

3 голосов
/ 08 июля 2011

Два слова: преждевременная оптимизация.

Вы беспокоитесь о производительности. Но, учитывая, что вы хотите сделать клон Майнкрафта, это означает, что игровой мир очень хорошо может быть представлен трехмерным массивом. Доступ к ним достаточно быстрый на всех упомянутых языках программирования; игровая логика должна занять гораздо больше времени, чем доступ к миллионам записей массива. Так зачем оптимизировать часть, которая в любом случае не займет большую часть вычислительного времени - даже до того, как вы написали минимально работающую версию?

Возможно, вы захотите создать интерфейс Java или черту Scala, представляющую игровой мир. Он предлагает методы для получения и хранения содержимого блоков игрового мира. Позже вы также можете добавить массовые методы для дальнейшей оптимизации производительности; например тот, который проверит, все ли блоки в данном кубе пусты, или посчитает количество деревянных блоков, что-то в этом направлении. Но в начале лучше не использовать эти методы или создавать тривиальные реализации, которые основаны на повторном вызове абстрактных методов. Вы можете оптимизировать их позже.

Затем вы можете предоставить очень простую реализацию этого интерфейса на Java / Scala, которая на самом деле использует трехмерный массив. Альтернативой может быть карта, ключи которой являются координатами, а значения - состояниями блоков. Преимущество состоит в том, что не будет никакого реального ограничения на размер игрового мира, и пустые блоки не будут занимать какую-либо память (для координат с пустыми блоками на карте нет записи). Недостатком, очевидно, может быть производительность.

В этот момент вы можете рассмотреть возможность более плотной упаковки данных, если они занимают слишком много памяти. Вы можете использовать наборы битов. Когда вы достигаете этой стадии, на самом деле имеет смысл использовать JNI для внедрения некоторого кода, написанного на C или C ++, в JVM. Таким образом, вы сохраняете игровую логику в Java / Scala и выполняете упаковку и поиск памяти в C.

Нет никакого реального смысла в создании общего «скриптового» источника, который может создавать Java / Scala и C / C ++ версию нативной части кода; нативные функции C / C ++ сильно зависят от оптимизаций, которые нельзя напрямую перевести на Java. Если вы хотите запустить сервер в «чистом режиме Java / Scala», то есть без функций JNI, просто используйте другие классы, которые вы создали в предыдущем шаге. Они могут быть немного медленнее, но они являются чистым байтовым кодом JVM. И поскольку вы сохранили их простыми, нет никакой опасности, что вам придется расширять их или вносить в них новые ошибки. По крайней мере, накладные расходы на создание или адаптацию генератора кода на разных языках программирования намного, намного больше, чем поддержание двух отдельных баз кода, особенно когда реализация Java / Scala действительно проста.

Конечно, битовая упаковка только уводит вас.Возможно, вы захотите заметить, что некоторые части игрового мира почти полностью пусты (особенно над поверхностью), а другие содержат огромные области, заполненные блоками одного типа (например, подземные области, состоящие почти исключительно из камня).Поддержание огромной структуры памяти с такой избыточностью на самом деле является пустой тратой памяти.Таким образом, вы, вероятно, рассмотрите возможность упаковки игрового мира в дерево, где каждый узел обозначает большую кубическую область игрового мира, и дети делят его дальше, вплоть до листьев, которые описывают содержимое только одной конкретной координаты игрового мира.Когда у одного узла есть только дочерние элементы одного и того же типа контента, вам не нужно хранить дочерние элементы.Просто срежьте дерево в этой точке и попросите узел сказать: «Вам не нужно смотреть дальше. Я полон воды, поэтому каждая координата, которая находится внутри меня, указывает на водную плитку».- Это значительно уменьшит использование памяти.Только части игрового мира, которые на самом деле являются сложными, будут занимать много памяти, и это правильно.Более скучные части мира занимают лишь несколько узлов в дереве.Это хорошо.А поскольку это дерево, то прохождение его от вершины к листу занимает в среднем логарифмическое время.Это очень хорошо!- Конечно, вы должны сохранить дерево изменчивым.Если скучная часть мира, представленная только одним узлом, изменится, вам нужно взломать этот узел и разделить его на двух или более дочерних узлов.Если после этого все снова станет простым, вы можете снова присоединиться к дочерним элементам и вырезать дерево.

Одна вещь, которую вы можете заметить на этом этапе: упаковка памяти и оптимизация доступа больше не являются проблемой.Такое дерево не может быть разумно оптимизировано с помощью встроенных функций для методов хранения и поиска.Если вы сможете получить больше, чем, скажем, 10% от такой оптимизации, это было бы невероятно и невероятно впечатляюще.(Скорее всего, это может означать, что аналоги Java / Scala были плохо оптимизированы.) Такое минимальное увеличение скорости не оправдывает огромных дополнительных усилий, которые необходимо вложить в него.Скорее вставьте лучший процессор в машину и наслаждайтесь временем, которое вы сэкономили, поедая мороженое, наблюдая за доктором Хаусом или продолжая улучшать игру и делать ее более интересной и привлекательной для игроков.Создавая что-то ценное, что действительно улучшит продукт.

Но это все-таки не так.Если я правильно помню, начальное состояние мира Minecraft генерируется процедурно.Используя фрактальные алгоритмы, вы действительно можете создавать бесконечные территории, которые в мгновение ока кажутся сложными и естественными.Поэтому вместо того, чтобы предварительно вычислять содержимое игрового мира и сохранять его в огромной структуре данных, вы можете использовать процедуру генерации мира в качестве метода поиска: вместо поиска содержимого координаты из памяти, просто рассчитайте его, используяалгоритм.Таким образом, начальное состояние мира может быть полностью сохранено в четырех байтах: начальное значение алгоритма.

Конечно, мир не всегда будет оставаться в этом состоянии.Когда игрок (или что-то еще) меняет мир, тогда это то, что вам нужно хранить.Таким образом, вы храните только мировое начальное значение и внесенные в него изменения.Всякий раз, когда вы просматриваете содержимое координаты, попробуйте найти его в хранилище измененных плиток.Когда это там, используйте эту информацию.Когда его нет, по умолчанию используется алгоритм генерации процедурного мира.Это значительно сократит потребление памяти.А поскольку изменения в мире относительно невелики и содержат огромные пустые области, вам будет относительно легко написать структуру данных, которая будет хранить эти изменения быстро и эффективно.Опять же, написание собственного кода для этого не приведет к значительному увеличению производительности и не стоит усилий.

Можно оптимизировать еще кое-что: алгоритм генерации процедурного мира.Это один из ключевых компонентов, который вы можете написать на C или C ++.Это должен быть относительно небольшой и не слишком большой код, но он требует много математики и будет вызываться очень часто.Так что оптимизируйте его хорошо и сделайте из него небольшую библиотеку JNI.Это даст вам огромный прирост производительности, который стоит усилий.(Конечно, вы, возможно, захотите сначала выполнить реализацию Java / Scala. Если это уже достаточно быстро, тогда нет необходимости попадать в проблему JNI.)

Если процедура генерации мира все еще должна быть слишкоммедленно, тогда вы можете реализовать кеш для него.Кэш может даже превентивно генерировать некоторые из окружений игрока, когда у JVM есть немного ленивое время.

Я изложил этот процесс разработки для вас как итерацию нескольких идей, одна лучше, чем предыдущая.Изображение, которое вы бы начали писать библиотеки оптимизированного кода C / C ++ уже на первом этапе.Это было бы пустой тратой времени;Вы могли бы выбросить все это на более поздних этапах.Эффективное хранилище массивов, использующее упаковку битов, написанное на C, - это хорошо, но оно абсолютно бесполезно, когда вы реорганизуете свой мир в дерево с разделенными двоичными пространствами.

Так что не переусердствуйте,Если вы не можете создать минимально работающую (но медленную и неоптимизированную) версию только в Java / Scala, то вы не можете создать оптимизированную версию в C / C ++ или в каком-либо кросс-компилируемом языке сценариев.Сначала делайте простые версии, затем тестируйте производительность и оптимизируйте только тогда, когда это действительно необходимо.Не начинайте свой проект, сначала создавая концепции для оптимизации.Подобные оптимизации должны быть последними вещами, над которыми вы будете работать.

2 голосов
/ 07 июля 2011

Синтаксис JavaScript похож на C / C ++ и Java.Существуют различные механизмы JavaScript, один из которых закодирован в Java: Rhino .

. Также существует LLVM , который представляет собой механизм компиляции, который компилирует код в свой собственный байт-код иоттуда к машинному коду.Он также имеет интегрированный JIT и существует несколько языковых интерфейсов.Я не слишком много знаю об этом проекте, но он выглядит интересно.

2 голосов
/ 07 июля 2011

Есть ли такой язык там?... Какой самый простой способ сделать это в JVM,

Я бы использовал простую Java и позволил бы JVM компилировать код в машинный код.Вы можете сделать этот сборник более агрессивным, если вам это нужно.

Возможно, вы могли бы уточнить, что вы надеетесь получить, чего JVM не дает вам уже.чтобы разработать свой собственный мини-язык, вы хотите иметь реалистичное представление о том, что потребуется.Если вы не возьмете на себя обязательство, вы, вероятно, придумаете что-то, что не так хорошо.

http://www.ohloh.net/p/openjdk/estimated_cost

OpenJDK: Project Cost Calculator

Include     
Codebase    4,782,885 lines
Effort (est.)   1451 person-years
Estimated Cost  $ 79,805,125
1 голос
/ 07 июля 2011

Так как Scala представляется опцией, просто придерживайтесь ее.

Вы можете вызывать интерпретатор (используемый REPL) непосредственно из вашего собственного кода, он скомпилирует скрипт в байт-код Javaкоторый тогда бежит.Вам будет очень трудно найти решение, которое соответствует этому с точки зрения мощности и гибкости - особенно с учетом требования статической типизации.

Что касается производительности, JVM отвечает за дальнейшую компиляцию байт-кода внизк нативному коду, это тоже неплохо на этой работе.Я сомневаюсь, что вы заметите какое-либо значительное повышение производительности с C / C ++ (время компиляции, в частности, будет намного хуже).

0 голосов
/ 09 июля 2011

Прочитав все ответы, я решил это сделать.Чтобы начать работу над моим проектом, я не буду использовать сценарии в начале.Вместо этого я буду программировать на Java, но без использования каких-либо проблемных конструкций .

Сначала я создам базовый класс API , полный любых служебных методов.может понадобиться.95% этого кода просто делегируют какой-то библиотеке, которая выполняет эту работу за меня.Этот класс API будет иметь фабричные методы для классов примитивных коллекций.Также будет несколько служебных классов, таких как Point, Event, ...

Затем я создам свой игровой код, расширив объект API.Я не буду использовать модификаторы доступа, поэтому все общедоступно.Я не буду использовать «final», «static», «this», «super», «abstract», «interface», массивы, универсальные шаблоны, приведение классов, «instanceof», «new» или обработку исключений.Я не буду ничего импортировать или получать доступ к этому стандартному Java API, кроме класса String.Все, что мне нужно от стандартного Java API, должно быть включено в мой базовый класс API.Есть также некоторые ограничения операторов, в частности побитовые.

Чтобы преодолеть ограничение, вызванное не использованием обобщений, не приведением классов или «instanceof», я буду использовать инверсию управления, внедрение зависимостии немного размышлений для решения проблемы.

Это должно быть относительно легко и быстро для программирования, но не будет работать.Позже, когда мой движок стабилизировался и был отлажен, я могу вернуться к своей первоначальной идее и создать парсер, который будет либо переводиться в оптимизированную Java, либо в C ++.Удаление всех этих специальных конструкций Java значительно упростит создание синтаксического анализатора, и, поскольку я буду использовать стандартный синтаксис Java, я могу просто использовать предопределенный синтаксический анализатор и настроить его в соответствии со своими потребностями.

0 голосов
/ 07 июля 2011

А как насчет JavaScript?Я не отвечаю всем вашим требованиям (они только слабо типизированы), но кажется, что удовлетворяет довольно многим из них: C-подобные, обычные операторы управления и операторы, массивы, функции, вы можете предложить свой собственный API ...Его даже можно скомпилировать в Java, но современные интерпретаторы в любом случае неплохо справляются с его компиляцией.Если вы пишете на Java, я настоятельно рекомендую вам взглянуть на Rhino .

0 голосов
/ 07 июля 2011

Я обнаружил, что Groovy довольно хорошо работает как язык сценариев, подобный C, на JVM.

Не уверен, насколько хорошо вы могли бы перевести его на C / C ++, но если у вас есть код C / C ++вам нужно позвонить, тогда вы можете легко ссылаться на него с помощью JNI.

Я не думаю, что в переводе кода на основе JVM в C / C ++ есть смысл.JVM JIT является действительно хорошим компилятором уже для очевидного пути компиляции (язык JVM -> байт-код JVM -> нативный) и почти наверняка побьет производительность всего, что пытается сделать намного более сложный (язык JVM -> C / C ++-> родной).

0 голосов
/ 07 июля 2011

Это полный C, но, возможно, полезный для вашей цели. Cibyl .

...