Introduction
What is Mewl?
Mewl is an esoteric programming language. It has syntax very similar to Lisp. Mewl can be very confusing, because many of its design choices I made, for example there are no concept of traditional number system in mewl, or there are no strings, no arrays, and cherry on top, you can not use any word except mew
(Comments are exception).
🤔 What,Why?
Well, 2 years ago in 2020, I created an esoteric programming language called Mewmew. It was just a fun and experimental language I made while tinkering with ANTLR, cause I was (am still) fascinated about programming languages, interpreter/compilers; how they work; how they basically become the medium of interaction between humans and computers and/or machines. But with ANTLR, I didn't actually learn much about compiler/interpreter construction. It just worked! No fun! So, In the October of 2021, I started re-writing the whole thing from scratch with Rust. I was able to build a lexer; a basic parser; But then I realized, syntax of 'mewmew' is ugly. I hurts my eyes to look at a 'mewmew' source code. Again in, March 2022, I started experimenting with mewmew lanugage but with lisp style syntax, 'cause lisp is awesome. So, here is the result, Mewl , mewmew reborn with the syntax similar to lisp. Most important thing, I am having fun while developing mewl, and the syntax doesn't hurt my eyes that much.
Numbers
There is no concept of traditional numbers in mewl instead we use mew
s.
For example you want to write 5
you could do something like this
mewmewmewmewmew
or maybe 2
mewmew
So basically 1 mew
is equivalent to 1; 2 mew
s is equivalent to 2 and so on.
:warning: Important Note: We don't have zero, to get zero we use subtraction [- mew mew]
(it's like 1-1
= 0) [Mathematical operations will be discussed later]
But what about large numbers like 100 , 2022 , 500 or maybe -10
, -3.1
, for that we have some shortcuts, like these :
To write large numbers we can use mathematics, like [* mewmew mewmewmewmewmew]
is equal to 10, or multiplying that expression with itself we can get 100. But that's cumbersome and complicated! Instead we have a simpler (relatively) syntax shortcut.
Lets write 100:
[mew [- mew mew] [- mew mew]]
How about 2022:
[mewmew [- mew mew] mewmew mewmew]
Above two examples will only work when assigning to a variable, but if we want to use these expressions anywhere we have to put this ' single single quote character just after the opening bracket. Something like this:
[' mew mew [+ mew mew]] //is equal to 112
It is being evaluated like this:
flowchart TD; A["[' mew mew [+ mew mew]"] --> B["[' mew mew [2]]"] B-->C["[' 1 1 2]"] C -- Output --> D[112]
But If we remove this ' character and it is not being assigned to a variable or being printed to the stdout, it is going to be evaluated like this and will throw an error:
flowchart TD; A["[ mew mew [+ mew mew]]"] --> B["[mew mew 2]"] B-->C["[ 1 1 2]"] C-->D{Error: No operation to do!}
Identifiers and Assignment
In mewl, identifiers just look like mew numbers, so be careful when reading/writing mewl programs.
Some backstory:
While I was designing mewl identifiers, I was confused about identifiers, I wanted something crazy but usable. So I just decided to go with
mew
, but to distinguish numbers from identifiers, I needed something special . Now, please continue.
Identifiers/Variables
In mewl, identifiers look something like this -> ~mew
, ~mewmew
etc.
So basically, Identifiers follow the same syntax as mew numbers but with a leading ~
(tilde) character.
~mew
, ~mewmew
, ~mewmewmewmewmew
, these all are identifiers.
Assignment
Assignments are little awkward, it'd be easy to understand with examples:
[=mew [+ mew mew]]
This expression assigns 2 to the variable ~mew
and this expression [:: ~mew]
would print the value of variable ~mew
(which is 2 )
If you want to assign something to variable, write the identifier with a leading =
(equal sign) without any space(s).
In short, =mew
tells the interpreter to evaluate the following expression(s) and store it in variable ~mew
.
For example,
[=mewmew [* mewmew mewmew]]
would store 9 in a variable which can be accessed via ~mewmew
.
I know, it is confusing.
More examples:
-
[=mewmewmew [+ mew mew [* mewmew mewmew]]]
would store 6 to a variable which to be accessed via~mewmewmew
-
Another one
[=mewmewmewmewmew [' mew mew mewmew]] [:: ~mewmewmewmewmew]
it would print 112 to stdout
[Info Note]: Assiging something using =mewmewmewmewmew
wouldn't change the meaning of mewmewmewmewmew
as a mew number which still is 5
Basic Operations
Binary Operations
Mewl supports few commonly used binary operators such as addition, subtraction, division, multiplication etc.
Operation | Symbol | Notes |
---|---|---|
Addition | + | - |
Subtraction | - | - |
Multiplication | * | - |
Division | / | [/ m1 m2 m3] -> m1 ÷ m2 ÷ m3 |
Power | ** | Evaluates just like division |
Remainder | % | evaluates just like division |
Unary Minus Operation
There're not specific way to use unary minus Operations in mewl, for example, [+ mew -mew] This should've been evaluated like this , (+1 -1) = 0. But mewl will throw an error if you do something like that. If we want to get -1, we have to do something like this
[- [- mew mew] mew]
It's basically, \(0-x = -x\)
Bitwise Operations
⚠️ Important Reminder : As Bitwise operations cannot be applied on floating point numbers; and in mewl all numbers are 64bit floats, so before doing any bitwise operation numbers are converted to 64bit signed integers and the answer returned is converted to float from signed integer
Operation | Symbol | Notes |
---|---|---|
Shift right | >> | [>> m1 m2 m3] -> m1 >> m2 >> m3 |
Shift Left | << | Same as above |
XOR | ^ | " |
AND | && | " |
OR | ## | " |
NOT | !! | [Note1] |
🙀 [Note1] : As bitwise not !!
Is an unary operation there can be unexpected behaviors if applied to an expression list, for that it will only be applied on the first element of an expression.
Comparisons (Boolean Operations)
Important Note: In mewl True = 1.0
(mew) and False = 0.0
([- mew mew])
Operation | Symbol | Note |
---|---|---|
Is equal | == | [== m1 m2 m3] -> m1== m2==m3 |
Not equal | != | similar to previous |
Less than | < | " |
Less than or equal | <= | " |
Greater than | > | " |
Greater than or equal | >= | " |
Or | # | " |
And | & | " |
Not | ! | As this is an unary operation so it's applied on the first element of the given expression |
Reading from Stdin and Writing to Stdout
Writing to Stdout
To print something on the stdout we have two options, first we can print the expression or atom as is or we can convert the expression values to ASCII characters and print them to stdout.
Symbol | What | Notes |
---|---|---|
:: | Print the expression or atom to stdout as-is | [:: mew mew] will print 1 1 to stdout |
::: | Convert the next atom/expression to ASCII characters and print to stdout | [:::['[+[* mewmewmew mewmew] mew] mewmew]] will print H to stdout |
Examples
Here's a overly complicated Hello World
program in mewl
[=mew [[+[* mewmewmew mewmew] mew] mewmew] ] //H
[=mewmew [mew [- mew mew] mew]] //e
[=mewmewmew [mew [- mew mew] [* mewmewmewmew mewmew]]] //l
[=mewmewmewmew [mew mew mew]] //o
[=mewmewmewmewmew [mewmewmew mewmew]] //SPACE
[=mewmewmewmewmewmew [[* mewmewmewmew mewmew] mewmewmewmewmewmewmew]] //W
[=mewmewmewmewmewmewmew [mew mew mewmewmewmew]] //r
[=mewmewmewmewmewmewmewmew [mew [- mew mew] [- mew mew]]] //d
[=mewmewmewmewmewmewmewmewmew [mewmewmew mewmewmew]] //!
[::: ~mew //H
~mewmew //e
~mewmewmew //l
~mewmewmew //l
~mewmewmewmew //o
~mewmewmewmewmew //SPACE
~mewmewmewmewmewmew //W
~mewmewmewmew //o
~mewmewmewmewmewmewmew //r
~mewmewmew //l
~mewmewmewmewmewmewmewmew //d
~mewmewmewmewmewmewmewmewmew //!
]
Reading From Stdin
Symbol | What? | Notes |
---|---|---|
\|> | Read a mew number or normal number from Stdin and store to a variable | Trailing whitespace gets trimmed |
`| | >` | Read a string from stdin, calculate the length of the string and store to a variable |
Read Mew/Normal Number from Stdin
Syntax of reading mew/normal number from stdin is:
[|> Variable_To_Store_Number]
Here's a simple example,
[|> =mew]
[:: ~mew]
This example, reads a number/mewnum from stdin and prints it to stdout.
- Learn about Identifiers/Assignment
Read a String from Stdin and store the length
Syntax is just like reading number from stdin,
[||> =mew]
[:: ~mew]
Just like before, read a string from stdin and print the length of the string.
Example/Usage
a. Count the character of a file using mewl
First, let's create a simple script (it is just the above example code)
[||> =mew]
[:: ~mew]
save it with filename char_len.mew.txt
Now, we need the target file, from which we will count characters from, for this example we will create a file,
$ echo "Foo bar" >foobar.txt
Now, run
$ cat foobar.txt | mewl char_len.mew.txt
If everything is right, you'll see 7
in the terminal!
Example Programs
Hello World
[=mew [[+[* mewmewmew mewmew] mew] mewmew] ] //H
[=mewmew [mew [- mew mew] mew]] //e
[=mewmewmew [mew [- mew mew] [* mewmewmewmew mewmew]]] //l
[=mewmewmewmew [mew mew mew]] //o
[=mewmewmewmewmew [mewmewmew mewmew]] //SPACE
[=mewmewmewmewmewmew [[* mewmewmewmew mewmew] mewmewmewmewmewmewmew]] //W
[=mewmewmewmewmewmewmew [mew mew mewmewmewmew]] //r
[=mewmewmewmewmewmewmewmew [mew [- mew mew] [- mew mew]]] //d
[=mewmewmewmewmewmewmewmewmew [mewmewmew mewmewmew]] //!
[::: ~mew //H
~mewmew //e
~mewmewmew //l
~mewmewmew //l
~mewmewmewmew //o
~mewmewmewmewmew //SPACE
~mewmewmewmewmewmew //W
~mewmewmewmew //o
~mewmewmewmewmewmewmew //r
~mewmewmew //l
~mewmewmewmewmewmewmewmew //d
~mewmewmewmewmewmewmewmewmew //!
]
Fibonacci