Подтвердить что ты не робот

Язык программирования для самоизменяющегося кода?

  • Недавно я думал о написании самоизменяющихся программ, я думаю, что это может быть мощно и весело. Поэтому в настоящее время я ищу язык, позволяющий легко изменять собственный код программы.
  • Я читал о С# (как обойти) и способности компилировать и выполнять код во время выполнения, но это слишком больно.
  • Я также думаю о сборке. Там легче изменить исполняемый код, но он не очень мощный (очень сырой).

Можете ли вы предложить мощный язык или функцию, которая поддерживает изменение кода во время выполнения?

Пример

Вот что я имею в виду, изменяя код во время выполнения:

  Start:
  a=10,b=20,c=0;
  label1: c=a+b;
  ....
  label1= c=a*b;
  goto label1;

и может создавать список инструкций:

  code1.add(c=a+b);
  code1.add(c=c*(c-1));
  code1. execute();
4b9b3361

Ответ 1

Malbolge было бы хорошим местом для начала. Каждая инструкция самомодифицируется, и с ней очень весело (*).

(*) Отказ от ответственности: на самом деле это не весело.

Ответ 2

Я очень рекомендую Lisp. Lisp данные могут быть прочитаны и exec'd как код. Lisp код может быть выписан как данные.

Он считается одним из канонических самомодифицируемых языков.

Пример списка (данные):

'(+ 1 2 3) 

или, вызывая данные как код

(eval '(+ 1 2 3)) 

запускает функцию +.

Вы также можете входить и редактировать элементы списков на лету.

изменить:

Я написал программу для динамического создания программы и оценки ее на лету, а затем сообщите мне, как она по сравнению с базовым (div на 0 был обычным отчетом, га).

Ответ 3

Каждый ответ до сих пор связан с компиляцией отражения/исполнения, но в комментариях, которые вы упомянули, вас интересует фактический самомодифицирующий код - код, который модифицирует себя в памяти.

Нет способа сделать это на С#, Java или даже (переносимо) на C, то есть вы не можете изменить загруженный двоичный файл в памяти с помощью этих языков.

В общем, единственный способ сделать это - сборка, и она сильно зависит от процессора. Фактически, он также сильно зависит от операционной системы: для защиты от полиморфных вирусов, большинство современных операционных систем (включая Windows XP +, Linux и BSD ) принудительно выполните W ^ X, что означает, что вы должны пройти через некоторые проблемы написать полиморфные исполняемые файлы в этих операционных системах, для тех, которые позволяют это вообще.

В некоторых интерпретируемых языках может быть возможно, что программа изменит свой исходный код во время его работы. Perl, Python (см. здесь), и каждая реализация Javascript, которую я знаю, не позволяет этого.

Ответ 4

Лично мне показалось довольно странным, что вы обнаружите, что сборка проще обрабатывать, чем С#. Я нахожу еще страннее, что вы считаете, что сборка не такая мощная: вы не можете получить более мощный, чем сырой машинный язык. В любом случае, каждому из них.

У С# есть отличные сервисы отражения, но если у вас есть отвращение к этому. Если вам действительно нравится C или С++, вы всегда можете написать программу, которая пишет C/С++ и выдает ее компилятору. Это было бы жизнеспособным, если бы ваше решение не требовало бы быстрого самозавершения времени поворота (порядка десятков секунд или более).

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

Ответ 5

Могу ли я предложить Python, хороший динамический язык высокого уровня с богатой интроспекцией (и, например, использование compile, eval или exec разрешает форму самомодифицирующего кода). Очень простой пример, основанный на вашем вопросе:

def label1(a,b,c):
    c=a+b
    return c

a,b,c=10,20,0    
print label1(a,b,c) # prints 30

newdef= \
"""
def label1(a,b,c):
    c=a*b
    return c
"""
exec(newdef,globals(),globals())

print label1(a,b,c) # prints 200

Обратите внимание, что в примере кода выше c изменяется только в области функций.

Ответ 6

Общий Lisp был разработан с учетом такого рода вещей. Вы также можете попробовать Smalltalk, где использование отражения для изменения кода не неизвестно.

В обоих этих языках вы, вероятно, будете заменять целую функцию или весь метод, а не одну строку кода. Методы Smalltalk имеют тенденцию быть более мелкозернистыми, чем функции Lisp, поэтому это может быть хорошим местом для начала.

Ответ 7

Многие языки позволяют eval код во время выполнения.

  • Lisp
  • Perl
  • Python
  • PHP
  • рубин
  • Groovy (через GroovyShell)

Ответ 8

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

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

Ответ 9

Я иногда, хотя очень редко делаю самомодифицирующийся код в Ruby.

Иногда у вас есть метод, в котором вы действительно не знаете, правильно ли инициализированы данные, которые вы используете (например, какой-то ленивый кеш). Итак, вы должны проверить в начале вашего метода, правильно ли инициализированы данные, а затем инициализировать его. Но вам действительно нужно только сделать эту инициализацию один раз, но вы проверяете ее каждый раз.

Итак, иногда я пишу метод, который выполняет инициализацию, а затем заменяет собой версию, которая не включает код инициализации.

class Cache
  def [](key)
    @backing_store ||= self.expensive_initialization

    def [](key)
      @backing_store[key]
    end

    @backing_store[key]
  end
end

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

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

EDIT: теперь, когда я думаю об этом, эта оптимизация не имеет большого смысла. Дорогая инициализация выполняется только один раз. Единственное, что позволяет избежать модификации, является условным. Было бы лучше взять пример, когда сам чек стоит дорого, но я не могу придумать этого.

Однако я подумал о классном примере самомодифицирующего кода: Maxine JVM. Maxine - это исследовательская виртуальная машина (ее технически на самом деле нельзя назвать "JVM", потому что ее разработчики не запускают тесты совместимости), полностью написанные на Java. Теперь есть много JVM, написанных сами по себе, но Максин - единственный, кого я знаю, который также работает сам по себе. Это чрезвычайно мощно. Например, JIT-компилятор может JIT компилировать себя, чтобы адаптировать его к типу кода, который он компилирует JIT.

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

В обоих случаях виртуальная машина может оптимизировать и перекомпилировать себя во время выполнения.

Ответ 10

Я написал код класса Python, который позволяет добавлять и удалять новые строки кода для объекта, распечатывать код и вызывать его. Код класса, показанный в конце.

Пример: если x == 1, код меняет свое значение на x = 2, а затем удаляет весь блок с условием, который проверял это условие.

#Initialize Variables
x = 1

#Create Code
code = Code()
code + 'global x, code' #Adds a new Code instance code[0] with this line of code => internally             code.subcode[0]
code + "if x == 1:"     #Adds a new Code instance code[1] with this line of code => internally code.subcode[1]
code[1] + "x = 2"       #Adds a new Code instance 0 under code[1] with this line of code => internally code.subcode[1].subcode[0]
code[1] + "del code[1]" #Adds a new Code instance 0 under code[1] with this line of code => internally code.subcode[1].subcode[1]

После создания кода вы можете его распечатать:

#Prints
print "Initial Code:"
print code
print "x = " + str(x)

Вывод:

Initial Code:

global x, code
if x == 1:
    x = 2
    del code[1]

x = 1

Выполните действие cade, вызвав объект: code()

print "Code after execution:"
code() #Executes code
print code
print "x = " + str(x)

Выход 2:

Code after execution:

global x, code

x = 2

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

class Code:

    def __init__(self,line = '',indent = -1):

        if indent < -1:
            raise NameError('Invalid {} indent'.format(indent))

        self.strindent = ''
        for i in xrange(indent):
            self.strindent = '    ' + self.strindent

        self.strsubindent = '    ' + self.strindent

        self.line = line
        self.subcode = []
        self.indent = indent


    def __add__(self,other):

        if other.__class__ is str:
            other_code = Code(other,self.indent+1)
            self.subcode.append(other_code)
            return self

        elif other.__class__ is Code:
            self.subcode.append(other)
            return self

    def __sub__(self,other):

        if other.__class__ is str:
            for code in self.subcode:
                if code.line == other:
                    self.subcode.remove(code)
                    return self


        elif other.__class__ is Code:
            self.subcode.remove(other)


    def __repr__(self):
        rep = self.strindent + self.line + '\n'
        for code in self.subcode: rep += code.__repr__()
        return rep

    def __call__(self):
        print 'executing code'
        exec(self.__repr__())
        return self.__repr__()


    def __getitem__(self,key):
        if key.__class__ is str:
                for code in self.subcode:
                    if code.line is key:
                        return code
        elif key.__class__ is int:
            return self.subcode[key]

    def __delitem__(self,key):
        if key.__class__ is str:
            for i in range(len(self.subcode)):
                code = self.subcode[i]
                if code.line is key:
                    del self.subcode[i]
        elif key.__class__ is int:
            del self.subcode[key]

Ответ 11

Вы можете сделать это в Maple (язык компьютерной алгебры). В отличие от многих ответов выше, которые используют скомпилированные языки, которые позволяют создавать и связывать код new во время выполнения, здесь вы можете честно похудеть изменить код текущей программы. (Ruby и Lisp, как указывают другие ответчики, также позволяют это делать, возможно, Smalltalk тоже).

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

Как указывали другие: для достижения этого вам нужен интерпретируемый язык с сильными средствами отражения и овеществления.

Я написал автоматический нормализатор/упрощение для кода Maple, который я начал запускать во всей библиотеке (включая сам); и потому, что я не был слишком осторожен во всем своем коде, нормализатор действительно модифицировал себя. Я также написал Partial Evaluator (недавно принятый SCP) под названием MapleMIX - доступный на sourceforge - но не мог полностью применить его полностью к себе (это не было целью дизайна).

Ответ 12

Вы посмотрели на Java? Java 6 имеет API компилятора, поэтому вы можете писать код и компилировать его в виртуальной машине Java.

Ответ 13

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

local oldMyFunction = myFunction
myFunction = function(arg)
    if arg.blah then return oldMyFunction(arg) end
    else
        --do whatever
    end
end

Вы также можете просто пахать над функциями, которые дают вам самомодифицирующийся код.

Ответ 14

Реализация Dlang LLVM содержит атрибуты функций @dynamicCompile и @dynamicCompileConst, позволяющие компилировать в соответствии с собственным хостом набор инструкций во время компиляции и изменять константы времени компиляции во время выполнения посредством перекомпиляции.

https://forum.dlang.org/thread/[email protected]

Ответ 15

В MICGBF он изменяет интерпретатор каждый раз, когда вы его запускаете.

Это также очень весело * для программирования.

* Отказ от ответственности: это может быть не очень интересно программировать.