Moon

a programming language

View on GitHub

Moon programming language

Variables:

$name = "mobin"
# this makes 'name' variable

grade = 'A'!
# normal one

<time = 5>
# with <>

number := 5
# another way to create a variable, it's by :=

my number = 0
# creating local variable by 'my'

local name = "Mobin"
# creating local variable by 'local'

native number = 5
# creating local variable by 'native'

our grade = 'A'
# normal variable

lit $n = 0
# creating variables with lit

set n to 8
# creating variables with set and to

@name = "Mobin"
# class variable that is created in __main__ class

static num = 0
# global variable

global n
n = 5
# another global

auto thing = [0, 1]
# auto type choose
# no diffrence, cause Python usually doesn't care about types

never shit = nothing
# a variable which, it will NOT be used, so: 'puts shit' has Error

let 🌑 = "Moon"
# a variable which will be saved on STACK dict
# NOTICE: this is let, and is diffrent with lit

NOTICE

When i was writing this file (REDAME), i did NOT write concepts by the degree of importance! I just wrote them wherever i was at the file (README)

Comments:

as you see in code, we use ‘#’ for writing comments

# moon is a programming language

NOTICE: Moon doesn’t have a multi-line comments NOTICE: Do NOT write comments in front of an expr, it will NOT be ran

lit

this is a keyword to make a varaible, but this will be saved into VARIABLES dict! maybe we can call it a version of local variables but you access these variables only with io.vprint or io.vprintln or io.vprintf

lit $name = "Mobin"
io.vprintln('$name')!

$

as you know, it’s a way for creating variables, but it has some features, like:

$a = () -> Nil
# lambda
$b = ?h
# char
$c = %s[Hello]
# string
$d = %(Hello)
# string
$e = (0..10)
# range
$f = !True
# ! = not
$g = "Woops"
# normal shit

OOP:

moon is an object-oriented programming language

class Car:
    def __init__(self, name, year):
	    self.name = name
	    self.year = year
end
# you should end the block with end
# but only the first block needs end
# so you do not need to use end for '__init__'

BMW = Car("BMW", 2024)
# creating an instance of Car
io.print(BMW)!
# for calling function there are some ways

Calling functions:

io.print("moon")!
# end with '!' for calling it

<io.print("moon")>
# write it between '<' and '>'

io.sprint -> "moon"
# use '->'
# but '->' prints the result
# so we use io.sprint for not getting nil
# because io.print at the end returns nil

# so:
$x = io.print("moon")
io.print(x == nil)!
# True

def say_hello():
    io.print("hello")
end
say_hello <-
# if the function gets no parameter, you can call it with <-
# you can also call this function (that takes no param) like this:
# say_hello -> 

io.print => "hello"
# this will not print the result
# so we do not take nil (e.g. in printing)

say_hello <=
# if the function gets no parameter, you can call it with <=
# you can also call this function (that takes no param) like this:
# say_hello => 
# but as i said, it does not print the result !

'printf "Hello"
# this is OK
# but only for the callings that they need at least one argument, not more !
# 'printf "Hello", "World"
# not OK
# note that for this one, it needs to be started with '

if - elif - else:

if True:
    io.print("one")
elif True:
    io.print("two")
else:
    io.print("three")
# one

alpha-numbers:

there are alpha-numbers in moon like one, two, …

io.print(one + two)
# 3
# it is from one to ten, not higher

# but you can make it like
# eleven = "1" + "1"
# so:
$eleven = to_i(to_s(one) + to_s(one))
# to_s function return the string type of the param
# to_i function return the int type of the param
# as same as: int("1" + "1")

Lambda functions:

$double  = lambda a: a * 2
$double2 = (a) -> a * 2

Loops:

for x in [1, 2]:
    io.print(x)
    # 1
    # 2
end

$x = 0
while x < 5:
    io.print(x)
    x += 1
    # 1 
    # ...
    # 4
end

$x = 0
until x < 5:
    io.print(x)
    x += 1
    # 1 ... 4
end

$x = 0
unless x == 5:
    io.print(x)
    x += 1
    # 1 .. 4
end

$list = Range('d', 'f').new()
foreach elem as list:
    printf(elem)
end

loop:
    fmt.Println("Hello")
end

Pipeline:

nil |> typeof |> io.print
# this is as same as:
io.print(typeof(nil))
# #<nil>

switch-case:

$name = "mobin"
switch name:
    case "mobin":
    # if name == "mobin": ...
        io.print("author")
    case _:
    # else: ...
        io.print("user")
end
# "case _" means else !

do-block

# FUNCTION_OR_STH do |NAME|:
#   ...
# end
io.open("main.txt", "r") do |file|:
    io.printf("%s", io.freads(file))
end

io

io is one of the built-in classes, it has so GOOOOD functions you can use in your program

print(*values, sep="\t") -> nil
# prints values with seperator \t (of course you can change it !) and at the end it does not print a new line, and returns nil

println(*values, sep="\t") -> nil
# prints values with seperator \t (of course you can change it !) and at the end it prints a new line, and returns nil

throw(__err, message: str = "") -> NoReturn
# raises the __err ( MUST be derived from BaseException ) with message message

open(file, mode) -> IO_WRAPER
# opens the file with mode mode

freads(file) -> list
# reads lines from file

fread(file) -> str
# reads a line from file

freadc(file) -> str
# reads a char from file

fprint(file, *values) -> nil
# puts values in file and a new line, then returns nil

fprintf(file, base: str, *other) -> nil
# puts base % other in file and a new line, then returns nil
# it formats the base
io.open("...", "r") do |file|:
    io.fprintf(file, "hello %s", "mobin")
end

close(file) -> NoReturn
# closes the file

status(file) -> str
# returns the status of the file (is opened or closed)

read(prompt) -> str
# gets an input with prompt, and saves the input in _

fwrite(*values, file) -> nil
# writes values in file, then returns nil

gets -> str
# gets an input string and saves it in _

getc -> str
# gets an input char and saves it in _

putc(*values) -> nil
# prints a char
# if any type except char is given, raises error

printf(base: str, *values) -> nil
# if base is not string, raises error
# prints base % values

sprint(value) -> Any
# returns value
$name = io.sprint("mobin")
# name = "mobin"

sprintf(base: str, *values) -> nil
# formatted sprint

var_dump(*values) -> nil
# prints some result about values
# prints: TYPE(LENGTH) VALUE
io.var_dump("hello")
# str(5) hello

Return(value) -> Any
# returns value

system(command) -> int
# this will use os.system to execute command

print_r(__value: list | dict | set | tuple) -> nil
# prints the __values but in pretty way
# if __value is not list or dict or set or tuple, raises error
# then returns nil

exit(code: int = 0) -> NoReturn
# system exit with code code

id(__obj: object) -> str
# return hex format of int id of __obj
# this is guaranteed to be unique for every object

rand(max: int) -> int
# returns random.randint(0, max)
# = 
# returns a random number in [0, max]
# this is a math range, if your math is good you uderstood it
# but if no, 
# [0, max] means, if we call the random number 'x'
# so: 0 <= x <= max
# if you didn't understand, just f*ck off BRO

sleep(sec: float) -> NoReturn
# sleeps for sec

format
# just like sprintf

catch(__to_do: str, __err_type)
# it tries: exec(__to_do)
# excepts BaseException as e, if type of e is not the __err_type
# returns ERR, else prints e, then returns True, and if there is no problem, returns nil
# so
# if there is error and __err_type is the error type, it returns True
# but if there is error and __err_type is not the error type, it returns ERR
# but if there is no error, 
# it returns nil
# look at this example: 
$x = io.catch("io.printf(hello)", NameError)
io.printf("%s", x == True)!
# error, True
$x = io.catch("io.printf(hello)", KeyError)
io.printf("%s", x == ERR)!
# True
$x = io.catch("io.printf('hello')", NameError)
io.printf("%s", x == nil)!
# 'hello', True

pprint(*values) -> nil
# pretty print values with \n

pprintf(base: str, *other) -> nil
# formated pretty print with \n

puts(*values) -> nil
# uses pprint to pretty print values

lprint(value) -> Any
# uses for printing local variables ( my, local, native )
# note that value must be string
# this function does not print an '\n' at the end

lprintln(value) -> Any
# uses for printing local variables ( my, local, native )
# note that value must be string
# this function does print an '\n' at the end

cprint(*values, sep="\t", end="\n", file=stdout) -> Any
# uses for printing values but, customly !

vprint(*values)
# prints variables that are created by lit keyword
# each value must be string

    lit $name = "moon"
    io.vprintln('$name')!

vprintf(format, *values)
# formated version

vprintln(*values)
# prints variables that are created by lit keyword, with \n at the end

warn(msg="")
# raises a warning with msg

error(__type, msg)
# raises the __type error with msg

putchar(code)
# returns chr of code

putchars(*codes)
# returns chr of codes in one string

countc(string, what_char)
# returns the count of what_char in string

assertEqual(a, b)
# asserts if a and b are equal

assertTrue(a)
# asserts if a is true (not just True, but also all true values)

assertFalse(a)
# asserts if a is false (not just False, but also all falsy values)

scanf()
# returns the input

strlen(s)
# returns the length of s

strcpy(s)
# returns a copy of s

strcat(a, b)
# returns joined version of a and b

atoi(s)
# returns int version of s

atof(s)
# returns float version of s

abort()
# exits the program with code 1

alert(value)
# returns a warning with msg

echo(key)
# it will print the value of the given key in STACK dict, that you can define vars with let keyword at it

fmt

a standard library for Moon

Fprint(write_to, *a)
# prints "a" to write_to file

Fprintf(write_to, format, *a)
# prints formated version of "a" in write_to file

Fprintln(write_to, *a)
# as same as Fprint but with a \n in the end

Print(*values)
# prints values

Printf(format, *values)
# prints formated version of values

Println(*values)
# prints values with \n at the end

Sprint(*values)
# returns values
# this is used to save values in variable(s)

Sprintf(format, *values)
# returns formated version of values

Sprintln(*values)
# returns values with \n at the end

Puts(*values)
# prints values

Putc(*values)
# prints char
# if values are not char, this will print the first char of value
# not for nums

Lprint(*values)
# prints values, but they must be list

Lprintln(*values)
# prints values, but they must be list with \n at the end

Pprintln(*values)
# pretty print of values with \n at the end

Pprintf(format, *values)
# pretty print of values with \n at the end

Open(file, mode)
# opens the file with mode mode

Fget(file)
# returns file.readline()

Fgets(file)
# returns file.readlines()

Fgetc(file)
# returns first char of file.readline()

Fputs(file, to_write)
# writes to_write in file

Eprint(message)
# prints message to stderr

Eprintf(format, message)
# prints formated message to stderr

Eprintln(message)
# prints message to stderr with \n at the end

discard

uses for deleting a variable from your file but it is used for local variables ( my, local, native )

my num = 0
io.lprint(num)!
discard num
io.lprint(num)!

defer

Defer is used to ensure that a function call is performed later in a program’s execution, usually for purposes of cleanup.

defer printf("Bye World")

END

END block will be executed last

END {
  
  printf("Bye World")

}

defer vs. END

defer is for doing a work but END is a block, so you can do numbers of works

note: if you have defer and END block at the same time in your file, first, defer will be ran, then END block so END block is a better end for your program

loop

creates an infinite loop

loop:
    fmt.Println("Hello")
end

macro

macros can be defined by define or macro keyword

define __my_macro(a, b) a if a < b else b
# func-like macro
# yeah, kinda hard to read
# it like:
# def __my_macro(a, b):
#   return a if a < b else b

define magic_number 2162
# var

macro __my(a, b) a if a < b else b
# func-like macro
puts __my(4, 8)

macro number 0xaa
# var-like macro
puts number

consume

moves a value to a new variable, leaving the original variable empty (nil)

a := 0
b := 1
consume a to b
puts a
# nil
puts b
# 0

back-ticks

you can use back-ticks (``) to run commands in your command line. it uses ‘system’ built-in function

`cd`

decoraters

as python, moon has decoraters you can use them with @

include('typing')
@typing.final
class Test:
    ...
end

Some special variables

here, we are going to introduce two special variables: _ and ERR

when you get any input from any function in ‘io’ that gets input, it is gonna save the result to _

puts _
# None
$x = io.read(">>> ")
# giving some inputs...
puts x == _
# True

when there is any error in your program, in many cases, moon continues to reading the file (except some errors) but if there is, the type and the message will be saved to ERR, but if there is no error, ERR is None

puts ERR
# None

io.throw(TypeError, "Mooooon")!
puts ERR
# #<TypeError: Mooooon>

match - case

match-case is exactly what switch-case does

$name = "Mobin"
match name:
    case "Mobin":
        printf("Admin")
    case _:
        printf("User")
end

!

! is used for executing code in python as like as <>

name = "Mobin"!
printf(name)!
# Mobin

todo

todo is a keyword that is used to specify that some code is not yet implemented.
e.g

todo as "I haven't completed it yet"

panic

it is used to crash the program when the program has reached a point that should never be reached.
e.g

panic as "Oh Noooooo"

local

this makes a local variable

local name = "Mobin"

native

this makes a native (local) variable

native secret_number = 2162

type

it is used for creating aliases

type number = int

struct

it is a bunch of variables, but, as you know, NOT with values, but with ONLY and ONLY with their TYPES

struct Student:
    name: str
    age: int
    grade: str
end

$Ali = Student()
$Ali.name = "Ali"
$Ali.age = 15
$Ali.grade = 'A'
puts Ali.name

enum

it is a bunch of values

enum week {"Sunday": iota()+1, "Monday": iota()+1, "Tuesday": iota()+1, "Wednesday": iota()+1, "Thursday": iota()+1, "Friday": iota()+1, "Saturday": iota()+1}
enum today week = 'Sunday'
# creating an instance, maybe we can call it, for our enum, with this syntax:
# enum A_NAME ENUM_NAME = STRING_NAME_OF_A_VALUE_OF_OUR_ENUM
puts today

say

prints the value note that say is a keyword

say "Hello"

eq, neq, gt, lt, ge, le

8 neq 9
# not equals
8 eq 8
# equals
8 gt 5
# greater than
8 lt 9
# less than
8 ge 8
# greater than equal
8 le 8
# less than equal

standard variables and functions

stdout, stdin, stderr The stdin , stdout , and stderr global constant pointers are standard streams for input, output, and error output

argv argv (ARGument Vector) is an array of character pointers listing all the arguments.

__FILE__ argv[0]

__VERSION__ version of moon

__LOCALS__ locals() ( python )

__GLOBALS__ globals() ( python )

__NAME__ __ name __  ( python ), and it is usually __ main __

FILE __ file __ ( python ), and it is directory for your file

ERR we talked about it

Any a simple object \ object() ( python )

self __ NAME __

__etype__(input_data) returns the exact type of the input you give

e.g

__ etype __(“123”)!
#int

each(_) iterate for the given iterator \ returns iter(_)

typeof(thing) returns the type of the given input

sizeof(thing) returns the size of the given input

lenof(thing) returns the length of the given input

require(module_package_or_sth) import the package or moodule you give but if there is any error in importing,  this will raise an error

include(module_package_or_sth) import the package or moodule you give but if there is any error in importing,  this will print a warning

NOTE THAT NOW WE HAVE ‘include’ AND ‘require’ AS KEYWORDS NOW

isinstanceof(__object, __class_or_tuple) checks if __object you give is instance of __class_or_tuple


measure() if you call it, after the whole program,  it will print the time of doing the work

e.g

measure <=
#processing time: 0.12876248359680176s

tostring(value)
toint(value)
tofloat(value) i think it is clear

to_s(value) string version of given input

to_i(value) int version of given input

to_f(value) float version of given input

to_c(value) complex version of given input

to_l(value) list version of given input

to_t(value) tuple version of given input

to_set(value) set version of given input

to_bin(value) binary version of given input

to_b(value) bool version of given input

to_o(value) octal version of given input

to_n(value) for every given input, it returns nil

to_d(key, value) dict version of given input \ but this takes two input \ 1. key 2. value \ it returns {key: value}

to_enum(value) enumerates version of given input

to_z(value) for every given input, it returns zero ( 0 )

to_r(value) fraction version of given input


RED
GREEN
PURPLE
CYAN
YELLOW
ORANGE colors

e.g printf(f”{CYAN}Hello{BASE}”)

UNDERLINE
BOLD i think these are clear

BASE it gives you a power to make your string a normal string, if you changed it to a colorful or bold or etc.


iota(reset=False) it returns an int from 0 to inf \ if you call it once in the program,  it will return 0 \ then for second time it will return 1, and so on until you make reset=True \

e.g

printf(“%d”, iota())!
#0
printf(“%d”, iota())!
#1
printf(“%d”, iota(reset=True))!
#0
printf(“%d”, iota())!
#1

is_zero(__obj) i think this one is clear too

__clear_exec__() it just clears the file that "mexec" function uses to execute the code you write in your terminal

responds_to(__obj, __name) returns if __obj has an attribute called __name

PLATFORM it is your platform \ e.g "Windows"

printf(base, *values) copy version of io.printf \ i made this because it is easier to write and use than io.printf

AND FOR "IO" ( class ) FUNCTIONS, YOU KNOW WE TALKED ABOUT THEM

pairs(__obj) if __obj is int or float, returns range(__obj) \ else, returns each(__obj)

strcpy(value) it just returns the value, so you can copy it in another variable

chop(__str) it returns __str.strip()[0:-1] version of __str

chomp(__str) it returns __str.strip()

argc it is the length of argv

make(__type) it returns __type(), so e.g if you give int, it will call "int()", so will return 0

system(command) executes the commad in terminal, and returns the result

update(__name, new_value) if __name is defined, it will change the value of __name to new_value, and if it is not defined, this will raise a NameError

mexec(code) this function is used to run code ( that is written in Moon) in terminal  \ so this will make a file called "__ exec __.moon" \ then writes the code you give in that file, then puts a "\n" \ then uses system function to call "moon __ exec __.moon"

but there are some problems with this one
suppose you made a mistake and wrote printff instead of printf, so moon will raise a NameError
but the problem is here, that if you made a mistake, the error will be given to you until you close the while program
( IF YOU RUN THE INTERACTIVE VERSION OF MOON, YOU WILL KNOW WHAT I SAY )
so i defined a function called “__ clear_exec __” ( that we talked about it ), that will clear the file ( __ exec __.moon )

parseStmt(value) parses the statment you give, and runs it \ it uses mexec function

next(string) returns next alphabet or number based on your string \ e.g. : \ next("abc")     # "bcd" \ next("a9b")     # "b0c" \ next("1-z")     # "2-a" \ i'm sure you get (by above example) that if there is a char in your string that is not known is alpha or nums, it will be in your result as it was in your string ( "-" was not known by function )

fail(message) raises RuntimeError with message message

div(a, b) a / b

unreachable(msg="") gives an assertion with msg

unimplemented() raises UnimplementedError

var_dump(*values) prints with this syntax: type(len) value

call(fn, *args) calls the function with args

each(arr, fn) for each element in arr, implements fn, then returns the result in an array

take(arr, n) returns first n values of arr

assert_equal(a, b) raises an assertion if a and b are not equal

assert_type(a, b) raises an assertion if a and b are not at the same type

retry(fn, *args, count=3) runs the fn with args count times

__random__() returns a 5 length random string (from both ascii letters and digits)

String(value) returns the str version of value

Number(value) returns the num version of value

Bool(value) returns the bool version of value

π math.pi

e math.e

𝜏 math.tau

addr

syntax: addr VALUE as SAVE
addr keyword gets the ptr of VALUE, and then saves it to SAVE

addr nil as nil_ptr
puts nil_ptr

when

it is just like if

$name = 'Mobin'
when name == "Mobin":
    printf("Admin")
else :
    printf("User")
end

&

when you start a line with &, you tell moon that you will have a block (a bunch or lines of code); DO NOT FORGET ‘end’

&print(
    "hi",
    "bye"
) end

# ---------------------------


&values = {
    0,
    1,
    2,
} end

# without &, you would get an error

puts values

# ---------------------------

&def person(
    name: str,
    age: int,
    city: str,
) -> str:
    return f"{name} is {age} years old that lives in {city}"
end

# suppose you are a fan of type annotation (sorry but f*ck type annotations), or you wanna write functions as Python recommends, you can do

puts person("mobin", 17, "Urmia")

private functions

you can make private functions not only in classes and even in module-level

class pub_and_priv:

    def pub(self):
        return "pub"
    
    @visibility.private
    def priv(self):
        return "priv"

    def another_pub(self):
        return "another pub"

end

$pp = pub_and_priv()
puts pp.pub()
puts pp.another_pub()
# puts pp.priv()
# error

note that only that function that is given to visibility.private is private, else are public (except for __SOME_NAME that Python itself sees them as private)

@visibility.private()
def pr():
    print("Hello")
end

# pr()!
# error

expect

it is a class that has some functions

expect(5).toBeEqualTo(8)
# False

expect(5).toBeGreaterThan(8)
# False

expect(5).toBeLessThan(8)
# True

expect(5).toBeGreterEqualTo(8)
# False

expect(5).toBeLessEqualTo(8)
# True

expect(5).toBeNotEqualTo(8)
# True

expect(5).toBeIn([2, 5, 3])
# True

expect(5).toBeNotIn([2, 3])
# True

channels

if you’ve ever programmed in Go, you know what channels are

chan.send("Hello, World")!
chan.send("Hello")!
chan.send("Bye")!
print(chan.is_empty())!
print(chan.size())!
print(chan.get())!
print(chan.size())!
print(chan.get())!
print(chan.get())!
print(chan.size())!
print(chan.is_empty())!
print(chan.is_full())!
chan.close()!
chan.send("hi")!
# error
# be aware that when you close a channel, sending and getting values cause Error

# chan.send sends a value to a channel
# chan.get gets and removes the last element (if exisits) and returns it
# chan.is_empty and chan.is_full checks for emptyness and fullness of that channel
# chan.size returns the size of the channel

# NOTICE: in chan class, when you close a chan, you can't make another one

# ------------------------------------------------------------
# ------------------------------------------------------------
# ------------------------------------------------------------
# ------------------------------------------------------------


# we have another type of channel which uses a strict typing shit and uses >> and << for putting and getting values from a channel
# which is on channel class not chan

c = channel(str)!
# a channel of type string (strict)
c >> "Hello, World"!
# putting value in c channel
print(c << void)!
# getting the value
# for the value of >> use: void, Nil, nil or None
# other values cause error

c2 = channel(int)!
c2 > 2162!
# notice we used > not >>
print(c2 < Nil)!
print(c2 < Nil)!
# if we do it by << not <, we will not get an error, but we get a waiting-like-shit
# but because of doing it by <<, it will give us an error

# > puts an item on channel without blocking
# >> puts and item on channel
# < gets an item on channel and delets it without blocking
# << gets and item on channel and delets it

# NOTICE: in channel class, you can have more than one channel, opposite of chan
# There were some funcs like size or is_empty or etc. that we had at chan, but we know that they are not reliable (as queue module (py) says), so we didn't implemented them

# Moon recomends you, to use channel, not chan

putv

it is for printing the value of lit variables

lit 5 = 6
putv 5
# 6

~>

this is called, soft-calling that is used for calling functions and methods but why soft? because it first checks that the given param(s) is(are) (a) valid thing(s) or not ! if it(they) is(are), prints the result of calling it. if it(they) is(are) not, passes so softly, without any errors

typeof ~> Nil
# #<Nil>

typeof ~> NotValid
# 
# 👆🏻 nothing in the result

let, fun

these keywords are used to make variables and functions, but the vars and funcs that are created by these keywords are saved to STACK

let name = "Moon"
io.echo("name")!
# use io.echo to print the value of let vars (NOTICE the string 'name')

fun add(a, b):
    print(a + b)
end
%add(7, 8)
# to call these funcs, use %

fun hello():
    print("Hello, World")
end
%hello(void)

# NOTICE: if your func (with fun keyword) does NOT accept any arg, in the calling (with %), use void or Nil or nil or None as param
# %hello(void)
# %hello(Nil)
# %hello(nil)
# %hello(None)
# so many (not all) other values are gonna work correctly but for an unwritten rule, we use these!

co

co is a keyword that runs a function (usually) concurrently (due to GIL)

def download():
    printf("%d", 1)
    io.sleep(2)
    printf("%d", 2)
end
co download()
printf("here")!

# 1
# here
# 2

:

this is a short hand for calling a function from a class

string := "Moon & Python"
string:split("&")
# this is as: print(string.split("&"))
# NOTICE: Moon will print the result auto, do NOT print it, if you do, you will get an Error

# generally: VAR:FUNC(SHIT)
# will be:   print(TYPE_OF_VALUE_OF_VAR(VALUE_OF_VAR).FUNC(SHIT))

if let

if let is an expr that checks for being None, you’d learn better with expamle

shit := "Mobin"
if let shit as name:
    printf(name)
end
# PYTHON:
# if shit is not None:
#     name = shit
#     printf(name)

NOTICE: this let in if let is diffrent with let for creating vars in STACK

use

use is used for importing but in a cool way

use sys.getsizeof
puts getsizeof("cls")

use os.*
puts cpu_count()
# the cool thing is: you don't need to os.cpu_count()
# Python: from os import *

load(expr)

a function that returns a function that runs expr

f := load('print(0)')
f()!

# or

load('print(0)')()!

var

creates a new variable but var has so many things that you can use them :)

soft-calling:

it is as mentioned, but here it returns the result !

=>

calling functions with params (but you can do it without params also)

var call = io.sprint => "Hi"
var res = A_FREAKING_FUNC =>

<=

calling functios without params

var another_call = int <=

fn

creates a lambda function

var func = fn (name)       ->    f"Hello {name}"
              ______       __    _______________
              parens       ->    no return keyword
              are          not   for returning !
              required     =>

add, sub, etc.

you can use these ops and etc. with var

var a = 5 add 5
var s = 5 sub 5
var m = 5 mult 5
var d = 5 div 5
var p = 5 pow 5
var m2 = 5 mod 5
var x = 5 xor 5
var s2 = 5 shr 5
var s3 = 5 shl 5
var e = 5 eq 5
var n = 6 neq 5
var g = 6 gt 5
var g_e = 6 ge 6
var l = 5 lt 6
var l_e = 5 le 5
var i_n = Nil isnot Nil
var i_i = Nil is Nil
var n_i = "h" notin "bye"
var s = sin pi
var c = cos pi
var t = tan pi
var sq = sqrt 4
var cb = cbrt 8
var l = log 10
var nl = ln e
var c = 4 <=> 5
var short_hand = 5 < 4 ? True : False
var d = printf("Hello") ?? "Error"
# if the left has errors returns right else passes
var block = do
    name = "Mobin"
    printf("Hello")
    printf(f"Hello {name}")
    printf("Bye")
end
var a = await 2 printf("Hello")
# await in var-level
# but syntax in not as function-level
# it gets two things: a number (seconds) to delay, then a work to do
var r = 0 through 10
var ar = 'a' through 'e'
# note: 'through' uses Range class
var contains = [0, 1] has 2
var contains2 = [0, 1] lacks 2
var abs = |-5|
# absolute value with ||
# note: || is only available with var
var fact = 5!
# factorial
# this is not as same as ! in the module-level that runs Python code!
var conv = 5_f
# to float
var conv2 = 1.5_i
# to integer
var conv3 = 0_b
# to boolean
var conv4 = 7895_s
# to string

say hi to new ops (that we saw examples of them above!): isnot, notin, has, lacks
isnot = is not
notin = not in
has = in
lacks = not in

pipeline (|>)

you can use them as you could in the module-level

var p = Nil |> io.sprint
puts p

~=, ===

for comparison

~= checks for loose equality === checks for strict equality

num := 5

var compar = 5.4 ~= 5
var compar2 = num === 5

div by zero

var divByZero = 1 / 0
puts divByZero
# undefined

if-else

var cond = if True:
        Nil
    else:
        nil
    end

puts cond
# Nil
# NOTICE: only if and else is ok, do NOT use elif

:

this is a short hand for calling a function from a class

string := "Moon & Python"
var sh = string:split("&")
# this is as: string.split("&")

# generally: var SOME_NAME = VAR:FUNC(SHIT)
# will be:   TYPE_OF_VALUE_OF_VAR(VALUE_OF_VAR).FUNC(SHIT)

# but this one is a little diffrent from module level ':'
# and that is the printing of it
# in module level Moon will print the result auto
# but in var level Moon will save the result in variable

;

you can use ‘()’ and split your exprs with ‘;’ and save them in your var NOTICE: the last expr result will be saved in your var. The other will be ran normally with exec

var area = (r = 2; __pi = 3.14; __pi * r * r)
puts area
# 12.56


inc, decr

inc is ++
decr is –

num := 5
inc num
puts num
# 6
decr num
puts num
# 5

whilst

as like as while

idx := 0
whilst idx < 5:
    printf("%d", idx)
    idx += 1
end

cast

a keyword that is available only with var

var new_value = cast[int](2.71)
# 2

nothing

it represents nothingness

mystery

represents a mystery value

@lazy

lazy is a class that delays function evaluation until its value is accessed

class Data:
    @lazy
    def show_my_number():
        return 2162
end

obj := Data()
# here nothing has happened yet !
printf("%s", obj.show_my_number)!

freeze

freezable is a class that makes an object then you can freeze it !

f := freezable("arg")
f.arg := "Hello"
printf(f.arg)!
f.freeze()!
# f.arg := "Bye"
# 👆🏻 here we have error ( uncomment it and run it to see )
# cause f is frozen

undo, redo

undoable is a class that makes an object then you can travel in time and get previous value

state := undoable({"c": 0})
state["c"] = 1!
state["c"] = 2!
print(state)!
state.undo()!
print(state)!
state.undo()!
print(state)!
state.redo()!
print(state)!

again

exectes the last line (not block) again

puts "hi"
again
# hi
# hi

block

block makes a block then in the future you can run it

block b:
    printf("Hello")
end
does b

does

as you saw in the last example, does is used to run the blocks

block b:
    printf("Hello")
end
does b
# Hello

also

evalutes two stmts after each other

printf("%s", Nil) also print(nil)

after

evalutes the first stmt after the second stmt

printf("%s", Nil) after print(nil)

before

evaluates the first stmt before the first stmt

printf("%s", Nil) before print(nil)

perhaps

like maybe

sleep, wait

sleeps and wait for some certain seconds

sleep 5
# 5s

wait 5
# 5s

lable, goto

we can define a lable and just use it in the future by goto

lable here:
    printf("Hello")
end

goto here

awaitfor

it is a syntax sugar (maybe we can call it that)

2 awaitfor printf("Hello")
# translates to: (Python)

# async def __RAND_NAME__():
#    await asyncio.sleep(2)
#    printf("Hello")
# asyncio.run(__RAND_NAME__())

# that __RAND_NAME__ is a random name that moon makes

fixme

this is used for telling the coder that that line or maybe that block needs some repair

fixme as "This code needs your fix to be ran"

object, of

with object keyword, you can create your object, then with of you can create an instance of it

object person:
    name, age
end
me = object of person {"Mobin", 16}
puts me.name

some new types

si := short_int(32767)
# (-32768, 32767]

usi := ushort_int(65535)
# (0, 65535]

ui := unsigned_int(4294967295)
# (0, 4294967295]

li := long_int(2147483647)
# (-2147483648, 2147483647]

uli := ulong_int(4294967295)
# (0, 4294967295]

lli := long_long_int(2**63)
# (-(2**63), (2**63)]

ulli := ulong_long_int(18446744073709551615)
# (0, 18446744073709551615]

errors

in Moon’s errors you can see some words like <module>, <string>, and name of functions and classes

<module> shows that error happend in imm.py in module level

<string> shows that an error happend while using exec or eval

[py] shows that an error happend at imm.py, either in module level or function or method or etc.

[moon] shows that an error happend at your moon file

e.g:

io.throw(Error, "Some shit happend")!                                  *****


ERROR MESSAGE AT OUTPUT:

.\main.moon: 1488: Some shit happend (Error)                            no. 1
stack traceback:                                                        no. 2
    [py]: 1601: in <module>                                             no. 3
    [py]: 1: in <module>                                                no. 4
    [py]: 762: in throw                                                 no. 5
    [moon]: 1488: in .\main.moon                                        no. 6

in no.1: 1488 shows line of error in your moon file

in no.1: “Some shit happend” is the message of error that we created it by io.throw by ourselves (in *****)

in no.1: (Error) shows which type of error happend (as you see we raised (or maybe we can say threw) an “Error”) (in *****)

in no.3: 1601 shows line of error in imm.py (if you look at it, it is refered to “!” expr, that we used at ***** to run it)

in no.5: 762 shows line of error in imm.py (if you look at it, it is refered to throw function at io, that we used it here, at this error shows us)

in no.6: 1488 shows line of error in your moon file (as same as in no.1)

NOTICE: these line may be changed, because of being updated or sth else

writing python code in moon

<global boobooli>
<boobooli = 0>
<print(boobooli)>
# 0
# <> uses 'exec' python function
io.println(boobooli)!
# even, it's available in your general program, so you can call it for making varibales
<name = "Mobin">
<printf(name)>
# Mobin

writing Ruby code in moon

with RB keyword, you can write ruby codes in your moon file

RB (

    p "Hello, World"

) end

note that you MUST put ‘) end’ at the end

writing Lua code in moon

with LUA keyword, you can write Lua code in your moon file

LUA (

    print("Hello")

) end

note that you MUST put ‘) end’ at the end

writing Zig code in moon

with ZIG keyword, you can write Zig code in your moon file

ZIG (
    const std = @import("std");

    pub fn main() void {
        std.debug.print("Hello", .{});
    }

) end

with these three keywords, you can write other language’s code in moon, and then, moon will run it auto :)

but we still have some languages, but the problem is here, that moon will NOT run that auto :(

writing C code in moon

with C keyword, you can write C code in your moon file

C (
    #include <stdio.h>

    int main() {
        printf("Hello, World");
        
        return 0;
    }

) end

writing Asm code in moon

with ASM keyword, you can write Asm code in your moon file

ASM (

    section .data
    ; and etc.

) end

writing Gleam code in moon

with GLEAM keyword, you can write Gleam code in your moon file

GLEAM (

    import gleam/io

    pub fn main() {

        io.print("Hello, World")

        Nil

    }

) end

writing C++ code in moon

with CPP keyword, you can write C++ code in your moon file

CPP (
    #include <iostream>

    int main() {
        std::cout << "Hello, World";

        return 0;
    }

) end

and note that the indentation between () with these keywords are not necessary

syntax highlighting for moon in vscode

we have a folder called syntax in the directory, that contains files that give you the syntax highlighting just copy the moon folder from syntax folder in the .vscode folder (that you have it on your device)

keywords:

| True     | shows boolean true value                                                                                      |
| False    | shows boolean false value                                                                                     |
| nil      | a type alias of None, but you'd better use Nil not nil for showing nothing                                    |
| Nil      | shows nothingness                                                                                             |
| module   | creates a module                                                                                              |
| alias    | creates a type alias                                                                                          |
| dec      | declares a varaible                                                                                           |
| def      | defines a new function                                                                                        |
| if       | creates conditions                                                                                            |
| else     | it can be used with: for, while, if, try, that does when the other blocks are not executed b/c of being false |
| elif     |                                                    ...                                                        |
| until    | do sth until condition is true                                                                                |
| unless   | do sth if condition is false                                                                                  |
| class    | creates a new class                                                                                           |
| switch   | switch-case stmt that check on variables                                                                      |
| case     | ...                                                                                                           |
| while    | a loop which goes until condition is false                                                                    |
| for      | a loop that usually is used for iterating over iterators                                                      |
| try      | try block that tries the code given and catchs errors                                                         |
| excpect  |                                                     ...                                                       |
| finally  | this block will be ran not based on try block caught any error or not                                         |
| async    | async functions                                                                                               |
| await    | used with only async functions                                                                                |
| end      | end the block, used with: if-else-elif, while, for, def, try, RB, LUA, ...                                    |
| yield    | used in generator functions                                                                                   |
| pass     | passes in a block                                                                                             |
| continue | continues in a block to the next one                                                                          |
| break    | breaks a block                                                                                                |
| is       | checks for an instance                                                                                        |
| in       | checks for containing                                                                                         |
| raise    | raises a new error                                                                                            |
| return   | returns a value or maybe no value and then exits function                                                     |
| and      | and operator                                                                                                  |
| or       | or op                                                                                                         |
| lambda   | creates a lambda and anonymous function                                                                       |
| as       | is used with importing modules and packages                                                                   |
| from     | is used with importing modules and packages                                                                   |
| assert   | raise a assert error if given condition is false                                                              |
| del      | deletes a varaibles or function or any object                                                                 |
| global   | declares a new globals variable                                                                               |
| not      | not op                                                                                                        |
| with     | is used to wrap the execution of a block with methods defined by a context manager                            |
| puts     | prints values in the console                                                                                  |
| putv     | prints the values of variables that are created with lit                                                      |
| maybe    | sth between True and False; we can have this definition: maybe is (True or False)                             |
| never    | makes a variable that is not gonna be used                                                                    |
| do       | is used with: while, blocks                                                                                   |
| undef    | undefines an object                                                                                           |
| import   | imports a pakcage or module                                                                                   |
| None     | shows nothingness, it is came from Python                                                                     |
| match    | is used with case keyword for a match-case                                                                    |
| todo     | is used to raise a todo error that warns coder that this code is not complete                                 |
| panic    | is used to panic when the code reaches where it shouldn't have been                                           |
| when     | is just if                                                                                                    |
| foreach  | for each element in an iterator do sth                                                                        |
| add      | at var: add op (+)                                                                                            |
| sub      | at var: sub op (-)                                                                                            |
| mult     | at var: mult op (*)                                                                                           |
| div      | at var: div op (/)                                                                                            |
| pow      | at var: pow op (**)                                                                                           |
| sqrt     | at var: square root                                                                                           |
| cbrt     | at var: cube root                                                                                             |
| sin      | at var: sin of a radian                                                                                       |
| cos      | at var: cos of a radian                                                                                       |
| tan      | at var: tan of a radian                                                                                       |
| log      | at var: log in base 10                                                                                        |
| ln       | at var: log in base e ( natural log )                                                                         |
| mod      | mod op (%)                                                                                                    |
| xor      | xor op (^)                                                                                                    |
| shr      | right shift op (>>)                                                                                           |
| shl      | left shift op (<<)                                                                                            |
| addr     | returns a pointer of a object and saves it in the varible you give; add STH as RES                            |
| type     | as a keyword, creates a new type alias                                                                        |
| struct   | creates a new struct                                                                                          |
| enum     | creates a new enum                                                                                            |
| say      | prints values to console                                                                                      |
| eq       | equal op (==)                                                                                                 |
| neq      | not equal op (!=)                                                                                             |
| gt       | greater than (>)                                                                                              |
| lt       | less that (<)                                                                                                 |
| ge       | greater than equal (>=)                                                                                       |
| le       | less than equal (<=)                                                                                          |
| my       | creates a local variable                                                                                      |
| our      | creates a global variable                                                                                     |
| defer    | is used to ensure that a function call is performed later in a program’s execution                            |
| END      | is used for doing bunch or maybe one work at the end, even if you write it at first of your file              |
| discard  | discards a object                                                                                             |
| mut      | creates a muttable varaible                                                                                   |
| package  | creates a new package                                                                                         |
| auto     | creeates a new variable                                                                                       |
| loop     | infinite loop                                                                                                 |
| lit      | creates a local variable, but a special one, LOOK AT THE END OF 'other things'                                |
| local    | creates a loacl variable                                                                                      |
| set      | creates a new variable; set STH to STH_ELSE                                                                   |
| to       | is used with set, mirror, consume,                                                                            |
| define   | creates a new macro; so it can be function-like-macro or varaible-like-macro                                  |
| nonlocal | declares a new variable which is a nonlocal; used in nested functions                                         |
| consume  | swap value of variables; consume A to B                                                                       |
| static   | creates a global variable                                                                                     |
| forever  | inf loop                                                                                                      |
| LUA      | gets a Lua code and runs it                                                                                   |
| RB       | gets a Ruby code and runs it                                                                                  |
| ZIG      | gets a Zig code and runs it                                                                                   |
| C        | gets a C code and does NOT run it                                                                             |
| CPP      | gets a C++ code and does NOT run it                                                                           |
| GLEAM    | gets a Gleam code and does NOT run it                                                                         |
| ASM      | gets a Asm code and does NOT run it                                                                           |
| var      | creates a new variable, but with so many feathers                                                             |
| fn       | is used in var, to make lambda functions                                                                      |
| nothing  | represents nothing :)                                                                                         |
| mystery  | represents a mystery value                                                                                    |
| also     | evaluates two stmts after each other                                                                          |
| after    | evaluates the first stmt after the second one                                                                 |
| before   | evaluates the second stmt after the fisrt one                                                                 |
| perhaps  | represents perhaps                                                                                            |
| mirror   | copys an object to another one                                                                                |
| sleep    | sleeps and waits for some seconds                                                                             |
| wait     | sleeps and waits for some seconds                                                                             |
| isnot    | checks for not being an object                                                                                |
| notin    | checks for not being in an iterator                                                                           |
| cast     | cast types                                                                                                    |
| inc      | ++                                                                                                            |
| decr     | --       note: decr is not dec                                                                                |
| macro    | as like as define                                                                                             |
| lable    | creates a new lable                                                                                           |
| goto     | is used to go to a lable                                                                                      |
| through  | is used to make Ranges                                                                                        |
| namespace| is used for making namespaces                                                                                 |
| interface| is used for making interfaces                                                                                 |
| again    | is used for redoing the last line                                                                             |
| block    | is used for creating blocks                                                                                   |
| does     | is used for running blocks                                                                                    |
| awaitfor | is a syntax sugar for async functions                                                                         |
| ensure   | just like assert                                                                                              |
| fixme    | is used to tell the coder that the code needs fix at a line or maybe block!                                   |
| has      | is like in keyword                                                                                            |
| lacks    | is like notin                                                                                                 |
| native   | is for making local variables                                                                                 |
| let      | is for making a type of variable which is saved on STACK dict                                                 | 
| fun      | is for making a type of function which is saved on STACK dict                                                 |
| object   | is for making an object                                                                                       |
| of       | is for creating an instance of an object created with object                                                  |
| co       | is for running a fuction like a thread                                                                        |
| use      | is for importing                                                                                              |
| affirm   | is for asserting                                                                                              |
| whilst   | is just like while                                                                                            |

Other Things:

$age = 16
$can_vote = age >= 18 and True or False
# False

puts nan == nan
# False !!!

mexec("if 1:\n\tio.println('hello')\nelse:\n\tio.println('bye'\nend"))
# executes moon code

require('math')
$a = {"p" : print}
<a["p"]("Hello, World")>
print = math.sin
<a["p"](print(1))>
$sin = a["p"]
<sin("Bye, World")>
# playing with name, but this is dangerous !

include('Int')
$even_or_odd = (num) -> "even" if Int.is_even(num) else "odd"
io.print(even_or_odd(5))!
# odd

io.print_r([nil, True, False])!
# print_r prints only list !
# print_r("hello")!
# error !!

include('Time')
io.print => Time.now

system => 'echo hello'
# execute command line code

io.sprint(true)?
# this is like a debuger
# true
#=> nil

with "hello" as item:
    io.print(item)
    # h
    # e
    # ...
end

io.print(Range("a", "e").new())!
# ['a', 'b', 'c', 'd', 'e']

never num = 7
# io.print(num)
# error: num is not defined
# creating variables with never makes the variables to be unusable !

$x = (7..15)
# a range from 7 to 15
$y = ?c
# a char using '?'
$z = %s[hello, world]
# a string
$a = %(hi)
# a string

$num = 0
undef num
# delets num

alias new = nil
# creating a type alias

$x = 0
do:
    io.print("hello")
while x > 1
end
# first does the 'do' block and then if condition is true it is gonna do that in a loop

try:
    io.print(1 / 0)
except ZeroDivisionError as e:
    io.print(e)
else:
    io.print(True)
finally:
    io.print("bye")
end
# division by zero
# bye

try:
    io.print(1 / 1)
except ZeroDivisionError as e:
    io.print(e)
else:
    io.print(True)
finally:
    io.print("bye")
end
# 1.0
# True
# bye

class Person:
    def __init__(self, name: str, age: int, id: int) -> None:
        self.name = name
        self.age = age
        self.__id = id
        # self.__id is private-like
        # but note that there is nothing called private in python !
end
$mobin = Person("mobin", 16, 122333)
# io.print(mobin.name, mobin.age, mobin.__id)!
# error: Person has no __id !!
# pyhton for '__' started things will add a '_ClassName' to the begining of it
# ClassName is the name of the class
io.print(mobin.name, mobin.age, mobin._Person__id)!
# true !

$x = io.catch("io.printf(hello)", NameError)
io.printf("%s", x == True)!
# error, True
$x = io.catch("io.printf(hello)", KeyError)
io.printf("%s", x == ERR)!
# True
$x = io.catch("io.printf('hello')", NameError)
io.printf("%s", x == nil)!
# 'hello', True

$result1 = stdin.readline()
puts result1
# getting input with stdin
# note that, there is no 's' at the end of readline !

$result2 = stdin.readlines()
# note that, there is a 's' at the end of readlines !
# infinitly getting input
# because when you are reading stdin, with readlines, this is going to read the lines till the end, but the end for stdin is ^C (i think this is only in Windows), so your program will not finish until ^C
puts result2
# error: result2 is not defined !

$pointers = {}
class io:

    def cout(*values):
        for value in values:
            print(value)

    def cin(prompt):
        return input(prompt)

    def __rshift__(self, value):
        return io.cout(value)

    def __lshift__(self, prompt):
        return io.cin(prompt)

    def __and__(self, value):
        pointers[hex(id(value))] = value
        return hex(id(value))

    def __mul__(self, pointer):
        try:
            return pointers[pointer]
        except KeyError:
            print(f"ERR: {pointer} is not defined or not a pointer")
end

$_ = io()
_ >> "hello"
# printing hello
_ >> (_ << ">>> ")
# printing the gotten input from user with <<
_ >> (_ & 7)
# printing pointer of 7 ! (&7)
_ >> (_ * (_ & 7))
# printing the direfrenced pointer of 7
# _ >>   ( _ * (        _ & 7 ) )
# print    direfrence   getting pointer
$p = _ & 'hello'
# saving pointer of hello in p
_ >> p
# prints p
_ >> (_ * p)
# derefrecing p
_ >> f"{p} -> {_ * p}"
# prints p and direfrenced version of p

with [2, 6, 1, 2] as num:
    printf(to_s(num))
    # 2
    # 6
    # 1
    # 2
end

with open("somefile", "r") as f:
    printf("%s", f)
    # reads the whole file
    # if i don't wanna lie, i don't know why is this reading the file !
end

puts hello
if ERR is not None:
    printf(ERR)
end
if not ok:
    printf(ERR)
end

require t
include t
# run these to see the diffrence

l := _list([1, 2, 3])
l << 4!
puts l
puts l.first
puts l.last
s := _str("Hell")
printf(s << "o")!

p := io.mem() &Nil
# pointer to Nil
printf("%s", io.mem() *p)!
# derefrencing
io.mem().imprint("User.name", "Mobin")!
# imprinting: writing sth on memory ('Mobin' at the key 'User.name')
puts io.mem().recall("User.name")
# recalling: loading the value of the key from memory

Kernel.printf(Kernel.io.mem() &None)!
# Kernel: just like Ruby's one

lit 5 = 6
# don't worry, no error here
# lit makes and saves variables in a dict
# so name can be everything, cause it is a string
putv 5
# putv used for printing lit variables