Обнаружение op_Addition ИЛИ реализующий метод для Expression.Add - PullRequest
2 голосов
/ 16 сентября 2010

Я пишу язык, используя деревья Antlr и Expression.

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

На данный момент это невероятно наивно, он просто делает это (незавершенный TDD-код часто выглядит наивным, верно!?):

protected Expression GenerateAdd(Expression left, Expression right)
{
  if (left.Type.Equals(right.Type))
    return Expression.Add(left, right);
  if (left.Type.IsValueType && right.Type.IsValueType)
    Promote7_2_6_2(ref left, ref right);
  return Expression.Add(left, right);
}

Где Promote7_2_6_2 генерирует выражения Convert, которые следуют правилам интегрального продвижения, изложенным в спецификации C # 7.2.6.2 (язык будет похож на C #, но будет пересекаться с JScript, а также с другими совершенно новыми ключевые слова).

Естественно, я перешел к тестированию добавления строк - т.е. "a" + "b";, и я получаю ошибку:

System.InvalidOperationException: The binary operator Add is not defined for the types 'System.String' and 'System.String'.

Достаточно справедливо - я отражаю System.String и уверен, что оператор действительно не определен. Генерация дерева выражений в тестовом методе, подобном следующему:

Expression<Func<string, string, string>> e = (s1, s2) => s1 + s2;

Показывает, что Add BinaryExpression действительно создано, но с методом реализации, установленным на один из string.Concat методов.

Я знал, что в некоторых случаях мне придется смотреть на что-то подобное, но сколько других типов определяют сложение таким образом? Это просто string?

Это правило, встроенное в компилятор C #, или есть какие-то обнаруживаемые метаданные, которые я могу использовать для автоматического обнаружения таких методов в других типах?

Заранее спасибо!

1 Ответ

1 голос
/ 18 сентября 2010

Кажется, я отлично справляюсь с ответами на свои вопросы!

Мои извинения, этот ответ может быть лучше отформатирован, но у меня желание HTC, и его клавиатура не поддерживает все символы!

Похоже, что нет способа «обнаружить» эти правила во время выполнения, именно язык хозяина должен решить, как реализовать такие вещи, как добавление строк.C # адаптируется к числу последовательных членов в добавлении, вызывая метод .Concat, который наиболее подходящим образом соответствует этому.

Итак, если я хочу, чтобы мой язык поддерживал добавление экземпляров классов, для которых, например, не определен оператор, я могу просто написать или найти статический метод для этого (с правильной сигнатурой, конечно!), а затем жестко связать язык, чтобы использовать его в этом случае.Классический пример здесь - поддерживать ли array1 + array2 с помощью статических методов Array.

Что касается обнаружения операторов, об этом заботится метод Expression.Add, но он автоматически не выполняет никаких преобразований, поэтомуКак и в случае с методом продвижения с целыми числами / с плавающей запятой, на который я ссылаюсь в этом вопросе, опять-таки это зависит от правил языка, чтобы определить, требуются ли другие преобразования, прежде чем пытаться построить выражение.Лучше всего сначала отразить оператор, чтобы увидеть, определен ли он для двух типов, а затем рассмотреть преобразование, если оно существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...