This language and its specification is still being developed by Darkrifts (talk), suggestions are welcome and appreciated. The language is "compiled" into an obfuscated set of characters and "decompiled" into regular text before being interpreted as plaintext (running as if used in the FOS shell command line), along with an alternate option of simply interpreting a file that hasn't been pseudocompiled yet. [NOTE: A DR ("Direct Run") app has LESS functionality than a pseudocompiled one, as only pseudocompiled programs have access to the if statements]
FOSC has an interesting way of passing command line arguments. As you cannot pass arguments when running a program, you have to get memory in there somehow for interesting programs, which is where the interesting properties of the stack and queue come into play (more on this lower down).
- repeat <text> - ALL text after the repeat statement in a line is outputted with a following newline.
- exit - End the current program and return control to the program that called it (or the FOS shell if invoked on the highest level)
- begin <programName> - Starts the program <programName>. To add parameters, include them after the program name. This does NOT begin a FOSC program, due to strange compilation only readable by the FOS shell.
- fosr <FOSCProgramName> - Starts the FOSC progam specified. No arguments can be specified. Control returns to the original program after running.
- fosr-x <FOS-XProgramName> Starts the FOS-X program specified. Same argument scheme as fosr.
- calc-r <CalcutapeProgramName> - Runs the specified calcutape program. Control returns to the original program after running. ? operations return control immediately.
- clear - Clears the shell's screen.
- push <number1 <number2 <...numberN>>> - For each integer number found after the push statement (space separated), it is pushed onto the stack object.
- pop <OPTIONAL: numberToPop> - Pops a number off of the stack and throws it away. Adding an optional integer argument pops that number of numbers off the stack. All numbers popped are outputted, with NO newline added.
- drop - Pops a number off of the stack and throws it away. No optional arguments or outputting of numbers.
- swap - Swaps the position of the top 2 elements of the stack. S1 = S2, S2 = S1.
- double - Duplicates the item at the top of the stack.
- s-q - Moves the item on top of the stack to the back of the queue
- in-s - Gets a single character input into the stack as an ASCII value
- pop-a <numToPop> - Outputs the number (<numToPop>) of numbers at the top of the stack as characters. No automatic newlines.
- nullstack - Resets the stack.
- enqueue <number1 <number2 <...numberN>>> - For each integer number found after the enqueue statement (space separated), it is added to the queue object.
- dequeue <OPTIONAL: numberToDequeue> - Dequeues a number off of the queue and throws it away. The optional argument specifies how many numbers to dequeue. All dequeued numbers are outputted, with NO automatic newlines.
- forget - Dequeues a numbber off of the queue and throws it away. No optional arguments or outputting of numbers.
- requeue - Take the item at the front of the queue and moves it to the back
- q-s - Takes the item from the front of the queue and moves it to the top of the stack.
- in-q - Gets a single character input into the queue as an ASCII value
- dequeue-a <numToDequeue> - Outputs the number of numbers at the front of the queue as characters. No automatic newlines.
- nullqueue - Resets the queue.
The "mem" register
Allows you to store a single value in a separate register. The mem register is recommended to be automatically initialized to 0 in inplementations (such as interpreters to allow working without the FOS system), but is not required by the standard.
- mem-set <arbitraryNumber> - Sets the mem register to a given number.
- mem<stack - Sets the mem register to the top value of the stack, popping it.
- mem<queue - Dequeues a number and sets the mem register to it.
- mem>stack - Pushes the mem register, saving the value.
- mem>queue - Enqueues the mem register, saving the value.
- mem-inc - Increments the mem register.
- mem-dec - Decrements the mem register.
- mem-sqr - Squares the mem register. Note, there is no square root built-in function.
Math in FOSC is done by using a prefix from the list of "add", "sub", "mult", or "div" and a postfix of "-s" for stack or "-q" for queue. Example "add-s" adds from the stack. Calculations are done by performing the specified operation on the first 2 values in the respective object, and pushing/enqueuing the result (removing the previous values in the process). There is no "-m" postfix for the memory register.
- if-s <linesToSkip> <numsToCheck> - Check the top value of the stack for the values specified. More than one integer (separated by spaces) can be specified in <numsToCheck>. Each number to check pops a new value off the stack and does NOT replace it. If all values (in order) are in the stack, it jumps forward <linesToSkip> lines.
- if-q <linesToSkip> <numsToCheck> - Same as if-s, but checking the start of the queue instead. Behavior works as you would expect from the queue.
- if-m <linesToSkip> <numToCheckFor> - Skips <linesToSkip> lines if the mem register is the number you provide as <numToCheckFor>. Only 3 arguments in this function.
- wait-s/wait-q/wait-m - Obtains a value from the specified register (popping/dequeing if s/q respectively) and waits for that many milliseconds.
- calc <calcutapeToEmbed> - Allows you to embed Calcutape into your application. A ? operation in embedded Calcutape returns control to the FOSCode being run and goes on. The stack is preserved entering and leaving Calcutape code.
- Comments - A comment is notated as a line started with the statement IGNORE.
- open-r <fileName> - Opens file <fileName> to be read from.
- open-w <fileName> - Opens file <fileName> to be written to.
- read-s - Reads the current character (as an ASCII value) to the stack. Moves the character pointer forward 1 character.
- read-q - Reads the current character (as an ASCII value) to the stack. Moves the character pointer forward 1 character.
- write-s - Writes a character to the current file from the stack (pops a value).
- write-q - Writes a character to the current file from the stack (dequeues a value).
- close-r - Closes the current file reading operation. (Automatically done before opening another file)
- close-w - Closes the current file writing operation. (Automatically done before opening another file)
If you attempt to pop or dequeue a number from an empty register, it returns as -1, but it doesn't make a visible error message. If you push to a full queue or stack (somewhat hard, as they can hold a large amount of numbers.) it won't store the value, so you may wish to invoke a nullstack or nullqueue operation at the start, if you don't need arguments.
There is no set way to define functions in FOSCode. One suggested way is to use if-s statements and push some value you check for right before calling. Another suggested way is to use separate programs and run them with a fosr command (as control is returned to the original program afterwards) or a calc/calc-r statement if it can be made in Calcutape (calc is more memory efficient than calc-r for obvious reasons.=).
Arguments are not specified in the typical way. The stack, queue, and mem registers you can modify with FOSC have an interesting property, they DONT clear all data in them after a program terminates or before one starts. This means a program can have arguments defined by calling push, mem-set, or enqueue before running a program or within a program before calling it. This is somewhat similar to how arguments are passed in assembly functions.
FOSCode is designed to be a low-level (but human readable even by people who are newbies to programming) language to develop on the FOS system (Currently in development, but this was released early to allow anyone who cares to already start working.).
FOSCode, being the lowest-level language for developing in for the FOS system (other than pseudocompiled FOSCode/Calcutape or FOS-X standard compiled code), it requires the most effort to do certain things, but has the most direct control of the stack and queue. As the language is currently in development (as are higher-level ones), some features may change, so don't forget to check back every once in a while to make sure you're visualizing the mechanics right. If you know how to use Calcutape, it is possible to develop FOS applications in it as well (Definitely be impressed to see someone make a Calcutape interpreter in FOSCode once File I/O syntax has been decided upon).
A simple Cat program (Input to output)
IGNORE This is an infinite cat program, and this comment is necessary for -5 jump in-s pop-a push 1 if-s -5 1
A "Hello, World! program
IGNORE repeat statements don't require quotes, as quotes will be output if they're there repeat Hello, World!
Numpad press -> Number program
IGNORE Turns a number key press into the respective number in-s push 48 swap sub-s IGNORE This leaves the number at the top of the stack, can also be done like... in-s push -48 add-s
IGNORE Required comment for line count. Never ends push 1 if-s -2 1
IGNORE This creates an annoying BEEP sound. Muting speakers won't stop it push 7 pop-a IGNORE This can be made into something evil in the following way push 7 pop-a push 1 if-s -5 1 IGNORE Causes beeping for as long as the FOS shell window is open
IGNORE This causes an event to happen an arbitrary amount of times. IGNORE Change how many times by changing the number of values pushed push 1 1 1 1 1 1 IGNORE Put arbitrary code here if-s <arbitraryNegativeNumber> 1 IGNORE Just change that value to jump to the start of the commands again. When it no longer IGNORE has 1's, it'll leave you with N+1 less values, where N is the number of times you loop
Compiling to be readable by the FOS system is easy. Just pick some random number from 3 to 20,000, write it to a file in binary form, and translate each character to its ASCII value multiplied by that "seed" number. In translating the characters, remember to keep new lines and translate their values too. Easy to compile, but makes it harder to read by just looking at it. If you really want to protect your data, compile it to FOS-X.