Mash, o básico do idioma

imagem

Prefácio


Esta linguagem foi desenvolvida por mim para fins educacionais. Não o considero (no momento) uma linguagem perfeitamente desenvolvida, mas talvez no futuro seja capaz de competir com os concorrentes.

Se você deseja experimentá-lo em ação - faça o download do repositório do projeto, nele você pode encontrar a versão montada do projeto ou montá-lo você mesmo, para o seu sistema operacional.

Este artigo descreverá um pequeno manual do projeto e considerará a sintaxe do idioma.

Variáveis ​​e ponteiros implícitos


No Mash, cada variável armazena um ponteiro para um objeto na memória. Ao transferir variáveis ​​para métodos, obter um resultado ou com simples manipulações com elas, o trabalho é feito com objetos na memória usando ponteiros para elas.

I.e. no código a seguir, uma matriz será passada para o método p (arr) como um ponteiro para um objeto já criado anteriormente.

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

A presença de ponteiros na linguagem, explícitos e implícitos, na minha opinião, oferece flexibilidade e funcionalidade adicionais, embora em alguns casos contribua para a geração de erros.

Variáveis ​​temporárias e coletor de lixo


Diferentemente de linguagens de programação semelhantes, o Mash possui um coletor de lixo semiautomático baseado no mecanismo de etiquetas de valor temporal, em vez de contar indicadores.

I.e. o próprio desenvolvedor decide quando limpar a memória do lixo e também pode fazê-lo manualmente, em certos casos.

A coleta de lixo é chamada usando gc () e libera memória de todos os objetos temporários.

Muitas ações simples com variáveis ​​são acompanhadas pela criação de objetos temporários na memória.

O desenvolvedor pode declarar explicitamente uma alocação de memória para trabalhar mais com ele, ou seja, declarar variáveis ​​para uso a longo prazo.

Exemplos de criação de uma variável temporária:

 x ?= 10 

E variáveis ​​não marcadas para o coletor de lixo:

 x ?= new(10) var x2 = 20 

Um exemplo de uso de gc ():

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

A memória também pode ser liberada manualmente:

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

Zonas de visibilidade variável


Variáveis ​​no Mash podem ser declaradas local e globalmente.

Variáveis ​​globais são declaradas entre métodos, através da instrução var. Local - métodos internos de qualquer maneira.

Tipos de dados


No Mash, digitação dinâmica. Detectar / substituir automaticamente tipos de dados para números não assinados e assinados, números fracionários e seqüências de caracteres. Além disso, de tipos de dados simples, matrizes (inclusive de vários níveis), tipos de enumeração (quase o mesmo que matrizes), métodos, um tipo de dados lógico e talvez tudo seja suportado.

Exemplos 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"] 

A introspecção permite determinar o tipo de variável que você precisa:

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

Matrizes e enums


Tarefas raras não forçam o desenvolvedor a declarar a próxima matriz no código.
O Mash suporta matrizes que consistem em um número arbitrário de níveis; matrizes + podem ser algo como árvores, ou seja, os tamanhos dos subníveis podem variar em um subnível.

Exemplos de declarações de matrizes e enumerações:

 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] 

Quaisquer objetos declarados através do novo operador não são marcados para o coletor de lixo.

Matrizes, como objetos regulares na memória, são liberadas chamando Free ()
Esse trabalho com transferências é bastante conveniente.

Por exemplo, você pode passar para métodos ou retornar deles muitos valores de uma variável:
 func doSomething(a, b, c): return [a+c, b+c] end 

Operadores de atribuição


Existem até três operadores de atribuição no Mash.

  • ? =
    Atribui uma variável a um ponteiro a um objeto (se uma variável é declarada, mas não armazena um ponteiro em um objeto na memória, esse operador deve ser usado para atribuir um valor a ele).
  • =
    Tarefa normal. Atribui a um objeto por ponteiro em uma variável o valor de outro objeto.
  • @ =
    Atribui um valor a um objeto por um ponteiro explícito para esse objeto (isso será discutido mais adiante).

Operações matemáticas e lógicas


Lista de operações matemáticas e lógicas atualmente suportadas:

  • + , - , * , /
    Não são necessários comentários.
  • \
    Divisão completamente.
  • %
    O restante da divisão.
  • &
    Lógico "e".
  • |
    Lógico "ou".
  • ^
    Lógico "exclusivo ou".
  • ~
    Lógico "não".
  • ++ , -
    Incremento e decremento.
  • << , >>
    Mudanças bit a esquerda e direita.
  • == , <> , > = , <=
    Operadores de comparação lógica.
  • em
    Verifica se um objeto pertence a uma enumeração ou a uma matriz.
    Um exemplo:
     if Flag in [1, 3, 5, 8]: ... 

Ponteiros explícitos


Parece, por que eles são necessários se não houver indicadores explícitos? Por exemplo, para verificar se as variáveis ​​A e B armazenam ponteiros para o mesmo objeto na memória.

  • @ - pega um ponteiro para um objeto e o coloca em uma variável, como um objeto.
  • ? - obtém o objeto por ponteiro do objeto na variável.
    Um exemplo:
     a ?= ?b 

Procedimentos e Funções


Decidi fazer a separação de linguagem dos métodos para retornar valores em procedimentos e funções (como em Pascal).

As declarações de método são feitas como os seguintes exemplos:

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

Construções linguísticas


Um exemplo de construção if..else..end.

 if <>: ... else: ... end 

For loop.

 for([]; <>; [  ]): ... end 

Enquanto. A condição é verificada antes da iteração.

 whilst <>: ... end 

Enquanto. Um loop que difere de enquanto a condição é verificada após a iteração.

 until <>: ... end 

switch..case..end..else..end ... é uma construção familiar para a criação de ramificações lógicas.

 switch <>: case < 1>: ... end case < 2>: ... end else: ... end 

Classes e elementos da linguagem OOP


O Mash implementa suporte para classes, herança, introspecção dinâmica e reflexão, polimorfismo. I.e. Um conjunto padrão de linguagens de script é suportado.

Considere uma declaração de classe simples:

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

Uma declaração de classe não contém implementações dos métodos declarados nela.
O construtor da classe é o método Create. Como destruidor - Grátis.

Depois que a classe é declarada, você pode descrever a implementação de seus 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 

Você pode notar o símbolo $ em alguns lugares do código - com esse símbolo eu simplesmente reduzi o tempo this->. I.e. código:

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

Equivalente a este código:
 return (this->a + this->b) / x ... Free(this->a, this->b, this) 

Isso contém um ponteiro para uma instância da classe em nome da qual o método dessa classe é chamado.

Para herdar a funcionalidade de uma classe, você precisa descrever a declaração de uma nova classe desta maneira:

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

MySecondClass - terá um construtor e destruidor de sua função ancestral + SomeFunction, que a classe ancestral possui, é substituída por uma função de uma nova classe.

Para criar instâncias de classe, o novo operador existe.

Exemplos de código:

 a ?= new MyClass //     

 b ?= new MyClass(10, 20) //         

O tipo de uma instância de uma classe pode ser determinado ao criar essa instância; portanto, a conversão de tipo está ausente no idioma.

A introspecção permite determinar o tipo de instância da classe, exemplo de código:

 x ?= new MyClass(10, 20) ... if x->type == MyClass: // -... end 

Às vezes, você precisa ativar uma função de classe e substituí-la por uma nova. Exemplo 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,     . 

Conclusão


Neste artigo, tentei introduzir possíveis pessoas interessadas em minha criação.

Obrigado pela leitura. À espera de comentários.

Source: https://habr.com/ru/post/pt437632/


All Articles