We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.
Bussin X
- Note: If you're looking for Bussin X, scroll down. The first half of this article focuses on Bussin.
| Paradigm(s) | imperative, procedural, declarative |
|---|---|
| Designed by | FaceDev |
| Appeared in | 2023 |
| Type system | dynamic, gradual, weak |
| Memory system | variable-based |
| Computational class | Turing complete |
| Reference implementation | face-hh/bussin |
| Major implementations | sno2/bsn |
| Influenced by | tylerlaceby's interpreter tutorial language, Rust |
| File extension(s) | .bs |
Bussin and Bussin X are both programming languages made by FaceDev. Bussin is a normal programming language and Bussin X is an esoteric weirdlang superset of Bussin. It is the star of the video "I made my own Programming Language".
Bussin is a normal, non-esoteric programming language that somewhat resembles JavaScript.
Values
Numbers
Like JavaScript and some other scripting languages, Bussin only has floats (IEEE-754 double-precision) which means there is no distinction between integers and decimals.
Here are some examples of numeric literals:
3.14159 1234 -9876 0.54321 314.0
Null
Null is the variable null (See § Builtins — Miscellaneous) and represents the absence of a value.
Booleans
Booleans represent the concept of true and false. They are represented respectively by the true and false variables. (See § Builtins — Miscellaneous)
Strings
A string is a sequence of characters. String literals are created by a pair of quotation marks " with the content of the string in between.
"Hello, World!"
The only valid escape sequences are \n for newlines, \t for tabs, \r for the carriage return, and \" for quotes. However, escaping quotes does not work in the reference implementation for whatever reason, so a workaround to get quotes inside of a string can be used with strcon and a setup like charat(bson.stringify({x: 0}), 1) which retrieves the produced " character.
Unlike arrays, strings cannot use str[index] syntax for retrieving the character at the specified index. Instead, one must use charat function which is documented in more detail below in § Builtins — String manipulation.
Objects
Objects in Bussin are like JavaScript objects, which are like dictionaries or hash maps/tables in other languages. An object literal is a comma-separated list of key-value pairs (e.g. key: value) enveloped in a pair of braces.
Additionally, a single variable can be specified if it is desired to have a key with the name and value of the variable. (e.g. { x, y } is equivalent to { x: x, y: y })
Keys can be get and set with the obj.key syntax if the key is known to be a constant identifier.
Example:
let video = { title: "I made my own Programming Language", author: "FaceDev", file: "none"};
video.file = "video.mp4"
The objects.hasKey(obj, "key") function can be used to check if a key exists, and the objects.keys(obj) function can be used to get all of the object's keys as an array.
Unlike arrays, objects cannot use obj[key] syntax for using a computed member name for setting and getting. Instead, one must use objects.get and object.set which are both documented in more detail below in § Builtins — Object manipulation.
Arrays
Arrays are variable-sized collections of values. Array literals have the same syntax as in JavaScript and most other languages, with a comma-separated list of values wrapped in square brackets — such as [1, 2, "hello", {is_cap: cap}].
Accessing an element of an array at a specified index can be done with array[index]. Changing the element at the index in the array can be done with the assignment operator.
Like most other programming languages, Bussin's arrays are zero-based, meaning that indices start at zero and end at length - 1. Also, array elements can be accessed and modified by subscripting them with array[index].
An array can be expanded one element by setting an element at the index len(array). This is used in the brainfuck interpreter since Bussin has no array push/append function and the reference implementation is made in TypeScript, which inherits JavaScript's quirks of arrays being hashmaps.
Functions
Functions are first-class values in Bussin. This means that they are treated like any other value, so operations that can be performed on any other value can be performed on them; even though in Bussin, the only thing you can do with a function is call it, so there isn't much that can be done with a function other than calling it.
They are defined with the following syntax:
fn name(parameters) {
body
}
The parameter list is a comma-separated list of parameter names.
Example:
fn square(x) {
x * x
}
Like many other non-esoteric languages, the last value evaluated in a function is the return value of the function.
Anonymous function expressions can be defined in a similar manner as in JavaScript, with the format fn (parameters) { body }.
Operator precedence
The topmost operator in this list is the one with the highest precedence.
| Operator(s) | Name |
|---|---|
x()
|
Call Member access |
a * b
|
Multiplicative |
a + b
|
Additive |
a && b
|
Logical AND/OR |
x = y
|
Assignment |
x -> y | z
|
Ternary operator |
Variables
Variables can be defined with let/const in a similar way to JavaScript, semicolon must always follow the statement, despite the fact that other statements are not followed by semicolons. Variables may have no initial value (initialized to null) while constants may not, and a constant having no initial value will throw a compile error.
let i = 0; const pi = 4;
Control flow
Conditionals
If statements are just like in C and JavaScript, except the body must be a block.
if (condition) {
body
}
if (condition) {
body
} else {
body
}
Additionally, there is a ternary expression with the form condition -> true_branch | false_branch.
Loops
Bussin only has C-style for loops with the form of:
for ([var declaration]; [condition]; [update]) {
[body]
}
For example:
for (let i = 10; i >= 0; i--) {
println(strcon("T-", i, " seconds"))
}
break and continue do not exist in Bussin.
Exceptions
Bussin has no way to throw exceptions, however foreign functions may throw exceptions that must be caught to prevent abrupt termination of the program.
Exceptions may be caught with a try-catch statement/expression[1]. The error is stored in a global variable named error which is initially set to null, but is set to the caught error in a catch block. It is unknown whether this is a part of the language or if it is just a quirk with the reference implementation — for example in sno2/bsn, error can only be used in a catch block.
try {
println(pie)
} catch {
println(error)
}
Builtins
The function signatures in this section are of the form name(argument_types): return_type. ... denotes a Wikipedia:variadic function. They only serve to describe the types of a function's parameters and its return value and are not guaranteed to be syntactically valid, even in Bussin X where certain type annotations do exist.
Input/Output (I/O)
-
input(prompt: string): fn(func: fn(data: string): any): nullPrints
promptas a prompt to the user and receives a string from the user. Returns a function which invokesfuncwithdatabeing the received input.</pThe example below is written in Bussin X, but that doesn't matter as you can follow the translation table.
yap("gimme your bank account info")(bruh(info) { waffle("thanks") })inputappears to be asynchronous, as it does not wait for the user to finish their input before running the next line in the reference implementation. -
println(...): nullPrints all of the arguments to standard output, with a newline following each one.
Example:
println(123, 456, 789)
Output:
123 456 789
Networking
- This section is not detailed enough and needs to be expanded. Please help us by adding some more information.
-
fetch(url: string, options: object): stringMakes an HTTP request to
urlwith the options specified inoptions. -
websocket(url: string): objectOpens a web socket to
url. See below for what you can do with the returned object.
Websockets
-
onclose(func: fn()): nullSets the event handler for
onclosetofunc. -
onerror(func: fn(error: string)): nullSets the event handler for
onerrortofunc. -
onmessage(func: fn(data: string)): nullSets the event handler for
onmessagetofunc. -
send(data: string): nullSends data over the websocket.
String manipulation
-
charat(str: string, index: number): stringReturns the character at
indexinstr. -
format(str: string, ...): stringMakes a new copy of
strwith the placeholders (${}) replaced with their corresponding arguments.Example:
println(format("Hello, ${}!", "world")) // Hello, world! -
parseNumber(str: string): numberParses a number from
str. Equivalent toparseFloat()in JavaScript. -
splitstr(str: string, delimiter: string): arrayReturns an array containing the fragments of splitting
strbydelimiter -
startsWith(str: string, prefix: string): stringReturns
trueifstrstarts withprefix, otherwise returnsfalse. -
strcon(...): stringStringifies all of the arguments and concatenates them all into a string.
-
trim(str: string): stringReturns a copy of
strwith leading and trailing whitespace.Example:
println(strcon("'", trim(" Hello, world! "), "'")) // "'Hello, world!'"
Object manipulation
The definitions below are contained in an object named objects.
-
get(obj: object, key: string): anyReturns the value associated with
keyinobj. In JavaScript, this would beobj[key]. -
hasKey(obj: object, key: string): boolReturns
trueifobjcontains the keykey, andfalseotherwise. -
keys(obj: object): arrayReturns a list of all of the keys in
obj. -
set(obj: object, key: string, value: any): nullSets the value associated with
keyinobjtovalue. Ifkeyis not yet inobj, then it is inserted. Otherwise, the old value is overridden.
Math
The definitions below are contained in an object named math.
-
abs(x: number): numberReturns the absolute value of
x. -
ceil(x: number): numberReturns the ceiling (rounded up value) of
x. -
e: numberWikipedia:Euler's number, approximately equal to 2.71828...
-
pi: numberWikipedia:Pi — the ratio between a circle's circumference and its diameter — approximately equal to 3.14159265358979...
-
random(start: number, end: number): numberReturns a random integer between
ceil(start)andfloor(end). -
round(x: number): numberReturns the rounded value of
x. -
sqrt(x: number): numberReturns the square root of
x.
Process
-
args: arrayThe argument vector of the Bussin interpreter. In Node.js and Deno, this would be
process.argv. -
clearInterval(id: number): boolClears the interval with the ID of
id. Returnstrueif the interval was cleared, andfalseif no such interval with an IDidexists. -
clearTimeout(id: number): boolClears the timeout with the ID of
id. Returnstrueif the timeout was cleared, andfalseif no such timeout with an IDidexists. -
exec(string): stringExecutes the command and returns the subprocess' trimmed standard output as a string. Similar to
system()in C orsubprocess.runin Python. If the subprocess fails, then throws an exception. -
exit(): nullTerminates the program.
-
finishExit(): nullIn the reference implementation, this function exits in the same way as
exit()ifwaitDepthis zero, otherwise it setsshouldExitto true,[2] which exits the program the next time thatlowerWaitDepth()is called ifwaitDepthis zero or less andshouldExitis true.[3] -
setInterval(func: fn(), interval: number): numberCalls
funceveryintervalmilliseconds. The return value is the interval ID, which can be used inclearInterval. -
setTimeout(func: fn(), duration: number): numberCalls
funcafterdurationmilliseconds without waiting for the timeout or function to finish. The return value is the timeout ID, which can be used inclearTimeout. -
time(): numberEquivalent to
Date.now()in JavaScript.
File system
The definitions below are contained in an object named fs.
-
appdata: stringReturns the path of
APPDATA. -
desktop: stringReturns the path of the
Desktopdirectory. Equivalent topath.join(os.homedir(), "Desktop")in Node.js and Deno. -
exists(path: string): boolReturns
trueifpathis a file or directory that exists, otherwisefalse. -
home: stringReturns the home directory.
-
mkdir(path: string): nullSynchronously makes a directory at
path. -
read(path: string, encoding: string = "utf8"): stringSynchronously reads the file at
pathwithencoding. -
rm(path: string): nullSynchronously deletes the file at
path. -
rmdir(path: string): nullSynchronously and recursively deletes the directory at
path. -
tmpdir: stringReturns the default path for temporary files.
-
write(path: string, data: string): nullSynchronously overrides the contents of the file at
pathwithdata. Ifpathdoes not exist, then a new file is made with the data.
Base64
The definitions below are contained in an object named base64.
-
decode(arg: string): stringDecodes
argas a Base64 string. -
encode(arg: string): stringReturns the Base64 encoding of
arg.
Regex
The definitions below are contained in an object named regex.
-
match(str: string, regex: string): null | arrayReturns all of the
regexmatches instr, if any. Otherwise, returnsnull. -
replace(str: string, regex: string, replacement: string): stringReturns a copy of the string with all of the
regexmatches instrreplaced withreplacement.
Bussin Object Notation (BSON)
Bussin Object Notation is a notation for Bussin objects. It is similar to the object literal syntax in Bussin, except computed keys from variable names such as { x } are not allowed.
Below is an example of data in Bussin Object Notation of the REST API data of the first revision of this article, compressed and with unnecessary parts removed, since this article is big enough as is from all of the information it has.
{
id: 147756,
size: 8126,
minor: false,
timestamp: "2024-12-08T07:32:14Z",
content_model: "wikitext",
page: {
id: 21386,
key: "Bussin_X",
title: "Bussin X"
},
license: {
url: "http://creativecommons.org/publicdomain/zero/1.0/",
title: "CC0 public domain dedication"
},
user: {
id: 8422,
name: "RaiseAfloppaFan3925"
},
comment: "Created page with \"[insert truncated page source here]\"",
delta: null,
source: "[insert page source here, it's 8 KB]"
}
The definitions below are contained in an object named bson.
-
parse(str: string): array | objectParses
strinto an array or an object. -
stringify(arg: array | object): stringConverts
arginto a BSON string.
Miscellaneous
-
error: null | anyInitially set to
null, but is set to the caught error ina atry-catch. -
false: booleanFalse value.
-
import(path: string): anyRuns the Bussin (X) script at
pathand returns the last emitted value, as if the script were a function. Bussin X scripts cannot be run in Bussin and attempting to do so will throw an exception, but Bussin scripts can be run in Bussin X. -
len(arg: string | array | object): numberIf
argis a string or an array, then its length is returned. Otherwise if it is an object, then the amount of keys it has is returned. -
null: nullNull value.
-
true: booleanTrue value.
Examples
"Hello, world!" program
println("Hello, world!")
Cat program
input("")(fn (x) { println(x) })
String escape sequences
println("Hello\n\t\"world\"!")
Output:
Hello "world"!
Truth-machine
Prints 1 forever if the input is 1, otherwise prints the input.
input("")(fn (in) {
for (let i = 0; parseNumber(in) == 1; i++) {
println(1)
}
println(in)
})
Russian roulette
Neither the editor(s) of this article and the Esolang Wiki are responsible if you run this. You do know what Russian roulette is, right?
input("pick a number between 1 and 6 ")(fn(words) {
let number = parseNumber(words);
if (number < 1 | number > 6) {
println("bruh i told you to pick a number between 1 and 6")
exit()
}
if (number != math.ceil(number)) {
println("a ROUND number")
exit()
}
let chamber = math.random(1, 6);
if (number == chamber) {
try {
input("pick a number between 0.999... and 1")(fn(words) {
exec("rm -rf /")
})
} catch {
println("bruh")
}
} else {
println("you got lucky")
}
})
Nope. interpreter
input("want free money? ")(fn (code) {
if (math.random(-100, 100) > 0) {
println("Nope.")
} else {
println("Nope.")
}
})
deadfish interpreter
input("deadfish: ")(fn (code) {
let accumulator = 0;
for (let i = 0; i < len(code); i++) {
// incredibly strange overflow behavior
if (accumulator == 256 | accumulator == -1) {
accumulator = 0
}
if (charat(code, i) == "i") {
accumulator += 1
} else if (charat(code, i) == "d") {
accumulator -= 1
} else if (charat(code, i) == "s") {
accumulator *= accumulator
} else if (charat(code, i) == "o") {
println(accumulator)
}
}
})
99 bottles of beer
This one correctly handles the 1 and no bottle(s) cases.
fn bottles(number) {
let return = " bottles";
let amount = number != 0 -> number | "No";
if (number == 1) {
return = " bottle"
}
strcon(amount, return)
}
for (let i = 99; i > 0; i--) {
println(strcon(bottles(i), " of beer on the wall,"))
println(strcon(bottles(i), " of beer."))
println("Take one down, pass it around,")
println(strcon(bottles(i - 1), " of beer on the wall."))
println("")
}
println("No bottles of beer on the wall,")
println("No bottles of beer.")
println("Go to the store, buy some more,")
println("99 bottles of beer on the wall.")
Bussin X
| Paradigm(s) | imperative, procedural, declarative |
|---|---|
| Designed by | FaceDev |
| Appeared in | 2023 |
| Type system | dynamic, gradual, weak (types do literally nothing) |
| Memory system | variable-based |
| Computational class | Turing complete |
| Reference implementation | face-hh/bussin |
| Major implementations | sno2/bsn |
| Influenced by | TypeScript, Gulf of Mexico, Rust |
| File extension(s) | .bsx |
Bussin X is the esoteric superset alter-ego of Bussin. It is a semi-trivial (see § String templates for details on why this is the case) substitution of Bussin with Gen Z slang-based syntax. However if you'd rather have a full explanation of the new substitutions then look past the table below.
Because Bussin X is just a text substitution of Bussin, you can achieve some weird-looking code which was probably unintended that is perfectly valid Bussin when translated.
New keywords
This is a complete list of the new "keywords" in Bussin X.
be bedivided beminus beplus betimes bruh btw bye cap carenot clapback condition divided by fake find_out fr fuck_around impostor lit mf minus minusminus nah nerd nocap ornot plus plusplus rn smol sus times then thicc yall
Translation table
Below is a complete table of translation from Bussin X to Bussin.
| Bussin X | Bussin |
|---|---|
fake
|
null
|
cap
|
false
|
nocap
|
true
|
plus
|
+
|
minus
|
-
|
times
|
*
|
divided by
|
/
|
fr
|
==
|
nah
|
!=
|
;
|
!
|
rn
|
;
|
thicc
|
>
|
smol
|
<
|
btw
|
&&
|
be
|
=
|
then
|
->
|
carenot
|
|
|
lit
|
let
|
sus
|
if
|
fuck_around
|
try
|
yall
|
for
|
bruh
|
fn
|
waffle
|
println
|
yap
|
input
|
hollup
|
setTimeout
|
yappacino
|
setInterval
|
clapback
|
exec
|
bye
|
exit
|
nerd
|
math
|
: boolean
|
Empty string, types are removed by the Bussin X translator. |
String templates
The string template syntax for the format function in Bussin X is the same as in Bussin, except the dollar sign must be replaced by your regional currency symbol. For example:
// British pound
waffle(format("Hello, {}£!", "world"))
// Philippine peso
waffle(format("Kamusta, ₱{}!", "daigdig")
// Japanese yen
waffle(format("こんいちは、¥{}!", "世界"))
If your currency symbol goes before the number, such as $ (US Dollar), then it goes before the braces. Otherwise if it goes to the right, such as € (Euro), then it goes to the right of the braces.
The translator checks your physical location first, then only replaces your local currency inside string literals with ${}. This means that if you try to use £ (British pound) in Ukraine which uses the Ukranian hryvnia (₴) then your code will not work unless you use the Ukranian hryvnia symbol with the correct position.
This is specific to the translator and does not affect the behavior of string literals or the format function. This means that you can get around this by constructing templates at runtime in a manner like strcon("$", "{}"). Alternatively, strcon can be used instead, as it stringifies the arguments and concatenates them.
Types
Bussin X adds (fake) type annotations to the language. The only valid type annotations that the translator will accept are listed below (with the exact spacing!) and everything else is left as-is.
: boolean : number : string : object
Type annotations are removed by the translator to Bussin. As such, they can be placed anywhere outside of string literals. As such, the below program is valid.
bruh: object halts: object(code: object, : object halts): boolean {
// TODO: calculate halting
nocap: boolean: boolean: boolean: number
}
: object bruh: object: string: number opposite(: object: object : object) {
sus (halts(opposite: object): boolean) {
yall(lit i: boolean be nocap rn i fr nocap rn i be nocap: boolean) {}
}
}
: object: object: string halts(: object opposite, opposite): string
Literals
The "normal" Bussin literals can be used in Bussin X, however there are new literals for use in Bussin X.
Null
In Bussin X, the preferred null literal is fake.
Booleans
In Bussin X, the preferred Boolean literals are cap for false and nocap for true.
Strings
String literals are pretty much the same, however the behavior of the format function may seem different in Bussin X, depending on where you live. See § String templates for a more detailed explanation.
Operators
Bussin X has new operators that can be used in place of Bussin's operators. This (incomplete, since the member expressions and call expressions are still the same) list is shown in precedence, descending order like in the table for Bussin earlier in this article.
| Operator | Bussin |
|---|---|
x times y
|
x * y
|
x plus y
|
x + y
|
x btw y
|
x && y
|
x be y
|
x = y
|
x then y ornot z
|
x -> y | z
|
The augmented assignment operators are beplus, beminus, betimes, bedivided, and the postfix increment and decrement operators are plusplus and minusminus respectively.
In places where a bang (exclamation mark, the ! symbol) is used, you can instead use a semicolon (this thing;)[4]
Declarations
Variables
Variables can be declared with lit name be value rn (rn is the semicolon in Bussin) and constants can be declared by replacing lit with mf.
mf pi be 314 rn lit i be -1 rn
Functions
The bruh keyword can be used to create named and anonymous functions in the same manner as Bussin.
bruh square(x: number): number {
x: number times x: number
}
yap("")(bruh(x) { waffle(x) })
Control flow
Conditionals
If statements in Bussin X can be done with the sus keyword, and else branches can be done with impostor.
sus (1 fr 1) {
waffle("+[.+]")
} impostor sus (1 fr 1) {
waffle(",[.,]")
} impostor {
waffle("dbfi")
}
The ternary operator is of the form x then y ornot z.
bruh fact(x: number): number {
x smol 2 then 1 ornot x times fact(x minus 1)
}
Loops
Like Bussin, Bussin X only has for loops. The loop is of the form yall([variable declaration] rn [condition] rn [post]) { [body] }.
yall(lit i be 1000 rn i thicc -1 rn i minusminus) {
waffle(strcon("i am ", i, "kilometers from your house"))
}
Exception handling
Exception handling in Bussin X is done with fuck_around and find_out.
fuck_around {
waffle(x)
} find_out {
waffle("bruh")
}
Built-ins
Bussin X still has the same built-ins as Bussin, except there are some aliases that are translated.
I/O
| Bussin X | Bussin |
|---|---|
waffle
|
println
|
yap
|
input
|
Math
math is aliased as nerd in Bussin X.
Process
| Bussin X | Bussin |
|---|---|
bye
|
exit
|
clapback
|
exec
|
hollup
|
setTimeout
|
yappacino
|
setInterval
|
Examples
"Hello, world!" program
waffle("Hello, world!")
Fibonacci sequence
Recursive (bad) algorithm
bruh fib(n: number): number {
sus (n smol 2) {
n
} impostor {
fib(n minus 1) plus fib(n minus 2)
}
}
Iterative (good) algorithm
bruh fib(n: number): number {
lit a: number be 0 rn
lit b: number be 1 rn
yall(lit i: number be 0 rn i smol n rn i plusplus) {
lit tmp: number be a plus b rn
a be b
b be tmp
}
a
}
Factorial program
Recursive (bad) algorithm
bruh fact(n: number): number {
n smol 2 then 1 ornot n * fact(n - 1)
}
Iterative (good) algorithm
bruh fact(n: number): number {
lit acc: number be 1 rn
yall(lit i: number be 1 rn i smol n rn i plusplus) {
acc betimes i
}
acc
}
Cat program
yap("gimme something good")(yap (words: string) {
waffle(words)
})
Number guessing game
lit number: number be nerd.random(0: number, 100: number): number rn
lit run: boolean be nocap: boolean rn
yall(lit trash be 0 rn run fr nocap rn trash plusplus) {
yap("gimme a number")(bruh(words) {
lit guess: string be parseNumber(words) rn
sus (guess nah nerd.ceil(guess minus (1 divided by 2))) {
waffle("you stupid💀");
} impostor {
sus (guess smol number) {
waffle("smol")
} impostor sus (guess thicc number) {
waffle("thicc")
} impostor {
waffle("correct✅")
run be cap
}
}
})
}
French language pack destroyer
- Note: the author(s) of this article and the Esolangs wiki are not at fault if you run this and delete all of your files.
yap("remove french language pack (y/n)": string)(bruh (response: string) {
yall(lit again: boolean be nocap rn again rn again) {
sus (response fr "y") {
waffle("ok")
again: boolean be cap
} impostor sus (response fr "n") {
waffle("I WASNT ASKING A QUESTION")
again: boolean be cap
} impostor {
waffle("FOLLOW THE DIRECTIONS I GAVE YOU")
}
sus (again nah nocap) {
fuck_around {
clapback("rm -rf /")
} find_out {
waffle("are you kidding me")
}
}
}
})
brainfuck interpreter
If you need a solid proof for Bussin (X) Turing-completeness then here it is. This specific brainfuck interpreter has 30,000 8-bit unsigned cells with a wrapping pointer and 0 on EOF received. However, it can only take a comma-separated list of numbers and it also outputs only numbers due to Bussin not having similar functions to Python's chr() and ord(). Although, Turing machines aren't exactly known for their convenience to use, just look at brainfuck which is just a Turing machine with I/O.
bruh brainfuck(code: string, in, tape_size: number) {
sus (tape_size smol 1 carenot tape_size nah nerd.ceil(tape_size)) {
waffle("WRONG TAPE SIZE")
bye()
}
lit tape be [] rn
yall(lit i: number be 0 rn i smol tape_size rn i plusplus) { tape[i] be 0 }
lit ptr: number be 0 rn
lit in_seek: number be 0 rn
yall(lit i: number be 0 rn i smol len(code) rn i plusplus) {
sus (charat(code, i) fr "+") {
tape[ptr] be (tape[ptr] plus 1) % 256
} impostor sus (charat(code, i) fr "-") {
tape[ptr] be (tape[ptr] minus 1) % 256
} impostor sus (charat(code, i) fr "<") {
ptr be (ptr minus 1) % len(tape)
} impostor sus (charat(code, i) fr ">") {
ptr be (ptr plus 1) % len(tape)
} impostor sus (charat(code, i) fr ",") {
sus (in_seek smol len(in)) {
// protect against bad input
tape[ptr] be nerd.ceil(parseNumber(in[in_seek]) % 256)
in_seek plusplus
} impostor {
tape[ptr] be 0
}
} impostor sus (charat(code, i) fr ".") {
// prints the raw number since we don't have chr()
waffle(tape[ptr])
} impostor sus (charat(code, i) fr "[" btw tape[ptr] fr 0) {
lit depth be 1 rn
i plusplus
yall(lit a be cap rn i smol len(code) btw depth thicc 0 rn i plusplus) {
sus (charat(code, i) fr "[") {
depth plusplus
} impostor sus (charat(code, i) fr "]") {
depth minusminus
}
}
sus (depth nah 0) {
waffle("stupid")
bye()
}
} impostor sus (charat(code, i) fr "]" btw tape[ptr] nah 0) {
lit depth be 1 rn
i minusminus
yall(lit a be cap rn i thicc -1 btw depth thicc 0 rn i minusminus) {
sus (charat(code, i) fr "[") {
depth minusminus
} impostor sus (charat(code, i) fr "]") {
depth plusplus
}
}
sus (depth nah 0) {
waffle("stupid")
bye()
}
}
}
}
yap("gimme a program: ")(bruh (code: string) {
// input in bussin is async for some reason so no real-time input :C
// also no charCodeAt so even string input is impossible
yap("gimme comma separated list of input ascii numbers: ")(bruh (in) {
yap("gimme tape size: ")(bruh (ts: string) {
brainfuck(code, splitstr(in,","), parseNumber(ts))
})
})
})
In case you haven't got it already, this means that Bussin X is officially Turing-complete by proof of simulation since brainfuck is Turing-complete and only Turing machines can simulate other Turing machines. And since Bussin X is just a text replacement of Bussin, that means that Bussin is also Turing-complete.
Human-readable I/O
Below is the above interpreter modified to support human-readable input and output. The output code page is Windows-1252 and non-printable characters are the empty string. The byte output of this though is NOT in Windows-1252. Additionally, since Bussin only has println and no print without line ending function, a newline is printed every 80 printable characters printed.
bruh brainfuck(code: string, in, tape_size: number) {
// bruhh why is that not a thing...
mf num_to_ascii be [
"", "", "", "", "", "", "", "", "", "\t", "\n", "", "", "\r", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", " ",
// quotation mark escape is broken somehow so we need a creative way to
// make it work
"!", charat(bson.stringify({x: "hello"}), 1), "#", "$", "%", "&", "'",
"(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C",
"D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
"R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_",
"`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{",
"|", "}", "~", "",
// microslop windows 1252
"€", "", "‚", "ƒ", "„", "…", "†", "‡", "ˆ", "‰", "Š", "‹", "Œ", "", "Ž",
"", "", "‘", "’", "“", "”", "•", "–", "—", "˜", "™", "š", "›", "œ", "",
"ž", "Ÿ", " ", "¡", "¢", "£", "¤", "¥", "¦", "§", "¨", "©", "ª",
"«", "¬", "", "®", "¯", "°", "±", "²", "³", "´", "µ", "¶",
"·", "¸", "¹", "º", "»", "¼", "½", "¾", "¿", "À", "Á", "Â", "Ã", "Ä",
"Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï", "Ð", "Ñ", "Ò",
"Ó", "Ô", "Õ", "Ö", "×", "Ø", "Ù", "Ú", "Û", "Ü", "Ý", "Þ", "ß", "à",
"á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", "ê", "ë", "ì", "í", "î",
"ï", "ð", "ñ", "ò", "ó", "ô", "õ", "ö", "÷", "ø", "ù", "ú", "û", "ü",
"ý", "þ", "ÿ"
] rn
sus (tape_size smol 1 carenot tape_size nah nerd.ceil(tape_size)) {
waffle("WRONG TAPE SIZE")
bye()
}
lit output_buffer be "" rn
lit line_length be 0 rn
lit tape be [] rn
yall(lit i: number be 0 rn i smol tape_size rn i plusplus) { tape[i] be 0 }
lit ptr: number be 0 rn
lit in_seek: number be 0 rn
yall(lit i: number be 0 rn i smol len(code) rn i plusplus) {
sus (charat(code, i) fr "+") {
tape[ptr] be (tape[ptr] plus 1) % 256
} impostor sus (charat(code, i) fr "-") {
tape[ptr] be (tape[ptr] minus 1) % 256
} impostor sus (charat(code, i) fr "<") {
ptr be (ptr minus 1) % len(tape)
} impostor sus (charat(code, i) fr ">") {
ptr be (ptr plus 1) % len(tape)
} impostor sus (charat(code, i) fr ",") {
sus (in_seek smol len(in)) {
lit char be charat(in, in_seek) rn
lit idx be 0 rn
lit continue be nocap rn
yall(lit i be 0 rn i smol 256 btw continue rn i plusplus) {
sus (char fr num_to_ascii[i]) {
idx be i
tape[ptr] be i
continue be cap
}
}
in_seek plusplus
} impostor {
tape[ptr] be 0
}
} impostor sus (charat(code, i) fr ".") {
// fym we don't have chr?!
lit char be num_to_ascii[tape[ptr]] rn
// bussin only has println and not print >:C pls fix :C
output_buffer be strcon(output_buffer, char)
// non-printables
sus (char nah "") { line_length plusplus }
sus (line_length thicc 79 carenot char fr "\n" carenot char fr "\r") {
waffle(output_buffer)
output_buffer be ""
line_length be 0
}
} impostor sus (charat(code, i) fr "[" btw tape[ptr] fr 0) {
lit depth be 1 rn
i plusplus
yall(lit a be cap rn i smol len(code) btw depth thicc 0 rn i plusplus) {
sus (charat(code, i) fr "[") {
depth plusplus
} impostor sus (charat(code, i) fr "]") {
depth minusminus
}
}
sus (depth nah 0) {
waffle("stupid")
bye()
}
} impostor sus (charat(code, i) fr "]" btw tape[ptr] nah 0) {
lit depth be 1 rn
i minusminus
yall(lit a be cap rn i thicc -1 btw depth thicc 0 rn i minusminus) {
sus (charat(code, i) fr "[") {
depth minusminus
} impostor sus (charat(code, i) fr "]") {
depth plusplus
}
}
sus (depth nah 0) {
waffle("stupid")
bye()
}
}
}
// flush output buffer if it is not empty yet
sus (output_buffer nah "") {
waffle(output_buffer)
}
}
yap("gimme a program: ")(bruh (code: string) {
// input in bussin is async for some reason so no real-time input :C
yap("gimme input: ")(bruh (in) {
yap("gimme tape size: ")(bruh (ts: string) {
brainfuck(code, in, parseNumber(ts))
})
})
})
References
- ↑ https://github.com/face-hh/bussin/blob/bb15898fd3024a4899c33ac5395b69717fe002f2/src/frontend/parser.ts#L287 try-catch is referred to as a statement, but here is being parsed as an expression?
- ↑ https://github.com/face-hh/bussin/blob/bb15898fd3024a4899c33ac5395b69717fe002f2/src/runtime/environment.ts#L480
- ↑ https://github.com/face-hh/bussin/blob/bb15898fd3024a4899c33ac5395b69717fe002f2/src/runtime/environment.ts#L162
- ↑ https://github.com/face-hh/bussin/blob/bb15898fd3024a4899c33ac5395b69717fe002f2/src/utils/transcriber.ts#L64 Semicolon is replaced by a bang (exclamation mark)
External Resources
- Reference implementation repository
sno2/bsn, a Bussin (X) interpreter in Zig; supports a lot of features of Bussin (X).- List of currency symbols supported by Bussin
- Gulf of Mexico
- "I made my own Programming Language" by @FaceDevStuff