ForWhile

From Esolang
Jump to navigation Jump to search

ForWhile is a minimalistic stack based Language created by User:Bsoelch.

The language is named after its main control flow structure the "For-While" loop

Syntax

  • Integer literals:

Any sequence of digits is interpreted as a decimal (64bit) integer and pushed onto the stack

For example 1234 5678 will push the two numbers 1234 and 5678 on the stack.

  • String literals:

String literals use the usual "string literal" syntax, \ can be used to escape quotation marks. A string literal will push all its characters (in the order they appear) onto the stack, followed by the length of the string, for example "Hello" will push 72 101 108 108 111 5

  • Comments:

\ comments out the rest of the line

\\\ starts/ends a block comment

  • For-While blocks:

A matching pair of() defines a for-while block, for while blocks are a mix for a for-loop and a do-while loop.

( (for) pops an integer from the stack and remembers it as the loop counter, if the loop-counter is less than one the program will jump after the matching ) Each iteration of the loop the current loop-counter will be pushed on top of the stack.

) (while) pops an integer form the stack if it is non-zero the loop-counter is decremented and if the loop-counter is greater than zero the program pointer will jump back to the matching (.

  • Operations:
Op Description
[ start of if-block: jumps to matching ] if top stack value is zero
] end of if-block
. pops the top element on the stack
: duplicates the top stack element
; copies the second value on the stack above the top value ( A B C -> A B C B )
' swaps the top two stack elements
, rotates the stack, see below

stack rotation: reads the top stack element (n), if it is positive the top n elements will be rotated down by one, if it is negative the top |n| elements will be rotated up by one. Examples:

 A B C D 3   ->   A C D B
 A B C D E -4   ->   A E B C D
Op Description
@ replaces the top stack element with the value at the corresponding memory location
$ stores the second value on the stack at the memory address given by the top stack value
# prints the lowest byte of the top stack value, keeps the value on the stack
_ reads one byte from standard input
+-*/% binary arithmetic operators on top two stack elements (the top stack value is the right operand)
` integer power (if the top two stack elements are A and B this will push AB
&|^ bit-wise logical operations
<=> compare top two stack elements, pushes 1 if comparison is true 0 otherwise (the top stack value is the right operand)
'<'> (logical) bit-shift
! checks if top stack value is zero, pushes 1 if comparison is true 0 otherwise
~ flip all bits in top stack element
~~ negate top stack element
  • Procedures

{ } defines a procedure, during normal program execution the code between { and } is skipped and the address of the first instruction within the procedure is pushed on top of the stack.

? sets the instruction pointer to the value on top of the stack and remembers the current position on the call stack, the program returns to this position when a the next } is reached.

Each call increases the recursion depth by one (and returning from a procedure decreases it again). If the maximum recursion depth (3 by default) is reached ? will not modify the instruction pointer.

Memory

The program memory is an unbounded array of integers (one cell for every possible value of an integer).

The original C-interpreter is limited to 64-bit integers, while the JavaScript version allows unbounded integers both as values and addresses.

  • The programs source code is stored at the memory addresses from -1 going downwards (first character at address -1, next at -2 ...) when executing the program the instruction pointer is decremented after each instruction, the instructions are read directly from this memory section, allowing modification of the source code at runtime.
  • Positive memory addresses can be used without impacting the program behaviour

Examples

Hello World:

 "Hello World!"(,#)

Print Fibonacci Numbers less than 1000:

 {0:![64(.;10%48+;2+~,1+'10/';)]'.(,#)10#.}0$     \ print positive int (with newline)
 1000 :(;'-1'0'(.;+'1).;;>:['0@?])

Test if a numbers is Prime:

 {0;1+(.;10%"0".+;2+~,1+'10/';)'.(,#)}0$          \ print positive int (without newline)
 {1;(.1+;;%)=}1$                                  \ short prime test
 {:2%::[.;;*1]![2'](.2+;;%:[.;;:*<:[..::]!])=}2$  \ faster prime test
 
 17 : 0@? 1@? 3@?
 42 : 0@? 1@? 3@?
 124443693149 : 0@? 2@? 3@?
 1234567 : 0@? 2@? 3@?

Print prime factors of number:

 {0;1+(.;10%"0".+;2+~,1+'10/';)'.(,#)10#.}0$      \ print positive int (with newline)
 
 {:(.:2%!:[.2/2';])1;(.2+;(.;;%!:[.:0@?';/':1=!]);;:*>).:1=[.]}3$
 12345678987654321 3@?

Quine (reads source code from program memory):

 0~100(.:@#.1-:@).

Count up forever:

 (!;$1-:){}9+:66(.:@;66-$1-:).9@1+:0;(.;10%48+'1+3,10/';)+(.#)9#$66

explanation

 \ ignored in first iteration
 (!;$1-:)
 \ push current instruction pointer, offset it to point at the start of the current code-section
         {}9+
 \ copy the code to the address immediately after the current source-code 
             :66(.:@;66-$1-:).
 \ load the value at address 9 (counter) and increment it
                              9@1+
 \ print the counter converted to a decimal string
                                  :0;(.;10%48+'1+3,10/';)+(.#)
 \ print a tab and store the new value of the counter at address 9
                                                              9#$
 \ push the length of the code
                                                                 66
 \ clear the previous code-section
 (!;$1-:)                                                            
 ...

Truth machine:

 _:49=[34(!;$1-]{}10+:34[:@;34-$1-:)49#$.]#

works similarly to the infinite counter

Computational class

By design all loops in ForWhile have a finite number of iterations (given by the loop counter) and recursion is limited to a finite depth (3 by default) so any program that uses only positive memory addresses is guaranteed to terminate.

Using self-modification it is possible to create a single infinite loops by continuously adding code to the left of the instruction pointer.

External resources