Attached simple quine program in Spin, written in 30 minutes, writes its own source code to serial port. Can someone come up with a less rude approach? Assembly anyone?
If quine.spin is non-ascii you may have a 0 byte in there...probably safer to name your terminating byte, and do a repeat and serial.tx() each byte individually.
Here's a shorter version that runs under SpinSim. I named it q.spin to shorten the name. If I run "spinsim q.binary >x" under Windows the file x is an exact copy of q.spin. q.spin is an 8-bit ASCII file, so it won't have any zeros in it.
OBJ s:"conio"
DAT t file "q.spin"
byte 0
PUB main
s.str(@t)
Using the file directive is cheating.
Not only that it is not even a good cheat as the result is wrong.
By using file you are effectively including a copy of the source within the source. But the printed output ony prints the top level copy not the included copy.
I don't think the file statement violates the quine rules. It basically includes itself, which means it is self-contained. I could give anybody the binary file, and they could run it to generate the source, and they could regenerate the binary. So it is completely self-contained. This is different than a C file that uses a #include to include source code that would print out the main file. You could not regenerate the complete source file from the binary.
I think Phil has a good point that a Spin file that includes an external object really shouldn't be allowed. Here is a version that doesn't include an object.
DAT t file "q.spin"
byte 0
PUB main
str(@t)
PUB str(ptr)
repeat while byte[ptr]
tx(byte[ptr++])
PUB tx(val)
long[$12340004] := val
word[$12340000] := 1
repeat while word[$12340000]
And for those that think that the "file" directive is cheating, here's a version without the file directive.
I don't think the file statement violates the quine rules. It basically includes itself, which means it is self-contained. I could give anybody the binary file, and they could run it to generate the source, and they could regenerate the binary. So it is completely self-contained. This is different than a C file that uses a #include to include source code that would print out the main file. You could not regenerate the complete source file from the binary.
I was thinking exactly the same. The file directive is a feature of the Spin compiler, which includes the file at compile time into the binary.
So here is a solution in binary form that needs no objects and runs on a real Propeller. The serial output at P30 has a baudrate of 9600 Baud.
You have 3 seconds after starting the binary to receive the output in a Terminal (i.e. PST). You get the source in the Terminal and you can compile this source again to a binary.
I disagree. The file directive is a cheat, because it pulls in data from somewhere else.
SpinSim uses the locations at $1234000X for console and file I/O. word[$12340000] is the system I/O command and long[$12340004] is a parameter used by the command. A character is sent to the console by storing the character at the parameter location and setting the command to 1. The command is completed when word[$12340000] becomes zero.
I've never heard of a quine before, but the simple definition is a program that prints out it's own source code. A Spin program that uses the file directive to include it's own source meets that criteria. "file" works because it's including itself. It wouldn't work if the file directive was including another file, because that other file wouldn't exist.
I think the test for whether a quine is valid is to comple it, run it and then compare the output to the source. The quine must be self-contained, meaning that it can't use an input stream to create its output.
Ariba's program contains a 9600 baud serial transmit routine. The output from his program is shown below. This could be combined with Andrey's method using hex or my method using ASCII to meet Phil's requirements.
BTW, I added a serial decoder to SpinSim to run Ariba's binary file. I'll include that in the next update.
' Copy this into the PropTool, save it as 'quine.spin' and press F10
CON _clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
PUB main : p | t,txd
outa[30]~~ ' set idle state
dira[30]~~ ' make tx pin an output
waitcnt(clkfreq*3+cnt)
repeat while (txd := data[p++]) ' read data
txd := ((txd | $300) << 2) ' add start and stop bits
t := cnt ' sync
repeat 11 ' start + eight data bits + 2stop
waitcnt(t += clkfreq/9600) ' wait bit time
outa[30] := (txd >>= 1) ' output bit
DAT
data file "quine.spin"
byte 0
My understanding of Quine is that you should not include the source as data in the program in any way. I do remember when I was first introduced to the concept, in interpreted BASIC (but that was in elementary school). I had written a program that in its code, in part, used a list command redirected to disk. My professor told me that this was a Quine.
My understanding of Quine is that you should not include the source as data in the program in any way. I do remember when I was first introduced to the concept, in interpreted BASIC (but that was in elementary school). I had written a program that in its code, in part, used a list command redirected to disk. My professor told me that this was a Quine.
That sounds backwards to me. Using the list command should not count as a quine, while including the source as data is the whole point of quining.
I hate these golf challenges!!! ... no really I don't it's great exercise for the brain.
I think the code below meets the requirements posted by Phil.
1. The program has to run natively on the Prop.
2. The program source cannot refer to external resources (i.e. no OBJ and no file directives).
CON
_CLKMODE = XTAL1 + PLL16X
_CLKFREQ = 80_000_000
Baud = 38400 'Tested up to 250000 baud
TX = 30
{{
According to Wikipedia, a 'quine' is a computer program which produces a copy of its own
source code as its only output.
[B]Thus far the solutions that I have seen have produced 'human readable' source code, but
isn't 'machine code' just as much valid source code as what you could read in PASM?[/B]
This program launches a PASM routine to serially transmit the upper 32768 bytes of the
Propeller at a desired baud and pin. The output is open-collector / inverted driven / with
1 start bit and no stop bit.
At 38400 baud it takes about 8.5 seconds to transmit the data.
_
(10/Baud)* 32768 = 8.53 seconds
}}
PUB QUINE
cognew(@PASM, 0)
DAT
PASM org
andn outa, PinMask 'PreSet pin LOW
andn dira, PinMask 'Make min an Input
mov Index, #0 '<-- Starting Address ; Clear/Reset Index
NextData rdbyte Buff, Index 'Read BYTE
add Index, #1 'Increment BYTE Index
cmp Index, SizeInBytes wz 'set Z flag if the last BYTE address has been reached
add Buff, #$100 'Add Start Bit ; LOGIC "1"
shl Buff, #1 'Add Stop Bit ; LOGIC "0"
mov BitCount, #10 'Start Bit + Stop Bit + Byte = 10 bits total
Bits ror Buff, #1 wc 'Send Bits LSB first
muxnc dira, PinMask 'Set Data Bit (Inverted data)
mov delay, BaudDelay 'Pause based on Baud
djnz delay, #$ 'delay
djnz BitCount, #Bits 'More Bits to send?
if_nz jmp #NextData 'Send Next Data Byte
cogid temp 'Shut down cog
cogstop temp
temp
PinMask long |<TX
BaudDelay long ((_CLKFREQ / Baud)>>2)-5
delay long 0
Index long 0
Buff long 0
BitCount long 0
SizeInBytes long $8000
Why wouldn't it be? ... if you saved the file as a EEPROM File, the output generated is a mirror copy <--- with the exception of the Stack space area during run-time, but the program itself (the source code) would be intact. Quine doesn't necessarily imply that it's human readable, just that it's valid source code of itself.
I have not looked at Andrey's assembler quine yet as I only have a phone to chat with today. But I'm thinking that an assembler language quine cold be written that essentially dis-assembles itself into a bunch of DAT LONG decalations with a little Spin header to get it started. That output could then be used as source to compile the same binary again.
Now this is odd because the resulting quine would be source code but basically obfuscated and not very human readable. More weird is the fact that the finished quine was written by the original asm program, not the author himself.
Because it outputs something different from the original code.
I think one of most precise definitions of a quine programs is the following:
fixed point (also known as an invariant point) of a function is a point that is mapped to itself by the function (f(x) = x). Quines are such fixed points, where:
x is the sourcecode, and f() is the interpreter / compiler with its underlaying system.
For Spin source code program, lets call it x1, f(x) is a combination of spin compiler and the chip ("underlaying system"), lets call it f1(x) . For compiled program, lets call it x2, f(x) is bare chip, lets call it f2(x). Obviously, x1 != x2, f1(x1) != x1, and f2(x2) == x2.
Now this is odd because the resulting quine would be source code but basically obfuscated and not very human readable.
My program does actual dissembling, so you get assembly source, with conditions, instructions and modifiers, not just a bunch of LONGs. With little effort, it can even be made to preserve original labels and use them instead of hard-coded operands. Then one can even understand how it works
More weird is the fact that the finished quine was written by the original asm program, not the author himself.
Does that matter at all? I do not think so. Is it a program? Yes. Does it produce an exact copy of its own source code? Who cares how it was generated?
So if you don't need to reproduce the source code then here is a solution with absolutely no external resources involved (no terminal, no compiler, no harddisk, no PC).
Once compiled and written to the EEPROM of the first Propeller, it reproduces itself on the next Propeller. The schematic shows 3 Propeller chips connected in a chain, but the number is not limited.
OBJ loader : "PropellerLoader"
PUB LoadPropeller
dira[16] := 1 'LED on
outa[16] := 1
waitcnt(clkfreq + cnt) 'wait a second
'reproduce code on next Propeller:
loader.Connect(0, 1, 2, 1, loader#LoadRun, 0)
This is not tested. For a possible test you can connect a LED on P16 of every Propeller.
Not sure if this is still the idea of a quine
Comments
If quine.spin is non-ascii you may have a 0 byte in there...probably safer to name your terminating byte, and do a repeat and serial.tx() each byte individually.
Jonathan
-Phil
Not only that it is not even a good cheat as the result is wrong.
By using file you are effectively including a copy of the source within the source. But the printed output ony prints the top level copy not the included copy.
I think Phil has a good point that a Spin file that includes an external object really shouldn't be allowed. Here is a version that doesn't include an object.
And for those that think that the "file" directive is cheating, here's a version without the file directive.
Yes it's the same idea as yours, but it doesn't include an external object, and it is less source code.
Dave
I was thinking exactly the same. The file directive is a feature of the Spin compiler, which includes the file at compile time into the binary.
So here is a solution in binary form that needs no objects and runs on a real Propeller. The serial output at P30 has a baudrate of 9600 Baud.
You have 3 seconds after starting the binary to receive the output in a Terminal (i.e. PST). You get the source in the Terminal and you can compile this source again to a binary.
Andy
Can you explain what your tx method is doing?
Andy,
I disagree. The file directive is a cheat, because it pulls in data from somewhere else.
-Phil
After reading this short discussion, I'm curious about characterizing file:
There is the loading of the program.
Then there is the running of the program.
And the output of the program.
If one were to type the program into the Propeller, that's not considered against the rules.
So, what if one were to use a software system to pull the program listing from a disk?
Both of those are loading the program, right?
How does file: differ?
When the program is run, all the program that is loaded is reproduced at the output right? Do the characters file: appear in the output?
If not, how does that differ from automatically loading a program, in the way I described above?
I've never heard of a quine before, but the simple definition is a program that prints out it's own source code. A Spin program that uses the file directive to include it's own source meets that criteria. "file" works because it's including itself. It wouldn't work if the file directive was including another file, because that other file wouldn't exist.
I think the test for whether a quine is valid is to comple it, run it and then compare the output to the source. The quine must be self-contained, meaning that it can't use an input stream to create its output.
Dave
1. The program has to run natively on the Prop.
2. The program source cannot refer to external resources (i.e. no OBJ and no file directives).
-Phil
I guess if you do 300 bps baud then spin could do serial easily though...
File just embeds characters, you can do that without the file command...
Then, it seems you just have to output almost the same thing twice...
BTW, I added a serial decoder to SpinSim to run Ariba's binary file. I'll include that in the next update.
That sounds backwards to me. Using the list command should not count as a quine, while including the source as data is the whole point of quining.
Properties:
Disclaimer
Trying to read and understand the source can lead to madness. Do not blame me if your mind is affected.You have been warned.
I think the code below meets the requirements posted by Phil.
To be precise, that code itself is not a quine, although its output can be considered a quine.
Why wouldn't it be? ... if you saved the file as a EEPROM File, the output generated is a mirror copy <--- with the exception of the Stack space area during run-time, but the program itself (the source code) would be intact. Quine doesn't necessarily imply that it's human readable, just that it's valid source code of itself.
Now this is odd because the resulting quine would be source code but basically obfuscated and not very human readable. More weird is the fact that the finished quine was written by the original asm program, not the author himself.
Because it outputs something different from the original code.
I think one of most precise definitions of a quine programs is the following:
For Spin source code program, lets call it x1, f(x) is a combination of spin compiler and the chip ("underlaying system"), lets call it f1(x) . For compiled program, lets call it x2, f(x) is bare chip, lets call it f2(x). Obviously, x1 != x2, f1(x1) != x1, and f2(x2) == x2.
My program does actual dissembling, so you get assembly source, with conditions, instructions and modifiers, not just a bunch of LONGs. With little effort, it can even be made to preserve original labels and use them instead of hard-coded operands. Then one can even understand how it works
Does that matter at all? I do not think so. Is it a program? Yes. Does it produce an exact copy of its own source code? Who cares how it was generated?
Once compiled and written to the EEPROM of the first Propeller, it reproduces itself on the next Propeller. The schematic shows 3 Propeller chips connected in a chain, but the number is not limited.
This is not tested. For a possible test you can connect a LED on P16 of every Propeller.
Not sure if this is still the idea of a quine
Andy