Magik (langage)

langage de programmation orientée objet

Magik est un langage de Programmation orientée objet qui supporte l'héritage multiple, le polymorphisme et le typage dynamique. il a été défini et implémenté en 1989 par Arthur Chance, de Smallworld Systems Ltd, dans le cadre du système d'information géographique Smallworld. À la suite de l'acquisition par General Electric de Smallworld en 2000, Magik est maintenant distribué par GE Energy, toujours en tant que composant de la plateforme Smallworld.

Magik a été implémenté pour la première fois en 1990 et a été amélioré au fil des années. La version actuelle est la version 4.0, dite Magik SF (Small Footprint).

En , les développeurs de Magik ont annoncé le portage du langage Magik sur la machine virtuelle Java. Le succès du portage a été annoncé par Oracle Corporation en novembre de la même année[1].

Similitudes avec Smalltalk ou Python. modifier

Magik partage avec Smalltalk, et surtout avec Python plusieurs similitudes en termes de fonctionnalités et d'architecture :

La machine virtuelle Magik est disponible sur différentes plateformes, dont Microsoft Windows, et différentes variantes d'Unix ou de Linux.

Magik est basé sur une console, et le code peut être modifié à la volée, même lorsqu'une application est en cours d'exécution. La console peut être utilisée à la fois pour exécuter du Magik ou pour voir les résultats. Le code compilé d'une application peut être enregistré dans un fichier unique, appelé fichier image, ou simplement image. Une image Magik comprend la définition des classes et variables globales, et l'état de la session. Il s'agit en fait de l'état complet de la mémoire de la machine virtuelle au moment de l'enregistrement du fichier image.

Fonctionnalités du langage modifier

Commentaires modifier

Magik utilise un # pour marquer le début d'une ligne de commentaire. Chaque ligne de commentaires doit débuter par # :

 # Ceci est un commentaire.
# Ceci est un commentaire réparti
# sur deux lignes

Affectation modifier

Magik utilise l'opérateur << («devient») pour les affectations :

  a << 1.234
  b << b + a
  c << "foo" + "bar" # Concat strings

Cette notation se lit "a devient 1.234" ou "b devient b plus a". Cette terminologie permet de séparer l'affectation de la comparaison.

Magik implémente également un opérateur compressé similaire à ceux existant en C:

  b +<< a # Équivalent à b << b + a

Pour imprimer la valeur d'une variable, on peut utiliser la commande suivante :

  a << "hello"
  write(a)

Symboles modifier

Outre les types de données habituels, comme les entiers (integer), les réels (float) ou les chaînes de caractères, Magik implémente également des symboles. Les symboles sont utilisés abondamment en Magik pour identifier les objets de manière unique. Ils se présentent sous la forme d'un caractère : suivi d'une chaine de caractères. Les symboles sont en principe constitués des caractères a-z (minuscules) et _, ! ou ?. Il est possible d'utiliser d'autres caractères en les plaçant entre barres verticales ( | ). Par exemple :

  a << :hello  # partout où :hello sera rencontré, il s'agira de la même instance
  b << :|hello world|

Typage dynamique modifier

Les variables Magik ne sont pas typées comme elles peuvent l'être en C, C++ ou Java. Elles peuvent, comme en lisp ou Python, référencer différents objets, de différentes classes, à différents moments. Magik ne différencie pas les classes et les types primitifs. En Magik, toute entité manipulée est un objet :

  a << 1.2     # Un réel est affecté à la variable 'a'
  a << "toto"  # Puis une chaîne de caractères est affecté à la variable 'a'
Objets

Les objets sont définis au moyen de prototypes appelés «exemplars». Ces prototypes définissent des classes, d'une manière proche de la définition des classes Python. Magik supporte l'héritage multiple, et les classes abstraites (mixins). Les nouvelles instances sont définies en clonant un objet de la classe, soit généralement le prototype, qui est lui-même une instance de la classe qu'il définit, mais tout objet de la classe peut être utilisé à la même fin.

le prototype est défini au moyen de la procédure def_slotted_exemplar(), par exemple:

  def_slotted_exemplar(:mon_objet,
  {
    {:slot_a, 42},
    {:slot_b, "bonjour"}
  }, {:classe_parente_a, :classe_parente_b})

Ce fragment de code définit une classe mon_object qui a deux attributs («slots») appelés slot_a (pré-initialisé à 42) et slot_b (pré-initialisé "bonjour") qui hérite des classes classe_parente_a et classe_parente_b.

Comparaison modifier

Magik implémente tous les opérateurs logiques (=, <, <=, >, >=, ~=/<>) pour la comparaison, ainsi que de moins habituels. Les opérateurs _is et _isnt sont utilisés pour comparer l'identité d'instances d'objets, plutôt que leurs valeurs.

Par exemple:

  a << "Robert"
  b << "Robert"

  a _is b   # est faux parce que les deux chaînes sont des instances différentes de la classe «chaîne de caractères».
  a =   b   # est vrai parce que les deux valeurs sont identiques
  
  a << "hello"
  b << a
  a _is b # est vrai, puisque les deux variables désignent la même instance (a a été affecté à b).
  a  =  b # est vrai, parce que la valeur d'une même instance est forcément identique 
            # (il est impossible d'avoir à la fois  a _is b vrai et a=b faux).

Méthodes modifier

Les méthodes sont définies sur les exemplars au moyen des mots-clés _method et _endmethod:

  _method mon_objet.ma_methode(a, b)
    _return a + b
  _endmethod

Par convention, on définit deux méthodes, new() (pour créer une instance) et init() (pour initialiser cette instance).

  # Méthode d'instanciation
  _method person.new(name, age)
    _return _clone.init(name, age)
  _endmethod

  # méthode d'initialisation.
  _private _method person.init(name, age)
     # utiliser si besoin l'implémentation de la ou des classes parentes.
     _super(classe_parente_a).init(name, age)
     # Initialiser les slots.
     .name << name
     .age << age
    _return _self
  _endmethod

_clone crée une copie (un clone) de l'instance de person à laquelle le message new() a été envoyé. L'instruction _super invoque l'implémentation de la même méthode dans la classe parente classe_parente_a. L'instance courante est référencée au moyen du mot-clé _self. Les valeurs des slots sont accessibles au moyen de l'opérateur unaire ..

Les méthodes qui ne font pas partie de l'interface publique de la classe peuvent être définies au moyen du mot-clé _private. Les méthodes «privées» ne sont accessibles qu'au moyen de _self, _clone, ou _super.

Les arguments optionnels peuvent être définis au moyen du mot-clé _optional statement. Dans ce cas, les arguments omis auront la valeur _unset (l'objet «NUL» de Magik). Une liste variable d'arguments peut être définie au moyen de l'opérateur _gather («rassembler»), similaire à l'opérateur * de Python dans le cas d'arguments variables (*args).

  _method my_object.my_method(_gather values)     
  _endmethod

Itération modifier

En Magik les mots-clés _for, _over, _loop et _endloop permettent l'itération.

  _method my_object.my_method(_gather values)
    total << 0.0
    _for a _over values.elements()
    _loop
       total +<< a
    _endloop
    _return total
  _endmethod

  m << my_object.new()
  x << m.my_method(1.0, 2, 3.0, 4) # x = 10.0

Ici values.elements() est un itérateur qui permet de parcourir les valeurs. Un itérateur Magik est un type particulier de générateur, dit compréhension de liste, permettant généralement de parcourir un ensemble.

Un itérateur est défini au moyen des mots-clés _iter et _loopbody :

  _iter _method my_object.even_elements()
    _for a _over _self.elements()
    _loop
      _if a.even? _is _true
      _then
         _loopbody(a)       
      _endif
    _endloop
  _endmethod

Procédures modifier

À l'instar de Python, Magik permet à la fois la programmation objet et/ou itérative. Magik permet donc la définition de procedures. Les procédures sont définies au moyen des mots-clés _proc et _endproc . Elles sont affectées à des variables pour pouvoir être invoquées :

  my_procedure << _proc @my_procedure(a, b, c)
    _return a + b + c
  _endproc

  x << my_procedure(1, 2, 3) # x = 6

Langue modifier

Magik, ayant été développé à Cambridge, au Royaume-Uni, utilise l'anglais britannique dans ses bibliothèques . Par exemple:

  Utiliser "initialise", pas "initialize" (en général, les terminaisons sont en "ise", pas ize",
  utiliser "centre" et non "center",
  etc.

Ensembles modifier

Magik permet la manipulation d'ensembles. On peut citer :

  • Simple Vector
  • Rope
  • Hash Table
  • Property List
  • Equality set
  • Bags

Hello World modifier

Voici la version Magik du traditionnel programme «Hello world» :

write("Hello World!")

Références modifier

  1. (en) Jim Connors, « Sprinkle Some Magik on that Java Virtual Machine », (consulté le ) : « With this new capability GE Energy has succeeded in hosting their Magik environment on top of the Java Virtual Machine »


Liens externes modifier