Could you please post the source code instead of the binary? Some of us don't have a Prop (or a serial-enabled version of SpinSim) within arm's reach to run the binary. I'm too lazy to get up from my chair to get my prop board that's sitting on a shelf 6 feet away.
Would not it be most challenging to use a decompiler (for high level languages) or disassembler (for assembly) that is sufficient to produce the original source of the author and include enough formatting information, symbol names and locations, and comments as data that is used in the decompilation of the app? Would not this meet the challenge of reproducing the authors original source? For (based on the understanding of a Quine as a challenge) what chalenge is there in simply outputting the source from data and then reproducing the data behind that?
I can not give my example at this time, as my only 2 Propellers are in continuous use for another test at this time. Thus I am unable to reliably test my code (I have not verified the accuracy of my PASM simulator, nor have I tested out a simulator by any one else, to know the differences from the real Propeller).
...what chalenge is there in simply outputting the source from data and then reproducing the data behind that?
The challenge, as I see it, is to devise the shortest program that can do that. But, according to this page on quines, they call what you describe a "cheat". I do notice from their examples, however, that facilities like print or printf are treated as an atomic element of many languages, which makes the job much easier.
A program may well be able to decompile itself. Perhaps not quite into the source as originally written. Generally there is no way it recreate the formatting or comments. That information is lost during compilation.
Heater:
As I stated above the decompiler should be written to use identifiers, comments, and formatting information from the data section of the program, and it would be a purpose specific decompiler, not general purpose.
Phil:
Beings that the authors original source would be reproduced, and all information used to due so is contained in the program; How is this a cheat?
Phil:
Further the page to witch you link gives examples of interpreted languages, in witch the source and the program are one and the same, using a command of the language with the same meaning as LIST in BASIC. While they say these are not cheats they say that doing so in BASIC is a cheat. So where is the standard? Would a basic program that peeks in memory from where it is being executed and then outputs this be a cheat? After all this is what the BASIC LIST command does (at least with most basic interpreters.
David Saunders,
OK I'll buy that decompiler idea.
Looking at some of those examples some of them seem to be feindishly short. Perhaps there is room for improvement in Spin.
10 DATA "B$='DATA '+CHR$(34)
20 DATA "FOR J=10 TO 180 STEP 10
30 DATA "READ A$
40 DATA PRINT J;B$;A$
50 DATA "IF J<>90 THEN 170
60 DATA "RESTORE
70 DATA "B$=' ' 80 DATA "NEXT J
90 DATA "END
100 B$='DATA '+CHR$(34)
110 FOR J=10 TO 180 STEP 10
120 READ A$
130 PRINT J;B$;A$
140 IF J<>90 THEN 170
150 RESTORE
160 B$=' '
170 NEXT J
180 END
This one is interesting to me.
a$[1]="a$[":a$[2]="]=":a$[3]="q$=chr$(34):for i=1 to 3:?a$[1]str$(i)a $[2]q$ a$q$ chr$(58);:next i:?a$[3]":q$=chr$(34):for i=1 to 3:?a$[ 1]str$(i)a$[2]q$ a$q$ chr$(58);:next i:?a$[3]
IMHO, including things like "list" uses a reference outside the program to complete the task. I think that's the standard; namely, limiting references to those entities in the program to the highest degree possible. A secondary standard would be the number of references used, where less is more. Finally, "clever", or "off label" uses of the language elements is "interesting", for bonus points.
Looking the examples over, I see two basic themes. One is where the program contains the data needed to output the program, and that data really is data.
The other is where the program really is the data, both executed and used as data, where the nature of the program is sufficient to output the program, without using something like "list".
IMHO, including things like "list" uses a reference outside the program to complete the task. I think that's the standard; namely, limiting references to those entities in the program to the highest degree possible. A secondary standard would be the number of references used, where less is more. Finally, "clever", or "off label" uses of the language elements is "interesting", for bonus points.
I don't think it's invalid. Seems to work just the same way the one in BASIC above does, where the program listing is in DATA statements. It's just not a very interesting one, because there is data, and there is the program. The program acts on the data to output itself.
The more interesting ones are where the data and the program are one and the same, with no discrete block of data that's easy to process.
And that's subjective, IMHO.
So is something like "list". Technically, "list" is part of the language, so I would call it valid, but not interesting. A BASIC program that uses peek and poke to read itself, parse, and output itself is far more interesting, because it is far more challenging. Frankly, the number of self-references is another point of interest. The "list" one does not require many, because "list" does most of the work. The program that interprets itself requires far more self-references. That's "interesting", IMHO.
BTW: A tangent that's probably gonna make a mess is the Propeller COG vs many other CPU's. I find Propeller PASM interesting because every long in the memory space is either program or data. The distinction is up to the programmer. A storage location is just a storage location, and each one is atomic, containing a value that is either instruction or data.
On many other CPUs, the distinction between program and data is not as pure. A storage location may contain part of a instruction, for example.
The interesting quines to me, and make no mistake I'm new to these just reading with interest, are those that are "pure" like that, where the data and the program are combined to appear as just a program, not a program that acts on a well defined unit of data.
Author: Bertram Felgenhauer
Notes: 80x86 TASM. Basically, the program reads it's own code/data segment and converts it
to decimal numbers, seperated by "\nDB ".
MODEL TINY
.CODE
.STARTUP
DB 177
DB 076
DB 186
DB 044
DB 001
DB 172
DB 180
DB 036
DB 179
DB 004
DB 191
DB 080
DB 001
DB 079
DB 136
DB 037
DB 212
DB 010
DB 004
DB 048
DB 134
DB 196
DB 075
DB 117
DB 244
DB 180
DB 009
DB 205
DB 033
DB 178
DB 071
DB 226
DB 228
DB 178
DB 038
DB 205
DB 033
DB 195
DB 013
DB 010
DB 069
DB 078
DB 068
DB 036
DB 077
DB 079
DB 068
DB 069
DB 076
DB 032
DB 084
DB 073
DB 078
DB 089
DB 013
DB 010
DB 046
DB 067
DB 079
DB 068
DB 069
DB 013
DB 010
DB 046
DB 083
DB 084
DB 065
DB 082
DB 084
DB 085
DB 080
DB 013
DB 010
DB 068
DB 066
DB 032
END
Beautiful! (if it does, in fact output that exact text)
It is beautiful because it references itself in every way, except for the output function. The only way to get a more self-referencing thing would be to code it for a specific machine, where the output can be displayed, or something with only the code input.
That's not portable, and because of that, not a significant consideration. STDOUT, printf, etc... are simply necessary things, but for a seriously pure and academic example, IMHO.
LIST is not a necessary thing, and perhaps that's where the line is on "cheats", and I think I'm just going to factor all that out, and say that if it outputs itself, it's a quine, with there being only interesting quines, and not so interesting ones, with interesting being keyed to the references that exist outside the input, and whether or not the program parses itself, rather than just outputting a formatted copy of itself.
Both of those increase difficulty, which makes them interesting.
Ok I see the point of the beauty, I agree that more complex and shorter solutions are much much more interesting.
My quine for the prop (witch I shall post once I have a free Propeller on witch to test it) uses a very similar method to the x86 asm one mentioned above. Of course it uses LONG instead of DB and has to reproduce the SPIN loader code (as it is meant to run by it self on a propeller). As such I am trying to assure my self that this is a valid quine, especially as other self referrals are often considered invalid, even when they do not rely on an external file in any way shape or form.
I should note that I wrote it before seeing the above code, it is just the most sensible method for doing such a thing in a pure way.
Yeah, I think it's valid. And the SPIN portion increases the overall difficulty. The pure assembly example above is not as difficult as one on the Prop will be, because the listing is less uniform, which presents a challenge in terms of overall size.
The nature of the machine has to be considered.
Edit: I just noticed you did cite the LAST example. I had looked at some of the earlier ones. Sorry, if that came across goofy.
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
VAR
byte s[4000]
word p, r
PRI dmp | i, c
r~~
repeat i from 0 to p - 1
case c := s[i]
1: str(string(32,32,98,117,102,40,115,116,114,105,110,103,40,34))
2: str(string(34,41,41,13))
other: tx(c)
str(string(32,32,100,109,112,13))
PRI buf(i)
s[p++] := 1
bytemove(@s[p], i, strsize(i))
p += strsize(i)
s[p++] := 2
str(i)
PRI str(i) | c
repeat while c := byte[i++]
if (r == 0 and c == 92)
c := 13
tx(c)
PRI tx(i) | t
t := cnt
i := (i | $300) << 1
repeat 11
waitcnt(t += 8333)
outa[30] := i & 1
i >>= 1
PUB go
waitcnt(cnt + clkfreq + outa[30]~~ + dira[30]~~)
buf(string("CON\\ _clkmode = xtal1 + pll16x\ _xinfreq = 5_000_000\\VAR\\ byte s[4000]\ "))
buf(string(" word p, r\\PRI dmp | i, c\\ r~~\ repeat i from 0 to p - 1\ case c := s[i]\"))
buf(string(" 1: str(string(32,32,98,117,102,40,115,116,114,105,110,103,40,34))\ 2:"))
buf(string(" str(string(34,41,41,13))\ other: tx(c)\ str(string(32,32,100,109,112,13))"))
buf(string("\\PRI buf(i)\\ s[p++] := 1\ bytemove(@s[p], i, strsize(i))\ p += strsize(i)\ "))
buf(string(" s[p++] := 2\ str(i)\\PRI str(i) | c\\ repeat while c := byte[i++]\ if (r ="))
buf(string("= 0 and c == 92)\ c := 13\ tx(c)\\PRI tx(i) | t\\ t := cnt\ i := (i | "))
buf(string("$300) << 1\ repeat 11\ waitcnt(t += 8333)\ outa[30] := i & 1\ i >>= 1\"))
buf(string("\PUB go\\ waitcnt(cnt + clkfreq + outa[30]~~ + dira[30]~~)\"))
dmp
Here's a Spin quine that generates it's source by looking at it's bytecodes. The first file is the actual quine and the second file is the one that generated it. They are functionally equivalent, but the quine doesn't contain comments or meaningful variable names.
Yes, genquine.spin is not a quine, but it's output is a valid quine. quine.spin will produce an identical copy of itself.
It took quite a few lines of code to generate Spin source from bytecodes. I had to limit the number of operators I used, and I use "repeat while" to do all my loops and if statements.
Comments
Produces more readable PASM code
Thanks,
Dave
I can not give my example at this time, as my only 2 Propellers are in continuous use for another test at this time. Thus I am unable to reliably test my code (I have not verified the accuracy of my PASM simulator, nor have I tested out a simulator by any one else, to know the differences from the real Propeller).
-Phil
As I stated above the decompiler should be written to use identifiers, comments, and formatting information from the data section of the program, and it would be a purpose specific decompiler, not general purpose.
Phil:
Beings that the authors original source would be reproduced, and all information used to due so is contained in the program; How is this a cheat?
Further the page to witch you link gives examples of interpreted languages, in witch the source and the program are one and the same, using a command of the language with the same meaning as LIST in BASIC. While they say these are not cheats they say that doing so in BASIC is a cheat. So where is the standard? Would a basic program that peeks in memory from where it is being executed and then outputs this be a cheat? After all this is what the BASIC LIST command does (at least with most basic interpreters.
OK I'll buy that decompiler idea.
Looking at some of those examples some of them seem to be feindishly short. Perhaps there is room for improvement in Spin.
10 LIST : REM MER : TSIL 01
This was not: Neither was this:
10 DATA "B$='DATA '+CHR$(34)
20 DATA "FOR J=10 TO 180 STEP 10
30 DATA "READ A$
40 DATA PRINT J;B$;A$
50 DATA "IF J<>90 THEN 170
60 DATA "RESTORE
70 DATA "B$=' ' 80 DATA "NEXT J
90 DATA "END
100 B$='DATA '+CHR$(34)
110 FOR J=10 TO 180 STEP 10
120 READ A$
130 PRINT J;B$;A$
140 IF J<>90 THEN 170
150 RESTORE
160 B$=' '
170 NEXT J
180 END
This one is interesting to me.
a$[1]="a$[":a$[2]="]=":a$[3]="q$=chr$(34):for i=1 to 3:?a$[1]str$(i)a $[2]q$ a$q$ chr$(58);:next i:?a$[3]":q$=chr$(34):for i=1 to 3:?a$[ 1]str$(i)a$[2]q$ a$q$ chr$(58);:next i:?a$[3]
IMHO, including things like "list" uses a reference outside the program to complete the task. I think that's the standard; namely, limiting references to those entities in the program to the highest degree possible. A secondary standard would be the number of references used, where less is more. Finally, "clever", or "off label" uses of the language elements is "interesting", for bonus points.
Looking the examples over, I see two basic themes. One is where the program contains the data needed to output the program, and that data really is data.
The other is where the program really is the data, both executed and used as data, where the nature of the program is sufficient to output the program, without using something like "list".
The more interesting ones are where the data and the program are one and the same, with no discrete block of data that's easy to process.
And that's subjective, IMHO.
So is something like "list". Technically, "list" is part of the language, so I would call it valid, but not interesting. A BASIC program that uses peek and poke to read itself, parse, and output itself is far more interesting, because it is far more challenging. Frankly, the number of self-references is another point of interest. The "list" one does not require many, because "list" does most of the work. The program that interprets itself requires far more self-references. That's "interesting", IMHO.
BTW: A tangent that's probably gonna make a mess is the Propeller COG vs many other CPU's. I find Propeller PASM interesting because every long in the memory space is either program or data. The distinction is up to the programmer. A storage location is just a storage location, and each one is atomic, containing a value that is either instruction or data.
On many other CPUs, the distinction between program and data is not as pure. A storage location may contain part of a instruction, for example.
The interesting quines to me, and make no mistake I'm new to these just reading with interest, are those that are "pure" like that, where the data and the program are combined to appear as just a program, not a program that acts on a well defined unit of data.
Beautiful! (if it does, in fact output that exact text)
It is beautiful because it references itself in every way, except for the output function. The only way to get a more self-referencing thing would be to code it for a specific machine, where the output can be displayed, or something with only the code input.
That's not portable, and because of that, not a significant consideration. STDOUT, printf, etc... are simply necessary things, but for a seriously pure and academic example, IMHO.
LIST is not a necessary thing, and perhaps that's where the line is on "cheats", and I think I'm just going to factor all that out, and say that if it outputs itself, it's a quine, with there being only interesting quines, and not so interesting ones, with interesting being keyed to the references that exist outside the input, and whether or not the program parses itself, rather than just outputting a formatted copy of itself.
Both of those increase difficulty, which makes them interesting.
My quine for the prop (witch I shall post once I have a free Propeller on witch to test it) uses a very similar method to the x86 asm one mentioned above. Of course it uses LONG instead of DB and has to reproduce the SPIN loader code (as it is meant to run by it self on a propeller). As such I am trying to assure my self that this is a valid quine, especially as other self referrals are often considered invalid, even when they do not rely on an external file in any way shape or form.
I should note that I wrote it before seeing the above code, it is just the most sensible method for doing such a thing in a pure way.
The nature of the machine has to be considered.
Edit: I just noticed you did cite the LAST example. I had looked at some of the earlier ones. Sorry, if that came across goofy.
-Phil
Yours is "beautiful" and "interesting" in exactly the opposite way of the one I cited above. Very well done. Impressive.
Dave
So I would say that this means that the generated file is a valid quine and the original source is not???
It took quite a few lines of code to generate Spin source from bytecodes. I had to limit the number of operators I used, and I use "repeat while" to do all my loops and if statements.