The perfectest programming language
Because people always seem to forget semicolons, Perfectness has a simple fix: Semicolons are not allowed.
x = 1; π¬π¬ Syntax Error: Semicolons are not allowed
And this doesn't just mean semicolons at the end of a line. It means ANY semicolons (including in comments and strings).
y = 'hello;' π¬π¬ Syntax Error: Semicolons are not allowed
π¬*
hi; π¬π¬ Syntax Error: Semicolons are not allowed
*π¬
Instead, you muse use a the escape sequence \x??
:
output('hello\x3b') :>> 'hello\x3b'
Many programming languages use //
for comments, but that's kind of confusing.
To fix this, Perfectness uses two of the 'Speech Balloon' emoji, like π¬π¬
(which makes much more sense).
π¬π¬ This is a comment!
// Attempted comment π¬π¬ Syntax Error: Comments must use speech balloons
This is similar for multiline comments. You just use π¬* *π¬
.
π¬*
This is a multiline comment!
*π¬
π¬**
* This is a PerfectDoc comment!
*π¬
To save space, indents must only be one space long.
{
thing() π¬π¬ This is fine.
}
{
otherThing() π¬π¬ Syntax Error: Indents must only be one space long
}
When creating a variable, you can type:
var
(optional)- Modifiers (optional)
- A Type (optional)
- The name of the variable
=
followed by a value (optional)
a = 1
Int b 2
var c = 3
var Int d = 4
There are many modifiers you can use:
const e = 5 π¬π¬ no editing
const Int f = 6
final g π¬π¬ no overriding
public h
protected i
private j
package k
static l
readonly m π¬π¬no assigning
let n π¬π¬ no recreating
You can also combine modifiers:
public static final readonly const let var Int x = 100
You can name variables with almost any characters:
var a = 1
var FRUIT = 'banana'
This includes spaces, special characters, and Unicode characters:
var String my name = 'Bob'
var 1/2 = 0.5
var π = 'Smiley Face'
You can also name variables with primitive values like numbers:
var 1 = 2
output(1) :>> 2
output(2 - 1) :>> 0
output(3 - 2) :>> 1
output(-1) :>> -2
A bit can be 0
or 1
.
A boolean can be true
, false
, or maybe
(just like in DreamBerd).
These are all valid booleans: false
, maybe
, true
.
Info: Booleans are stored as one and a half bits (just like in DreamBerd).
maybe
will be true
half of the time, and false
the other half.
if (maybe) {
output('The maybe was true.')
} else {
output('The maybe was false.')
}
However, this does not apply to if/else/perhaps
statements:
if (maybe) {
output('This will never run.')
} else {
output('This will never run.')
} perhaps {
output('This will always run.')
}
In an if/perhaps
statement, false
won't run anything, true
will run the if
part, and maybe
will run the perhaps
part.
if (condition) {
output('This will run when true.')
} perhaps {
output('This will run when maybe.')
}
The chance(n)
function returns a Chance
, which is basically a boolean with about an n
chance of being true
.
In the following code, the if statement will only run 10% of the time:
if (chance(0.1)) {
output('There was a 1/10 chance of this happening!')
}
You can also set a variable to a chance:
var Chance ch = chance(0.25)
output(ch) π¬π¬This will be true 25% of the time, and false 75% of the time.
Chance
s will never be maybe
.
Note: the behavior of a Chance
in an if/perhaps
or if/else/perhaps
statement is undefined.
- Bytes -
10
- Integers -
123456
- Longs -
10000000000l
- Floats -
123.45
- Doubles -
123.45
Because Windows does not allow double quotes in file names, all strings must use single quotes ONLY:
output("Hi") π¬π¬ Syntax Error: Windows file names can't contain double quotes
output('Hello') :>> 'Hello'
To cast a value to another type, put the type to cast to after the value to cast, with to
in between:
output(5 to String) :>> 5
expect Boolean == Bit[8] :>> Byte
expect Byte :>> Bit[1.5]
expect Int == Bit[32] :>> Byte[4]
expect Long == Bit[64] == Byte[8] :>> Int[2]
expect Float == Bit[32] == Byte[4] :>> Int
expect Double == Bit[64] == Byte[8] == Float[2] :>> Long
To log a message to the console, use say()
. You can also use debug()
, warn()
, and error()
for debugging, warnings, and errors:
console.say(message)
console.debug(message)
console.warn(message)
console.error(message)
You can also use output()
to output the value of an operation:
output(123 * 456)
The :>>
operator will show users reading your code what an output()
statement will return, but it doesn't actually do anything.
output(1 + 2) :>> 3 π¬π¬ This is fine
output(9 + 10) :>> 21 π¬π¬ This is also fine, even though it's not true
In some programming languges, you can use the assert
keyword to confirm that something is true. However, this word is rarely used in real life. Instead, Perfectness uses the expect
keyword.
expect 1 + 1 == 2
assert 1 + 1 == 2 π¬π¬ Syntax Error: Use 'expect' instead.
expect 1 + 1 == 3 π¬π¬ Argument Exception: Something unexpected happened.
If the value of the condition is not what you expected, just use the assume
keyword to make it true for you.
All of these are true.
assume 1 + 2 = 5
output(1 + 1) :>> 2
output(1 + 2) :>> 5
output(1 + (1 + 1)) :>> 5
output(1 + 3) :>> 4
output(3) :>> 3
output(2 + 1) :>> 3
assume false = true
output(false) :>> true
output(1 = 2) :>> true
output(1 > 2) :>> true
output(!true) :>> true
assume false = !true
output(false) :>> true
output(true == false) :>> true
Addition and subtraction are the same as in most other programming languages:
output(1 + 1) :>> 2
output(1 - 1) :>> 0
However, this is not the case for multiplication and division:
output(1 * 1) π¬π¬ Syntax Error: Unknown symbol '*'
output(1 / 1) π¬π¬ Syntax Error: Unknown symbol '/'
Because the meaning of *
for multiplying and /
for dividing is not very obvious, use the characters meant for those operations instead:
output(1 Γ 2) :>> 2
output(1 x 3) :>> 3
output(1 Γ· 2) :>> 0.5
You can also use the modulus and exponent operators. However, they use different symbols than most programming languages.
output(5 o/o 2) :>> 1
output(5 % 2) π¬π¬ Syntax Error: Unknown usage of '%'
output(10 ^ 3) :>> 1000
output(10 ** 3) π¬π¬ Syntax Error: Unknown symbol '**'
You can also use superscript for exponents:
Int exp1 = 3
output(2α΅Λ£α΅ΒΉ) :>> 8
And /
//
for square/cubic/fourth/other roots:
The %
symbol can be used for percentages:
output(20%) :>> 0.2
To use negative numbers, put a !
before them:
output(!1) ::> !1
output(-1) π¬π¬ Syntax Error: Unknown usage of '-'
For all numbers and operators, you can use a spelled out version of the number or operator instead.
output(one) ::> 1
output(two plus two) :>> 4
output(two to the power of four) :>> 16
output(negative pi) :>> !3.14159263589
All valid numbers and operators are: β°ΒΉΒ²Β³β΄β΅βΆβ·βΈβΉ
Number | Spelling | Number | Spelling | Number | Spelling |
---|---|---|---|---|---|
0 |
zero |
1000 |
thousand |
Ο |
phi or golden ratio |
1 |
one |
1000000 |
million |
e |
e or euler's number |
2 |
two |
1000000000 |
billion |
Ο |
pi |
3 |
three |
10ΒΉΒ² |
trillion |
Ο |
tau or 2Ο |
4 |
four |
10ΒΉβ΅ |
quadrillion |
Ο |
psi or supergolden ratio |
5 |
five |
10ΒΉβΈ |
quintillion |
Ξ³ |
gamma or euler's constant |
6 |
six |
10Β²ΒΉ |
sextillion |
G |
gravitational constant |
7 |
seven |
10Β²β΄ |
septillion |
c |
speed of light (in a vacuum ) |
8 |
eight |
10Β²β· |
octillion |
h |
planck constant |
9 |
nine |
10Β³β° |
nonillion |
β΅β |
aleph null or aleph zero |
10 |
ten |
10Β³Β³ |
decillion |
Ο |
omega or number higher than everything else |
11 |
eleven |
`` | 10ΒΉβ°β° |
googol |
|
12 |
twelve |
`` | 1010100 |
googolplex |
|
13 |
thirteen |
`` | β |
infinity |
|
14 |
fourteen |
`` | |||
15 |
fifteen |
`` | |||
16 |
sixteen |
`` | |||
17 |
seventeen |
`` | |||
18 |
eighteen |
`` | |||
19 |
nineteen |
`` | |||
20 |
twenty |
`` | |||
30 |
thirty |
`` | |||
40 |
forty |
`` | |||
50 |
fifty |
`` | |||
60 |
sixty |
`` | |||
70 |
seventy |
`` | |||
80 |
eighty |
`` | |||
90 |
ninety |
`` | |||
100 |
hundred |
10Β³β°Β³ |
centillion |
Operator | Spelling | Operator | Spelling |
---|---|---|---|
+ |
plus or added to or incresed by |
+= |
increase ? by or add # to |
- |
minus or subtracted from (inverted) or decreased by |
-= |
decrease ? by or subtract # from |
++ |
increment ? or increase ? |
-- |
decrement ? or decrease ? |
Γ or x |
times or multiplied by |
Γ= |
multiply ? by |
Γ· |
over or divided by |
Γ·= |
divide ? by |
o/o |
mod |
o/o= |
modulus ? by |
To check for equality, use ==
:
output(2 == 2) :>> true
You can use ===
to be more specific:
output(1 == '1') :>> true
output(1 === '1') :>> false
To be even more specific, use ====
:
output(1 to Int === 1 to Float) :>> true
output(1 to Int ==== 1 to Float) :>> false
To be even more specific than that, use =====
Int x = 1
output(x ==== 1) :>> true
output(x ===== x) :>> true
output(1 ===== 1) :>> true
output(x ===== 1) :>> false
Or, if you want to be less specific, use only one =
:
output(1.4 = 1) :>> true
To be less specific than that, remove the =
entirely:
output(1 'cat') :>> true
If specificity isn't important to you, use the -=
operator (not to be confused with subtracting from a variable), optionally with more =
s to be less specific:
You can make classes. However, you cannot use new
to create an instance of them, so you'll have to find another way.
class Example {
x = 'woof'
int y = 3
}
Example e = new Example() π¬π¬ Syntax Error: Cannot use the 'new' keyword to create classes
Example f = (()=>{
var ex = {}
ex.prototype = Example
return ex
})() π¬π¬ This works
You can make an array of values:
Array x = [1, 'apple', false]
Int[] y = [1, 2, 3]
Note: Array<Type>
and Type[]
are the same.
output(Array<String> === String[]) :>> true
When creating an array, you can specify a length of the created array. This can also include floats, strings, and other arrays:
Boolean[] a = new Boolean[3]
Int[5] b = [1, 2, 3, 4] π¬π¬ Type Error: Array [1, 2, 3, 4] has wrong length for Int[5]
Float[] c = new Float[2.4]
Double[] d = new Double['cat']
String[] e = new String[[1, 2, 3]]
Byte['z'] f = new Byte['z']
You will still get the correct lengths:
output(c.length) π¬π¬ 2.4
output(d.length) π¬π¬ 'cat'
output(e.length) π¬π¬ [1, 2, 3]
Array indexes can also be floats:
Array<Float> list = [1, 2]
list[0.5] = 1.5
output(list) :>> [1, 1.5, 2]
Or strings.
x['apple'] = 3
output(x) :>> [1, 1.5, 2, 'apple' = 3]
Or anything else.
x[['banana']] = 4
output(x) :>> [1, 1.5, 2, 'apple' = 3, ['banana'] = 4]
x[false] = 0
output(x) :>> [false = 0, 1, 1.5, 2, 'apple' = 3, ['banana'] = 4]
Even keywords and operators.
x.push([++ = 'dog', = = 'cat', if = 'hello', (,) = 'goodbye', (String) = 'string'])
output(x) :>> [false = 0, 1, 1.5, 2, 'apple' = 3, ['banana'] = 4, [++ = 'dog', = = 'cat', if = 'hello', (,) = 'goodbye', (String) = 'string']]
Or nothing at all.
Array ( ) = [ = 'something', = 'something else']
output(( )) :>> [ = 'something', = 'something else']
You can create maps in a similar way to arrays:
Map f = [a = 1, b = 2, c = 'dog']
Map<Int> [1 = 2, 'meow' = 1000, (Byte) = 2147482647, ~ = -99999]
Please note that maps are just arrays:
output(Map === Array) :>> true
π¬π¬ Also...
output(Map === Set) :>> true
We'll talk about sets later.
Sets are usually really slow. In Perfectness, sets are just arrays.
Loops can sometimes get confusing. Instead, you need to use the goto
and label
keywords.
int i = 0
label 'cat'
otherThing()
i++
if (i < 10) {
goto 'cat'
}
You can also use comefrom
.
label 'dog'
otherThing() π¬π¬ This will never run
comefrom 'cat'
If you want to own something, it ABSOLUTELY MUST contain the word 'Perfectness' formatted as Perfectness. Otherwise, you won't own your code.
Examples:
The Perfectness Game
- This is good, you own this.A Perfectness Project
- Sorry, you don't own this. Please change it.Google
- Sorry, you don't own this. Please change it.My Own Code
- Sorry, you don't own this. Please change it.
To install Perfectness, please follow these steps:
- Run the command:
curl "https://www.github.com/SuperYoshi10000/Perfectness/a-totally-real-url-and-file-path/installer/Perfectness_program_app_installer_download.<ext>" -O
- Replace
<ext>
withexe
on Windows,elf
on Linux, orapp
on Mac.
- Run the downloader. This will download the installer.
- Run the installer. This will install the program app.
- Run the program app. This will ask you whether you want to install the program or delete it.
- Run the program. This will install the Perfectness executor and the compiler.
To run a Perfectness file, please follow these steps:
- Double click on the file.
- In the menu, click
Open in Perfectness compiler
. - Click
Menu > Options > General Options > Compiler > Use built-in compiler > Compile this file > Compile Now
. - Double click on the compiled file.
- In the menu, click on
Open in Perfectness executor
. - Click
Execute > Execute this file > Execute Now
. - Click
Start
.
Alternatively, you can run the following commands to do it faster:
- To Compile:
perfectness-compiler compile --file <file_path> --compiler built-in --what this-file --when now
- To Run:
perfectness-executor execute --file <file_path> --run-now true --auto-start true