Преводачи
Преводачи
Материално съдържание
В първите три части от тази серия разгледахме анализирането и компилирането на математически изрази, постепенно и методично преминавайки от много прости едносимволни „изрази“, състоящи се от един термин, през изрази в по-обща форма и завършвайки с доста пълен парсер, който може да анализира и превежда операции за присвояване с многознакови токени, вложени пространства и извиквания на функции. Сега ще ви преведа отново през този процес, но с цел интерпретиране, а не компилиране на обектен код.
Ако тази серия е за компилатори, тогава защо трябва да се интересуваме от интерпретаторите? Просто искам да видите как природата на анализатора се променя с промяната на целите. Също така искам да комбинирам концепциите на тези два вида преводачи, за да можете да видите не само разликите, но и приликите.
Помислете за следното задание:
В компилатора искаме да принудим процесора да направи това присвояване по време на изпълнение. Самият транслатор не извършва никакви аритметични операции... той само произвежда обектен код, който ще накара процесора да го направи, когато кодът се изпълни. В горния пример компилаторът ще създаде код за оценка на стойността на израза и ще съхрани резултата в x.
За интерпретатор, обратно, не се генерира обектен код. Вместо това, аритметичните операции се изпълняват незабавно, веднага щом настъпи анализ. Например, когато присвояването се анализира, x ще съдържа новата стойност.
Методът, който използваме в тази серия, се нарича „превод, управляван от синтаксиса“. Както вече знаете, структурата на синтактанализаторът е много тясно свързан със синтаксиса на структурите, които анализираме. Създадохме процедури в Pascal, които разпознават всяка конструкция в езика. Всяка от тези конструкции (и процедури) е свързана със съответното „действие“, което прави това, което трябва да направи, след като конструкцията бъде разпозната. В нашия компилатор всяко действие включва излъчване на обектен код за изпълнение по-късно по време на изпълнение. В интерпретатора всяко действие включва нещо, което да се изпълни незабавно.
Това, което бих искал да видите е, че планът... структурата... на анализатора не се променя. Само действията се променят. Така че, ако можете да напишете интерпретатор за даден език, тогава можете да напишете и компилатор и обратно. Въпреки това, както ще видите, има разлики, и то значителни. Тъй като действията са различни, процедурите, които завършват разпознаването, са написани по различен начин. Характерно е, че в интерпретатора рутинните процедури за окончателно разпознаване са написани като функции, които връщат числова стойност на програмата, която ги е извикала. Нито една от процедурите за анализ на нашия компилатор не прави това.
Нашият компилатор всъщност е това, което бихме могли да наречем "чист" компилатор. След като конструкцията бъде разпозната, обектният код се издава незабавно. (Това е една от причините, поради които кодът не е много ефективен.) Интерпретаторът, който се каним да изградим, е чист интерпретатор в смисъл, че няма превод от тип "токенизация", извършен върху изходния код. Това са двете крайности на превода. В реалния свят преводачите не са толкова чисти, но са склонни да използват част от всяка техника.
Мога да дам няколко примера. Вече споменах един: повечето интерпретатори, като Microsoft BASIC, например, превеждат оригиналатекст (токенизирайте го) в междинна форма, за да улесните анализирането му в реално време.
Друг пример е асемблерът. Целта на асемблера, разбира се, е да произвежда обектен код и обикновено го прави по ясен начин: една инструкция на ред от изходния код. Но почти всички асемблери също позволяват изрази като параметри. В този случай изразите винаги са константи и асемблерът не е предназначен да произвежда обектен код за тях. По-скоро той "интерпретира" израза и оценява съответната стойност, която всъщност се връща с обектния код.
Всъщност бихме могли да използваме част от него сами. Транслаторът, който създадохме в предишната глава, прилежно ще изплюе обектен код за сложни изрази, дори ако всеки член в израза е константа. В този случай би било много по-добре, ако компилаторът се държи малко като интерпретатор и просто изчислява съответната стойност на константата.
В теорията на компилацията съществува концепция, наречена "мързелив" превод. Идеята е, че не просто издавате код при всяко действие. Всъщност, в краен случай, вие изобщо не излъчвате нищо, докато не е абсолютно необходимо. За да се постигне това, действията, свързани с рутинните анализи, обикновено не издават само код. Понякога го правят, но често те просто връщат информация обратно към програмата за повикване. Въоръжена с тази информация, програмата за повикване може да направи по-добър избор какво да прави.
Например за този израз
x = x + 3 - 2 - (5 - 4)
нашият компилатор прилежно ще изплюе поток от 18 инструкции за зареждане на всеки параметър в регистри, извършване на аритметика и съхраняванерезултат. Мързеливата оценка ще разпознае, че израз, съдържащ константи, може да бъде оценен по време на компилиране и ще намали израза до
Дори мързеливата оценка ще бъде достатъчно умна, за да разбере, че това е еквивалентно на
което изобщо не изисква никакви действия. Успяхме да намалим 18 инструкции до нула!
Моля, обърнете внимание, че няма начин да оптимизираме нашия компилатор по този начин, тъй като всяко действие се извършва в него незабавно.
Оценката на мързелив израз може да създаде много по-добър обектен код, отколкото бихме могли да създадем. Предупреждавам ви обаче: това прави кода на парсера много по-сложен, защото всяка подпрограма вече трябва да вземе решение дали да излъчи или не обектен код. Мързеливата оценка със сигурност не е наречена така, защото е по-лесна за авторите на компилатори!
Тъй като основно сме KISS, няма да се задълбочавам повече в тази тема. Просто искам да знаете, че можете да получите известна оптимизация на кода чрез комбиниране на техники за компилация и интерпретация. По-специално, трябва да сте наясно, че рутинните анализи в по-интелигентен компилатор обикновено връщат нещо на програмата, която ги е извикала, и понякога го очакват. Това е основната причина да обсъждаме преводачите в тази глава.
Не използвайте нестандартна лексика.
Моля, напишете вашите коментари, наблюдения и всичко друго , което ще помогне за подобряване на информацията, предоставена на този сайт.
ВСИЧКИ КОМЕНТАРИ СА РЪЧНО МОДЕРИРАНИ, ТАКА ЧЕ НЕ ПРАЩАЙТЕ СПАМ!