Рубрики
Без рубрики

Polyglot Mainception с Graalvm. Почему? Потому что это весело 🏄

Давайте тестируем диск Graalvm с программой, которая использует много языков вместе. Почему? Потому что это весело!. Помечено Java, Python, JavaScript, Rust.

Первоначально опубликовано в Deepu.ech Отказ

Вы слышали о Граалвм ? Если вы еще не должны проверить это. Это захватывающая технология, вы знаете, что получает разработчик Polyglot Point 😉

С сайта:

Graalvm – это универсальная виртуальная машина для беговых приложений, написанных в JavaScript, Python, Ruby, R, r, JVM-языкам, такими как Java, Scala, Groovy, Kotlin, Clojure и LLVM, такие языки, как C и C ++.

Граалвм – один из своего рода. Это полиглот VM, разработанный в Oracle и отдельно от своих возможностей многоглот, он также был доказан, что является довольно исполнительным и имеет меньшую площадь памяти. Он имеет поддержку для строительства нативных изображений и некоторых современных структур Java Microvize, таких как Микронаут и Quarkus Поддержка Graalvm, поскольку он обеспечивает более быстрый запуск и меньший след, который идеально подходит для архитектур микровиссов.

Так каковы возможности Граальвма? Давайте посмотрим

Hraalvm Особенности

Установите Graalvm.

Прежде чем мы начнем, позвольте нам настроить Graalvm. Я использовал SDKMAN, вы также можете следовать Это Если вы хотите установить его вручную.

  1. Первый Установить SDKMAN Если у вас нет этого уже
sdk list java
# you can use a newer version if available
sdk install java 19.3.1.r11-grl
sdk use java 19.3.1.r11-grl
# Check everything
java -version
node -v
lli --version

Вышепередается установится Graalvm и настроить его как Java , Узел и Лли контекст. Пожалуйста, обратите внимание на : Если вы начнете новую сеанс терминала, вам придется запустить SDK Используйте Java 19.3.1.R11-GRL опять таки.

  1. Установите MLVM Toolchain, Python и Ruby служба поддержки
gu install llvm-toolchain
export LLVM_TOOLCHAIN=\$(lli --print-toolchain-path)

gu install python
gu install ruby
  1. Установите ржавчину
curl https://sh.rustup.rs -sSf | sh

Вот и мы готовы катиться!

Как разработчик полиглота, Graalvm довольно интересен для меня, так как я могу использовать многие языки, которые я люблю вместе, используя лучшие части от каждого. Давайте рассмотрим возможности полиглот, предлагаемые Graalvm, обратите внимание, что поддержка Python, Ruby, R и ржавчины все еще находятся на экспериментальной стадии, и, следовательно, ваш пробег может варьироваться. Мы построим программу сегодня, используя Java, JavaScript, Ruby, Rust, Python и C ++.

Я хотел использовать ржаветь и идти так хорошо. Пока ржавчину в основном работает через Graalvm Лли Командная строка, она имеет много ограничений при встроенном режиме Polyglot. После многих возобновляемых мне удалось работать. Для Голанга это может быть возможно с Это Go Llvm Compiler, как показано на рисунке здесь Но он имеет свой собственный набор вопросов, когда я пытался. Так что я уже отказался от Голанга. Дайте мне знать, если кто-нибудь из вас получил работу.

У нас будет простое (глупуе 😉) приложение, написанное в Java, который составляет методы с разных языков для каждого шага из Java

  1. Python : Фильтрует число фибоначчи из данного входного массива
  2. JavaScript : Найдите кубик каждого номера в выходе на массиве с предыдущего шага
  3. C++ : Получите сумму чисел в выходной массиве с предыдущего шага
  4. Ржавчина : Найдите кубик-корень числа с предыдущего шага
  5. Ruby : Найти факториал числа с предыдущего шага
  6. Java : Наконец-то распечатайте результат (это также программа обертки)

Если вы предпочитаете более сложный пример, проверьте Это вне.

Шаг 1: Джава

Начнем с нашей программы Java Wrapper Polyglot.java.

import java.io.*;
import org.graalvm.polyglot.*;

class Polyglot {
    // We create a polyglot context to evaluate source files
    static Context polyglotCtx = Context.newBuilder().allowAllAccess(true).build();

    // Utility method to load and evaluate a source file
    static Value loadSource(String language, String fileName) throws IOException {
        File file = new File(fileName);
        Source source = Source.newBuilder(language, file).build();
        return polyglotCtx.eval(source);
    }

    // Utility method to convert arrays between languages
    static int[] getIntArrayFromValue(Value val) {
        int[] out = new int[(int) val.getArraySize()];
        if (val.hasArrayElements()) {
            for (int i = 0; i < val.getArraySize(); i++) {
                out[i] = val.getArrayElement(i).asInt();
            }
        }
        return out;
    }

    public static void main(String[] args) throws IOException {

        int[] input = new int[] { 4, 2, 8, 5, 20, 1, 40, 13, 23 };

        /* PYTHON: Get the Fibonacci numbers from the array */
        loadSource("python", "pythonpart.py");
        Value getFibonacciNumbersFn = polyglotCtx.getBindings("python").getMember("getFibonacciNumbers");
        int[] fibNumbers = getIntArrayFromValue(getFibonacciNumbersFn.execute(input));

        /* JAVASCRIPT: Find cube of numbers in the output array */
        loadSource("js", "jspart.js");
        Value findCubeOfNumbersFn = polyglotCtx.getBindings("js").getMember("findCubeOfNumbers");
        int[] sqrNumbers = getIntArrayFromValue(findCubeOfNumbersFn.execute(fibNumbers));

        /* C++: Get the sum of the numbers in the output array */
        loadSource("llvm", "cpppart");
        Value getSumOfArrayFn = polyglotCtx.getBindings("llvm").getMember("getSumOfArray");
        int sum = getSumOfArrayFn.execute(sqrNumbers, sqrNumbers.length).asInt();

        /* Rust: Find the cube root of sum */
        Value cubeRootFn = loadSource("llvm", "rustpart.bc").getMember("cube_root");
        // println! macro does not work from Rust when embedded, some issue with mangling
        System.out.println("Rust => Find cube root of the number");
        Double cubeRoot = cubeRootFn.execute(sum).asDouble();

        /* RUBY: Find factorial of the number */
        Value factorialFn = loadSource("ruby", "rubypart.rb");
        long out = factorialFn.execute(cubeRoot).asLong();

        System.out.println("Sum: " + sum);
        System.out.println("Cube Root: " + cubeRoot);
        System.out.println("Factorial: " + out);
    }
}

Утиливые функции должны упростить код, теперь давайте посмотрим на каждый шаг, где он составляет функции.

Шаг 2: Python

Мы выполняем getfibonaccinumbers Функция, расположенная в файле pythonpart.py и прохождение нашего входного массива.

/* PYTHON: Get the Fibonacci numbers from the array */
loadSource("python", "pythonpart.py");
Value getFibonacciNumbersFn = polyglotCtx.getBindings("python").getMember("getFibonacciNumbers");
int[] fibNumbers = getIntArrayFromValue(getFibonacciNumbersFn.execute(input));

Давайте посмотрим на pythonpart.py , это стандартная программа Python, которая принимает массив и фильтрует номера фибоначчи из него и возвращает результирующий массив.

import math

def isPerfectSquare(num):
    n = int(math.sqrt(num))
    return (n * n == num)

# Function to check if the number is in Fibonacci or not
def getFibonacciNumbers(array):
    print("Python => Filtering Fibonacci number from the array");

    out = []
    n = len(array)
    count = 0
    for i in range(n):
        if (isPerfectSquare(5 * array[i] * array[i] + 4) or
            isPerfectSquare(5 * array[i] * array[i] - 4)):

            out.append(array[i]);
            count = count + 1

    if (count == 0):
        print("None present");

    return out

Шаг 3: JavaScript

Мы выполняем FindCubeofnumbers Функция, расположенная в файле jspart.js и прохождение результата из функции Python.

/* JAVASCRIPT: Find cube of numbers in the output array */
loadSource("js", "jspart.js");
Value findCubeOfNumbersFn = polyglotCtx.getBindings("js").getMember("findCubeOfNumbers");
int[] sqrNumbers = getIntArrayFromValue(findCubeOfNumbersFn.execute(fibNumbers));

Давайте посмотрим на jspart.js , это стандартная функция JavaScript, которая принимает массив и отображает элементы и возвращает массив. Но нам пришлось позвонить Array.prototype.map.call вместо просто array.map Поскольку массив, пройденный Java, не является стандартным массивом JS.

function findCubeOfNumbers(array) {
  console.log("JS => Getting cube of numbers in the array");

  return Array.prototype.map.call(array, (it) => Math.pow(it, 3));
}

Шаг 4: C ++

Мы выполняем gentumofarray Функция, расположенная в CPPPART бинарный файл. Мы проходим результат от функции JS и длину массива здесь. Мы должны использовать скомпилированный бинарный здесь, в отличие от Python, Ruby и JavaScript, которые интерпретируются языками.

/* C++: Get the sum of the numbers in the output array */
loadSource("llvm", "cpppart");
Value getSumOfArrayFn = polyglotCtx.getBindings("llvm").getMember("getSumOfArray");
int sum = getSumOfArrayFn.execute(sqrNumbers, sqrNumbers.length).asInt();

Источник двоичного в CPPPART.CPP файл. Который скомпилирован с помощью ниже

export LLVM_TOOLCHAIN=$(lli --print-toolchain-path)
$LLVM_TOOLCHAIN/clang++ -shared cpppart.cpp -lpolyglot-mock -o cpppart

Давайте посмотрим на CPPPART.CPP Это стандартная программа C ++, которая экспортирует функцию. Это принимает массив и его длина как аргументы и возвращает номер

#include
using namespace std;

// Function to find the sum of integer array
// extern "C" is required to suppress mangling
extern "C" int getSumOfArray(int array[], int size) {
    printf("C++ => Find sum of numbers in an array\n");

    int i, sum = 0;
    for(i = 0; i < size; i++) {
        sum += array[i];
    }
    return sum;
}

Шаг 5: ржавчина

Мы выполняем Cube_root Функция, расположенная в файле Rustpart.bc , скомпилирован от rustpart.rs. . Мы проходим результат от функции C ++ здесь.

/* Rust: Find the cube root of sum */
Value cubeRootFn = loadSource("llvm", "rustpart.bc").getMember("cube_root");
// println! macro does not work from Rust when embedded, some issue with mangling
System.out.println("Rust => Find cube root of the number");
Double cubeRoot = cubeRootFn.execute(sum).asDouble();

Давайте посмотрим на Rustpart.rs , это стандартная функция ржавчины, которая принимает номер, находит свой кубик и возвращает его. Но нам нужно указать # [no_mangle] Аннотация и мы не можем использовать какие-либо ящики, а также видимо. Смерты функции с примитивными ARGS/выходом, кажется, работают, но более сложные функции не работают при встроенном.

#[no_mangle]
fn cube_root(arg: f64) -> f64 {
    arg.cbrt()
}

fn main(){}

Мы компилируем источник ржавчины в двоичный код, используя Rustc Компилятор с --emit = llvm-bc флаг

rustc --emit=llvm-bc rustpart.rs

Шаг 6: Ruby

Мы выполняем факториал Функция, расположенная в файле RUBYPART.RB Отказ Мы передаем результат от функции ржавчины здесь.

/* RUBY: Find factorial of the number */
Value factorialFn = loadSource("ruby", "rubypart.rb");
long out = factorialFn.execute(cubeRoot).asLong();

Давайте посмотрим на RUBYPART.RB Это стандартная функция Ruby Lambda, которая принимает номер и возвращает его факториал.

factorial = -> (num) {
    puts "Ruby => Find factorial of the number"
    (1..num).inject {|product, num| product * num }
}

И, наконец, мы распечатаем выходы с Java.

Запустите программу

Чтобы запустить эту программу, нам нужно сначала компилировать файлы C ++, Rust и Java, а затем запустить его с помощью JVM, предоставляемой GRALVM. Ниже приведены шаги, вы можете сохранить это как Run.sh и выполнить это.

export LLVM_TOOLCHAIN=$(lli --print-toolchain-path)
$LLVM_TOOLCHAIN/clang++ -shared cpppart.cpp -lpolyglot-mock -o cpppart || exit

rustc --emit=llvm-bc rustpart.rs || exit

javac Polyglot.java && java Polyglot

Это даст выход ниже:

Разве это не было так весело? Так что такая способность полиглота полезна? Хорошо, что зависит, возможности полиглот Граалвм все еще не готовы к производству Но он все еще полезен, поскольку он открывает дверь для совместимости на реальную языку, представьте, что это может использовать библиотеку с любого языка из вашей программы, это уже возможно для многих библиотек C, Ruby, R, JS и Java с Graalvm, а как Поддержка становится лучше, мы сможем освободиться от ограниченности одного языка. Граалвм, кажется, гораздо быстрее для языков, таких как Ruby, чем стандартный Croby или JRuby, например, и это многообещается, поскольку это будет означать, что вам не придется беспокоиться о накладных расходах при включении нескольких языков в вашей программе.

Граалвм – одна из самых революционных технологий, которые я встречал в последнее время И я надеюсь, что языковая поддержка полиглота становится готовой к производству, вскоре в сочетании с собственными возможностями изображения Это будет очень мощная платформа для по-настоящему полиглот-приложения.

Если вам нравится эта статья, пожалуйста, оставьте вроде или комментарий.

Вы можете следовать за мной на Twitter и LinkedIn Отказ

Обложка изображений кредита: на основе официальных логотипов соответствующих проектов.

Оригинал: “https://dev.to/deepu105/polyglot-inception-with-graalvm-why-because-it-s-fun-aa”