Selon mon expérience, Wikipedia et Réponses antérieures , une langue de script est une catégorie vague de langues de haut niveau (pas de gestion de la mémoire manuelle) et interprétée. Les exemples populaires sont Python, Ruby, Perl et TCL.
Certaines langues de script peuvent être " incorporé ". Par exemple:
On dit parfois que Lua est plus facilement intégré que Python ou cela Typescript est difficile à incorporer . De même, Wren est "destiné à l'incorporation dans les applications".
Quels facteurs font une langue intégrée? Est-ce uniquement la taille et la vitesse de l'interprète de base ou que d'autres facteurs entrent-ils en jeu?
Incorporer une langue (je vais éviter de le caractériser comme "script") signifie que ce qui suit a été effectué:
La première balle est littéralement la définition de l'incorporation. La principale raison d'intégrer une langue dans une application est de fournir un moyen facile d'étendre la fonctionnalité de l'application. Les raisons incluent:
La grande question est donc, Quels facteurs simplifient l'incorporation?
La ligne de fond est qu'il est possible d'intégrer une large gamme de langues dans une autre application. Dans certains cas, le travail acharné a déjà été fait pour vous et vous devez simplement inclure la langue dans votre application. Par exemple, IronPython est construit sur .NET et Jython est construit sur Java vous permettant d'intégrer facilement Python dans les applications construites sur ces plates-formes.
En ce qui concerne la manière dont la mise en œuvre est robuste ou complète, vous obtiendrez des résultats mitigés. Certains projets sont plus matures que d'autres. Certaines langues sont simplement plus faciles à mettre en œuvre (il y a une raison pour laquelle LISP était l'une des premières langues intégrées).
En théorie, toute langue peut être intégrée. S'il n'y a pas de contraintes sur la solution, c'est en fait le cas. C'est une conséquence naturelle de la complétude de Turning I.e. Vous pouvez toujours construire un émulateur.
Ce que je pense que vous demandez est "Qu'est-ce qui rend une langue pratique à cette fin?" Je pense que l'une des principales choses qui fait une langue un bon choix est un bon choix qui est défini en termes de comportements par opposition aux implémentations. Si la langue en question présente des règles très spécifiques sur la manière dont les valeurs INT doivent être représentées en mémoire, par exemple, cela crée des difficultés lors de la course au-dessus d'une autre application dont les idées sur les entiers ne sont pas exactement les mêmes.
Un bon exemple de ceci est Python qui est défini en termes de fonctionnement de son comportement et d'avoir peu à dire sur la manière dont elle est mise en œuvre. Cela signifie que vous pouvez écrire un interprète entièrement fonctionnel Python en tant que façade pour Java (ou C #, etc.). Cela signifie non seulement vous pouvez exécuter les scripts Python, vous pouvez l'utiliser pour interagir avec des parties de l'application écrite en Java.
Un autre facteur est la simplicité dans la sémantique de la langue. Plus la langue est complexe, plus il est difficile de construire un interprète pour cette langue pour des raisons évidentes.
Il y a quelques facteurs:
si la langue a pris en charge l'intégration de l'API. Certaines langues de script comme Python et Lua ont officiellement pris en charge les API spécialement conçues pour intégrer ces langues dans une application hôte. Cela inclut la spécification de la manière dont la langue interagit avec l'interface de fonction étrangère, les poignées d'objets étrangers, les classes étrangères, etc et spécifiant une API pour les langues étrangères à appeler et à travailler avec des objets dans la langue. Les langues conçues pour l'incorporation peuvent faire ressembler ces objets étrangers et se comporter, comme des classes et des objets réguliers sans classes d'emballage compliquées. Langues à base de protocole comme = Python a tendance à être très bon à cela.
Les implémentations de langues conçues pour incorporer sont souvent conçues pour partager un thread avec l'application principale. En effet, les éléments d'interface utilisateur ne peuvent généralement être mis à jour que sur le thread d'interface utilisateur, de sorte que les interprètes pour les langages incorporés doivent être en mesure de fonctionner, céder au fil principal, appelez les mises à jour de l'interface utilisateur et reprendre l'exécution sans prendre complètement le fil principal. Les implémentations linguistiques qui ne sont pas conçues pour l'intégration peuvent nécessiter l'interprète de fonctionner dans des threads ou des processus distincts et communiquer avec le fil de l'interface utilisateur de l'application uniquement via un mécanisme de file d'attente RPC/Message, qui vient à un coût de performance significatif.
Sécurité de la mémoire. Mémoire Safe Langues et langues sans accès à la mémoire directe sont plus faciles à incorporer car le code écrit dans la langue de script ne peut pas planter la demande principale en raison de l'accès à la mémoire directe.
Quelle est la taille du support d'exécution pour ces langues. Les langues avec les grandes bibliothèques standard ont tendance à être désavantagées pour l'incorporation, car cela signifie bloquant la taille de la demande. D'autre part, il existe de nombreuses applications dans lesquelles l'énorme bibliothèque standard est la raison pour laquelle une langue de script spécifique est choisie, de sorte que les Scripters peuvent réellement accéder aux fonctionnalités que l'application principale elle-même ne veut pas réellement fournir directement.
Des défis supplémentaires tels que Typescript ne peuvent être incorporés que par l'intégration d'un interprète JavaScript. Il existe donc le défi supplémentaire de l'intégration de l'interprète JavaScript, même si vous vous souciez que de documents.
Les langues conçues pour être incorporables Essayez de fournir des fonctionnalités pour faciliter l'accès à l'application hôte. Il y a deux couches à cela, la syntaxe et la sémantique de la langue réelle et la mise en œuvre d'exécution de la langue que vous essayez d'intégrer.
Prenons par exemple les deux Python et TCL, qui sont étiquetés comme intégrés. De mon expérience, Python est beaucoup plus difficile à intégrer que TCL (les deux, dans plusieurs contextes).
Pourquoi est-ce si?
Python est l'opinionner, le monde est supposé ressembler à une configuration de POSIX. L'API du système de fichiers, les API de la console, les API du réseau NE PAS abstraite beaucoup, principalement des emballages directs autour de POSIX C-API. TCL n'est-ce pas proche du matériel, il essaie de résumer la plupart des API et ne fournit pas beaucoup d'API de faible niveau aux couches de script. Donc, si vous essayez d'incorporer Python, vous devez fournir une abstraction de fichier comme un fichier posix. Pour TCL, vous n'avez rien à faire, si vous ne vous souciez pas des fichiers. Moins de travail, plus facile à incorporer.
(C) Python est fondamentalement fileté avec un verrou global. TCL n'a pas de serrure globale. Donc, si votre application hôte est multi-filetée et que vous avez incorporé Python pour des éléments critiques, vous venez d'ajouter une serrure globale à votre application. Ainsi, l'intégration Python dans les programmes multi-filetés est beaucoup plus douloureuse.
Système de module Pythons par carte par défaut dans un système de fichiers. Vos noms de module et noms de fichiers de fichiers sont liés. Votre langue est donc limitée par le système de fichiers que vous fournissez et rompt soudainement lorsque vous le portez à un système de fichiers insensible. TCL n'a pas lié son système de module à une disposition de système de fichiers. Le système de fichiers ne modifie pas la sémantique de votre langue.
Python suppose que le monde bloque et synchrone (comme POSIX), n'adoptant lentement ASYNC API. TCL tente plus difficile de faire des API et des raclages non bloquants. Comme il est beaucoup plus facile d'aller simuler des API de blocage sur ASYNC que l'inverse, vous avez généralement moins de travail à faire.
TCL est plutôt minime. Vous pouvez dépouiller toutes les choses que vous n'avez pas besoin, facilement. Comme se débarrasser de toutes les API de système de fichiers. Ou contrôle des processus. Ou des expressions régulières. Python a une tonne de trucs dans son espace de noms intégré et est presque impossible à verrouiller et sécurisé contre le code non approuvé en raison de l'accès à l'écriture du bytecode. Il n'est même pas considéré comme un bug que pur Python code peut planter le processus (par exemple Python _ bytecode utilise parfois un pointeur brut et l'écrit). Il est donc difficile d'intégrer si vous essayez d'exécuter un code d'utilisateur non approuvé.
La bibliothèque standard de Pythons suppose souvent qu'il est en contrôle du monde. TCLS ne le fait pas. Par exemple, Python souffle souvent lorsque vous rencontrez des problèmes de mémoire et tue votre processus. Certaines Python appels API pourraient même jeter des erreurs critiques à STDRERR (qui pourrait n'existerait peut-être pas dans une situation d'intégration, par exemple Windows Service Contexts et tuer votre demande), tandis que TCL essaie généralement de contrôler l'application sans casser ou sortir. Donc, être un bon invité est important.
Donc, des choses qui rendent une langue facile à incorporer, c'est être comme un bon invité: