Παραγωγή Ενδιάµεσου Κώδικα Παραγωγή Ενδιάµεσου Κώδικα Κώδικας σε αρχική γλώσσα Γιώργος Μανής Κώδικας σε ενδιάµεση γλώσσα Κώδικας σε γλώσσα µηχανής (assembly) Παραγωγή Ενδιάµεσου Κώδικα Ενδιάµεση Γλώσσα Ο ενδιάµεσος κώδικας είναι ένα σύνολο από τετράδες. ένας τελεστής Συντακτικό δέντρο Παραγωγή ενδιάµεσου κώδικα Ενδιάµεσος κώδικας τρία τελούµενα π.χ. + a b t_1 * t_1 2 t_2 = t_2 c Ενδιάµεση Γλώσσα Ενδιάµεση Γλώσσα op, x, y, z όπου op ένας από τους τελεστές +, -, *, / αντιστοιχεί στην παράσταση z:=x op y :=, x, _, z αντιστοιχεί στην παράσταση z:=x jump, _, _, z µεταπήδηση χωρίς όρους στη θέση z relop, x, y, z όπου relop ένας από τους τελεστές =, >, <, <>, >=, <= µεταπήδηση στη θέση z αν ισχύει η x relop y 1
Ενδιάµεση Γλώσσα Ενδιάµεση Γλώσσα par, x, m, _ όπου x παράµετρος συνάρτησης και m ο τρόποςµετάδοσης CV : µετάδοση µε τιµή REF: µετάδοση µε αναφορά RET: επιστροφή τιµής συνάρτησης call, name, _, _ κλήση συνάρτησης name begin_block, name, _, _ αρχή υποπρογράµµατος ή προγράµµατος name end_block, name, _, _ τέλος υποπρογράµµατος ή προγράµµατος name ret, _, _, _ τέλος συνάρτησης επιστροφή τιµής halt, _, _, _ τέλος προγράµµατος Μεταβλητές Ιδιοτήτων Μεταβλητές Ιδιοτήτων µεταβλητή PLACE περιέχει τη θέση που βρίσκεται µία τιµή αν είναι σταθερά περιέχει τη σταθερά αλλιώς περιέχει τη θέση του αντικειµένου που περιέχει µία τιµή π.χ. το αποτέλεσµα της παράστασης a+b βρίσκεται αποθηκευµένο στη µεταβλητή w µεταβλητή NEXT περιέχει µία λίστα από ετικέτες τετράδων που έχουν παραχθεί κατά τη µετάφραση ενός συµβόλου της γραµµατικής οι τετράδες αυτές είναι τετράδες άλµατος προς την πρώτη τετράδα της επόµενης εντολής ο λόγος που κρατάµε αυτές τις τετράδες είναι ότι η ετικέτα της επόµενης εντολής δε µας είναι γνωστή ακόµα µόλις αυτή γίνει γνωστή οι τετράδες αυτές θα συµπληρωθούν Μεταβλητές Ιδιοτήτων Μεταβλητές Ιδιοτήτων µεταβλητές TRUE και FALSE λίστες όµοιες µε τηnext περιγράφουν λογικές συνθήκες ετικέτες τετράδων που περιέχουν εντολές άλµατος οι ετικέτες των τετράδων στις οποίες θα γίνει το άλµα δεν είναι ακόµα γνωστές µόλις γίνουν γνωστές οι τετράδες αυτές θα συµπληρωθούν µεταβλητές TRUE και FALSE Η λίστα που αντιστοιχεί στη µεταβλητή TRUE περιέχει τις τετράδες που πρέπει να συµπληρωθούν µε την ετικέτα της εντολής στην οποία πρέπει να µεταφερθεί ο έλεγχος αν η λογική συνθήκη ισχύει Η λίστα που αντιστοιχεί στη µεταβλητή FALSE περιέχει τις τετράδες που πρέπει να συµπληρωθούν µε την ετικέτα της εντολής στην οποία πρέπει να µεταφερθεί ο έλεγχος αν η λογική συνθήκη δεν ισχύει 2
Βοηθητικές Υπορουτίνες Βοηθητικές Υπορουτίνες NEXTQUAD() επιστρέφει τον αριθµό τηςεπόµενης τετράδας που πρόκειται να παραχθεί GENQUAD(op, x, y, z) δηµιουργεί την επόµενη τετράδα (op, x, y, z) NEWTEMP() δηµιουργεί και επιστρέφει µία νέα προσωρινή µεταβλητή οι προσωρινές µεταβλητές είναι της µορφής T_1, T_2, T_3 EMPTYLIST() δηµιουργεί µία κενή λίστα ετικετών τετράδων MAKELIST(x) δηµιουργεί µία λίστα ετικετών τετράδων που περιέχει µόνο το x MERGE (list 1, list 2 ) δηµιουργεί µία λίστα ετικετών τετράδων από τη συνένωση των λιστών list 1, list 2 Βοηθητικές Υπορουτίνες Αρχή και Τέλος Block BACKPATCH(list,z) ηλίσταlist αποτελείται από δείκτες σε τετράδες των οποίων το τελευταίο τελούµενο δεν είναι συµπληρωµένο η backpatch επισκέπτεται µία µία τις τετράδες αυτές και τις συµπληρώνει µε τηνετικέταz <PROGRAM> ::= program ID <PROGRAMBLOCK (ID) <PROGRAMBLOCK (name) > ::= <DECLARATIONS> <SUBPROGRAMS> genquad( begin_block,name, _, _ ) <BLOCK> if (this is the main program block) genquad( halt, _, _, _ ) genquad( end_block,name, _, _ ) Έστω η γραµµατική Ε -> T ( + T )* T -> F ( F )* F -> ( E ) F -> id όπου id ακέραιος αριθµός Χρειαζόµαστε τετράδες της µορφής ( + a b c ) ( a b c ) για την παραγωγή του ενδιάµεσου κώδικα και προσωρινές µεταβλητές T_1, T_2 κλπ για τα ενδιάµεσα αποτελέσµατα των πράξεων 3
Παράδειγµα: x+(y+z) w ενδιάµεσος κώδικας: 1: +,y,z,t_1 2:,T_1,w,T_2 3: +, x, T_2, T_3 Ε -> T 1 ( + T 2 {P 1 })* {P 2 } {P 1 }: w = newtemp() genquad( +,T 1.place,T 2.place,w) T 1.place=w {P 2 }: E.place=T 1.place T->F 1 ( F 2 {P 1 })* {P 2 } {P 1 }: w = newtemp() genquad(,f 1.place,F 2.place,w) F 1.place=w {P 2 }: T.place=F 1.place F -> ( E ) {P 1 } {P 1 }: F.place=E.place F -> id {P 1 } {P 1 }: F.place=id.place procedure E (E.place) begin T ( T 1.place ) while token=plustk do begin lex(); T (T 2.place) w:=newtemp() genquad( +, T 1.place, T 2.place, w) T 1.place :=w end E.place := T 1.place end Παράδειγµα: x > y or x <w and t > x 100: >, x, y, _ 101: jump, _, _, 102 102: >, x, w, 104 103: jump, _, _, _ 104: >, t, w, _ 105: jump, _, _, _ B.true B.false 4
Έστω η γραµµατική B- Q ( or Q )* Q - R ( and R )* R - ( B ) R - E relop E B -> Q 1 {P 1 } ( or {P 2 } Q 2 {P 3 })* {P 1 }: B.true = Q 1.true B.false = Q 1.false {P 2 }: quad = nextquad() {P 3 }: backpatch(b.false, quad) B.true = merge(b.true, Q 2.true) B.false = Q 2.false Q -> R 1 {P 1 } ( and {P 2 } R 2 {P 3 })* {P 1 }: Q.true = R 1.true Q.false = R 1.false {P 2 }: quad = nextquad() {P 3 }: backpatch(q.true, quad) Q.false = merge(q.false, R 2.false) Q.true = R 2.true R -> ( B ) {P 1 } {P 1 }: R.true=B.true R.false=B.false R -> E 1 relop E 2 {P 1 } {P 1 }: R.true=makelist(nextQuad()) genquad( relop, E 1.place, E 2.place, _ ) R.false=makelist(nextQuad()) genquad( jump, _, _, _ ) Παράδειγµα: x>y or x>w and t>x Έστω ότι βρισκόµαστε στην τετράδα 100 Καλείται η B η Q και η R για την x>y p1: Rtrue = [100] Rfalse = [101] 100: >, x, y, _ 101: jump, _, _, _ Επιστρέφουµε στηνq: p1: Qtrue = R1true = [100] Qfalse = R1false = [101] Επιστρέφουµε στηνb: p1: Btrue=Q1true = [100] Bfalse = Q1false = [101] p2: p2quad=nextquad() = 102 5
Καλείται η B η Q και η R για την x>y p1: Rtrue = [102] Rfalse = [103] 102: >, x, w, _ 103: jump, _, _, _ Επιστρέφουµε στηνq: p1: Qtrue = R1true = [102] Qfalse = R1false = [103] p2: p2quad=nextquad() = 104 Καλείται η B η Q και η R για την x>y p1: Rtrue = [104] Rfalse = [105] 104: >, t, x, _ 105: jump, _, _, _ Επιστρέφουµε στηνq: p3: backpatch(qtrue,p2quad) = backpatch([102],104) Qfalse = merge(qfalse, R2false) = merge([103],[105]) Qtrue = R2true = [104] Επιστρέφουµε στηνb: p3: backpatch(bfalse,p2quad) = backpatch([101],102) Btrue = merge(btrue, Q2true) = merge([100],[104]) Bfalse = Q2false = [103, 105] x > y or x <w and t > x 100: >, x, y, _ 101: jump, _, _, 102 102: >, x, w, 104 103: jump, _, _, _ 104: >, t, w, _ 105: jump, _, _, _ B.true B.false Κλήση Υποπρογραµµάτων Κλήση Υποπρογραµµάτων Κλήση διαδικασίας: call assign_v (in a, inout b) Κλήση συνάρτησης: error = assign_v (in a, inout b) par, a, CV, _ par, b, REF, _ call, _, _, assign_v par, a, CV, _ par, b, REF, _ w = newtemp() par, w, RET, _ call, _, _, assign_v 6
Εκχώρηση οµή if S -> id := E {P1}; {P1} : genquad( :=,E.place, _,id) snext=nil S -> if B then {P1} S 1 {P2} TAIL {P3} p1quad=nextquad() list=makelist(nextquad) genquad( jump, _, _, _ ) p2quad:=nextquad() {P3}: backpatch(b.true,p1quad) backpatch(b.false,p2quad) S.next=merge(S 1.next,list,tail.next) οµή if οµή while TAIL -> else S 2 {P1} TAIL.next=s2.next TAIL -> ε {P1} TAIL.next= null S -> while {P1} B do {P2} S 1 {P3} {P3}: p1quad:=nextquad() p2quad:=nextquad() backpatch(b.true,p2quad) backpatch(s 1.next,p1quad) S.next=B.false genquad( jump, _, _,p1quad) οµή for οµή Repeat Until S -> for ( assignment; {P1} condition; {P2} assignment) {P3} S {P4} {P3}: {P4}: condquad=nextquad() genquad( jump, _, _,condquad) assignquad=nextquad() squad=nextquad() genquad( jump, _, _,assignquad) backpatch(cond.true,squad) backpatch(cond.false,nextquad()) S -> repeat {P1} S 1 until (cond) {P2} squad:=nextquad() backpatch(cond.true,squad) backpatch(cond.false,nextquad()) 7
Εντολή return οµή forcase S -> return (E) {P1} genquad( retv,e.place, _, _ ) snext=nil S -> forcase ( when (condition) do sequence end do ) * endforcase Ξεκινώντας από την αρχή ελέγχονται διαδοχικά οι συνθήκες condition των µελών µέχρι να βρεθεί ότι κάποια συνθήκη ισχύει. Τότε εκτελούνται οι εντολές sequence για εκείνο το µέλος και στη συνέχεια ο έλεγχος µεταφέρεται στην αρχή του forcase. ηλαδή ο έλεγχος θα µεταβεί έξω από τη δοµή όταν καµία από τις συνθήκες condition δεν ισχύει οµή forcase οµή incase S -> forcase {P1} ( when (condition) do {P2} sequence {P3} end do ) * endforcase {P3}: p1quad=nextquad() backpatch(cond.true,nextquad()) genquad( jump, _, _,p1quad) backpatch(cond.false,nextquad()) S -> incase ( when (condition) do sequence end do ) * endincase Ξεκινώντας από την αρχή ελέγχονται διαδοχικά οι συνθήκες condition των µελών µέχρι να βρεθεί ότι κάποια συνθήκη ισχύει. Τότε εκτελούνται οι εντολές sequence για εκείνο το µέλος και στη συνέχεια ο έλεγχος µεταφέρεται στην επόµενη incase. O έλεγχος θα µεταβεί έξω από τη δοµή ότανκαµία από τις συνθήκες condition δεν ισχύει οµή incase S -> {P3}: {P4}: incase {P1} ( when (condition) do {P2} sequence {P3} end do ) * endincase {P4} w=newtemp() p1quad=nextquad() genquad( :=,1, _,w) backpatch(cond.true,nextquad()) genquad( :=,0, _,w) backpatch(cond.false,nextquad()) genquad( =, w,0,p1quad) 8