Skip to content

Phrases, Sentences and Blocks

Jinze Wu edited this page Oct 2, 2022 · 9 revisions

Tinymoe has three kinds of functions: phrase, sentence and block.

Phrases

Phrases are functions that can return a value. Tinymoe wants you to process every return values of function calls, so calling a phrase cannot be a statement, it should be an expression. If you don't understand the difference between expressions and statements, you can read Expressions and Statements.

Let's begin with a phrase without any argument:

phrase pi
	set the result to 3.14
end

Then you can use the following code to call this phrase and print the result:

print pi

Then you will get 3.14.

So how about a phrase with one argument? Let's define one:

phrase the number after (the number)
	set the result to the number + 1
end

Now we have a phrase for calculating "x+1". Calling this phrase is very similar to the definition:

print the number after 1

Then you will get 2.

So what about more arguments? Tinymoe still enable you to do that:

phrase sum from (first number) to (last number)
	set the result to 0
	repeat with the current number from first number to last number
		add the current number to the result
	end
end

This is a sample which has already appeared several times before, which calculates first number + (first number + 1) + ... + (last number - 1) + last number. You may know how to call this phrase:

print sum from 1 to 100

Then you will get 5050.

You can put argument in wherever you want inside a pharse, but you cannot make an argument just following another one, like:

phrase this is wrong (a) (b)

Variadic Argument

In some situation we need to deal with arguments but we don't know how many of them. Tinymoe offered a simple way to do that:

phrase sum of (list those numbers)
	set the result to 0
	repeat with the number in those numbers
		add the number to the result
	end
end

If an argument begins with list, it becomes an argument that can receive a list. So calling to this kind of phrase is a little different:

print sum of (1, 2, 3, 4, 5)

Then you will get 15.

The argument becomes an array inside the phrase. You can use the techniques in Manipulating Arrays to deal with it:

phrase the second number in (list numbers)
	set the result of item 2 of array numbers
end

So when you call:

print the second number in (6, 7, 8, 9, 10)

Then you will get 7.

Function Referencing

Arguments in phrases can also be functions. Tinymoe is not designed to be a functional programming language, so Tinymoe don't provide lambda expressions. But Tinymoe still have closure for doing Coroutine. Besides of closure, you can still pass a function as an argument to another function.

First, you need to define an alias to a phrase:

phrase (x) is odd : odd number
	set the result to x % 2 = 1
end

When you use odd number in your code, it will no longer call the function, it is the function itself. Now you can design a phrase whose argument receives a function:

phrase sum of all (phrase (x) satisfies the condition) in (list those numbers)
	set the result to 0
	repeat with the number in those numbers
		if the number satisfies the condition
			add the number to the result
		end
	end
end

When an argument begins with phrase or sentence, you can use it as a function. You can call these two phrases together like this:

print sum of all odd number in (1, 2, 3, 4, 5)

Then you will get 9.

Sentences

Sentences are very similar to phrases, but calling a sentence can be a statement, because sentences are functions that don't return a value.

And besides of list, sentences can use two kinds of new argument: expression and assignable.

Sentences and Deferred Arguments

If an argument begins with expression, it becomes a deferred argument. That means, the argument is evaluated when the code inside the called sentence read this argument. For example:

phrase one
	print "one"
	set the result to 1
end

sentence print double (x)
	print "double1"
	print x + x
end

sentence print deferred double (expression x)
	print "double2
	print x + x
end

When you call print double one, you will get

one
double1
2

But when you call print deferred double one, you will get

double2
one
one
2

Because in print deferred double one, the argument receiving one is declared as (expression x), so when you call this sentence, the evaluation of one has not started yet. The evaluation is passed to the sentence as an argument.

Then in the print deferred double sentence, it read the argument x twice, so the expression one is evaluated twice.

If you don't read the deferred argument inside a sentence, the argument will never be evaluated. This feature is useful when you need to decide the timing of the evaluation of arguments.

Sentences and Reference Arguments

If an argument begins with assignable, it becomes a reference argument. A reference argument can receive a variable. When you change the argument inside the sentence, the variable will also be changed. If the passed variable does not exist, a new variable will be created and initialized to null:

sentence add (value) to (assignable target)
	set target to target + value	
end

phrase main
	set x to 10
	add 20 to x
	print x
end

You will get 30.

Blocks

Blocks are a kind of sentences that can additionaly bring a block of code as one of the argument.

To define a block, the block name should begin with an normal argument receiving the body of the code as a function. For example:

block (sentence do it) repeat (number) times
	repeat with i from 1 to number
		do it
	end
end

This is a block called repeat N times, which will repeat the body of the code for N times. Calling a block is similar to a sentence, except that you should provide several lines of code ending with end to be the block body:

repeat 3 times
	print "I love Tinymoe!"
end

Then you will get

I love Tinymoe!
I love Tinymoe!
I love Tinymoe!

Blocks and Parameterized Bodies

Tinymoe allow you to provide arguments when calling the block body. For example:

block (sentence deal with (it)) repeat (number) times with (argument counter)
	repeat with i from 1 to numbers
		deal with i
	end
end

When an argument begins with argument, it means there is a room for the user to name one of the argument for the block body. This is not a real argument, this is a definition. So the code in the block cannot actually see counter.

At the mean time, when you defined the body argument sentence deal with (it), you are respponsible to keep the number of the arguments equals to the number of all argument arguments.

Calling this block is similar as before, except that the caller need to define the name of the argument and embed it inside the calling code:

repeat 3 times with the counter
	print "I love Tinymoe " & the counter & " times!"
end

repeat 3 times with the counter calls the block, with 3 passed to the number argument, and the counter defines the argument name of the body code print "I love Tinymoe " & the counter & " times!".

Then you will get

I love Tinymoe 1 times!
I love Tinymoe 2 times!
I love Tinymoe 3 times!