As Franck said, this is Genetic Programming, and as Adrien said genetic algorithms usually reason on Intermediate Representations of programs, like most compilers by the way. Ignoring typed variants, I know of two major classes of IRs for GP. The most popular one is based on Trees, and the other one is based on Stacks. Now when you have a program work directly on IR you probably want a readable representation of that IR in order to debug it (a bit like you prefer to read assembly code than machine code). It turns out there are programming languages that are very close to these two IRs, and hence can be used to represent and reason on them: Lisp for Trees and Forth for Stacks. About abstraction: it can indeed be useful for GP, especially to avoid redundancy, and it resembles abstraction mechanisms in the aforementioned languages: functions in Lisp and words in Forth. In Tree-based IR, introducing this kind of abstraction can be implemented by turning the Tree into a more general Graph, whereas the most straightforward way to do it in Stack-based IR is to introduce new operands via an extensible Lookup Table mechanism. Note that introducing this kind of abstraction also makes the evolution algorithm more complicated, because you have to deal with not one but several program chunks. Doing so efficiently is AFAIK still not a solved problem.