
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:
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.