1
0
www.mikescher.com/www/data/programs/desc/BefunGen/02_TextFunge/01_Language.markdown
2014-07-11 19:29:19 +02:00

9.7 KiB

TextFunge is the c-like language used for BefunGen.
Most constructs are very similar to C and Pascal, so you won't have trouble writing anything in it.

Note:
TexFunge programs are case-insensitive. (but please be consistent with your naming)

###Program structure

A TextFunge program starts with the keyword program and the program name and ends with end

program example_01 : display[0, 0]
	begin
		// code
	end
	
	void method()
	begin
		// code
	end
end

between programandend` you can put your methods. The first method has no header and is called the main method. This method is called upon the beginning and when this method has finished the program terminates.

You can specify a display by writing : display[width, height], if the display is not specified its has a width and height of zero.

###Types

TextFunge knows 9 different variable types:

  • Integer: A single integer value
  • Digit: A single Base-10 digit (integer in the range from 0 to 9 )
  • Character: A single character
  • Boolean: A boolean value (TRUE or FALSE)
  • Void: Nothing, used for methods that return nothing
  • Integer Array: An fixed-length array of multiple integer
  • String: An fixed-length array of multiple character
  • Digit Array: An fixed-length array of multiple digits
  • Boolean Array: An fixed-length array of multiple booleans
int a1;
integer a2;
int[4] a3;

char b1;
character b2;
character[4] b3; 

bool c1;
boolean c2;
bool[4] c3; 

digit d1;
digit[4] d2; 

You can freely cast all value types into each other and all array-types with the same length (see Casts for more information)

###Variables

Between each method header and the begin keyword you can specify local variables under the var keyword:

void method()
var
	int var_1, var_2;
	int var_3     := 77;
	int[4] var_4  := {0, 1, 1, 0};
	char[4] var_5 := "FFFF";
begin

These variables have a local scope and can't be accessed from anywhere else.

You can also at the beginning of the program specify variables with a global scope

program example_02
global
	int gvar_1, gvar_2;
	int gvar3;

Note:
Global variables (unlike local variables) can not have an initializer, they will initially have the value which you specified while compiling.

To access a variable as whole just write its name, to access an specific array index write the index in square brackets:

var_1[0] = var_2[4 + 1];

###Constants

At the same position as global variables can (global) constants be defined:

program example_02
const
	int VERSION := 14;
	int COL_BLUE := 0x0000FF;
	char UNDERSCORE := '_';

Be aware that constants are always in the compiled program inlined. So constants are only syntactical sugar and result in the same as writing the literal everywhere, where you use the constant.

Note:
You can only define constants for value types, array constants are not yet supported.

###Literals

You can specify (Base-10) integer literals by simply writing the number:

0
9283
-9283

And also Base-16 (Hexadecimal) integer literals with 0x

0x00
0xF0F
0x123

Digit literals have a # prefix:

#0
#6
#9

Char literals are surrounded by single ticks:

' '
'A'
'a'

Boolean literals consist of the two boolean keywords:

true
false
TRUE

String literals are surrounded by quotation marks: (Be aware that a string literal is only a shortcut notation of an char array)

""
"hello"
"hello \r\n second line"

And Array literals are the values inside of a set of curly braces:

{0, 1}
{'h', 'e', 'l', 'l', 'o'}
{true, false, true}

###Methods

Methods consist of 2 parts, the header and the body:

int[9] method(int a, int b, int[9] c)
var
	int var_1 := 0;
	int var_2;
begin
	// Code
	// Code
	// Code
	
	return c;
end

In the header you define the return type (value type, array type or void), the method name (the normal C naming restriction are valid) and the parameter list (multiple value or array types).

Then you can (optionally) define local variables.

And finally between begin and end you can write your code.

Note:
Every path of an method must result in an return statement.
If the return type is void the compiler can automatically add an return to the end.

###Control Structures

If / Elsif

if (a) then
	// Code [a == true]
elsif (b) then
	// Code [b == true]
elsif (c) then
	// Code [c == true]
else
	// Code [else]
end

You can write a branch statement with the keyword if.
Unlike C you have to write additional else if-branches with the keyword elsif and you have to end the whole block with end

While do

The while loop repeats a statement block until a condition is false

while (running) do
	// Code
end

Every loop the condition is evaluated and checked.

Repeat until

The repeat until loop repeats a statement block until a condition is true

while (running) do
	// Code
end

The difference to a while loop is that the condition is executed at least once.

For

The for loop is a more comfortable loop, because it has an initializer field, a condition field, and a statement field

//  (init ; cond  ; stmt)
for (i = 0; i < 10; i++ ) do
	// Code
end

Each field can also be empty, allowing for this simple, infinite loop:

for (;;) do
	// Code
end
// <-- unreachable (without goto)

Switch case

If you want to distinct multiple values you can use a switch statement:

switch(c)
begin
	case ' ':
		// Code
	end 
	case '0':
		// Code
	end
	default:
		// Else-Code
	end
end

Note:
This is not C, there is no fall-through with empty case blocks.

Note:
Having a lot of cases in a single switch can increase the horizontal size of your program drastically. Think about using other possibilities in this case

Goto

goto MLBL;
out "Nobody sees me";
MLBL:
out "end";

You can define labels by writing the identifier and a colon (instead of a semicolon).
And you can write goto statements with the keyword goto

Note:
This is not C, you have to end an goto statement with an semicolon, like every other statement too.

Note:
Use goto's sparely, they are pretty slow and I'm not sure if they are bug-free.

###Expressions ####Mathematical operators

You can use the normal mathematical operators +, -, *, /, % (modulo), ( and ).
Normal precedence rules apply

a = ((5 + 5)*4 - 10)/-1 % 4;

####Boolean operators

You can use the boolean operators && (AND), || (OR), ^ (XOR), ! (NOT).

a = (10 == x) ^ true;
b = !(10 == x);

####Comparison

You can use the normal c-like comparison operators ==, !=, <, >, <= and >=

while (a < 100 && a > -100) do
	a *= 2;
end 

###Special Statements

####Random

You can either generate a random boolean value by using rand, or a random integer value by using rand[?].

rand[n] generates a random number from [0, 4^n), where 0 is included and 4^n is excluded. So you are only able to set the upper border to results of the formula 4^n.

if (rand) do
	a = rand[6] % 10;
end 

Note:
Be aware that in the example above not all values are equally distributed (4^6 % 10 != 0), but approximately it is good, and it becomes better with bigger values for n.

####Quit

The statement quit, stop or close instantly terminates the program. The main method will always implicitly have an quit at the end.

if (error != 0) then
	out "FATAL ERROR";
	quit;
end

####Code block

You can start everywhere a new code block, it probably wont change the resulting program but has its use in structuring the source code.

// Code
begin
	// Code
	// Code
end
// Code

####De-/Increment

With ++ and -- you can increment/decrement a variable in a shorter way than a assignment.

a++;
a = a + 1; // equally

####Assignments

With a single = you can assign a value to a variable.

a = 3;
b[3] = 0;

###Method calls

Method calls are pretty much like in every other language.

method_1(0, 6, "hello");
method_2(getA(), getB(0));

###Comments

You can write either full line comments with // or block comments with /* and */

/* Comment
 * Comment
 */

// Comment

method_99( /* comment */ ); 

###Casts

TextFunge supports explicit and implicit casting.

The cases in which implicit casts happen are:

  • digit -> int
  • digit[] -> int[] (with same length)

You can cast all other value types into each other and array types if they have the same length.

var
	bool b;
	int i;
	char c;
begin
	c = (char)i;
	b  = (bool)c;

Note:
When casting no information is lost, so hard casting to an digit can yield to an illegal value.
Also casting something from an boolean does not always result in 0 or 1 (it results in 0 / not 0). If you want this you can enable "explicit boolean casting" in the compiler options.

###Input/Output

####Out

With the statement out you can output either a value or a string:

out 99;
out 'a';
out "Hello World";
out var_1;

####OutF

Outf is a shortcut to writing multiple out statement. You can give it a comma-separated list of expressions to output

out 99, 'a', "Hello World", var_1;

####In

With the In Statement you can ask the user for a value, the input routine differs when you give it a integer variable or a character variable.

var
	int var_1;
	char var_2;
begin
	in var_1; // Asks for number
	in var_2; // Asks for character