Tutorial - TehFlaminTaco/RProgN-2 GitHub Wiki
To Install RProgN2, simply download the file "RProgN_vVERSION.jar", and save it somewhere convenient.
Ensure Java 8 is installed.
Run your scripts through the command-line by calling java -jar RProgN_vVERSION.jar <target> [, <arguments>]
Flags can be added in the arguments in the form --d
. Valid flags are:
-
--d
: Output a breakdown of the code to STDERR -
--b
: Output the current bytemap, and which functions are mapped to them, to STDERR. -
--t
: Output the time it took to execute to STDERR
Programs are to be written in Win-1252 (Rather than UTF-8). Most text editors have an option to change encoding.
Alternatively, you can run your scripts online through Try it Online
Before execution, RProgN2 compiles the input script into what's referred to as a "Concept Array". This chunks up the script, so the interpreter can read it much faster, and doesn't need to guess anything else.
A concept is a chunk that should be executed as a single part, for example, "Hello, World"
is a single concept, as is +
, however, {<some commands>}
is many concepts, {
and }
is one each.
The rules for splitting concepts are fairly simple:
- Group up all strings, That is,
"string"
and'string'
. - Group up all
$
s followed by numbers. - Group up all
`
s and their following character. EG,`a
- Group up all
#
s and their following character. - Otherwise, each character is its own concept.
After compiling, the program runs left to right across the Concept Array, and attempts to call each concept as a function. The rules for determining the function to call are:
- Is this concept a string? ("" or '' wrapped)? Use a function that pushes that string.
- Is this concept defined in the current scope? Use that.
- Is this defined in it's parent's scope?
- And so on with scopes...
- Is this defined in the default functions?
- Is this formatted like a number? If so, use a function that pushes the value of that number.
- Is the first character of this a
`
? If so, use a function that pushes a string representing the rest of this. Useful for single character literals. - Is the first character a
#
? Use a function that pushes the function that the rest of this represents. EG.#+
pushes the function+
, as it is now, to the stack. - Is the first character a
$
? Use a function that pushes the rest of this as a number. - Is this wrapped in "" or ''? Use a function that pushes the inner contents as a string. Note, this is different to the first rule, as this happens after compiling, a concept generated otherwise may not be correctly identified as a string.
There are 4 types of variables, which can generally be used interchangeably without any problem, they are:
- Number
- String
- Stack
- Function (Concept Array, Callable)
Numbers are arbitrary precision decimals, that is, decimals of any finite size. Feel free to do math in the scale of 1e300. Strings are character arrays. Nothing fancy there. Stacks are by-reference modifiable variables that store other variables in a FIFO stack. When something outputs a stack, double check which way it's facing, it's never obvious. Functions are things that can be called to execute a subroutine. Sometimes they're internal, some times their Concept Arrays, aka, defined by the user.
The program has two ways to store memory, a stack and an associative array.
The first, "The Stack", also known as "The Registry Stack" is where most of the fun occurs.
The second is, "The Memory", or "The Scope", (even though both these things are technically the memory), this is a Map of strings to functions, and it's where you want to put user-defined functions to call them later. You can put any variable on this however, and if it isn't a callable, it will turn it into one, by wrapping it in a function{push(x)}
. As the name suggests, this is scoping, but only in one very particular case.
Programs are post-fix, in the style of Reverse Polish Notation and GolfScript. Eg, 4+5
can be written as 4 5 +
TIO, and (1+3)*2
can be written as 213+*
TIO. Let's take a closer look at this case.
Firstly, numbers are pushed individually, so the stack looks like 2 1 3
. Then, +
is executed, which takes the top two values of the stack, and adds them together. Now the stack looks like 2 4
. Lastly, *
is executed, which multiplies the top two values of the stack, which gives us 8
, our output.
Assigning variables is rather easy, as it's a single function. =
will take the string on top of the stack, and the variable underneath it, and assign the variable to the string. Then, when a concept tries to call for a function with that string, the variable is called instead. In the case of everything that isn't a function, this will wrap it in a function. TIO
Stack control is very important if you don't want to have to keep assigning and reassigning variables to do anything useful. There are 3 main functions behind controlling this. [
, ]
and \
.
-
[
pops the top value of the stack and does nothing with it. Useful for removing unnecessary values. -
]
duplicates the top of the stack. -
\
swaps the top two elements of the stack.
All flow of control is handled through defining functions, and executing other functions on them. Also, functions can generally be called later, by assigning it to the Memory.
{1+}
is a very basic function, which pushes 1
to the stack, and then runs +
, which pops the top two values of the stack, and adds them TIO. Functions like this take input and put output on the stack when called, just like calling any other function.
Flow of control is done by a group of functions that work on functions. The most prominent example is ?
, which is the Ternary/If Operator. The most basic usage of this is <Some variable>{truthy function}{falsey function}?
. This takes the variable, and if it's truthy, it executes "truthy function", otherwise, it executes "falsey function".
Functions in the form of {}
use the most global scope it has access to. This means, if you define a function {3`x=}
TIO, call it, and then call x
, x
will return 3
.
The other way to define functions is to use «»
, which define their own scope. Not only this, but they access the global scope as is at time of definition. Essentially, this means it can be called infinitely many times, and never remember anything. (Unless it has access to a stack). An example of this is:
«{7p}x=x»`x=xx
This monster of an expression prints 7
twice.
When «{7p}x=x»
is defined, x
is set to the default value, (Which is "x"
). So even though the function itself is defined as x
, and called with it, when it is called, it still sees x
as "x"
, which means we can define the function {7p}
as x
, and then call it with x
. After the first call, the global scope can't see the changes the function made to x
, so when it calls x
a second time, it still references the function. The function, when called again, doesn't see it's old mutated x
, and sees x
as "x"
again. Thus, it runs fresh.
These are not all the functions by a long shot. Your best bet for a complete list right now is to check the source code.
-
=
Assign a value / function to a string. -
\
Swap the top two values of the stack. -
]
Duplicate the top of the stack. -
[
Pop the top of the stack. -
{
Define a globally-scoped function to the next}
-
}
Halt execution of the current function/program. -
«
Define a locally-scoped function to the next»
-
»
Do literally nothing.
-
+
Calculate a + b. -
-
Calculate a - b. -
*
Calculate a × b. -
/
Calculate a / b. -
÷
Calculate a // b (Integer Division) -
^
Calculate a to the power of b -
%
Calculate a mod b
-
.
Concatenate a and b. -
s
Create a new stack. -
S
Convert to a stack. -
‘
Pop the top value of a stack. Does not leave a reference to the stack. -
’
Push a onto b. -
R
Create a stack of numbers from a to b -
c
Get the numeric representation of a character (Or characters) -
o
Get the ordinal representation of a number (Or numbers) -
r
Replace, accepts<stack><function>
, or<string><match><function>
, or `
-
?
Ternary if, accepts<value condition><function truthy><function falsey>
or<value condition><function truthy>
-
;
For, iterate through a list. Accepts<stack><function>
. Also accepts strings and numbers, for convenience. -
:
While. Pops a value, if it's truthy, executes the function, then repeats. Accepts<value><function>
-
C
Call a function. Works on strings.
These are just some possibly strange choices made by the language, all in the interest of brevity, of course.
- if
{
can't match a}
, the program moves back to index1
. This skips whatever the first instruction was. This will probably loop forever if not explicitly terminated, but makes for a really short Quine.{`{.}{
.{`{.}
Defines a function.{
can't pair, so it jumps back to index1
, skipping the function definition. ```{.`` then appends a{
to the function, which stringiness it, yielding a string representation of now the entire program, then `{` terminates. TIO - If
«
can't match a»
, then the rest of the function/program will be used for the body of a new function, and the program will continue executing from where it is.