FOS-X

From Esolang
Jump to navigation Jump to search
This is still a work in progress. It may be changed in the future.

This is a standard for developing for the FOS system so you can create compilers for other languages to develop with. This is developed by Darkrifts (talk) and is currently a work in progress. Supply suggestions in the talk page.

Documentation

Documentation for each command will follow the design <value> - <operation> with hexadecimal values, from 00 - FF
All values are stored as bytes, written to a file with each byte written as a character.
Any value not documented is assumed to be a NOP and is ignored. There is no comment notation, short of writing a program to never execute a section.

00 - No operation. Useful for alignment and 1D/1E operations
01 - Push 1 onto the stack
02 - Enqueue 1
03 - Set mem to 0
04 - Increment the top of the stack
05 - Decrement the top of the stack
06 - Square the top of the stack
07 - Increment the front of the queue (pushes to the back)
08 - Decrement front of queue (pushes to the back)
09 - Square front of queue (pushes to the back)
0A - Move the top of the stack to the mem register (pops)
0B - Move the front of the queue to mem (dequeues)
0C - Push mem onto the stack
0D - Enqueue mem
0E - Increment mem
0F - Decrement mem
10 - Square mem
11 - If the top of the stack is less than the second number, skip an instruction (pops)
12 - Above but with the queue (dequeues)
13 - Jump forward N operations. N = top of stack (pops)
14 - Above but front of queue (dequeues)
15 - Pop a value and discard it. 
16 - Dequeue a value and discard it. 
17 - Pops a value and output it
18 - Dequeue a value and output it
19 - Pop a value and output as character. 
1A - Dequeue value and output as character. 
1B - If the top of the stack is greater than the second number, skip an instruction (pops)
1C - Above but with queue (dequeues)
1D - Change operation A (position) to B (byte value). A = top of stack, B = second in stack. Cannot append instructions to end of file. Must change instruction present in code. Use 00 (NOP) to help align values.
1E - Same as above, but with queue
1F - Pop a value off the stack and wait that many milliseconds
20 - Above with queue
21 - Wait for a key press and push the result as an ASCII value. Doesn't show
22 - Above with queue
23 - Exit program and return control to caller
24 - Pops N characters off the stack and combines them into a string and calls that file as a FOS-X program. N = top of stack
25 - Above with queue
26 - Pops N characters off the stack and combines them into a string and calls that file as a FOSCode program. N = top of stack
27 - Above with queue
28 - Pops N characters off the stack and combines them into a string and calls that file as a .exe program. Arguments are passed by spaces. N = top of stack
29 - Above with queue
2A - Reset stack
2B - Reset queue
2C - If A = B, skip one instruction. A = top of stack, B = second in stack
2D - Above with queue
2E - Jump to instruction N. N = top of stack
2F - Above with queue
30 - Invert direction (Allows for reverse code execution)
31 - Set mem to a random number from A to B. A = top of stack, B = second in stack
32 - Above with queue
33 - Send the front of the queue to the back with no change
34 - Duplicate the top value of the stack
35 - Above with queue (new copy pushed to back, original still in front)
36 - Swap top of stack with second in stack
37 - Add top 2 values of stack together and pushes the result (pops)
38 - Above with queue
39 - Subtract top 2 values of stack and push the result. Top - 2nd. (Pops)
3A - Above with queue
3B - Multiply top 2 values of stack & pushes result. (pops)
3C - Above with queue
3D - Divide top 2 values of stack & pushes result. Top / 2nd. (pops)
3E - Above with queue
3F - Modulo top 2 values of stack & pushes result. Top mod 2nd. (pops)
40 - Above with queue
41 - Pushes the program's length
42 - Above with queue
43 - Push byte N of the program. N = value of mem register. 1-indexed (first byte is accessed by 1, not 0)
44 - Above with queue
45 - Pop N numbers off the stack, concatenates them together into a string (based on ASCII values), and opens that file for reading. N = top of stack.
46 - Above with queue
47 - Same as 44, but for writing instead.
48 - Above with queue
49 - Write a value from the mem register as an ASCII character to the writing file currently open
4A - Read a character from the current reading file to the mem register. -1 means end of file has been reached.
4B - Close current reading file. (Auto invoked when opening a new file, but should be done anyway)
4C - Close current writing file. (Auto invoked when opening a new file, but should be done anyway)
4D - Accesses value N from the stack and pushes it to the front (leaves a copy where it was). N = value of mem
4E - Above, but with queue
4F - Moves forward 1 command, saves its value to the mem register, and does not perform that command's operation. 4F 03 OC pushes the value 3 to the stack, for example
50 - Clear the output screen
More coming later

The stack, queue, and mem registers don't have to be of a specific size, though there must be 1 stack, 1 queue, and 1 single value register. In the FOS, the stack is of 2^16 32bit integers, the queue is of 2^16 32bit integers, and the mem is a 32bit integer.

Storing more values

Since you only have 1 register, 1 stack, and 1 queue, it can be difficult to do some things.
One potential solution is to store data as bytes in the program with 1D/1E, or to access the stack/queue with 4D/4E. The problem with the first is the potential to execute arbitrary commands (which may be what you want to do).
It could be used to create an array by having an unreachable NOP (00) section and rewriting values there, with the indexer having some value added to it to read certain bytes. One problem is writing outside of such a dedicated memory section and potentially corrupt the program (Runtime byte changing does not persist after restarting a program), such as turning a random operation to a 23 (Exit) operation.

Unexpected behavior

Popping a value from an empty stack/queue returns -1. This can cause some operations to fill the stack with -1 values. Pushing/enqueueing to a full structure doesn't write a value. Stack, queue, and mem is preserved across applications, so you may wish to reset them before beginning an app.
The instruction pointer moves 1 in the current direction AFTER jumps ( i.e. -1 relative reruns the jump operation. To start operation from the beginning, jump to 0, which would be 00. To go back N steps, jump -(N+1) steps). Jumping negative absolute jumps (2E/2F) jumps to 0, which starts execution at 1.
In getting bytes from the source code, it is 1-indexed, but 0-indexed when jumping and when changing bytes in the source code.

Sample programs/functions

This will use values to represent operations.
"hello" program. No comma or punctuation of any kind

68 65 6C 6C 6F 03 0E 43 19 0E 43 19 0E 43 19 0E 43 19 0E 43 19
Length: 21 bytes

Cat program

21 19
Length: 2 bytes

Truth-machine

This checks for the press of the 1 key on the keyboard as input for 1. All else assumed 0. 
01 05 05 05 05 05 4F 31 21 2C 23 01 17 34 13
Length: 15 characters

Compiling

This part is up to whatever you're compiling to FOS-X, as it is less of a true language and more like machine code readable by the FOS system.
All byte values have their character representations written onto the file, which is later read and interpreted. An official direct FOS-X IDE that turns hex values as text (like "24") into their counterparts and allows for interpretation on the spot is currently in the works.

Reductions from other languages

FOS-X is designed to allow other languages to be ported down to it.
Rulesets are defined like "<originalValue>: <replacementValues>", with special symbols "begin" meaning to prepend a series of bytes, and "end" to append a series of bytes.

Deadfish

Note: Does not wrap to 0 at 256 and -1. Creation of an interpreter for an arbitrary Deadfish program with FOS-X is possible though, including wrapping.

'i': 0E
'd': 0F
's': 10
'o': 0C 17
begin: 03
end: 03 (Recommended for memory to be reset each time. Not required)

Calcutape

'0': 01 05
'1': 01
'2': 01 04
'3': 01 04 04
'4': 01 04 06
'5': 4E 05 0C
'6': 4E 06 0C
'7': 4E 07 0C
'8': 43 08 0C
'9': 4E 09 0C
'+': 37
'-': 39
'*': 3B
'/': 3D
':': 4E 64 4E 0A 3B 01 31 0C (Changes mem, but not used in Calcutape)
'%': 17
'@': 19
'|': 36
'_': 34
'&': 4D
'^': 1F
'=': 50
'?': 23
'V': 21
'#': Not gonna even try to reduce this one. Should involve 30, 1B, 2C (probably), and 13. Good luck. I'd recommend forgetting about reversing, and just use 01 05 11 13 (01 05 11 to check if negative/ is 0)