Как стать автором
Обновить

Комментарии 36

Зачем нужен отдельный клас LocalByRef[type] со всякми геттерами-сеттерами, почему бы не использовать вместо него массив из одного элемента?

Для чего в примерах нужен main(String[]) в дополнение к Main(string[]), что мешает генерировать его автоматически при трансляции?
Зачем нужен отдельный клас LocalByRef[type] со всякми геттерами-сеттерами, почему бы не использовать вместо него массив из одного элемента?

Класс LocalByRef[type] является наследником абстрактного класс ByRef[type] который в свою очередь представляет единый интерфейс для всех типов ссылок (на локальную переменную, на поле объекта или элемент массива). А массив из одного элемента подходит только для передачи по ссылке локальных переменных.

Для чего в примерах нужен main(String[]) в дополнение к Main(string[]), что мешает генерировать его автоматически при трансляции?

Ничего не мешает. В будущем будет реализовано.
Класс LocalByRef[type] является наследником абстрактного класс ByRef[type] который в свою очередь представляет единый интерфейс для всех типов ссылок (на локальную переменную, на поле объекта или элемент массива).
А что нам даст единый интерфейс для случая ref-параметра метода, чего не может дать массив? Из приведённого примера кода это не ясно.
Попробую объяснить примером:
Исходный код на C#
public class Program
{
	public int field;

	public void Foo(ref int value)
	{
		value = 10;
	}

	public void Main(string[] args)
	{
		int localVar = 10;
		Program p = new Program();

		Foo(ref localVar);
		Foo(ref p.field);
	}
}


Превратится в:
Результат
public abstract class ByRefInt
{
	public abstract int get_Value();
	public abstract void set_Value(int newValue);
}

public sealed class LocalByRefInt
{
	private int value;

	public LocalByRefInt(int value) { this.value = value; }

	public int get_Value() { return this.value; }
	public void set_Value(int newValue) { this.value = newValue; }
}

public sealed class FieldByRefInt
{
	private object target;
    private java.lang.reflect.Field field;
    private int value;
 
    public FieldByRefInt(object target, Field targetField)
    {
        this.target = target;
        this.field = targetField;
        paramField.setAccessible(true);
        this.value = targetField.getInt(target);
    }
 
    public int get_Value()
    {
        return this.value;
    }
 
    public void set_Value(int newValue)
    {
        this.field.set[type](this.target, newValue);
        this.value = newValue;
    }
}

public class Program
{
	public int field;

	public void Foo(ByRefInt value)
	{
		value.set_Value(value);
	}

	public static void Main(string[] args)
	{
		int localVar = 10;
		Program p = new Program();

		LocalByRefInt tempLocal = new LocalByRefInt(localVar);
		Foo(tempLocal);
		localVar = tempLocal.get_Value();

		Foo(new FieldByRefInt(p, Program.class.getDeclaredField("field")));
	}
}
на платформу Java, версии не выше 1.6


Два вопроса:
1. Как вам удалось сломать совместимость с более свежими JVM?
2. Почему не Java 8? В ней есть указатели на методы и лямбды, на которые хорошо ложатся делегаты из C#.

Но в целом, конечно, круто.
Видимо не правильно сформулировал с топике. Имелось в виду что результирующий код должен запускаться на Java версии не ниже 1.6. Поэтому 1.7 и 1.8 соответственно отпадают. Почему 1.6? Что бы охватить большее количество платформ.
тогда поправьте на «версии 1.6 и выше»
Поправил. Спасибо.
Для чего используете или будете использовать ваш проект?
Пока ни для чего не используется. Изначально задумывался как аналог dot42 — для написания приложений под Android на C#.
Проект хорош. А какой overhead всего этого генерируемого кода?
Всё зависит от конкретных ситуаций и кода. Если в коде не используется вещей которых нет в Java (делегаты, значения по ссылке, значимые типы и т.д.) то оверхед минимальный, а то и вообще не будет, код получается идентичный если писать его сразу на Java. Конкретных цифр к сожалению назвать не могу — тесты пока не проводил.
Было бы отлично увидеть бенчмарки простых кусков кода.
Ваш компилятор написан на C#. Можно ли его скомпилировать вашим компилятором в Java? Какой будет провал в производительности?

Генерируете ли вы StackMapTable? Говорят, без неё на новых JVM никак. Или вы именно поэтому остановились на Java 1.6?

Вообще, конечно, невероятный пласт работы. Мне пока вряд ли это пригодится, но очень внушает. Поставил плюсики, где мог.
Ваш компилятор написан на C#. Можно ли его скомпилировать вашим компилятором в Java? Какой будет провал в производительности?

Пока нельзя. Нет реализации стандартных библиотек. Для mscorlib есть только заглушки (весь код усеян throw new NotImplementedException();), а остальных библиотек нет даже заглушек. И получается ситуация что компилятор подхватывает стандартные библиотеки от .NET, которые мало того, что не подходят, так ещё и собраны так, что mscorlib от .NET даёт им доступ к internal типам, которых нет в моей реализации mscorlib. Но на то это и альфа версия. План минимум — это что бы компилятор мог скомпилировать самого себя.

Генерируете ли вы StackMapTable? Говорят, без неё на новых JVM никак. Или вы именно поэтому остановились на Java 1.6?

Нет не генерирую. Если честно раньше думал что она не обязательна и не стал заморачиваться.

Вообще, конечно, невероятный пласт работы.

Впереди работы не меньше =)

Поставил плюсики, где мог.

Спасибо
Нет не генерирую. Если честно раньше думал что она не обязательна и не стал заморачиваться.

Ну если я правильно понимаю, пока вы используете версию .class-файлов 50, любая JVM простит вам отсутствие StackMapTable. Иначе сломается обратная совместимость. Вот если захотите перейти на более новую версию .class-файлов, придётся заморачиваться :-)
Версия class файлов — 49. Почему именно её — уже не помню. Код для работы с Java файлами писался довольно давно.
Глянул одним глазом в corlib. Как я понимаю, System.Array.Resize проще написать через
array = java.util.Arrays.copyOf(array, newSize);

Да, тут работы непаханый край. Вроде всё в одну строчку реализуется, но надо кидать именно C#-исключения, поэтому все границы диапазонов придётся проверять вручную… Ищите помощников, а то рутина заест :-)
К сожалению не получится. java.util.Arrays.copyOf(array, newSize); имеет перегруженные версии для примитивных типов, которые нельзя привести к Object[] что бы использовать единый T[] copyOf(T[] original, int newLength). Да и смысл если под капотом у них все тот же System.arraycopy.
Ваша правда.
Нет реализации стандартных библиотек.


А стандартные библиотеки планируется тоже перекомпилировать в код на java вашим компилятором или вы хотите сделать заглушки-аналоги стандартных библиотек в Net через стандартные библиотеки java? В смысле чтобы вместо метода X класса Y, вызывался некий java аналог?
По возможности будет напрямую вызываться java аналог. Но там где аналогов нет, либо он по какой то причине не подходит, будет своя реализация впоследствии компилируемая в java.
А с помощью какой библиотеки C# вы формируете байткод JVM?
Судя по сорцам, всё самописное.
Да, весь код по работе с байт кодом и class файлами писал сам по «Java Virtual Machine Specification». Вся работа с class файлами собрана в пространстве имён CIL2Java.Java, плюс есть класс CIL2Java.JavaBytecodeWriter для упрощения генерации байткода и класс CIL2Java.StackSimulator для трассировки получившегося кода и заполнения значений max_stack и max_locals в Code_attribute.
Если есть overload метода для типа int и enum-а (void Foo(int) и void Foo(MyEnum)), то код после трансляции перестанет работать.
Такая ситуация предусмотрена. После трансляции void Foo(MyEnum) превратится в void Foo__0MyEnum(int). То же самое касается и беззнаковых типов.
Забыл правда упомянуть что такое не работает с конструкторами (их переименовывать нельзя) и там действительно код перестанет работать (верификатор не пропустит).
Можно добавлять фиктивный параметр произвольного типа, который не конфликтует с имеющимися сигнатурами :-)
Вы прямо прочитали мои мысли =)
Респект за проделанную работу!
Вы пробовали портировать какое-либо приложение полностью?
Вряд ли автору это удалось, судя по практически полному отсутствию стандартной библиотеки.
Жаль. Например, для PHP5 есть quercus на jvm.
Quercus implements PHP 5 and a growing list of PHP extensions including APC, iconv, GD, gettext, JSON, MySQL, Oracle, PDF, and Postgres. Many popular PHP application will run as well as, if not better, than the standard PHP interpreter straight out of the box. The growing list of PHP software certified running on Quercus includes DokuWiki, Drupal, Gallery2, Joomla, Mambo, Mantis, MediaWiki, Phorum, phpBB, phpMyAdmin, PHP-Nuke, Wordpress and XOOPS.


В случае запуска .NET на jvm, интересно кто кого засудит за нарушение патентов Oracle Microsoft или Microsoft Oracle? Повторится ли давняя история!?)
Очень интересно!

В списке нереализованых фич у вас нет stackalloc/localloc — или это подпадает под раздел «указатели»?

В CLR намного более гибкая система с переопределением методов в классах-наследниках — newslot, явное указание переопределяемого метода etc — как именно вы это реализовываете? Генерацией имен при необходимости?

(кстати, вот на этом месте сразу возникает вопрос, как будет работать рефлекшн, если там много где нужно делать name mangling...)

Как вы обрабатываете (или планируете обрабатывать) виртуальные дженерик-методы?

Как насчет vararg-методов, ArgIterator и TypedReference?

При перегрузке методов, в сигнатуре помимо типов параметров учитываются также модификаторы modopt и modreq. Причем эти штуки могут быть еще и вложенными, что в принципе позволяет пихать в сигнатуры практически произвольную информацию. Вы это как-то транслируете, или код на C++/CLI, где, например, перегружен метод на int и long (они там различаются как раз через modopt), сломается?

Дотнет (в отличие от спеки CLI) позволяет в верифицируемом коде методам возвращать managed pointer. Правда, вернуть таким образом они могут только результат ld[s]flda — но это вам может потенциально усложнить жизнь…
В списке нереализованых фич у вас нет stackalloc/localloc — или это подпадает под раздел «указатели»?

В принципе да, пока нет полной поддержки указателей, эти вещи смотреть бесполезно. Для localloc есть заглушка, просто создающая массив байт указанного размера — просто на время сделал так.

В CLR намного более гибкая система с переопределением методов в классах-наследниках — newslot, явное указание переопределяемого метода etc — как именно вы это реализовываете? Генерацией имен при необходимости?

И тут вы правы — такие методы просто переименовываются что бы эмулировать поведение CLR.

(кстати, вот на этом месте сразу возникает вопрос, как будет работать рефлекшн, если там много где нужно делать name mangling...)

В будущем планирую просто добавлять к переименованным методам аннотацию с его настоящим именем. Да и вообще в аннотациях держать всю недостающую информацию для рефлексии (проперти, события и т.д.)

Как вы обрабатываете (или планируете обрабатывать) виртуальные дженерик-методы?

Пока никак =) Забыл про такую ситуацию. Так что спасибо что напомнили =)
Ну а обрабатывать их я вижу только одним способом — если метод был инстансирован, то и все его перегруженные варианты так же должны инстансироваться с тем же списком параметров.

Как насчет vararg-методов, ArgIterator и TypedReference?

Только что выкатил на github поддержку vararg, ArgIterator и частичную поддержку TypedReference

При перегрузке методов, в сигнатуре помимо типов параметров учитываются также модификаторы modopt и modreq. Причем эти штуки могут быть еще и вложенными, что в принципе позволяет пихать в сигнатуры практически произвольную информацию. Вы это как-то транслируете, или код на C++/CLI, где, например, перегружен метод на int и long (они там различаются как раз через modopt), сломается?

Вот за это спасибо. Не думал что modopt и modreq несут ещё и такую функцию. Пока они вообще никак не учитываются (не считая volatile у полей), но я обращу на них внимания.

Дотнет (в отличие от спеки CLI) позволяет в верифицируемом коде методам возвращать managed pointer. Правда, вернуть таким образом они могут только результат ld[s]flda — но это вам может потенциально усложнить жизнь…

Manged pointer у меня подменятся на ByRef[type]. Так что пускай возвращает =) По идее не должно ничего сломаться.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории