Skip to content

lambda-larry/no-brain

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 

Repository files navigation

no-brain

no-brain is a no-level programming language with zero brain abstraction, the true successor to JDSL.

Introduction

Mandatory introduction ritual:

print_f("Hello world"_s);

Hungarian notation

In no-brain, we embrace Hungarian notation to promote readability, compatibility and type-safety.

Negative numbers are prefixed with -

s32_p my_negative_v = -1; // For demonstration only!

Positive numbers are prefixed with +

u32_p my_positive_v = +1; // For demonstration only!

Imaginary numbers are not prefixed at all

i32_p my_imagination_v = 1; // For demonstration only!

String literals are suffixed with _s

string_T my_string_v = "Hello world!"_s;

Variables are suffixed with _v

string_T my_string_v = "I can be mutated"_s;
my_string_v = "Like a ninja turtle!"_s;

Constants are suffixed with _c

string_T my_string_c = "Immoveable object"_s;
my_string_c = "Unstoppable force"_s; // ERROR: my_string_c is a constant

Warning

c and v is right next to each other on a QWERTY keyboard. Be sure to type check your code to enforce type safety. Typos has been proven to waste hours of work.

Keywords are suffixed with _k

if_k (true_k) {
    print_f("Hello world"_s);
}

Functions are suffixed with _f

printf_f("{}"_s, "Hello world"_s);

Standard library identifiers are not prefixed at all

print_f("Hello world"_s); // Who needs std:: anyways?

To ensure compatibility, user defined identifiers are prefixed with my_

my_log_f("Hello world"_s); // Because we don't have namespaces

Primitives are suffixed with _p

ipv6_p my_bind_address_c = localhost_ipv6_c;

Composite types are suffixed with _T instead of _t to avoid collision with POSIX

// Might break in the future
type_k my_player_t {
    i32_p id;
    i32_p health_points;
};

// Valid type name
type_k my_player_T {
    i32_p id;
    i32_p health_points;
};

Arrays are suffixed with _a

string_T my_array_of_strings_ac[] = {
    "Hello"_s,
    "World"_s,
};

Operators are suffixed with _o

// Equivalent to this C macro
// #define LEN(X) (sizeof (X) / sizeof *(X))
size_p
my_length_f(i32_p my_array_ac[])
{
    return_k sizeof_ok my_array_ac
         /_o sizeof_ok *_o my_array_ac;
}

size_p my_p_size_c = my_length_f(my_p_ac);

Integer literals

Decimal

Due to design decisions made in other parts of the language, we have abandoned Western Arabic numerals in favor of Chinese numerals for integer literals.

Here is a quick reference to get you up to speed:

0 1 2 3 4 5 6 7 8 9
一万 一億
10 100 1000 10'000 100'000'000

Here is a couple of examples:

i32_p my_leet_c = 千三百三十七; // leet code baby!

s32_p my_int_max_c = +二十一億四千七百四十八万三千六百四十七; // 2^31 - 1

Because of the Chinese pronunciation of the number four (四: Sì) and the word death (死: Sǐ) are too similar for beginners, we have decided to to remove the offending number from the language. Megaman Battle network 4 was a bad game anyway.

i32_p my_four_twenty_c = 四百二十;   // ERROR, four twenty contains four!
i32_p my_two_plus_two_c = 二 +_o 二; // ERROR, gets computed to four at compile time!
i32_p my_sixty_nine_c = 六十九;      // Allowed, you can use sixty nine

u8_p my_1k_buffer_ca[千二十四] = {}; // ERROR, arrays cannot have size which contains four
u8_p my_array_ca[百二十八] = {};     // アッカリ~ン. The array does not exists, the size is imaginary
u8_p my_array_ca[+百二十八] = {};    // Allowed, arrays size is a positive number

s32_p my_int_max_c = +二十一億四千七百四十八万三千六百四十七; // ERROR, contains four

We have been proactive and made 4 a keyword, just like Java had proactively made goto a keyword to prevent programmers from using it.

If the user input contains four, the input function gets stuck in an infinite loop forever. You have to write a new program from scratch. We don't want to kill the program after all.

i32_p my_user_input_c = i32_p(input_f());

Octal

To represent octal values, use bagua.

Little endian

7 6 5 4 3 2 1 0

Big endian

0 1 2 3 4 5 6 7
i32_p my_flag_of_south_korea_c = ☰☵☲☷;

Super convenient for UNIX file permission.

chmod_f("/etc/shadow"_s, +☰☰☰);   // bash: chmod 777 /etc/shadow

ASCII friendly literals

To make no-brain accessible to non-Chinese programmers. We provide alternatives to the Chinese characters by allowing Roman numerals.

LXIX ==_o 六十九; // true

Alternatively, you can also use the predefined literals from the standard library. Here is a partial reference implementation:

i32_p zero_c = 零;
i32_p one_c = 一;
i32_p two_c = 二;
i32_p three_c = 三;
アッカリ~ン
i32_p five_c = 五;
i32_p six_c = 六;
i32_p seven_c = 七;
i32_p eight_c = 八;
i32_p nine_c = 九;

They are pretty useless since they are imaginary numbers.

Arithmetic

Any arithmetic that involves imaginary numbers is undefined behaviour.

Signed integer overflow is defined behaviour. It is defined to be undefined behaviour.

Unsigned integer overflow gets promoted to a signed integer.

Comments

For single line comment, use the C++ style comment to explain your code.

// This is a comment

Be careful, any no-brain code embedded in the comment will be executed!

// sql_f("DROP TABLE customer;"_s);

To ensure that your code does not execute, please use SaRcAsM cAsE to let the compiler know to ignore it.

// sQl_F("DrOp TaBlE cUsToMeR;"_s);

If you need to explain your code in-depth (in other words apologize), you can write multi-line comments simply by writing in Japanese.

昔々、ある天才なプログラマーがいました。
名前を「トム様」と言いました。
このプログラムを壊しまったある日。
トム様は全力でブグを解析ました。
三日の解析後 ブグの原因は理解まだ不明です。
結局、彼は諦めてしまいました。
ゼロから一, トム様は新たなフレームワークを作りました。
天才しがいないこの強力なフレームワークは誰にも理解できません。
名前を「JDSL」と言いました。

トム様は天才です。

Since Japanese also uses the Chinese numerals for their number system. no-brain supports Western Arabic numerals in multi-line comments to avoid numbers being parsed as numbers.

これはNGです: 千三百三十七 // Parse error: Expected type, got integer

これは数字です: 1337       // Valid comment

To use SaRcAsM cAse in multi-line comments, please alternate between hiragana and katakana. Kanji is too serious.

とムさマは スごイぃィぃ
とムさマは テんサいィぃ
とムさマ ばンざイ

// But we all know he IS a genius
トム様はすごいい
トム様は天才
トム様万歳
マジで

To document legacy code, please use hentaigana to clearly communicate its legacy. Nobody can read the code nor the documentation anyway.

Note

The compiler will turn 10% of the comments to hentaigana if the source file has been untouched for over 30 days.

Conditionals

In a conditional, the lvalue must be on the right-hand side and the rvalue must be on the left-hand side. A rule of thumb, use condition Yoda.

// Correct
if_k (+一 ==_o one_c) {
    print_f("Use condition Yoda you must"_s);
}

// ERROR
if_k (one_c >=_o two_c) {
    print_f("Use condition Yoda you fail"_s);
}

Tip

prvalue must be on the left-hand side, xvalue can be on whatever side.

// Correct (prvalue == xvalue)
if_k (true_k ==_o (one_c >=_o two_c)) {
    print_f("Master condition Yoda you do"_s);
}

Comments can also be used in if_k.

if_k (
    // Comments always lie
) {
    print_f("Never gets executed"_s);
}

Multi-line comments also work.

if_k (うそだよ) {
    sql_f("DROP TABLE customers;"_s);
}

To combat the proliferation of boolean operators, no-brain has only one boolean operator, namely the nand_ok operator. Other operators can be implemented with this operator alone!

my_x_c nand_ok my_y_c; // x NAND y
my_x_c nand_ok my_x_c; // NOT x

(my_x_c nand_ok my_y_c) nand_ok (my_x_c nand_ok my_y_c); // x AND y
(my_x_c nand_ok my_x_c) nand_ok (my_y_c nand_ok my_y_c); // x OR y

// XOR has been left as an exercise for the reader.

Line ending

Linux uses LF for line endings, Windoze uses CRLF. To prevent Windows programmers from checking out CRLF to version control, no-brain uses the null-byte (\0) as line ending.

Functions

Functions declared needs to have its return type on its own line.

// Compiles
u32_p
my_add_f(u32_p my_x_c, u32_p my_y_c)
{
    return_k my_x_c +_o my_y_c;
}

// ERROR
u32_p my_add_f(u32_p my_x_c, u32_p my_y_c) {
    return_k my_x_c +_o my_y_c;
}

We also support recursion with the recurse_fk keyword.

u32_p
my_fibonacci_f(u32_p my_n_c)
{
    if_k (+零 ==_o my_n_c)
        return_k my_n_c;
    if_k (+一 ==_o my_n_c)
        return_k my_n_c;

    return_k recurse_fk(my_n_c -_o +一)
         +_o recurse_fk(my_n_c -_o +二);
}

To break out of deep recursion, use the backtrack_k keyword.

u32_p
my_func_f(u32_p my_x_c, u32_p my_y_c)
{

    if_k (my_x_c <_o my_y_c)
        return_k my_func_f(my_x_c, my_y_c -_o +二) +_o my_func_f(my_x_c +_o +二, my_y_c);


    // Jumps back to the original caller with zero as the result
    backtrack_k +零;
}

Warning

Does not work with mutual recursion.

Iterations

no-brain does not have traditional loops like for and while, instead we have recursion.

Undefined behaviour

Undefined behaviour (aka アッカリ~ン) is actually defined behaviour. It is defined to not have behaviour, thus allows the compiler to optimize the code's existence away. You can't have slow code, if there is no code.

Note

You may occasionally hear the sound effect アッカリ~ン as the code compiles.

Version control support

Version control is the flagship feature of no-brain where git is a first class citizen.

// Suppose we have a git history that looks like this:
//
// * 13eb837 (HEAD -> master) Update README.md
// * d700ff9 Another one
// * 2d2f361 Work plz
// * afd276f Fix
// * 74f21a9 Initial commit

void_pk
my_foo_f(void_pk)
{
    // HEAD_c is a revision-time constant of HEAD
    printf_f("Hello from {}"_s, HEAD_c);
}
string_T my_ref_c = sprintf_f("{}", HEAD_c);

my_foo_f();         // Hello from 13eb837
print_f(my_ref_c);  // 13eb837

By appending @<git REF> after any identifier to use another version of the identifier.

my_foo_f@d700ff9();         // Hello from d700ff9
print_f(my_ref_c@d700ff9);  // d700ff9

You also can use relative selection.

my_foo_f@HEAD~2();             // Hello from 2d2f361
my_foo_f@master@{yesterday}(); // Hello from afd276f


// You can use commits from the future too
my_foo_f@HEAD~-2();
my_foo_f@master@{tomorrow}();

Range selection will execute all of them.

my_foo_f@HEAD..afd276f(); // Hello from 13eb837
                          // Hello from d700ff9
                          // Hello from 2d2f361
                          // Hello from afd276f

print_f(my_ref_c@HEAD..afd276f);  // 13eb837 d700ff9 2d2f361 afd276f

It also works with recursion.

// 74f21a9
void_pk
my_truth_f(void_pk)
{
    print_f("Tom is a genius!"_s);
    recurse_fk@master();
}

// afd276f..
void_pk
my_truth_f(void_pk)
{
    print_f("Tom is a genius!"_s);
    recurse_fk@HEAD^();
}

my_truth_f(); // Prints "Tom is a genius" forever

Example of an infinite list.

// 74f21a9
string_T my_list_ac[] = {"Tom is a genius!"_s} + my_list_ac@master;
// afd276f..
string_T my_list_ac[] = {"Tom is a genius!"_s} + my_list_ac@HEAD^;

About

The true successor to JDSL

Topics

Resources

Stars

Watchers

Forks