Pxem
Paradigm(s) | Imperative paradigm |
---|---|
Designed by | ぬこ/nk.[1] |
Appeared in | 2008 |
Type system | none |
Memory system | stack-based |
Dimensions | one-dimentional |
Computational class | Turing complete |
Reference implementation | (Original ("ぬこ"/nk's)) pxemi.7z, text2pxem.pl (wktk's) rpxem |
File extension(s) | .pxe , .pxem |
Pxem(pronounced "ペクシム" [pekushimu] by the creator[2]) is a programming language designed by "ぬこ" [nuko] or "nk."[1]. According to nk, "Pxem" is only named as such because "it's easy to type with a keyboard."[3]
History
Pxem used to be published in author's own website before, which does not exist anymore. According to their new blog[2], they used to compete in coding-golf held on anarchy golf using Perl, PHP, and brainfuck. One day, shinh, the host of the site, introduced GolfScript, which is designed for coding-golf. In some courses, the script enables you to code with only one-byte files. This inspired them to design a new language for coding-golf working with zero-byte files.
Specifications
Virtual machine
Pxem interpreter works with a virtual machine with a stack ― stores values as integer type ―, a buffer ― stores a string for stacking into the stack ―, a temporary memory ― stores only a value at the same time, as integer type. The stack and the temporary memory will be initialized with no values.
According to original interpreter, it is distinguished whether temporary memory has been used or not.
File name and contents
Pxem interpreter recognizes file name mainly as a source code of program. Contents of file, on the other hand, will be ignored unless file name includes either .e
or .f
, which is described in further sections.
How the code gets read
At first content of file name will be read from beginning to end. When it reaches to .d
or end, the program terminates. When it reaches to .e
, the interpreter begins to read content of file as the new process, which will be interpreted as part of Pxem code, from beginning to end. When it reaches to .d
or end of file, the process ends, then original process gets continued. Vice versa when it reaches to .e
inside file.
Instructions
Each command is a .
(dot), and a case-insensitive ASCII character. Before the pointer reaches to the command, the character currently read will be added to the buffer as a character code. When the pointer reaches to the command, the content in the buffer gets pushed into the stack before the command gets operated.
For example, the file abcd.stuv.pxe
can be separated into 5 parts: abcd
, .s
, tuv
, .p
, and xe
. Before reaching to the first instruction .s
, the four characters d, c, b, and a get stacked in those order, which d is in bottom while a is in top. Then, by .s
instruction, the top value 'a' gets popped. Later, the three characters v, u, and t get stacked in that order. By .p
, the stack will be empty, because each content gets outputted as an ASCII character. Finally, two characters get pushed in following order then the program terminates: e, and x.
Output
Command | Description |
---|---|
.p |
Pops and outputs as a character, then repeats until the stack gets empty.[ins 1]
|
.o |
Pops once and outputs as a character.[ins 1]
|
.n |
Pops once and outputs as an integer value.[ins 1]
|
Input
Command | Description |
---|---|
.i |
User inputs a character of a byte to stack. EOF values -1.
|
._ |
User inputs a signed integer to stack.
|
Operating stack
Command | Description |
---|---|
.c |
Duplicate: Pops once, then pushes the popped item twice.[ins 1]
|
.s |
Drop: Pops once and discards the item.[ins 1]
|
.v |
Reverses content of the stack.
|
Operating content of file
Command | Description |
---|---|
.f |
Stacks content of file as a string. This command never erases content of file.
|
.e |
Execution: Recognizes content of file as a part of Pxem code and begins new process there, making a new stack memory(items in original stack will be copied) and a temporary register (empty)[2]. After the process ends,
You may run this command as many times as you'd like.
|
Random value
Command | Description |
---|---|
.r |
Pops an item x, then pushes a signed random integer between 0 and (x-1). For example, if x were 10, one of 0-9 would be generated.[ins 1][ins 3]
|
Conditional looping
All of the following instructions may be nested.
Command | Description |
---|---|
.w |
Loop while not zero: Pops top value and tests if it is 0 or not[ins 4]. If it's zero, skip to the matching .a instruction.[ins 5]
|
.x |
Loop while less: Pops two top values. If firstly popped value is equal or greater than secondly popped one[ins 6], skip to the matching .a instruction.[ins 5]
|
.y |
Loop while greater: Pops two top values. If firstly popped value is equal or less than secondly popped one[ins 7], skip to the matching .a instruction.[ins 5]
|
.z |
Loop while not equal: Pops two top values. If they are equal, skip to the matching .a instruction.[ins 5]
|
.a |
End of loop: Jumps back to corresponding one of four above. If there are not, the program results in an error[2]. |
- Note
- Five commands above can be nested.
- Example 1
Hello, world.w.pxe
Hello, world.a.pxe
- Both two above results in an error during running. Former one is because of reaching to no
.a
's while other is because of reaching.a
before four others.
- Both two above results in an error during running. Former one is because of reaching to no
- Example 2
abcdeffggghijj.z.a.pxe
- Output
hijj
- Example 3
abcdeffggghijj.x.a.pxe
- Output
hijj
- Example 4
abcdeffggghijj.y.a.pxe
- Output
cdeffggghijj
- Example 5
a.w.a.pxe
- This program will never terminate, for causing an infinite loop.
Temporary memory
Command | Description |
---|---|
.t |
Pops top value. The value gets stored in temporary register.[ins 8][ins 9] |
.m |
Pushes content in temporary register.[ins 10] If the register is empty, nothing happens. |
Termination
Command | Description |
---|---|
.d |
Return[ins 11]. This instruction works differently on either file name or content.
|
Arithmetic operation
Command | Description |
---|---|
.+ |
Addition operation: Pops two top values, then pushes sum of them.[ins 12] |
.- |
Subtraction operation: Pops two top values, then substrates smaller one from larger one. Pushes the result.[ins 12] |
.! |
Multiplication operation: Pops two top values, then pushes their product.[ins 12] |
.$ |
Division operation: Pops two top values, then divides larger one by smaller one. Pushes the quotient.[ins 12][ins 13] |
.% |
Modulo operation: Pops two top values, then divides larger one by smaller one. Pushes the remainder.[ins 12][ins 13] |
- ↑ 1.0 1.1 1.2 1.3 1.4 1.5 If stack is empty, nothing happens
- ↑ This is not officially documented, but pxem.h of pxemi.7z satisfies this specification.
- ↑ It was not originally specified what would happen if top value were either 0 or -1 on original description page, but according to pxem.h of pxemi.7z, the original interpreter, it is implemented in following function:
inline void Pxem::getRand(){ int aaa = rand() % pStack.top(); pStack.pop(); pStack.push(aaa); }
Therefore the program would result in an error by dividing by 0.
- ↑ It won't test if stack is empty.
- ↑ 5.0 5.1 5.2 5.3 It was not specified on original description page, but according to revival blog page, the author clarified what would happen the number of values in the stack were not enough: nothing would happen to content of the stack. However, it was not clarified whether the program loops or not. But according to the original interpreter pxem.h of pxemi.7z, the program will loop.
- ↑ Original description said: if first-popped item is NOT smaller than the other.
- ↑ Original description said: if first-popped item is NOT greater than the other.
- ↑ Old content in the register will be lost.
- ↑ It is not clarified what would happen if the stack were empty.
- ↑ The content of the register will not be lost.
- ↑ Original description just says to stop execution.
- ↑ 12.0 12.1 12.2 12.3 12.4 If the stack has less than two values, nothing happens.
- ↑ 13.0 13.1 The program would result in an error if top value were 0, according to pxem.h of pxemi.7z, the original interpreter.
Examples
Hello, world!
To output Hello, world!, the filename should be:
Hello, world!.pxe
while the contents of file is arbitrary.
Other example
This alternative example is efficient if you prefer not to use symbols other than period and hyphen. This program outputs a newline, too.
Hello.pAa.-Am.-.pworld.pak.-Ab.-.pxe
Echo (or cat program in exact)
- Filename
1.w.o.i.c12.-.+.a.s.pxe
- File Contents
- (none)
Ultimate problem
- Filename
42.pxe
- File Contents
- (none)
delete last line
- Filename
- 1.w.i.c12.-.+.a1.zak.-.a.v.pxe
- File Contents
- (none)
FizzBuzz
- Filename
ak.-akbuzz.-ak4.-akfizz.-ak2.-1.p05.-.tab.z01.-.c.m.+.c.t05.-.%.w.s01.-.m03.-.%.W.s.m.nak.-.p00.-.c.c.c.a.wak.-fizz.p00.-.c.c.a.a.w01.-.m03.-.%.w.sak.-buzz.p00.-.c.c.a.wak.-fizzbuzz.p00.-.c.a.a.md2.-02.-.!.a.d.pxe
- File Contents
- (none)
Prints 10 one-digit random numbers
- Filename
ak.-.z.tak.-.c.r.n.p.m01.-.-.c00.-.a.pxe
Implementations
By original designer
pxemi.exe (original)
Original author used to publish its interpreter named "pxemi.exe", which was developed in C++ and would work on Windows only.
Lost code generator
On original page there used to be a code generator, which seems to be lost.
pxemi.7z
After ten years, its original interpreter got published again on original author's blog[2]. In this page the interpreter is distributed as pxemi.7z, zipping two files pxem.h and pxemInterpreter.cpp.
Bug
As on January 1st, 2020, the header file pxem.h has a following bug:
inline void Pxem::copy()
— a method for command.c
— is missing the procedure for an empty stack; the specification supposes the command works like an NOP in the case, but the actual implementation is missing the part.
text2pxem.pl
There's also a simple supportive kit text2pxem.pl. It compiles a text file into Pxem code file and emulates with text file. The usage is:
- Put pxemi.exe[4] and text2pxem.pl in the same directory.
- Make a text file with any name (name does not matter).
- Write filename first. You can separate into lines. You put any horizontal tab characters at the beginning of a line, they are ignored. You put a tab in the end, you can write a comment followed by the character.
- If you'd like to write content of the file, you have to put one line of
__EOF__
to imply the end of filename. Then following contents are recognized as contents. - Run text2pxem.pl with following arguments:
- 1st argument must be filename for text file you made. With no 2nd argument, it compiles into Pxem file.
- You specify 2nd argument
-e
, it does not only compile, but also execute with the file.
- Usage example
-
- Your file
n4-).- mk ':-)' ak.- mk '\n' n4-.- mk ':-' ak.- mk '\n' n4.-.p mk ':' 01.-.t mk 0 and toreg .z loop A n4-).- mk ':-)' ak.- mk '\n' .p print .m fromreg .e exec file .v.s.v delete flag .p print .m fromreg 12.-.+ mk 1 and add .t toreg .m .a end loop A .d.pxe __EOF__ .t toreg .z loop B 01)).-.m.-.t 00.-.m .a end loop B
This file[2], for example, generates a file named n4-).-ak.-n4-.-ak.-n4.-.p01.-.t.zn4-).-ak.-.p.m.e.v.s.v.p.m12.-.+.t .m.a.d.pxe
, with content .t.z01)).-.m.-.t00.-.m.a
.
- Using the tool
txt2pxem.pl filename
- Just a compilation.
txt2pxem.pl filename -e
- Not only compilation, but also execution.
- You must put an
-e
exactly on the second argument.
By the way you have to replace every \r\n
into \n
if you're running text2pxem.pl on non-Windows environments.
Others
As on September 2018, there are three repositories for interpreter-development, which are on #External Links.
Turing-completeness
"nk." originally predicted Pxem is not Turing-complete because Pxem has no built-in command for "swap" operation of the stack[2].
In May 2020, several proofs of Turing-completeness of Pxem gets published on a personal blog [5].
External Links
- Original description page (Japanese) (from the Wayback Machine; retrieved on 5 June 2012)
- The blog by original author (Japanese) ― Original interpreter source (and supportive tools) available! (Stated to be licensed under WTFPL)
- Pxemでネギを振ってみた - NicoNico Video ― The only video to try running Pxem.(Japanese)
- wktk/rpxem ― The interpreter developed in Ruby. Some commands (
.d
and some) doesn't work properly.- wktk's blog ― Two programs are shown. One is to output whether the number is prime number or not and the other one is to calculate the factorial.
- rhwckl/pxem ― The compiler-time interpreter developed in C++. Two libraries:Boost and Sprout are necessary in order to compiler. The syntax is modified.
- GH-TpaeFawzen/Pxem2Cplusplus11 — Implemented in Bourne shell. Translates into C++11 program.
References
- ↑ 2.0 2.1 2.2 2.3 2.4 2.5 2.6 Pxemの思い出 — ビビビッ (Vivid Bit) (Japanese).
- ↑ No reliable sources about this origin known, as of 2019/08/04.
- ↑ It implies that interpreter's name must be "pxemi.exe". It seems that you have to change
pxemi.exe
of the file into appropriate name. - ↑ Minimalization of Pxem — Acid Forums.