Mash, the basics of the language

  • Tutorial
image

Foreword


This language was developed by me for educational purposes. I do not consider it (at the moment) a perfectly developed language, but perhaps in the future it will be able to compete with competitors.

If you have a desire to try it in action yourself - download the project repository , in it you can find the assembled version of the project or assemble it yourself, for your OS.

This article will describe a small project manual and consider the syntax of the language.

Variables and Implicit Pointers


In Mash, each variable stores a pointer to an object in memory. When transferring variables to methods, obtaining a result, or with simple manipulations with them, work is done with objects in memory using pointers to them.

Those. in the following code, an array will be passed to the p (arr) method as a pointer to an object already created earlier.

proc p(arr):
  ...
end
proc main():
  arr ?= [1, 2, 3, 4, 5]
  p(arr)
end

The presence of pointers in the language, both explicit and implicit, in my opinion gives it additional flexibility and functionality, although in some cases it contributes to the generation of errors.

Temporary variables and garbage collector


Unlike similar programming languages, Mash has a semi-automatic garbage collector based on the mechanism of time value labels, rather than counting pointers.

Those. the developer himself decides when to clear the memory of garbage and can also do it manually, for certain cases.

Garbage collection is called using gc () and frees memory from under all temporary objects.

Many simple actions with variables are accompanied by the creation of temporary objects in memory.

The developer can explicitly declare a memory allocation for further work with it, i.e. declare variables for long-term use.

Examples of creating a temporary variable:

x ?= 10

And variables not marked for the garbage collector:

x ?= new(10)
var x2 = 20

An example of using gc ():

while a > b:
  doSomething(a, b)
  gc()
end

Memory can also be freed manually:

var a = 10, b = 20, c = 30
...
Free(a, b, c)

Variable Visibility Zones


Variables in Mash can be declared both locally and globally.

Global variables are declared between methods, through the var statement. Local - inside methods in any way.

Data types


In Mash, dynamic typing. Automatically detect / override data types for unsigned and signed numbers, fractional numbers and strings. In addition, from simple data types, arrays (including multi-level ones), enum types (almost the same as arrays), methods, a logical data type, and perhaps everything are supported.

Code Examples:

x ?= 10
x += 3.14
x *= "3"
x /= "2,45"
x ?= [1, 2, 3.33, func1(1, 2, 3), "String", ["Enum type", 1, 2, 3], "3,14"]

Introspection allows you to determine the type of variable you need:

if typeof(x) == TypeInt:
  ...
end

Arrays & Enums


Rare tasks do not force the developer to declare the next array in the code.
Mash supports arrays consisting of an arbitrary number of levels, + arrays can be something like trees, i.e. the sizes of sublevels may vary on one sublevel.

Examples of declarations of arrays and enumerations:

a ?= new[10][20]
var b = new[10][20]
c ?= [1, [], 3, 3.14, "Test", [1, 2, 3, 4, 5], 7.7, a, b, ["77", func1()]]
var d = [1, 2, 3]

Any objects declared through the new operator are not marked for the garbage collector.

Arrays, like regular objects in memory, are freed by calling Free ()
Such work with transfers is quite convenient.

For example, you can pass to methods or return from them many values ​​of one variable:
func doSomething(a, b, c):
  return [a+c, b+c] 
end

Assignment Operators


There are as many as 3 assignment operators in Mash.

  • ? =
    Assigns a variable a pointer to an object (if a variable is declared but does not store a pointer to an object in memory, then this operator must be used to assign a value to it).
  • =
    Normal assignment. Assigns to an object by pointer in a variable the value of another object.
  • @ =
    Assigns a value to an object by an explicit pointer to this object (this will be discussed later).

Mathematical and logical operations


List of currently supported mathematical and logical operations:

  • + , - , * , /
    No comments are needed.
  • \
    Division completely.
  • %
    The remainder of the division.
  • &
    Logical "and."
  • |
    Logical "or".
  • ^
    Logical "exclusive or".
  • ~
    Logical "not."
  • ++ , -
    Increment and decrement.
  • << , >>
    Bitwise left and right shifts.
  • == , <> , > = , <=
    Logical comparison operators.
  • in
    Checks whether an object belongs to an enumeration or to an array.
    Example:
    if Flag in [1, 3, 5, 8]: ...

Explicit Pointers


It would seem, why are they needed if there are no explicit pointers? For example, to check whether variables A and B store pointers to the same object in memory.

  • @ - get a pointer to an object and put it in a variable, like an object.
  • ? - get the object by pointer from the object in the variable.
    Example:
    a ?= ?b

Procedures and Functions


I decided to make the language separation of methods for returning values ​​into procedures and functions (as in Pascal).

Method declarations are made like the following examples:

proc SayHello(arg1, arg2, argN):
  println("Hello, ", arg1, arg2, argN)
end
func SummIt(a, b):
  return a + b
end

Language constructions


An example if..else..end construct.

if <условие>:
...
else:
...
end

For loop.

for([инициализация]; <условие>; [операции с переменными]):
...
end

While. The condition is checked before iteration.

whilst <условие>:
...
end

Whilst. A loop that differs from while in that the condition is checked after iteration.

until <условие>:
...
end

switch..case..end..else..end ... is a familiar construction for creating logical branches.

switch <переменная>:
  case <значение 1>:
    ...
  end
  case <значение 2>:
    ...
  end
  else:
   ...
end

Classes and Elements of OOP Language


Mash implements support for classes, inheritance, dynamic introspection and reflection, polymorphism. Those. A standard set of scripting languages ​​is supported.

Consider a simple class declaration:

class MyClass:
  var a, b
  proc Create, Free
  func SomeFunction
end

A class declaration does not contain implementations of the methods that are declared in it.
The constructor of the class is the Create method. As a destructor - Free.

After the class is declared, you can describe the implementation of its methods:

proc MyClass::Create(a, b):
  $a ?= new(a)
  $b ?= new(b)
end
proc MyClass::Free():
  Free($a, $b, $)
end
func MyClass::SomeFunction(x):
  return ($a + $b) / x
end

You might notice the $ symbol in some places in the code - with this symbol I simply shortened the long this->. Those. the code:

return ($a + $b) / x
...
Free($a, $b, $)

Equivalent to this code:
return (this->a + this->b) / x
...
Free(this->a, this->b, this)

This contains a pointer to an instance of the class on behalf of which the method of this class is called.

In order to inherit the functionality of a class, you need to describe the declaration of a new class in this way:

class MySecondClass(MyClass):
  func SomeFunction
end
func MySecondClass::SomeFunction(x):
  return ($a - $b) / x
end

MySecondClass - will have a constructor and destructor from its ancestor + SomeFunction function, which the ancestor class has, is overwritten by a function from a new class.

To create class instances, the new operator exists.

Code Examples:

a ?= new MyClass  //выделение памяти под структуру класса

b ?= new MyClass(10, 20)  //выделение памяти под структуру класса и последующий вызов конструктора

The type of an instance of a class can be determined when creating this instance; accordingly, type conversion is absent in the language.

Introspection allows you to determine the type of class instance, code example:

x ?= new MyClass(10, 20)
...
if x->type == MyClass:
  //делаем что-нибудь...
end

Sometimes you need to turn to a class function and overwrite it with a new one. Code example:

func class::NewSomeFunction(x):
  return $x * $y * x
end
...
x ?= new MyClass(10, 20)
x->SomeFunction ?= class::NewSomeFunction
x->SomeFunction(33) //Вызывается NewSomeFunction, будто это оригинальная функция класса.

Conclusion


In this article, I tried to introduce possible interested people to my creation.

Thanks for reading. Waiting for comments.

Only registered users can participate in the survey. Please come in.

Was this article interesting to you?

  • 21% Yes. 12
  • 35% Yes, but I didn’t learn anything special. 20
  • 43.8% None. 25

Also popular now: