估计阅读时长: 3 分钟

https://github.com/dotvanilla/vanilla

vanilla编译器项目是我之前开发过的一个实验性质的项目。主要是为了解决在浏览器端的一些高性能计算的需求,例如数据加密和解密,基于WebGL的计算机图形项目,力学物理规律模拟,网络可视化布局计算等。

当然,上面的操作目前都存在有对应的JavaScript代码库来实现。但是JavaScript是一门动态类型的语言,在计算性能上,数据量增大了以后,无法满足实际的计算需求。所以就诞生了WebAssembly项目。WebAssembly项目主要是为了满足浏览器端或者基于nodejs后台的高性能计算的需求。vanilla编译器项目可以将一个完整的VisualBasic.NET项目以WASM为编译目标平台,编译出一个WebAssembly应用程序。

在这里我将介绍vanilla编译器项目是如何开发的。这些文章,将会帮助你可以深入的理解vanilla编译器项目。或者你可以通过以vanilla编译器项目为参考,开发出自己的编译器项目将其他的编程语言编译为WebAssembly应用程序。

在本博客中相关的教程文章:

VanillaBasic编译器项目

在这个编译器项目之中,主要由三大部分模块组成:

  • 将VB.NET代码转换为WAST中间代码
  • 将WAST中间代码编译为WebAssembly
  • 一个用于支撑VB.NET程序在浏览器中运行的TypeScript运行时环境

之所以称呼这个VisualBasic.NET语言的编译器项目为VanillaBasic,是因为你可以使用VB.NET的语法进行开发,但是没有办法使用.NET框架。你只能够从零开始编写一个应用程序,使用原生的VisualBasic语言从头开发,没有任何框架可以被依赖使用。

经过了很多年的发展,VisualBasic.NET语言的语法目前已经足够成熟和复杂了。我们如果从头开始编写VisualBasic语言的语法解析器,很明显是一件很不现实的事。好在微软开源了一个名称为Roslyn的编译器项目。我们可以借助这个编译器项目很轻松的就可以进行VisualBasic源代码文件的解析操作,得到相关的语法单元用于编译为WebAssembly程序。

关于Roslyn编译器进行VisualBasic源代码解析的操作,可以阅读《Roslyn编译器开发》这篇文章。

VB.NET编译器

使用Vanilla编译器进行VisualBasic源代码的WASM平台编译是非常的简单的,你只需要简单的调用几个相关的函数即可。在这里带你简单的了解一下是如何使用Vanilla编译器将一个VisualBasic源代码文件编译为WebAssembly程序:

  • 首先我们会需要创建一个Vanilla的编译器对象
  • 接着就可以通过VisualStudio工具得到一个VisualBasic项目中的源代码文件,传递进入编译器对象进行源代码文件的解析操作
  • 之后可以将解析完成的源代码项目转换为WAST源代码文件
  • 最后将WAST源代码文件送入WebAssembly编译器工具中即可完成整个编译过程了。

例如通过下面的一段代码可以进行VisualBasic项目的源代码解析:

Imports Microsoft.VisualBasic.ApplicationServices.Development.VisualStudio
Imports Microsoft.VisualBasic.ApplicationServices.Development.VisualStudio.vbproj
Imports VanillaBasic.Roslyn
Imports VanillaBasic.WebAssembly.Compiler

Dim vb As Project = Project.Load("/path/to/target.vbproj")
Dim wasm As New Scanner(vb)

For Each file As String In vb.EnumerateSourceFiles(skipAssmInfo:=True, fullName:=True)
    wasm.AddModules(file)
Next

Call wasm.Workspace _
    .ToSExpression _
    .SaveTo("/path/to/webassembly.wat")

将解析得到的VisualBasic源代码项目编译为WebAssembly程序集,可以通过VanillaBuild编译器来完成,例如下面的一个例子就是将解析得到VisualBasic项目通过Compile方法进行WebAssembly目标编译:

<Extension>
Private Sub CreateWasm(VisualBasic As Workspace, debug As Boolean, output$)
    Dim config As New Wat2wasm With {.output = output}

    If debug Then
        config.debugNames = True
        config.debugParser = True
        config.verbose = True
    End If

    Call VanillaBuild.WastDump(VisualBasic, output.ChangeSuffix("*.wast"))
    Call VanillaBuild.HexDump(VisualBasic, output.ChangeSuffix("*.dmp"), verbose:=True)
    Call VanillaBuild.Compile(VisualBasic, config)
End Sub

TypeScript运行时环境

在WebAssembly之中,由于其是专门针对于数学计算的需求而开发的。所以很多的在JavaScript之中的API,例如DOM操作,ajax网络请求等API都是缺失掉的。所以我们会需要一个对应的JavaScript胶水代码库来帮助WebAssembly应用程序来调用这些数值计算以外的功能API函数。

另外,WebAssembly一般无法直接通过类似于javascript一样的,可以直接在HTML页面之中通过script标签加载。所以我们会需要通过对应的JavaScript代码加载WebAssembly程序文件。在Vanilla编译器项目之中,建立了一个TypeScript胶水代码项目用来支持所编译出来的VisualBasic程序在浏览器上的运行。

下面,我们来学习如何通过这个JavaScript运行时环境来执行你所编译出来的VisualBasic程序把:

// WebAssembly Demo
vanilla.Wasm.showDebugMessage(false);
vanilla.Wasm.RunAssembly("../vbscripts/base64.wasm", {
  run: encoder => {
    let base64 = encoder.base64Encoder;
    let handleInput = function () {
      displayBase64.innerText = base64.encode(textInput.value);
      textOutput.innerText = base64.decode(displayBase64.innerText);
    }

    console.log("WebAssembly structure is keeps the same as your VB.NET source file:");
    console.log(encoder);
    console.log("Here is the application info get from AssemblyInfo.vb file:");
    console.log(encoder.AssemblyInfo);

    textInput.onkeypress = handleInput;
    textInput.oninput = handleInput;
    textInput.oninput();
  },
  api: { console: true, text: true, array: true }
});

下面我们来逐行解读上面的TypeScript运行时环境代码。

首先,vanilla.Wasm.showDebugMessage这一句是用于控制WebAssembly程序的调试模式的函数。我们只需要通过这个函数设置一个逻辑值,就可以打开或者关闭调试模式了。
在VanillaBasic环境之中运行一个编译为WebAssembly程序的VB.NET应用,其实只需要调用vanilla.Wasm.RunAssembly这个函数就可以了。这个函数接受两个参数:第一个参数就是目标WebAssembly文件的网络位置;第二个参数就是用来描述怎样执行这个WebAssembly文件的配置对象了。在这里我们主要是着重来讲解这个运行时配置对象的使用。

在这个运行时配置对象中,最终的一个接口就是run属性,其是运行你的WebAssembly程序是必须的。这个run属性只需要接收一个函数集合对象就可以了。例如:

{
    run: function(webassembly) {
        webassembly.method1();
    }
}

没错,这个run函数的参数就是你的WebAssembly程序。WebAssembly环境会通过这个运行时配置对象,将加载好的webAssembly程序传递到这个run函数之中,然后你就可以通过这个参数来得到对应的WebAssembly程序,调用相应的函数了。

Attachments

One response

  1. Hi theere it’s me, I amm also viiting this webb sie oon a regular basis, this site iis actuazlly good and thhe usesrs aree actually sharingg good thoughts.

    来自意大利

Leave a Reply

Your email address will not be published. Required fields are marked *

博客文章
May 2023
S M T W T F S
 123456
78910111213
14151617181920
21222324252627
28293031  
  1. […] 在上面所提到的线性变化转换过程,其实就是一个热图绘制的过程。我们一般按照不同的颜色谱做线性变换映射,就可以得到对应的不同颜色系列下的NRRD热图成像渲染结果。对于NRRD图像文件的热图成像渲染原理,其实是和质谱成像的渲染原理一摸一样的(对于质谱成像渲染而言,其主要的原理也就是将对应的扫描点上的目标离子的intensity值取出,构建出一个和NRRD文件中的光栅矩阵数据一摸一样的矩阵数据,基于这个矩阵数据进行线性变换映射到对应的颜色值完成热图成像可视化操作)。 […]

  2. […] 如果我们需要将得到光栅矩阵数据进行可视化,该怎样做呢?其实,如果我们了解过热图成像或者质谱成像的原理的话,实际上对于这个光栅矩阵的原始数据进行成像的原理应该就会很清楚了。在我们拿到这个矩阵之后,可以将矩阵的行和列看作为二维图像空间之中的x和y坐标信息,然后对应的矩阵中的单元格值可以映射为一个对应的颜色,即可将从NRRD文件之中拿到的光栅矩阵数据给可视化出来。将光栅矩阵中的数值映射为对应的颜色值的方法原理,大家可以参考一下《【热图数据可视化】颜色插值计算原理》的内容介绍,一摸一样。 […]