Présentation
Depuis 2016 (avec des interruptions), je développe mon propre langage de programmation. Le nom de cette langue est «Ü». Pourquoi Ü? Parce que je voulais un nom à une lettre, et toutes les lettres de l'ensemble de AZ sont déjà prises.
Cet article a pour mission de familiariser le public avec cette langue, d'en donner une idée générale. L'article n'a pas l'intention de décrire complètement la langue, une description plus complète de la langue, si nécessaire, sera donnée dans les articles suivants.
Pourquoi avons-nous besoin d'une autre langue?
J'ai examiné un certain nombre de langues compilées statistiquement existantes, plus ou moins connues, et suis arrivée à la conclusion qu'aucune d'entre elles ne me convenait complètement. Tous ont des défauts "fatals".
Points spécifiques:
- C - niveau trop bas et dangereux
- C ++ - hérité de nombreux défauts de bas niveau, nouvelles façons de se tirer une balle dans le pied, manque de réflexion
- D - garbage collector, types de référence séparés
- Java est un garbage collector, tous les types composites sont référencés, attachement fort à une machine virtuelle. Une grande partie de cela s'applique également aux langages basés sur JVM.
- C # - les défauts ressemblent beaucoup à Java
- Rust - la nécessité de prendre explicitement des liens et de les déréférencer explicitement, (subjectivement) le danger d'une approche quand tout est une expression et renvoie un résultat, la présence d'une indication explicite de conformité au protocole, le manque d'héritage
- Go - garbage collector, manque de modèles
- Swift - types de référence, nécessité d'une conformité explicite au protocole
Ayant découvert l'imperfection de toutes les langues ci-dessus, j'ai décidé de créer la mienne, dépourvue, comme il me semble, de tous les défauts.
Informations générales
Ü est un langage compilé, typé statiquement avec un typage fort. Le langage contient des fonctions libres, des structures, des classes, des méthodes pour les structures et les classes. Types de types existants - fondamentaux, structurels (structures, classes), tableaux de taille constante, tuples, énumérations, pointeurs vers des fonctions. Les classes peuvent participer à l'héritage et avoir des fonctions virtuelles. Le langage prend en charge les modèles, il existe des modèles pour les classes et les structures, des alias de types, des fonctions et des méthodes. Il y a une surcharge de fonctions et d'opérateurs (avec quelques restrictions).
Le langage prend en charge les destructeurs pour les classes et les structures. Les destructeurs sont utilisés pour gérer les ressources, y compris la mémoire.
Ce qui est déjà là
Compilateur basé sur LLVM. Le compilateur prend en charge toutes les plates-formes prenant en charge LLVM. Le compilateur ne sait pas encore comment créer des fichiers purement exécutables, mais il peut générer des fichiers objets, du code assembleur, du code binaire ou texte llvm. Il est possible de communiquer avec du code C, il existe un utilitaire qui facilite l'écriture d'en-têtes Ü pour les bibliothèques C.
Buts et objectifs
Le langage est créé de manière à capturer le nombre maximum d'erreurs typiques lors de la compilation. Les décisions sur la conception du langage sont prises principalement sur la base de cette tâche. Le deuxième objectif est la facilité (relative) d'écrire des programmes et la facilité de les lire.
Le langage ne contient pas de constructions qui pourraient provoquer l'écriture de code erroné, et ne contient pas non plus de fonctionnalités qui pourraient compliquer considérablement la compréhension de ce qui se passe dans le programme.
Malgré les points ci-dessus, la question des performances ne peut être ignorée. Par conséquent, au détriment des performances, les décisions de conception de langage ne sont pas prises.
Alors, regardons quels sont les moments dans Ü qui correspondent aux objectifs déclarés.
Système de type
Contrairement à C ++, dans Ü il n'y a pas de pointeurs et de références en tant que types. Il n'y a pas de pointeurs du tout, il y a des liens, mais seulement en tant que liens de pile, arguments de référence de fonction, champs de référence. De plus, les modificateurs mut / imut ne font pas partie d'un type, mais font partie d'une variable, d'une référence, d'un argument de fonction, d'un champ.
Grâce à cette simplification, on comprend mieux où se trouve ce type, en particulier dans le code passe-partout. Il n'y a aucun doute quant à la déclaration d'un lien ou d'une variable, des doutes résultant de typeof (analogue du decltype de C ++), des doutes sur la constante / non constante.
Le revers de cette simplification est la nécessité d'un traitement séparé de la cohérence et des liens dans les modèles. Bien que cela ajoute de la clarté lorsque le paramètre de constance est passé au modèle en tant qu'argument explicitement séparé.
Initialiseurs
Il est impossible de déclarer une variable et de ne pas l'initialiser. Tout octet de la variable déclarée doit être initialisé.
Les types fondamentaux (et certains autres) nécessitent une initialisation obligatoire:
var i32 x= 22, y(12345);
:
struct Vec{ f32 x; f32 y; }
...
var Vec v{ .x= -56.1f, .y= 42.0f };
var Vec v_uninit; //
, :
struct Vec
{
f32 x; f32 y;
fn constructor()
( x= 0.0f, y= 0.0f )
{}
}
...
var Vec v; //
, .
, :
struct Vec
{
f32 x= 0.0f;
f32 y= 0.0f;
}
, [] , :
var [ i32, 4 ] a[ 1, 1, 3, 4 ];
var tup[ i32, f32 ] t[ 8, 0.5f ];
var [ f32, 16 ] a_uninit; // , .
var[ i32, 3 ] aa[ 0, 1 ]; // ,
C++, , . , , — .
. , , — . this, - /, :
struct Vec
{
f32 x; f32 y;
fn constructor()
( x= y, y= 0.0f ) // , «y»
{}
fn constructor( f32 val )
( x= val, y= x ) // . «x» «y»
{}
}
. , , . .
:
var i32 mut x= 0;
var i32 &mut ref0= x;
++x; // ,
var i32 &imut ref1= x; // , , . .
:
var i32 mut x= 0;
var i32 &imut ref0= x;
var i32 &mut ref1= x; // , ,
:
var i32 mut x= 0;
var i32 &mut ref0= x;
var i32 &mut ref1= ref0; // , . . ,
:
fn Mutate( i32 &mut x, i32 &mut y );
...
var i32 mut x= 0;
Mutate( x, x ); // ,
. C++
std::vector<int> vec;
vec.push_back(1);
int& ref= vec.front();
vec.push_back(2); // , ref
Ü :
var ust::vector</i32/> mut vec;
vec.push_back(1);
var i32 &imut ref= vec.front();
vec.push_back(2); // , vec,
( ). — polymorph, interface, abstract . . , .
:
- . , , .
:
class A interface
{
fn virtual pure Foo(this);
}
- . . . , this, , . . . abstract call, , , C++.
:
class A abstract
{
fn virtual pure Foo(this);
fn virtual Bar(this){}
i32 x= 0;
}
- . . . - , .
:
class A interface
{
fn virtual pure Foo(this);
}
class B : A
{
fn virtual override Foo(this){}
}
- . , , .
. .
fn virtual pure Foo(this); // . , , .
fn virtual Foo(this){} // . , .
fn virtual override Foo(ths){} // , . , .
fn virtual final Foo(this){} // , . , . - , .
2019— , , Ü . . , , , , .
:
fn Foo( i32 mut x ) : i32
{
while(x < 100 )
{
x+= 10;
continue;
x+= 20; // ,
}
return x;
++x; // ,
}
:
fn Foo( i32 x ) : i32
{
if( x < 10 ) { return 0; }
else if( x > 100 ) { return 1; }
// ,
}
else , return .
, - , halt ( ). , , , return.
. , (. ). () .
:
struct CallableObject
{
i32 &mut x;
op()( mut this )
{
++x;
}
}
...
var i32 mut x= 0;
var CallableObject mut obj{ .x= x };
auto thread= ust::thread_create( move(obj) );
++x; // , «x», «thread»
++ obj.x; //
- , , - , .
(mutable C++), . . . , - , .
, ? — shared_ptr_mt . , , lock_mut() lock_imut(), . « , ».
:
struct Incrementer
{
ust::shared_ptr_mt_mut</ i32 /> ptr;
op()( mut this )
{
auto mut lock= ptr.lock_mut(); // «lock»
++lock.get_ref();
}
}
...
var ust::shared_ptr_mt_mut</ i32 /> ptr(0);
var size_type mut i(0);
var ust::vector</ ust::thread</Incrementer/> /> mut threads;
while( i < size_type(64) )
{
var Incrementer incrementer{ .ptr= ptr };
threads.push_back( ust::thread_create(incrementer) );
++i;
}
threads.clear(); // .
halt if( ptr.lock_imut().get_ref() != 64 ); // , ,
, , . . «shared». , , , - , «shared».
. , , constexpr . , .
, Ü, - , C.
C++, (=, +=, *= . .) , , . ++ –.
:
if( x = 0 ) {}
x++; // ++
x += x += x; // , +=
x+= x++ + ++x; //
. void, .
, , . :
auto a = select( condition ? x : y );
select .
. . . .
? , - :
- . - , , .
- . . - NullPointerException - , - . , , . . .
- . , , , . - - , . , .
- . , , .
, , ?
, . . «» , , std::optional/std::variant C++ Option/Result Rust.
, -, , halt. ( Ü ) , , , .
, - . , import, , . C++, , .
. , *.cpp *.hpp C++.
, , , .
, , . , , , . , - , .
→
→
, , .
→
.
, . . , .