-
Notifications
You must be signed in to change notification settings - Fork 0
Sample codes
Make a simple Hello, World! program.
Input code:
OUTPUT interpreter
PRINT "Hello, World!"Output:
Hello, World!
A simple program to print out the good old "Hello, World!" message which also illustrates how the OUTPUT and PRINT functions work!
Calculate 9 + 3^2 * 4 – (6 % 3).
Input code:
OUTPUT interpreter
DO sub(sum(9, pro(pow(3, 2), 4)), mod(6, 3)); var1
RETURN var1Output:
var1 = 45
In math, the convention is: (1) parentheses, (2) exponentiation, (3) multiplication and divsion, (4) addition and subtraction. When following the conventional order of operations:
- Parentheses:
(6 % 3)gets carried out first to get0. - Exponentiation:
3^2gets carried out to get9. - Multiplication and division:
3^2 * 4or9 * 4gets carried out to get36. - Addition and subtraction:
9 + 3^2 * 4or9 + 36gets carried out to get45. Then,9 + 3^2 * 4 – (6 % 3)or45 - 0gets carried out to get45.
However, in Piège, the order of operations starts from the most deeply-nested operator to the least. Consequently, the order of operations might look something like this:
1 sub( | | | | | | | | | | )
2 sum(| | | | | | ), mod(| | )
3 9, pro( | | | |) 6, 3
4 pow(| |), 4
5 3, 2The values inside each operator have been shifted down to the next line. By the order of operations in Piège, the operator whose values are in the lowest line will be carried out first, then the second lowest will be carried out.
The process might look like this:
# Step 1
1 sub( | | | | | | | | )
2 sum(| | | |), mod(| | )
3 9, pro(| |) 6, 3
4 9, 4
# Step 2
1 sub( | | | | | | )
2 sum(| | ), mod(| | )
3 9, 36 6, 3
# Step 3
1 sub(| |)
2 45, 0
# Step 4
1 45It is easily seen that pow(3, 2) was calculated a whole 2 steps before mod(6, 3) was, even though the modulo operation was technically inside the parentheses. Though, the original expression using regular math syntaxes can be rewritten as ((9 + ((3^2) * 4)) – (6 % 3)), and the logic would be the same as in Piège.
Calculate the circumference and area of a circle of radius 5, given pi = 3.14159.
Input code:
OUTPUT interpreter
DO 3.14159; pi
DO 5; radius
DO pro(2, pi, radius); circumference
DO pro(pi, pow(radius, 2)); area
RETURN circumference
RETURN areaOutput:
circumference = 31.41590
area = 78.53975
The DO function has two sections: operation and output. When the operation is a single float value, the function basically acts as an assignment statement, with the output variable being assigned the value in the operation section.
In this example, the variable pi gets assigned a value of 3.14159, and the variable radius gets assigned a value of 5. These variables are then used in the following operations.
Swap the values of variable a = 5 and b = 6.
Input code:
OUTPUT interpreter
DO 5; a
DO 6; b
RETURN a
RETURN b
DO a; c
DO b; a
DO c; b
RETURN a
RETURN bOutput:
a = 5
b = 6
a = 6
b = 5
In addition to assigning values to a variable, you can assign the value of one variable to another just by calling the variable name.
If necessary, include DELETE c at the end to remove the temporary variable c.
Increase an index i from 1 to 5 step 2 and printing out the index after each increment.
Input code:
OUTPUT interpreter
DO 1; i
RETURN i
DO sum(i, 2); i
RETURN i
DO sum(i, 2); i
RETURN iOutput:
i = 1
i = 3
i = 5
In addition to assigning one variable to another, you can assign a variable to the value of itself. Well, that wouldn’t be of much use unless you use that variable in a math operator like in Example 5, where the variable i is assigned the value of the sum of the value of itself and 2. Or, in programming syntax, i = i + 2 or i += 2.
Return the value of 2^i for each i in range from 0 to 5 (including 5) step 1.
In this example, we’ll try to execute this using 3 methods:
- Method 1: Use
SETCURwithtype = char - Method 2: Use
SETCURwithtype = line - Method 3: Use
MOVECURwithtype = char
Method 1
Input code:
OUTPUT interpreter
DO 0; i
DO pow(2, i); a
RETURN a
DO sum(i, 1); i
SETCUR char = 29; notmore(i, 5)Output:
a = 1
a = 2
a = 4
a = 8
a = 16
a = 32
In a way, the function works similarly to the do–while statement in many programming languages, except it doesn’t loop back to the start of the code block but instead loops to (a) a specific character index, or (b) a specific line in the whole code.
In this case, the function set the cursor at char = 29, which is where our DO pow(2, i); a line starts. And, when we run the code, the loop will work! Every function from line 7 to line 11 will run 6 times in total, and the output should have 6 return values for the variable a.
In versions prior to 2.0, there used to be a function called getIndex[] (or GETINDEX if it was still here) that would have taken the starting index of the next line. However, this function was deprecated in version 2.0, thus making this method a lot less useful and intuitive.
Method 2
Input code:
OUTPUT interpreter
DO 0; i
DO pow(2, i); a
RETURN a
DO sum(i, 1); i
SETCUR line = 5; notmore(i, 5)Output:
a = 1
a = 2
a = 4
a = 8
a = 16
a = 32
Instead of using type = char, this now uses the much more intuitive type = line, which sets the cursor to the start of the exact line in the whole code.
Method 3
Input code:
OUTPUT interpreter
DO 0; i
DO pow(2, i); a
RETURN a
DO sum(i, 1); i
MOVECUR line = -4; notmore(i, 5)Output:
a = 1
a = 2
a = 4
a = 8
a = 16
a = 32
The SETCUR line = index method can break if you add more code before the referenced line of code. Instead, you can use the more errorproof MOVECUR line = amount method.
In the example code above, the MOVECUR function checks if i ≤ 5 is True and moves 4 lines back if it is. Since i starts at 0 and only increases by 1 at line 8 before MOVECUR, MOVECUR will be activated precisely 5 times before i surpasses 5 and the condition returns False.
The following examples will also include:
- Runtime from the Piègeur interpreter
- Ratio of that runtime to 1 second, or ratio of 1 to # of times the same program can be executed back-to-back in 1 second
Calculate the first 20 Fibonacci numbers.
Input code:
OUTPUT interpreter
DO 20; numberToReturn
DO 1; index
DO 0; a
DO 1; b
DO sum(a, b); result
RETURN result
DO b; a
DO result; b
DO sum(index, 1); index
MOVECUR line = -6; notmore(index, numberToReturn)Output:
result = 1
result = 2
result = 3
result = 5
result = 8
result = 13
result = 21
result = 34
result = 55
result = 89
result = 144
result = 233
result = 377
result = 610
result = 987
result = 1597
result = 2584
result = 4181
result = 6765
result = 10946
Runtime:
0.00377s
Ratio:0.00377 : 1or1 : 265.25199
Output prime numbers between 1 and 100.
Input code:
OUTPUT interpreter
DO 2; n
RETURN n
DO 3; n
DO 100; maxToCheck
DO 2; i
DO mod(n, i); remainder
MOVECUR line = 6; equal(remainder, 0)
DO sum(i, 1); i
MOVECUR line = -4; less(i, n)
RETURN n
DO sum(n, 1); n
MOVECUR line = -9; notmore(n, maxToCheck)Output:
n = 2
n = 3
n = 5
n = 7
n = 11
n = 13
n = 17
n = 19
n = 23
n = 29
n = 31
n = 37
n = 41
n = 43
n = 47
n = 53
n = 59
n = 61
n = 67
n = 71
n = 73
n = 79
n = 83
n = 89
n = 97
Runtime:
0.48984s
Ratio:0.48984 : 1or1 : 2.04148
This one might be hard to follow, so let me explain.
DO 2; n and RETURN n simply outputs 2, which we can consider to be a prime number.
After that, the cycle starts from the number n = 3 and should end at maxToCheck = 100. For each n, an index i is set at value 2, and then we calculate n % i and assign to remainder.
If remainder == 0, then the first MOVECUR moves the cursor 6 lines forward to DO sum(n, 1); n to increase n by 1. If, however, the condition is incorrect, then that MOVECUR will not be activated, and we move on to DO sum(i, 1); i to increase index i by 1.
The second MOVECUR function checks if i < n. If True, then it moves the cursor back 4 lines to executing the modulo operation. Otherwise, it continues to RETURN n, which will give the supposed prime number.
Afterwards, n increases by 1, and the third MOVECUR checks if n ≤ maxToCheck. If True, it moves to the line that sets i back to 2, and the cycle continues. If not, the cursor will move to the end of the math operator.
Basically, if any number n is divisible by any number i from 2 to itself - 1, it is not a prime number, and we skip to the next n to process. Otherwise, we consider that n to be a prime. When we haven't reached the maxToCheck value, we reset i back to 1, and we do all that checking once again. When we eventually reach the max value, we do nothing and let the program run to the end.
Calculate the derivative of f(x) = x^2 at x from range -4 to 4 step 1.
Input code:
OUTPUT interpreter
DO -4; x0
DO sum(x0, pow(10, -15)); x
DO pow(x0, 2); y0
DO pow(x, 2); y
DO round(rat(sub(y, y0), sub(x, x0)), 4); derivative
DO sum(x0, 1); x0
DO sum(x0, pow(10, -15)); x
RETURN derivative
MOVECUR line = -7; notmore(x0, 4)Output:
derivative = -8
derivative = -6
derivative = -4
derivative = -2
derivative = 0
derivative = 2
derivative = 4
derivative = 6
derivative = 8
Runtime:
0.00227s
Ratio:0.00227 : 1or1 : 440.52863
Calculate the definite integral of f(x) = x^2 from 0 to 2.
Input code:
OUTPUT interpreter
DO 0; a
DO 2; b
DO a; x
DO 0.0001; step
DO 0; defIntg
DO pow(x, 2); y
DO sum(pro(y, step), defIntg); defIntg
DO sum(x, step); x
MOVECUR line = -4; notmore(x, b)
DO defIntg; result
RETURN resultOutput:
result = 2.666866670000
Runtime:
3.21193s
Ratio:3.21193 : 1or1 : 0.31134
For your information, the runtime of this program has massively improved through different versions of Piègeur (from 41s (v0.1.5) to 27s (v0.2.0), to now 3s (v0.3.0)). Not that it's anything important, just a fun thing to know.
Calculate e^0.25 using Maclaurin series to degree 10.
Input code:
OUTPUT interpreter
DO 0; n
DO 0.25; x
DO 0; result
DO sum(result, rat(pow(x, n), fact(n))); result
DO sum(n, 1); n
MOVECUR line = -3; notmore(n, 10)
RETURN resultOutput:
result = 1.284025416687735384313728023
Runtime:
0.00213s
Ratio:0.00213 : 1or1 : 469.48357
Approximate pi by counting points inside the circle.
Input code:
OUTPUT interpreter
DO 0; points
DO 1; radius
DO 0.01; step
DO sub(0, radius); x
DO sub(0, radius); y
DO sum(pow(x, 2), pow(y, 2)); value1
MOVECUR line = 2; more(value1, 1)
DO sum(points, 1); points
DO sum(y, step); y
MOVECUR line = -5; notmore(y, radius)
DO sum(x, step); x
MOVECUR line = -10; notmore(x, radius)
DO rat(rat(points, pow(radius, 2)), 10000); piApprox
RETURN piApproxOutput:
piApprox = 3.1417
Runtime:
16.8628s
Ratio:16.8628 : 1or1 : 0.0593
Similarly to the definite integral example, this program used to run very slowly (100+s (v0.1.5) to 52s (v0.2.0).
The following examples are done using the Piègeur interpreter which has its own data formatting. Other interpreters might have different visual interpretation and formatting.
Input code:
OUTPUT interpreter
DO 12; a
VISUAL quantity = |; 15
VISUAL magnitude = <>, before; aOutput:
||||||||||||||| 15
12 <><><><><><><><><><><><>
In Piègeur, the value will either go before or after the string of characters that represents the magnitude or quantity of that value, depending on your second option of before or after.
Notice how in the second VISUAL, there can be two characters.
Input code:
OUTPUT interpreter
VISUAL matrix = brackets, 2; 1, 4, 2, 6, 4, 7
VISUAL matrix = brackets, 2; 1, 4, 2, 6, 4Output:
⎡ 1 4 2 ⎤
⎣ 6 4 7 ⎦
⎡ 1 4 ⎤
⎣ 2 6 ⎦
The first VISUAL correctly displays a 2×3 matrix with 6 entries.
The second only has 5 input entries. Consequently, only 4 entries are accepted to make a 2×2 matrix.
Input code:
OUTPUT interpreter
VISUAL matrix = parentheses, 3; 5, -2, 7, 0, 0.4, 7, 4, 6, -5, 8, -26, 1.7Output:
⎛ 5 -2 7 0 ⎞
⎢ 0.4 7 4 6 ⎥
⎝ -5 8 -26 1.7 ⎠
The matrix is scaled based on the length of the value with the longest string representation.
Input code:
OUTPUT interpreter
VISUAL graph = bar, scaled; "2023", 70, "2024", 48, "2025", 102
VISUAL graph = bar, literal, noBetween; "2023", 70, "2024", 48, "2025", 102Output:
▕
2023▕███████████████████████████▍ 70
▕
2024▕██████████████████▊ 48
▕
2025▕████████████████████████████████████████ 102
▕
▕
2023▕▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌ 70
2024▕▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌ 48
2025▕▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌ 102
▕
In graph type bar of scale type scaled, all values are scaled based on the biggest value. In Piègeur, the largest value by default has 40 block characters, and the other values are scaled in relation to it. You can change this in option 4.
In graph type quantity of scale type scaled, all values show the full quantity representation, even if it's a million. You can also set the padding in option 3 to change the gap in between bars.
Input code:
OUTPUT interpreter
VISUAL table = row, 3; "x", 1, 2, 3, 4, "x^2", 1, 4, 9, 16, "x^3", 1, 8, 27, 64
VISUAL table = column, 3; "x", 1, 2, 3, 4, "x^2", 1, 4, 9, 16, "x^3", 1, 8, 27, 64Output:
┍━━━━━┯━━━━┯━━━━┯━━━━┯━━━━┑
│ x │ 1 │ 2 │ 3 │ 4 │
┝━━━━━┿━━━━┿━━━━┿━━━━┿━━━━┥
│ x^2 │ 1 │ 4 │ 9 │ 16 │
┝━━━━━┿━━━━┿━━━━┿━━━━┿━━━━┥
│ x^3 │ 1 │ 8 │ 27 │ 64 │
┕━━━━━┷━━━━┷━━━━┷━━━━┷━━━━┙
┍━━━━━┯━━━━━┯━━━━━┑
│ x │ x^2 │ x^3 │
┝━━━━━┿━━━━━┿━━━━━┥
│ 1 │ 1 │ 1 │
┝━━━━━┿━━━━━┿━━━━━┥
│ 2 │ 4 │ 8 │
┝━━━━━┿━━━━━┿━━━━━┥
│ 3 │ 9 │ 27 │
┝━━━━━┿━━━━━┿━━━━━┥
│ 4 │ 16 │ 64 │
┕━━━━━┷━━━━━┷━━━━━┙
Object parameters should always go in the same order: name / label -> variable / value, then the next name / label -> variable / value, and so on. This way, if you change the orientation from row to column, the table will adjust accordingly.
Additionally, if the number of rows / columns chosen is different from the intended number of names / labels, the table might create an extra row / column to fit the extra values, and the formatting might break.
This section is dedicated to scripts that do things outside of what Piège should really be used for. Things that are not (yet) directly supported by Piège, but can be achieved by ridiculously convoluted methods.
I know this is really solvable by just implementing more features, but I don't want to stray away from the main focus (calculator disguised as a programming language). Also, figuring these things out is infinitely more fun, and it makes learning about Piège more easily.
Input code:
OUTPUT interpreter
# Initial start and end indices
DO 0; startIndex
DO 5; endIndex
# Initialise index
DO startIndex; index
# Read list
DO 0; list
DO sum(pro(dif(sign(dif(index, 0)), 1), 6), list); list
DO sum(pro(dif(sign(dif(index, 1)), 1), -1), list); list
DO sum(pro(dif(sign(dif(index, 2)), 1), 3), list); list
DO sum(pro(dif(sign(dif(index, 4)), 1), 1), list); list
DO sum(pro(dif(sign(dif(index, 5)), 1), -9), list); list
# Print list
PRINT "list[", index, "] = ", list
# Add index & continue looping to list reader if index <= endIndex
DO sum(index, 1); index
SETCUR line = 11; notmore(index, endIndex)Output:
list[0] = 6
list[1] = -1
list[2] = 3
list[3] = 0
list[4] = 1
list[5] = -9
Alright, what do I mean by a "list"? A list is an ordered and changeable set of numbers, with each element of the set having assigned an index, usually starting from 0 for the leftmost element.
There is no concept of a list in Piège, at least not in any versions of it.
What I'm doing here is simulating a list by making a chain of DO functions, with each one acting as a "signal" that takes in an outside index and returns a value when that index matches its own assigned index. When the chain finishes, the final output of list should only be the value corresponding to that outside index.
To understand this better, I'll disect one of the lines of code:
DO sum(pro(dif(sign(dif(index, 0)), 1), 6), list); list
DO | | | | | | | | | | ; list
sum( | | | | | | | | | )
pro( | | | | | | |), list
dif( | | | | |), 6
sign( | | | ), 1
dif( | |)
index, 0Let's look at the pro(df(sign(dif(index, 0)), 1), 6) first. This one contains two key components: the index detector (left part of the pro( operator), and the set value (right part).
The index detector is dif(sign(dif(index, 0)), 1), which returns 0 if index == 0 is True, and 1 if not. How?
- The
sign(operator is an operator that takes in one value and returns 1 if that value is positive, -1 if it's negative, and 0 if it's zero. This is the only operator that returns only set values. When you combine with theabs(operator, it only returns exactly 2 set values:1and0. - The
dif(operator insidesign(acts as a comparator between the outside indexindexand the set index0. Whenindex == 0is True,dif(returns 0. Otherwise, it just returns the difference, which is always positive. However, since this operator is inside ofsign(, we can convert all non-zero difference values into1. This turns the wholesign(dif(chunk into a binary operator. - However, the
sign(operator actually returns 0 if True and 1 if False. I needed them to switch (you'll see why later), so I simply took the difference between thesign(and 1.
All of this equate to: If index = set index, the detector returns 1. If not, the detector returns 0.
This is the binary operation stripped to its minimum if you need to use it:
DO 1; value1
DO 2; value2
DO dif(sign(dif(value1, value2)), 1); returnValue
RETURN returnValueWhat I can do next is take the result of that index detector and multiply it by the value I want to store, which in the line of code above I've put 6. When the index detector returns 1, I can retrieve the value 6, and when it returns 0, I get 0.
So, that one piece of code is done; why so many lines of the same code? Since each has a set index and a corresponding value, you can actually have multiple indices, with each one saving its own value. And since only one index can make the condition of one index detector be True, when the interpreter go through all the sum( operators, what you ultimately get is the precise value at the exact index that you requested. When I set the index to 1, it looks through all of the codes, and returns what the value is set for the index 1.
Alright, that was crazy. But the rest of the code is actually very normal. The first three DO functions just put preset values in variables to reference in the following code, the PRINT function prints... and the last few increases the index and moves to the chain if its own condition is True (index between startIndex and endIndex).
The wiki references version 2.1 (25 February, 2026) of the Piège programming language.
Due to a change in syntaxes, any version prior to 2.0 is completely incompatible with the latest version.