Samoodtwarzający Się Kod

  • Ostatnio zastanawiam się nad napisaniem samodzielnych programów , myślę, że może to być potężne i zabawne... Tak więc obecnie Szukam języka, który pozwala łatwo modyfikować własny kod programu..

  • Czytałem o C # (jako sposób na obejście) i możliwości kompilowania-i wykonywania - kodu w runtime, ale to zbyt boli..

  • myślę też o zgromadzeniu ... łatwiej jest tam zmienić działający kod, ale nie jest to zbyt potężne (bardzo surowe)...

czy możesz zasugerować mi potężny język - lub funkcję-która obsługuje modyfikowanie kodu w trybie runtime..?

Podpowiedzi
To co mam na myśli modyfikując kod w runtime:

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

I może tworzyć listę instrukcji:

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

Dzięki!

Author: skaffman, 2010-06-17

13 answers

 42
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-16 22:00:55

Bardzo polecam Lisp. Dane Lispu mogą być odczytywane i używane jako kod. Kod Lispu można zapisać jako dane.

Jest uważany za jeden z kanonicznych języków samodoskonalących.

Przykładowa lista (DANE):

'(+ 1 2 3) 

Lub, wywołując dane jako kod

(eval '(+ 1 2 3)) 

Uruchamia funkcję+.

Możesz również wejść i edytować członków listy w locie.

Edit:

Napisałem program do dynamicznego generowania programu i oceny go w locie, a następnie zgłoś mi, jak to się stało w porównaniu do wartości wyjściowej (div przez 0 był zwykłym raportem, ha).

 20
Author: Paul Nathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-16 22:28:01

Każda dotychczasowa odpowiedź dotyczy kompilacji reflection/runtime, ale w komentarzach, o których wspomniałeś, interesuje Cię rzeczywisty samododajny kod - kod, który modyfikuje się w pamięci.

Nie ma sposobu, aby to zrobić w C#, Javie, lub nawet (przenośnie) w C - to znaczy, nie można modyfikować załadowanych w pamięci binarnych za pomocą tych języków.

Ogólnie rzecz biorąc, jedynym sposobem na to jest montaż, który jest wysoce zależny od procesora. W rzeczywistości jest to wysoce operacyjny system zależne również: aby chronić przed wirusami polimorficznymi , większość nowoczesnych systemów operacyjnych (W Tym Windows XP+, Linux i BSD) wymusza W^X, co oznacza, że musisz zadawać sobie pewne problemy, aby pisać polimorficzne pliki wykonywalne w tych systemach operacyjnych, dla tych, które w ogóle na to pozwalają.

W niektórych interpretowanych językach może być możliwe, aby program zmodyfikował swój własny kod źródłowy podczas jego działania. Perl, Python (Zobacz też tutaj), każda implementacja Javascript, którą znam, na to nie pozwala.

 12
Author: BlueRaja - Danny Pflughoeft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-20 18:23:29

Mogę zaproponować Python , ładny dynamiczny język bardzo wysokiego poziomu, który zawiera bogatą introspekcję (i np. compile, eval lub exec pozwala na samodzielną modyfikację kodu). Bardzo prosty przykład oparty na twoim pytaniu:

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

Zauważ, że w powyższym kodzie {[4] } zmienia się tylko zakres funkcji.

 9
Author: ChristopheD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-16 22:36:28

Osobiście uważam to za dość dziwne, że łatwiej jest obsługiwać assembly niż C#. Wydaje mi się jeszcze dziwniejsze, że uważasz, że assembly nie jest tak potężny: nie możesz uzyskać większej mocy niż surowy język maszynowy. W każdym razie, dla każdego.

C # ma świetne usługi refleksyjne, ale jeśli masz do tego awersję.. Jeśli jesteś naprawdę wygodne z C lub c++, zawsze można napisać program, który pisze C / C++ i wydaje go do kompilatora. Byłoby to możliwe tylko wtedy, gdy twój rozwiązanie nie wymaga szybkiego samoczynnego przepisywania czasu zwrotu (rzędu kilkudziesięciu sekund lub więcej).

Javascript i Python wspierają również reflection. Jeśli myślisz o nauce nowego, zabawnego języka programowania, który jest potężny, ale nie jest bardzo wymagający technicznie, proponuję Python.

 8
Author: Reinderien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-16 22:06:49

Common Lisp został zaprojektowany z myślą o tego typu rzeczach. Możesz również spróbować Smalltalk , gdzie używanie reflection do modyfikowania działającego kodu nie jest nieznane.

W obu tych językach prawdopodobnie zastępujesz całą funkcję lub całą metodę, a nie pojedynczy wiersz kodu. Metody Smalltalk są zwykle bardziej drobnoziarniste niż funkcje Lispu, więc może to być dobre miejsce do rozpoczęcia.

 7
Author: Norman Ramsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-16 22:40:22

Wiele języków umożliwia ewalowanie kodu w czasie wykonywania.

  • Lisp
  • Perl
  • Python
  • PHP
  • Ruby
  • Groovy (via GroovyShell)
 6
Author: Kevin Panko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-21 20:00:28

W językach wysokiego poziomu, w których kompilujesz i wykonujesz kod w czasie wykonywania, nie jest to tak naprawdę samoodtwarzający się kod, ale dynamiczne ładowanie klasy. Korzystając z zasad dziedziczenia, można zastąpić klasę Factory i zmienić zachowanie aplikacji w czasie wykonywania.

Tylko w języku asemblera istnieje prawdziwa samodoskonalenie, pisząc bezpośrednio do segmentu kodu. Ale nie ma praktycznego zastosowania. Jeśli lubisz wyzwania, napisz samoszyfrujący, może polimorficzny wirus. Byłoby fajnie.

 4
Author: Kenny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-23 14:11:42

Napisałem Kod klasy Pythona, który umożliwia dodawanie i usuwanie nowych linii kodu do obiektu, drukowanie kodu i wykreślanie go. Kod klasy pokazany na końcu.

Przykład: jeśli x = = 1, kod zmienia swoją wartość na x = 2, a następnie usuwa cały blok z warunkowym, który jest zaznaczony dla tego warunku.

#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]

Po utworzeniu kodu można go wydrukować:

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

Wyjście:

Initial Code:

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

x = 1

Wykonaj cade wywołując obiekt: code ()

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

Wyjście 2:

Code after execution:

global x, code

x = 2

Jak widać, kod zmienił zmienną x na wartość 2 i usunął cały blok if. Może to być przydatne, aby uniknąć sprawdzania warunków po ich spełnieniu. W prawdziwym życiu, ten scenariusz przypadku może być obsługiwany przez system coroutine, ale ten sam modyfikujący się eksperyment kodowy jest tylko dla Zabawy.

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]
 2
Author: Cristian Garcia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-22 20:56:35

Czasami, chociaż Bardzo rzadko robię samoodtwarzający się kod w Rubim.

Czasami masz metodę, w której tak naprawdę nie wiesz, czy dane, których używasz (np. jakiś leniwy cache), są prawidłowo zainicjowane, czy nie. Musisz więc sprawdzić na początku metody, czy dane są prawidłowo zainicjowane, a następnie je zainicjować. Ale naprawdę musisz zrobić tę inicjalizację tylko raz, ale sprawdzasz ją za każdym razem.

Więc czasami piszę metoda, która dokonuje inicjalizacji, a następnie zastępuje się wersją, która nie zawiera kodu inicjalizacji.

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

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

    @backing_store[key]
  end
end
Ale szczerze mówiąc, nie sądzę, żeby to było tego warte. Szczerze mówiąc, wstydzę się przyznać, że nigdy nie sprawdzałem, czy ten JEDEN warunkowy rzeczywiście robi jakąś różnicę. (Na nowoczesnej implementacji Ruby z agresywnie optymalizującym kompilatorem JIT opartym na sprzężeniu zwrotnym prawdopodobnie nie.)

Zauważ, że w zależności od tego jak zdefiniuj "samododający się kod", może to być, ale nie musi być to, czego chcesz. Ty zastępujesz część aktualnie wykonującego program, więc ...

EDIT: teraz, gdy o tym myślę, ta optymalizacja nie ma większego sensu. Kosztowna inicjalizacja i tak jest wykonywana tylko raz. Jedyną rzeczą, której modyfikacja unika, jest warunek. Lepiej wziąć przykład, gdzie sam czek jest drogi, ale nie mogę myśleć o jeden.

Pomyślałem jednak o fajnym przykładzie samoodtwarzającego się kodu: Maxine JVM . Maxine jest maszyną badawczą (technicznie nie pozwala nazywać się "JVM", ponieważ jej programiści nie uruchamiają testów zgodności) napisaną całkowicie w Javie. Teraz, jest mnóstwo JVMs napisane w sobie, ale Maxine jest jedynym, który wiem, że również działa w sobie. To jest niezwykle potężne. Na przykład kompilator JIT może kompilować się do dostosuj go do typu kodu, który kompiluje JIT.

Bardzo podobna rzecz dzieje się wKlein VM , która jest maszyną wirtualną dla języka programowania Self. W obu przypadkach maszyna wirtualna może zoptymalizować i przekompilować siebie w czasie wykonywania.
 2
Author: Jörg W Mittag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-23 14:12:28

Możesz to zrobić w Maple (język algebry komputerowej). W przeciwieństwie do wielu powyższych odpowiedzi, które używają skompilowanych języków, które pozwalają tylko na tworzenie i linkowanie w Nowego kodu w czasie wykonywania, tutaj możesz szczerze modyfikować kod aktualnie uruchomionego programu. (Ruby i Lisp, jak wskazują inni answers, również pozwalają na to; prawdopodobnie Smalltalk też).

Właściwie, w Maple standardem było to, że większość funkcji bibliotecznych to małe stuby, które ładowały się ich "prawdziwe" ja z dysku na pierwszym wywołaniu, a następnie samodzielnie modyfikować się do załadowanej wersji. Tak już nie jest, ponieważ ładowanie biblioteki zostało zwirtualizowane.

Jak wskazywali inni: aby to osiągnąć, potrzebny jest język interpretowany z silnym zapleczem refleksji i reifikacji.

Napisałem automatyczny normalizer / simplifier dla kodu Maple, który zacząłem uruchamiać na całej bibliotece (w tym samej); a ponieważ nie byłem zbyt ostrożny we wszystkich moich kod, normalizator sam się zmodyfikował. Napisałem również częściowy ewaluator (ostatnio zaakceptowany przez SCP) o nazwie MapleMIX-dostępny na sourceforge - ale nie mogłem go w pełni zastosować do siebie (nie był to cel projektu).

 1
Author: Jacques Carette,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-17 00:28:56

Oglądałeś Javę ? Java 6 posiada API kompilatora , dzięki czemu można pisać kod i kompilować go w maszynie wirtualnej Java.

 0
Author: Brian Agnew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-16 22:01:58

W Lua można "zaczepić" istniejący kod, co pozwala na dołączenie dowolnego kodu do wywołań funkcji. Chodzi o coś takiego:

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

Możesz także po prostu zaorać funkcje, które w pewnym sensie dają Ci własny kod modyfikujący.

 0
Author: RCIX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-19 02:19:01