Транслятор

Транслятор перетворює дерево синтаксичного розбору на набір мікрооперацій абстракної мови асемблера, але у внутрішньому представленні (список кортежів мови Python). Вона може бути однозначно перетворена у текст програми асемблера, але цей крок робиться для того, щоб можна було зробити оптимізацію.

В даній реалізації транслятор перетворює дерево в код, який специфічний для операційної системи GNU/Linux.

  1. Системні визови до ядра Linux (номери функції ядра)
  2. Переривання визову функції ядра int 0x80
  3. Використання функцій бібліотеки libc

Але модульна архітектура компілятора дозволяє легко реалізувати транслятор для інших систем при необхідності та без впливу на інші модулі програми.

Транслювання відбувається в 2 етапи:

  1. Збір інформації
  2. Генерація псевдо-асемблерного коду

Збір інформації

Для перетворення коду транслятор в першу чергу робить обхід по дереву та збирає дані про майбутній код, такі як:

  • Змінні
  • Строкові літерали
  • Оголошені функції
  • Виклики функцій виводу та вводу

Особливістю є, що транслятор шукає тільки унікальні строки, то ж якщо в коді зустрічаються наприклад виводи на екран тієї самої строки кілька разів, строка буде включена у дані програми тільки один раз.

Якщо в коді не зустрічаються визови вводу/виводу чи інші функції з бібліотеки libc, то бібліотека не буде прилінкована.

class pyCompiler.utils.gen.TreeStats
pyCompiler.utils.gen.find_vars(t)

Функція збору інформації

Parameters:t – дерево розбору
Return type:структура TreeStats з інформацією про код

Генерація псевдо-асемблерного коду

Кожен оператор мови високого рівня (myl) транслюється в послідовність команд асемблеру.

pyCompiler.utils.gen.gen_code(t, stat)

Функція, що відповідає за генерацію псевдо-асемблерного коду

Parameters:
  • t – дерево розбору
  • stat – дані про код
Return type:

список операторів псевдо-асемблеру

Оголошення функції

function mul(x,y)
    R = x*y;
    return R;
endfunc;

Транслюється в:

jmp             Func0End
label           Func_mul
mov             eax, esp+4
mov             vmul_x, eax
mov             eax, esp+8
mov             vmul_y, eax
; Тіло функції
mov             dword   eax, [vmul_x]
mov             dword   ebx, [vmul_y]
imul    ebx
; Кінець тіла
ret
label           Func0End

Оператор return

Повернення результату з функцыї:

return x;

Всередині функції транслюється в:

mov eax, vFUNC_x
ret

Оператор print

  1. Для строк:

    print "123"
    

Транслюється в:

push        str0
call        printf
add         esp,    4
push        [stdout]
call        fflush
add         esp,    4

де str0 це:

str0:           db      "123"
str0len:        equ     $-str0
  1. Або для змінних:

    print x;
    

транслюється в:

mov         eax, [vx]
push        eax
push        numbs
call        printf
add         esp,    8
push        [stdout]
call        fflush
add         esp,    4

де numbs це:

numbs:  db              "%d", 0

Оператор read

Читання числа з клавіатури з записом результату в змінну x:

read x;

транслюється в:

push        vx
push        numbs_in_format
call        scanf
add         esp,    8
call        getchar

де numbs_in_format це:

numbs_in_format:        db              "%d",0

Оператор присвоювання

x = 1

транслюється в:

mov [vx], 1

Інші оператори

Транслювання інших операторів дивитись в доданку з вихідним кодом (https://github.com/antigluk/pyCompiler), файл utils/gen.py, функція gen_text_section