LINUX.ORG.RU

Eval Ruby и магия

 


0

2

Дано:

method = "i => Label1.text = i.ToString()"
var = method[/[^ ]*/]
new1 = eval("method.gsub!(/#{var}\\\./, 'auto_var.')")
Всё работает как и задумывалось и на выходе я получаю
i => Label1.text = auto_var.ToString()
Но стоит чуть-чуть изменить строку на входе на
i => Label1.text = i[0].ToString()
то в итоге на выходе переменная new1 становится равной nil. В чём проблема? Аналогичный код на js работает
let v = m.match(/[^ ]/)[0];
let r = eval(`m.replace(/${v}\\\./, 'auto_var.')`);
return eval(`r.replace(/${v}\\\[/, 'auto_var[')`);

он же ищет var + точка

TDrive ★★★★★
()
Ответ на: комментарий от theNamelessOne

Допустим что есть. В принципе регулярку можно и по другому собирать. Просто хочется понять принципы работы интерпретатора. просто с целью узнать что-то новое.

NextGenenration ★★
() автор топика
Ответ на: комментарий от NextGenenration

У тебя код на Ruby и на Javascript не эквивалентный. gsub! — деструктивный метод, который меняет оригинальную строку и возвращает nil, если замена не произведена, replace же (не деструктивный метод, т.к. возращает новую строку) в таком случае вернёт оригинальную строку; такого поведения в Ruby можно добиться с помощью метода gsub. Плюс у тебя в Javascript выполняется две замены в отличие от одной в Ruby.

def dummy_replace(code, replacement, continuations: ['.', '['])
  var = code[/^\s*([^ ]+) /, 1]
  pattern = /\b#{Regexp.escape(var)}(#{Regexp.union(continuations)})/
  code.gsub(pattern, "#{replacement}\\1")
end

puts
puts 'Works out of the box!'
puts dummy_replace('i => Label1.text = i.ToString()', 'auto_var')
puts dummy_replace('i => Label1.text = i[0].ToString()', 'auto_var')

puts
puts "Doesn't work :'("
puts dummy_replace('i => Label1.text = i(2, 3)', 'auto_var')

puts
puts 'But this one does!'
puts dummy_replace('i => Label1.text = i(2, 3)', 'auto_var', continuations: '(')

Результат:

Works out of the box!
i => Label1.text = auto_var.ToString()
i => Label1.text = auto_var[0].ToString()

Doesn't work :'(
i => Label1.text = i(2, 3)

But this one does!
i => Label1.text = auto_var(2, 3)
theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 1)
method = "i => Label1.text = i.ToString()"
var = method[/[^ ]*/]
new1 = eval("method.gsub!(/#{var}([\\[|\\.])+/, 'auto_var\\1')")

puts new1

Работает для

i => Label1.text = i.ToString()
и
i => Label1.text = i[0].ToString()

Sorcus
()
Ответ на: комментарий от Sorcus

Плюс лишний.

/#{var}([\\[|\\.])/
Вот так лучше.

P.S. Почему нельзя редактировать сообщения? Ппц как неудобно :-/ И инфы не нашел по редактированию...

Sorcus
()
Ответ на: комментарий от theNamelessOne

да тут сразу видно диагноз, чувакк «пруфы» сделал и топик создал, а сам в одной строчке кода запутался

anonymous
()

Сейчас бы код строками генерировать в 2017

loz ★★★★★
()
Ответ на: комментарий от theNamelessOne

Плюс у тебя в Javascript выполняется две замены в отличие от одной в Ruby.

На самом деле я привёл не весь код на руби. В данный момент код целиком имеет следующий вид

code = "if(Class.Method(arg).With(i => Label1.text = i[0].ToString()) == 0) {
	Stop();
}"

index = code.index("With")

b1 = 0 # []
b2 = 0 # {}
b3 = 0 # ()

start = index - 1

while b1 > -1 and b2 > -1 and b3 > -1
	start -= 1
	if code[start] == "("
		b3 -= 1
	elsif code[start] == ")"
		b3 += 1
	elsif code[start] == "["
		b1 -= 1
	elsif code[start] == "]"
		b1 += 1
	elsif code[start] == "{"
		b2 -= 1
	elsif code[start] == "}"
		b2 += 1
	end
end

start +=1

print(code[start..index - 2])

body_end = index
b3 = 0
load = true

while b3 != 0 or load
	body_end += 1
	if code[body_end] == "("
		b3 -= 1
		load = false
	elsif code[body_end] == ")"
		b3 += 1
	end
end
method = code[index + 5..body_end - 1]
var = method[/[^ ]*/]
new1 = eval("method.gsub(/#{var}\\\./, 'auto_var.')")
new2 = eval("new1.gsub(/#{var}\\\[/, 'auto_var[')")

print(new2)
Разрабатываю данный велосипед с целью проверить идею о том насколько можно автоматизировать изменение кода на c#. по началу думал создать плагин для студии, но пока смотрел на объём кода на c++ автоматически сгенерированного при создании проекта желание отпало.

NextGenenration ★★
() автор топика
Ответ на: комментарий от theNamelessOne

Тут парсер нужен.

может плохо искал, но привязок к ruby|js не нашёл. надо будет посмотреть как это дело выглядит на самом c#. Хотя это должно быть лишь полуавтоматическим процессом и я допускаю то что возможно в некоторых местах надо будет доредактировать руками. при текущих требованиях проще будет десяток костылей прикрутить чем реализовывать по стандартам. Возможно позже поделюсь наработками.

NextGenenration ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.