Whitespacers

Implementation of programming language Whitespace

Whitespacers is a collection of Whitespace interpreters, collected from various sources over Internet. It contains interpreters written in C, C++, Haskell, Perl, Python, Rebol, Ruby and Whitespace itself. The interpreters are not equivalent: some of them run certain examples perfectly while others fail with various errors.

Examples:

Hello, World!:

Example for versions Whitespacers (Ruby)

This code is commented to simplify understanding it: letter means that next piece of whitespace pushes on the stack ASCII-code of this letter, and print means invoking the command of printing topmost element of the stack. The numbers that correspond to ASCII-codes are contained within brackets (except for the delimiting newline which is outside of the brackets for readability).

H  { 	  	   }
print	
  e  { 		  	 	}
print	
  l  { 		 		  }
print	
  l  { 		 		  }
print	
  o  { 		 				}
print	
  ,  { 	 		  }
print	
  space  { 	     }
print	
  W  { 	 	 			}
print	
  o  { 		 				}
print	
  r  { 			  	 }
print	
  l  { 		 		  }
print	
  d  { 		  	  }
print	
  !  { 	    	}
print	
  \n  { 	 	 }
print	
  


end

Factorial:

Example for versions Whitespacers (Ruby)

This example uses a slightly different method of commenting — each command is preceded with its literal description. Numbers and labels are enclosed in brackets.

The example works as follows: heap is used to store variables (1 — index of the first factorial which doesn’t need to be calculated, 2..5 — ASCII-codes of special characters used in printing, 6 and 7 — current number and its factorial), and stack is used to run commands). Factorial is calculated iteratively, on each iteration previously calculated values are printed, and new ones are calculated and stored to memory. After this, the newly calculated number is compared with contents of cell 1: if it is less, the loop continues, otherwise it halts.

A curious thing to note is that in Whitespace numeric system zero is “negative”: a number must have at least one Tab in its notation, and binary notation of zero has no 1s, so it has to be written as Tab (only sign bit).

push_1  { 	}
push_17  { 	   	}
store		 push_2  { 	 }
push_33  { 	    	}
store		 push_3  { 		}
push_32  { 	     }
store		 push_4  { 	  }
push_61  { 				 	}
store		 push_5  { 	 	}
push_10  { 	 	 }
store		 push_6  { 		 }
push_0  {	 }
store		 push_7  { 			}
push_1  { 	}
store		 label
  { }
printing_block_push_6  { 		 }
retrieve			print_as_number	
 	push_2  { 	 }
retrieve			print_as_char	
  push_3  { 		}
retrieve			print_as_char	
  push_4  { 	  }
retrieve			print_as_char	
  push_3  { 		}
retrieve			print_as_char	
  push_7  { 			}
retrieve			print_as_number	
 	push_5  { 	 	}
retrieve			print_as_char	
  increase_counter_block_push_6  { 		 }
push_6  { 		 }
retrieve			push_1  { 	}
add	   store		 calculate_next_factorial_block_push_7  { 			}
push_7  { 			}
retrieve			push_6  { 		 }
retrieve			multiply	  
store		 conditional_return_block_push_6  { 		 }
retrieve			push_1  { 	}
retrieve			subtract	  	jump_if_negative
		{ }
quit


end

Fibonacci numbers:

Example for versions Whitespacers (Ruby)

This example is similar to factorial one, except for that it makes more use of stack data storage and duplicate command to avoid extra readings from memory cells. Also, in this case the counter is negative and increased at each iteration, as opposed to positive and compared to fixed number of iterations.

push_1  { 	}
push_-16  {		    }
store		 push_2  { 	 }
push_44  { 	 		  }
store		 push_3  { 		}
push_32  { 	     }
store		 push_4  { 	  }
push_0  {	 }
store		 push_5  { 	 	}
push_1  { 	}
store		 label
  { }
start_loop_push_5  { 	 	}
push_4  { 	  }
retrieve			push_4  { 	  }
duplicate 
 push_5  { 	 	}
retrieve			duplicate 
 print_as_number	
 	push_2  { 	 }
retrieve			print_as_char	
  push_3  { 		}
retrieve			print_as_char	
  store		 retrieve			add	   store		 push_1  { 	}
duplicate 
 duplicate 
 duplicate 
 retrieve			add	   store		 retrieve			jump_if_negative
		{ }
push_10  { 	 	 }
push_46  { 	 			 }
duplicate 
 duplicate 
 print_as_char	
  print_as_char	
  print_as_char	
  print_as_char	
  quit


end

CamelCase:

Example for versions Whitespacers (Ruby)
push-1  { 	}
push-1  { 	}
save		 LOOP-START.label-0
  { }
push-2  { 	 }
readchar	
	 push-2  { 	 }
load			CHECK-WHETHER-IS-EOL.duplicate 
 push-10  { 	 	 }
subtract	  	if-0-goto-1
	 {	}
CONVERT-TO-LOWERCASE.duplicate 
 push-A  { 	     	}
subtract	  	if-neg-goto-2
		{	 }
duplicate 
 push-Z  { 	 		 	 }
swap 
	subtract	  	if-neg-goto-2
		{	 }
push-32  { 	     }
add	   label-2
  {	 }
CHECK-WHETHER-IS-LETTER.duplicate 
 push-a  { 		    	}
subtract	  	if-neg-goto-3
		{		}
duplicate 
 push-z  { 				 	 }
swap 
	subtract	  	if-neg-goto-3
		{		}
ACTION-IF-LETTER.CHECK-WHETHER-LAST-WAS-SPACE.push-1  { 	}
load			if-0-goto-4
	 {	  }
push-32  { 	     }
subtract	  	label-4
  {	  }
print	
  push-1  { 	}
push-0  {	 }
save		 goto-0
 
{ }
label-3
  {		}
ACTION-IF-NOT-LETTER.push-1  { 	}
push-1  { 	}
save		 goto-0
 
{ }
label-1
  {	}
push-10  { 	 	 }
print	
  


end.memory:1-was-last-space,2-currentchar