Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Beef, un nouveau langage de programmation orienté performance,
Espère fournir une expérience de développement fluide et agréable pour les applications en temps réel hautes performances

Le , par Stéphane le calme

102PARTAGES

16  0 
Beef est un langage de programmation compilé axé sur les performances. La syntaxe et la conception de la bibliothèque principale dérivent de C#, mais il existe de nombreuses différences sémantiques en raison d'objectifs de conception différents. Le langage a été développé en même temps que son environnement EDI et une attention particulière a été portée à la satisfaction globale du développement d'applications Beef. Le public visé est le développeur axé sur les performances qui apprécie la simplicité, la lisibilité du code, l'itération de développement rapide et un bon débogage.

L'objectif principal de Beef est de fournir une expérience de développement fluide et agréable pour les applications en temps réel hautes performances telles que les jeux vidéo, avec des fonctionnalités de bas niveau qui le rendent adapté au développement de moteur, combiné à une ergonomie de haut niveau adaptée au développement de code de jeu.

Le langage a d'abord été publié le 29 septembre en version 0.42.0 et a reçu une mise à jour le 31 décembre qui a apporté :
  • une amélioration des capacités de compilation croisée ;
  • un ajout de cibles de build macOS, iOS et Android ;
  • des optimisations pour le GC d'allocateur de débogage ;
  • une prise en charge supplémentaire des contraintes de l'opérateur ;
  • un ajout d'attributs de remplacement d'alignement d'allocations ;
  • une prise en charge étendue de la liste de capture lambda pour inclure des noms de variables spécifiques ;
  • des capacités annulables améliorées, y compris les opérateurs.

Beef permettrait de mélanger en toute sécurité différents niveaux d'optimisation sur un niveau par type ou par méthode, permettant au code critique de performance d'être exécuté à la vitesse maximale sans affecter la débogabilité du reste de l'application.

La gestion de la mémoire dans Beef est manuelle et inclut un support de première classe pour les allocateurs personnalisés. Des précautions ont été prises pour réduire le fardeau de la gestion manuelle de la mémoire grâce à l'ergonomie du langage et aux sécurités d'exécution - Beef pourrait détecter les fuites de mémoire en temps réel et offrirait une protection garantie contre les erreurs d'utilisation après libération et de double suppression. Comme avec la plupart des fonctions de sécurité de Beef, ces sécurités de mémoire peuvent être désactivées dans les versions pour une performance maximale.

Le Beef IDE prend en charge des fonctionnalités de productivité telles que la saisie semi-automatique, les correctifs, le reformatage, les outils de refactorisation, l'inspection de type, la compilation de code d'exécution (échange de code à chaud) et un profileur intégré. Le débogueur polyvalent de l'EDI serait capable de déboguer des applications natives écrites dans n'importe quel langage, et est destiné à être un débogueur autonome complet, même pour les développeurs C / C ++ purs qui souhaitent une alternative au débogage de Visual Studio.

Modèle de compilation

Le contexte de compilation Beef est un espace de travail, qui se compose de plusieurs projets. Un projet peut être soit une bibliothèque, soit produire un binaire tel qu'un exécutable ou une DLL. Les sources sont analysées, transmises via un préprocesseur limité, compilées et une collection de fichiers objet est créée pour les types et méthodes référencés, qui sont ensuite liés aux binaires cibles. Le modèle de compilation à l'échelle de l'espace de travail permet aux paramètres par espace de travail d'affecter les compilations de groupes spécifiques de méthodes ou de types, en modifiant le préprocesseur et les paramètres de compilation (par exemple: niveau d'optimisation) du code même lorsqu'il est contenu dans des bibliothèques tierces référencées.

La compilation incrémentielle est prise en charge, avec un graphe de dépendances reconstruisant uniquement les objets potentiellement affectés et avec un cache principal pour éviter de reconstruire des objets sans modifications fonctionnelles. La compilation incrémentielle peut être désactivée pour créer des versions reproductibles.

Beef prend en charge plusieurs backends de compilateur, y compris LLVM et un backend de « débogage amélioré » (Og +) personnalisé qui effectue certaines optimisations de code qui n'ont pas d'incidence négative sur le débogage et a quelques améliorations dans les informations de débogage émises sur LLVM.

Plusieurs éditeurs de liens sont pris en charge, y compris les éditeurs de liens système et l'éditeur de liens LLVM qui peuvent être utilisés pour les générations optimisées au moment de la liaison (LLVM LTO / ThinLTO).

Fonctionnalités de sécurité

Beef prend en charge une variété de fonctionnalités de sécurité optionnelles, dont beaucoup peuvent être désactivées pour des groupes de code spécifiés pour les versions de « sécurité mixte ». Par défaut, les vérifications suivantes sont activées pour tout le code dans les versions de débogage et elles sont désactivées dans les versions de version.

Vérification des limites

La vérification des limites est implémentée dans la bibliothèque standard pour les tableaux, les collections, les étendues et les chaînes. Dans de nombreux cas, ceux-ci sont implémentés en ayant un accesseur [Checked] qui effectue des vérifications des limites et un autre accesseur [Unchecked] qui ne vérifie pas les limites. Cela permet de vérifier les limites sur le site d'appel plutôt que d'être déterminé à l'échelle de la collection.

Code : Sélectionner tout
1
2
// Désactiver la vérification des limites pour cet index spécifique
    int val = arr[[Unchecked]i];
Code : Sélectionner tout
1
2
3
4
5
6
    // Ne fait aucune vérification dans cette méthode
    [DisableChecks]
    void Calculate()
    {
        int val = arr[i];
    }
Vérification dynamique de la distribution

Les transtypages d'objets explicites vers un type dérivé non valide seront interceptés lors de l'exécution.

Fuites de mémoire

Les fuites peuvent être détectées en temps réel avec le gestionnaire de mémoire de débogage. La mémoire accessible sera tracée en continu lors de l'exécution et la mémoire qui n'est plus accessible, mais qui n'a pas été correctement libérée sera immédiatement signalée comme une fuite, avec l'emplacement du code où l'allocation s'est produite. La profondeur de trace de pile pour ce suivi d'allocation est réglable.

Double libération / utilisation après libération

Lorsque le gestionnaire de mémoire de débogage est activé, les objets dont la libération a été demandée seront marqués comme « libérés », mais la mémoire ne sera pas récupérée physiquement tant qu’il n’y aura plus de références à la mémoire qu’elle occupe. Toute tentative d'utilisation de la mémoire après qu'elle a été marquée comme libérée est garantie d'échouer immédiatement, et la valeur de cet objet libéré et sa trace de pile d'allocations seront valides et visibles dans le débogueur.


Gestion de la mémoire

Allocation de la mémoire

Les allocations peuvent être placées sur la pile, l'allocateur global ou un allocateur personnalisé. Les allocations de pile utilisent le mot clé «scope», qui peut spécifier une étendue de l'étendue actuelle (c.-à-d.: Bloc de code) à l'étendue de la méthode entière (même dans une boucle).

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
static void Test(StreamReader fs)
{
    let strList = scope List<String>();
    for (let line in fs.Lines)
    {
        /* The scope of this string is the whole method */
        let lineStr = scope:: String(line);
        strList.Add(lineStr);
    }
    strList.Sort();
}

static void Test(StreamReader fs)
{
    Sort:
    {
        let strList = scope List<String>();
        for (let line in fs.Lines)
        {
            /* The scope of this string is the "Sort" scope */
            let lineStr = scope:Sort String(line);
            strList.Add(lineStr);
        }
        strList.Sort();
    }
}
Les allocations de portée peuvent augmenter dynamiquement la taille de la pile, et il faut veiller à ce que suffisamment d'espace de pile soit disponible pour le calcul donné, tout comme les méthodes récursives doivent garantir que la profondeur de récursivité n'épuise pas la pile.

Les allocations via l'allocateur global utilisent le mot clé « new ».

Code : Sélectionner tout
1
2
3
4
String AllocGlobalString(int len)
{
    return new String(len);
}
Les allocations via un allocateur personnalisé utilisent le mot-clé «new» avec une instance d'allocateur personnalisée spécifiée.

Code : Sélectionner tout
1
2
3
4
String AllocCustomString(int len)
{
    return new:customAllocator String(len);
}
Au minimum, un allocateur personnalisé doit implémenter une seule méthode Alloc, mais une méthode AllocTyped peut être ajoutée pour ajouter une logique d'allocation spécifique au type. La mémoire est libérée via une méthode Free.

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct ArenaAlloc
{
    public void* Alloc(int size, int align)
    {
        return Internal.StdMalloc(size);
    }

    public void* AllocTyped(Type type, int size, int align)
    {
        void* data = Alloc(size, align);
        if (type.HasDestructor)
            MarkRequiresDeletion(data);
    }

    public void Free(void* ptr)
    {
        Internal.StdFree(ptr);
    }
}
Notez que si la vérification des fuites en temps réel est activée et que les allocateurs personnalisés utilisent une mémoire qui n'est pas déjà suivie par le vérificateur de fuites, l'allocateur devra signaler sa mémoire pour analyser les références d'objet.

Les allocations personnalisées peuvent également être allouées via des mixins, ce qui peut même permettre une allocation conditionnelle sur la pile. Le mixage ScopedAlloc, par exemple, effectuera de petites allocations sur la pile et de gros objets sur le tas.

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static mixin ScopedAlloc(int size, int align)
{
    void* data;
    if (size <= 128)
    {
        data = scope:mixin [Align(align)] uint8[size]* { ? };
    }
    else
    {
        data = new [Align(align)] uint8[size]* { ? };
        defer:mixin delete data;
    }
    data
}

void ReadString(int reserveLen)
{
    String str = new:ScopedAlloc! String(reserveLen);
    UseString(str); 
}
Allocateur global

L'allocateur global est sélectionné pour chaque espace de travail. Par défaut, les allocateurs CRT malloc / free sont utilisés, mais n'importe quel allocateur global de style C peut être utilisé, comme TCMalloc ou JEMalloc. De plus, Beef contient un allocateur de débogage spécial qui permet des fonctionnalités telles que la vérification des fuites en temps réel et la compilation à chaud.

Les allocations Beef sont de style C en ce sens qu'elles ne sont pas délocalisables et qu'il n'y a pas de garbage collector.

Libérer de la mémoire

Les allocations de portée sont automatiquement débloquées à la fin de scope, mais les allocations manuelles doivent être débloquées manuellement avec le mot-clé «delete». De même que pour les allocations d'allocateurs personnalisées, la suppression peut spécifier une cible d'allocateur personnalisée pour libérer de la mémoire à partir d'allocateurs personnalisés.

Source : dépôt du langage Beef

Et vous ?

Que pensez-vous de Beef dans l'absolu ? Allez-vous chercher à en savoir un peu plus sur ce langage ?
Quels sont les éléments qui peuvent vous pousser à apprendre un nouveau langage de programmation ?
Le plus souvent le faites-vous pour des projets personnels ou des projets dans votre entreprise ?
En général, vous orientez-vous vers un langage de programmation mainstream ou êtes-vous parfois curieux de découvrir d'autres langages qui ne sont pas forcément autant populaires, mais qui font bien leur travail ?
Que pensez-vous de la prolifération des nouveaux langages de programmation ? Y en a-t-il trop ou pas assez selon vous ?
À quel moment est-ce pertinent selon vous de créer un nouveau langage de programmation ?

Voir aussi :

Programmation : le C « langage de l'année 2019 » devant C# et Python, d'après les chiffres de la première édition de l'index TIOBE pour l'année 2020
Joyeux anniversaire ANSI C : cela fait déjà 30 ans que le langage de programmation C a été normalisé, petit tour d'horizon sur son évolution
Pourquoi la programmation fonctionnelle n'est-elle pas la norme de l'industrie du code ? L'auteur de « Elm in action » s'exprime, « c'est une question de temps avant que la POO soit détrônée »
Quels sont les meilleurs langages de programmation à apprendre en 2020 ? Voici un classement de ces langages selon le cas d'utilisation

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de mattdef
Membre actif https://www.developpez.com
Le 09/01/2020 à 12:04
Ouffffff j'ai eu peur, je pensais qu'on allait pas avoir de nouveau langage ce mois-ci !
20  0 
Avatar de stef-13013
Membre actif https://www.developpez.com
Le 09/01/2020 à 12:42
J'attends avec impatience février pour un nouveau langage !!
11  0 
Avatar de transgohan
Expert éminent https://www.developpez.com
Le 09/01/2020 à 13:01
Le terme performance j'accepte.
Mais pourquoi temps réel ? Il n'y aurait pas un abus de langage ?
Du code "temps réel" qui est exécuté sur un OS non temps réel c'est... Du code normal pour moi.
10  0 
Avatar de vanquish
Membre éprouvé https://www.developpez.com
Le 10/01/2020 à 8:13
Citation Envoyé par Stéphane le calme Voir le message
Le public visé est le développeur axé sur les performances qui apprécie la simplicité, la lisibilité du code, l'itération de développement rapide et un bon débogage.
Ce langage n'est pas pour moi.
Moi j'attends un langage lent, compliqué, illisible , qui prenne un temps fou pour chaque développement et un débogueur inutilisable.

J'avoue que seule l'absence d'une réelle communauté de développeurs pourrait me séduire.
10  0 
Avatar de Darkzinus
Expert éminent https://www.developpez.com
Le 10/01/2020 à 13:50
Ca y est c'est la mort du COBOL
1  0