
Prólogo
Este lenguaje fue desarrollado por mí con fines educativos. No lo considero (por el momento) un lenguaje perfectamente desarrollado, pero quizás en el futuro pueda competir con los competidores.
Si desea probarlo usted mismo en acción, descargue
el repositorio del proyecto, en él puede encontrar la versión ensamblada del proyecto o ensamblarlo usted mismo, para su sistema operativo.
Este artículo describirá un pequeño manual del proyecto y considerará la sintaxis del lenguaje.
Variables y punteros implícitos
En Mash, cada variable almacena un puntero a un objeto en la memoria. Al transferir variables a métodos, obtener un resultado, o con simples manipulaciones con ellos, se trabaja con objetos en la memoria utilizando punteros a ellos.
Es decir en el siguiente código, se pasará una matriz al método p (arr) como puntero a un objeto ya creado anteriormente.
proc p(arr): ... end proc main(): arr ?= [1, 2, 3, 4, 5] p(arr) end
La presencia de punteros en el lenguaje, tanto explícito como implícito, en mi opinión le da flexibilidad y funcionalidad adicionales, aunque en algunos casos contribuye a la generación de errores.
Variables temporales y recolector de basura.
A diferencia de lenguajes de programación similares, Mash tiene un recolector de basura semiautomático basado en el mecanismo de etiquetas de valor de tiempo, en lugar de contar punteros.
Es decir el desarrollador mismo decide cuándo limpiar la memoria de basura y también puede hacerlo manualmente, en ciertos casos.
La recolección de basura se llama usando gc () y libera memoria de todos los objetos temporales.
Muchas acciones simples con variables van acompañadas de la creación de objetos temporales en la memoria.
El desarrollador puede declarar explícitamente una asignación de memoria para seguir trabajando con ella, es decir declarar variables para uso a largo plazo.
Ejemplos de creación de una variable temporal:
x ?= 10
Y variables no marcadas para el recolector de basura:
x ?= new(10) var x2 = 20
Un ejemplo de uso de gc ():
while a > b: doSomething(a, b) gc() end
La memoria también se puede liberar manualmente:
var a = 10, b = 20, c = 30 ... Free(a, b, c)
Zonas de visibilidad variable
Las variables en Mash se pueden declarar tanto local como globalmente.
Las variables globales se declaran entre métodos, a través de la declaración var. Local: métodos internos de cualquier manera.
Tipos de datos
En Mash, escritura dinámica. Detecta / anula automáticamente los tipos de datos para números sin signo y con signo, números fraccionales y cadenas. Además, desde tipos de datos simples, matrices (incluidas las de varios niveles), tipos de enumeración (casi lo mismo que las matrices), métodos, un tipo de datos lógico y tal vez todo sea compatible.
Ejemplos de código:
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"]
La introspección le permite determinar el tipo de variable que necesita:
if typeof(x) == TypeInt: ... end
Matrices y enumeraciones
Las tareas raras no obligan al desarrollador a declarar la siguiente matriz en el código.
Mash admite matrices que consisten en un número arbitrario de niveles, + las matrices pueden ser algo así como árboles, es decir Los tamaños de los subniveles pueden variar en un subnivel.
Ejemplos de declaraciones de matrices y enumeraciones:
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]
Cualquier objeto declarado a través del nuevo operador no está marcado para el recolector de basura.
Las matrices, como los objetos normales en la memoria, se liberan llamando a Free ()
Tal trabajo con transferencias es bastante conveniente.
Por ejemplo, puede pasar a métodos o devolver de ellos muchos valores de una variable:
func doSomething(a, b, c): return [a+c, b+c] end
Operadores de asignación
Hay hasta 3 operadores de asignación en Mash.
- ? =
Asigna una variable a un puntero a un objeto (si se declara una variable pero no almacena un puntero a un objeto en la memoria, entonces este operador debe usarse para asignarle un valor). - =
Asignación normal Asigna a un objeto por puntero en una variable el valor de otro objeto. - @ =
Asigna un valor a un objeto mediante un puntero explícito a este objeto (esto se discutirá más adelante).
Operaciones matemáticas y lógicas
Lista de operaciones matemáticas y lógicas actualmente admitidas:
Punteros explícitos
Parecería, ¿por qué son necesarios si no hay punteros explícitos? Por ejemplo, para verificar si las variables A y B almacenan punteros al mismo objeto en la memoria.
- @ : obtenga un puntero a un objeto y colóquelo en una variable, como un objeto.
- ? - Obtener el objeto por puntero del objeto en la variable.
Un ejemplo: a ?= ?b
Procedimientos y funciones
Decidí hacer la separación del lenguaje de los métodos para devolver valores en procedimientos y funciones (como en Pascal).
Las declaraciones de métodos se realizan como los siguientes ejemplos:
proc SayHello(arg1, arg2, argN): println("Hello, ", arg1, arg2, argN) end func SummIt(a, b): return a + b end
Construcciones de lenguaje
Un ejemplo if..else..end construct.
if <>: ... else: ... end
Por bucle.
for([]; <>; [ ]): ... end
Mientras. La condición se verifica antes de la iteración.
whilst <>: ... end
Mientras. Un ciclo que difiere de mientras que la condición se verifica después de la iteración.
until <>: ... end
switch..case..end..else..end ... es una construcción familiar para crear ramas lógicas.
switch <>: case < 1>: ... end case < 2>: ... end else: ... end
Clases y elementos del lenguaje OOP
Mash implementa soporte para clases, herencia, introspección dinámica y reflexión, polimorfismo. Es decir Se admite un conjunto estándar de lenguajes de secuencias de comandos.
Considere una declaración de clase simple:
class MyClass: var a, b proc Create, Free func SomeFunction end
Una declaración de clase no contiene implementaciones de los métodos que se declaran en ella.
El constructor de la clase es el método Create. Como destructor - Gratis.
Después de declarar la clase, puede describir la implementación de sus métodos:
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
Puede notar el símbolo $ en algunos lugares del código; con este símbolo simplemente acorté el largo this->. Es decir codigo:
return ($a + $b) / x ... Free($a, $b, $)
Equivalente a este código:
return (this->a + this->b) / x ... Free(this->a, this->b, this)
Contiene un puntero a una instancia de la clase en nombre de la cual se llama al método de esta clase.
Para heredar la funcionalidad de una clase, debe describir la declaración de una nueva clase de esta manera:
class MySecondClass(MyClass): func SomeFunction end func MySecondClass::SomeFunction(x): return ($a - $b) / x end
MySecondClass: tendrá un constructor y un destructor de su ancestro + la función SomeFunction, que tiene la clase ancestro, se sobrescribe con una función de una nueva clase.
Para crear instancias de clase, existe el nuevo operador.
Ejemplos de código:
a ?= new MyClass //
b ?= new MyClass(10, 20) //
El tipo de una instancia de una clase se puede determinar al crear esta instancia; en consecuencia, la conversión de tipo está ausente en el idioma.
La introspección le permite determinar el tipo de instancia de clase, ejemplo de código:
x ?= new MyClass(10, 20) ... if x->type == MyClass: // -... end
A veces necesita recurrir a una función de clase y sobrescribirla con una nueva. Ejemplo de código:
func class::NewSomeFunction(x): return $x * $y * x end ... x ?= new MyClass(10, 20) x->SomeFunction ?= class::NewSomeFunction x->SomeFunction(33) // NewSomeFunction, .
Conclusión
En este artículo, traté de presentar a posibles personas interesadas a mi creación.
Gracias por leer Esperando comentarios.