Compile AVM – Lenguaje de alto nivel – Variables – NewEconoLabs

Este artículo está escrito por Li Jianying (Light Li) en chino y traducido al inglés por Robbie.

Código fuente de referencia: https://github.com/lightszero/neovmbook/tree/master/samples/compiler_csharp01

Ya hemos discutido la traducción de direcciones antes, por lo que este artículo trata sobre cómo los lenguajes de alto nivel se convierten a AVM.

El primer problema es la variable. En el lenguaje de alto nivel, estamos acostumbrados a las variables, pero en la secuencia de instrucciones NEOVM, obviamente no hay ninguna variable.

int a = 0;

Entonces, una instrucción de lenguaje de tan alto nivel es obviamente inconvertible.

int a = 1;

int b = 2;

devuelve a + b;

Tenemos que pensar en lo que tenemos en NEOVM. Tenemos una pila de cálculo y una pila temporal. Es más fácil calcular una expresión de evaluación simple, como "1 + 2 + 3 + 4", pero una vez que aparece la variable. Parece ser más complicado.

El cálculo de constantes es fácil de expresar con la pila de cálculo

const int a = 0;

const int b = 2;

devuelve a + b;

==>

PULSAR 0

PULSAR 2

AÑADIR

JUBILADO

La razón por la cual la variable es problemática es que la variable puede cambiar, por lo que la variable debe provenir de una posición en lugar de un valor específico.

Por ejemplo, una lista de variables, echemos un vistazo al programa con la idea de una lista de variables.

Supongamos que tenemos una lista global de variables

// tenemos una lista valores;

int a = 1; // a es valores (0)

// valores (0) = 1;

int b = 2; // b es valores (1)

// valores (1) = 2;

devuelve a + b;

// valores de retorno (0) + valores (1)

De hecho, para compilar este código, necesitamos crear una lista de variables. Primero diseñamos dos pseudocódigos para manipular nuestra lista de variables. STLOC pone el valor en la tabla de variables. LDLOC toma el valor de la tabla de variables.

Use pseudocódigo para indicar este programa. Sus

// int a = 1

PULSAR 1

STLOC 0

// int b = 2

PULSAR 2

STLOC 1

// devuelve a + b

LDLOC 0

LDLOC 1

AÑADIR

JUBILADO

Luego escribimos la lista de variables directamente en forma de código NEWARRAY PICKITEM SETITEM. NEOVM tiene estas operaciones. creamos una lista de variables en la pila temporal cuando se inicia la función y eliminamos la lista de variables en la función RET.

// CreateArray size = 2

PULSAR 2

NEWARRAY

TOALTSTACK

// int a = 1

DUPFROMALTSTACK // getarray

PULSAR 0 // índice

PUSH 1 // valor

TITULO

// int b = 2

DUPFROMALTSTACK // getarray

PUSH 1 // índice

PUSH 2 // valor

TITULO

// obtener valor a

DUPFROMALTSTACK // getarray

PULSAR 0 // índice

PICKITEM

// obtener valor b

DUPFROMALTSTACK // getarray

PUSH 1 // índice

PICKITEM

//añadir

AÑADIR

//regreso

// matriz

FROMALTSTACK

SOLTAR

JUBILADO

Puede encontrar este programa en samples / compiler_csharp01

Su código está dividido en varias partes. El paso 01 es traducir el código fuente de c # al árbol de sintaxis abstracta (AST). Aquí podemos resolver el problema directamente llamando a rosyln. No importa qué lenguaje de alto nivel planee compilar, básicamente podemos traducirlo a AST, en el que hay muchas cosas listas para usar.

Step02 es la parte que convierte AST en el ensamblaje. Esta parte es el trabajo principal del compilador.

Step03 es el trabajo del enlazador. No importa lo que quiera compilar, de qué compilar, esta parte es siempre la misma. En el siguiente artículo, discutiremos el código con la misma función compilada de IL a AVM, luego encontrará que step03 sigue siendo el mismo código.

Entonces es convocar a NEOVM para probar, sin duda, obtendrá el resultado 3.

Programa de clase

{

vacío estático Main ()

{

int a = 1;

int b = 2;

devuelve a + b;

}

}

// resultado 3

Esta es su salida