Реализация post / pre приращения / декремента при переводе на Lua - PullRequest
4 голосов
/ 03 февраля 2012

Я пишу переводчик LSL в Lua, и у меня возникают всевозможные проблемы с реализацией увеличивающихся и уменьшающихся операторов.В LSL есть такие вещи, в которых используется обычный синтаксис C (x ++, x--, ++ x, --x), а Lua - нет.Просто для того, чтобы избежать массового набора текста, я называю такие операторы «созданиями».В приведенном ниже коде я буду использовать «...» для представления других частей выражения.

... x += 1 ...

Не работает, потому что Lua имеет только простое назначение.

... x = x + 1 ...

Не сработает, потому что это утверждение, и Lua не может использовать выражения в выражениях.LSL может использовать выражения в выражениях.

function preIncrement(x)  x = x + 1;  return x;  end
... preIncrement(x) ...

Хотя он и обеспечивает правильное значение в выражении, Lua передается по значению для чисел, поэтому исходная переменная не изменяется.Если бы я мог заставить это действительно изменить переменную, тогда все хорошо.Взаимодействие с окружающей средой может быть не очень хорошей идеей, не знаю, что такое область действия x.Я думаю, что я исследую это дальше.Переводчик может выводить подробности области действия.

При условии, что вышеуказанная функция существует -

... x = preIncrement(x) ...

Не будет работать по причине "это утверждение".

Другие решения начинают получатьочень грязно.

x = preIncrement(x)
... x ...

Работает нормально, кроме случаев, когда оригинальный код LSL выглядит примерно так -

while (doOneThing(x++))
{
  doOtherThing(x);
}

, который становится целой банкой червей.Использование таблиц в функции -

function preIncrement(x)  x[1] = x[1] + 1;  return x[1];  end
temp = {x}
... preincrement(temp) ...
x = temp[1]

Еще более беспорядочно и имеет те же проблемы.

Начиная с того, что мне, возможно, придется фактически анализировать окружающий код, а не делать простые переводы.чтобы разобраться, каким будет правильный способ реализации любого данного творения.У кого-нибудь есть простые идеи?

Ответы [ 5 ]

1 голос
/ 03 февраля 2012

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

Примечаниечто, по крайней мере, в C вы можете отложить постинкремент / декремент до следующей «точки последовательности» и поместить преинкременты / декременты перед предыдущей точкой последовательности;Точки последовательности расположены только в нескольких местах: между операторами, у «операторов короткого замыкания» (&& и ||) и т. д. (подробнее здесь)

Итакможно заменить x = *y++ + z * f (); на { x = *y + z * f(); y = y + 1; } - пользователь не может предполагать, что y будет увеличиваться до чего-либо еще в выражении, только то, что значение, используемое в *y, будет y до того, какувеличивается.Аналогично, x = *--y + z * f(); можно заменить на { y = y - 1; x = *y + z * f (); }

0 голосов
/ 11 августа 2013

В большинстве ваших оценок настраиваемость к коду. Вы пытаетесь жестко передать типы данных из одного в другой. И назовите это «переводчиком». И во всем этом вы упускаете регулярные выражения и другие возможности сопоставления с образцом. Которые гораздо больше присутствуют в LUA, чем в LSL. И так как код LSL передается в LUA. Попробуйте использовать их вместе с другими функциями. Который определил бы работу больше как переводчик, чем как жесткий пас.

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

0 голосов
/ 04 февраля 2012

После некоторых исследований и размышлений у меня появилась идея, которая может сработать.

Для глобальных переменных -

function preIncrement(x)
  _G[x] = _G[x] + 1
  return _G[x]
end
... preIncrement("x") ...

Для локальных и функциональных параметров (которые являются локальными) IВ то время как я знаю, что при синтаксическом анализе инструмента он является локальным, я могу сохранить четыре флага, чтобы сообщить мне, какой из четырех инструментов используется в структуре переменных AST.Затем, когда придет время вывести определение переменных, я могу вывести что-то вроде этого -

local x;
function preIncrement_x() x = x + 1;  return x;  end
function postDecrement_x() local y = x;  x = x - 1;  return y;  end
... preIncrement_x() ...
0 голосов
/ 03 февраля 2012

Предлагаемое решение будет работать только тогда, когда все переменные Lua являются глобальными. Если это не то, что делает LSL, у вас возникнут проблемы с переводом программ LSL, которые используют переменные, называемые одинаково в разных местах.

Lua может изменять только одно lvalue на оператор - таблицы, передаваемые в функции, являются единственным исключением из этого правила. Вы могли бы использовать локальную таблицу для хранения всех местных жителей, и это помогло бы вам с предварительными ... ;-; они могут быть оценены до выражения, в котором они содержатся. Но пост -...- инструменты должны быть оценены позже, что просто невозможно в lua - по крайней мере, без какого-то уродливого кода с анонимными функциями.

Итак, у вас есть один вариант: вы должны принять, что некоторые операторы LSL будут переведены в несколько операторов Lua.

Скажем, у вас есть оператор LSL с такими приращениями:

f(integer x) {
  integer y = x + x++;
  return (y + ++y)
}

Вы можете перевести это в утверждение Lua, например:

function f(x) {
  local post_incremented_x = x + 1 -- extra statement 1 for post increment
  local y = x + post_incremented_x
  x = post_incremented_x -- extra statement 2 for post increment

  local pre_incremented_y = y + 1
  return y + pre_incremented_y
  y = pre_incremented_y -- this line will never be executed
}

Таким образом, вам, по сути, нужно будет добавить два оператора в .., которые используются в ваших утверждениях. Для сложных структур это будет означать вычисление порядка, в котором вычисляются выражения.

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

0 голосов
/ 03 февраля 2012

Lua спроектирован так, чтобы быть практически невосприимчивым к реализациям такого рода вещей.Это может быть сделано как проблема компилятора / интерпретатора, поскольку интерпретатор может знать, что переменные изменяются только при выполнении оператора.

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

Луа не хочет, чтобы вы это делали;Лучше всего найти способ работать в рамках ограничения.А это означает анализ кода.

...