INF5110 16. april, 2013 Kap. 8 Noen oppgaver som er meget relevante for Oblig 2 Oppgave: Ut fra den objektorienterte trestrukturen vi laget for å representere Tiny-programmer (se neste foiler), gjør følgende for uttrykks-nodene: 1. Skisser en metode «void GenCodeP()» i hver nodeklasse for uttrykk, slik at vi får lagt ut P-kode for uttrykket. Legg ut ved «void emit(string code) {» 1. Koden skal lages som ren tekst-kode 2. Vi tenker ikke på typen av operandene 2. Skisser tilsvarende en metode «String GenCodeTA()» som legger ut (ved emit) TA-kode Anta at metoden «String NewTemp(){» leverer et nytt navn 1 til en temporær variabel.
Nodeklasser for OO-utgave av abst.-synt.-tre for Tiny-språket. Merk: Dette er altså en fast subklasse-struktur i kompilatoren, og må ikke forveksles med det abstrakte syntaks-treet for et gitt program! TreeNode int lineno Program Stmt firststmt Stmt Stmt nextstmt Expr Char type IfStmt Expr cond Stmt thenstmts Stmt elsestmts RepStmt Stmt stmt Expr cond AssStmt Ident id Expr ex ReadStmt Ident id WriteStmt Expr ex Const Int value Kan også ha (gjerne virtuelle) metoder i nodene, f.eks: Ident String name BinOp Char op Expr left Expr right - dosemanalyses(); Gjør semantisk analyse av noden, og av subtreet det er rot i - generatecode(); Genererer kode for noden, og for subtreet det er rot i 2
ReadStmt lnr = 1 nextstm x Program lnr = 1 firststmt IfStmt lnr = 2 nextstm cond stm1 stmt2 Const left lnr = 2 (type) 0 BinOp lnr = 2 (type) < right Ident lnr = 2 (type) x fact lnr = 3 Assign nextstm lnr = 3 (type) 0 Merk at typen vanligvis ikke blir satt på før under semantikkanalysen, så den vil her stå tom. ex left Ident = fact fact Assign lnr = 5 BinOp lnr = 5 (type) * right RepStm lnr = 4 nextstm stm nextstm ex cond Ident= x left Ident= x Assign lnr = 6 nextstm x BinOp lnr = 6 (type) WriteStm lnr = 8 nextstm ex ex - right Ident Const= 1 lnr = 8 (type) fact 3
Oppgave 1 er altså å lage noe slikt (for P-kode): Antar at vi har «void emit(string code) {» I klassen Const: void GenCodeP() { I klassen Ident: void GenCodeP() { I klassen BinOp: void GenCodeP(){ Men hva med void GenCode(){ i klassen Expr?
Litt bakgrunn fra forelesningsfoilene P-kode (Pascal-kode) utfører beregning på en stakk Instruksjonene utføres normalt etter hverandre, unntak: jump push koder (= load på stakken): lod ; load value ldc ; load constant lda ; load adress 5 2 = a 5
Mer bakgrunn: P-kode II 6
Bakgrunn: P-kode for fakultets-funksjonen 1 2 Blir typisk mange flere P-instruksjoner enn TA-instruksjoner for samme program (Hver P-instruksjon har maks én lager-adresse ) 3 4 5 1 2 3 4 5 6 7 8 9 6 7 8 9
Generering av P-kode fra tre-struktur (progr.strukt. ikke som Oblig 2) rek.kall rek.kall rek.kall switch kind { case OpKind: switch op{ Oversiktlig versjon: Merk: Identifikator og konstant-streng ligger i noden case Plus: { rek. kall for venstre subtre; rek. kall for høyre subtre; emit1 ( adi ); case Assign: { emit2 ( lda, identifikator); rek. kall for eneste subtre; emit1 ( stn ); case ConstKind { emit2 ( ldc, konstant-streng); case IdKind { emit2 ( lod, identifikator);
Nodeklasser for OO-utgave av abst.-synt.-tre for Tiny-språket. Merk: Dette er altså en fast subklasse-struktur i kompilatoren, og må ikke forveksles med det abstrakte syntaks-treet for et gitt program! TreeNode int lineno Program Stmt firststmt Stmt Stmt nextstmt Expr Char type IfStmt Expr cond Stmt thenstmts Stmt elsestmts RepStmt Stmt stmt Expr cond AssStmt Ident id Expr ex ReadStmt Ident id WriteStmt Expr ex Const Int value Kan også ha (gjerne virtuelle) metoder i nodene, f.eks: Ident String name BinOp Char op Expr left Expr right - dosemanalyses(); Gjør semantisk analyse av noden, og av subtreet det er rot i - generatecode(); Genererer kode for noden, og for subtreet det er rot i 9
Svarforslag for «void GenCodeP()» Vi lager først en abstrakt «void GenCodeP();» i klassen Expr (eller gjerne i klassen TreeNode). Så en konkret en i hver av klassene Const, Ident og BinOp: I klassen Const: void GenCodeP() { I klassen Ident: void GenCodeP() { I klassen BinOp: void GenCodeP(){
Svarforslag for «void GenCodeP()» Vi lager først en abstrakt «void GenCodeP();» i klassen Expr (eller gjerne i klassen TreeNode). Så en konkret en i hver av klassene Const, Ident og BinOp: I klassen Const: void GenCodeP() { emit ("ldc " + Value); I klassen Ident: void GenCodeP() { I klassen BinOp: void GenCodeP(){
Svarforslag for «void GenCodeP()» Vi lager først en abstrakt «void GenCodeP();» i klassen Expr (eller gjerne i klassen TreeNode). Så en konkret en i hver av klassene Const, Ident og BinOp: I klassen Const: void GenCodeP() { emit ("ldc " + Value); I klassen Ident: void GenCodeP() { emit ("lod " + Name); I klassen BinOp: void GenCodeP(){
Svarforslag for «void GenCodeP()» Vi lager først en abstrakt «void GenCodeP();» i klassen Expr (eller gjerne i klassen TreeNode). Så en konkret en i hver av klassene Const, Ident og BinOp: I klassen Const: void GenCodeP() { emit ("ldc " + Value); I klassen Ident: void GenCodeP() { emit ("lod " + Name); I klassen BinOp: void GenCodeP(){ left.gencodep(); // Kan være et større uttryks-tre right.gencodep(); // ---- " ---- emit ( <P-kode-instruksjonen tilsv. op> );
Bakgrunn: Hånd -oversettelse til TreAdresse-kode 1 2 3 4 5 6 7 8 9 Mange valg å gjøre ved design av TA-kode: -Er det egne instruksjoner for int, long, float,..? -Hvordan er variable representert? -ved navn -peker til deklarasjon i symbol-tabell -ved maskinadresse -Hvordan er hver instruksjon lagret? - kvadrupler, de tre adressene, og operasjonen - (Eller: tripler, der adressen til instruksjonen er navn på en ny temporær variabel) 1 2 3 4 5 6 7 8 9 Eller?: x = x - 1 14
Bakgrunn: Generering av rent tekstlig TA-kode fra tre-struktur Hoved-delen av en rekursiv metode. Metoden eksekverer inne i noden og leverer et navn eller en konstant-streng: switch kind { case OpKind: switch op { case Plus: { tempnavn = nytt temporær-navn; opnavn1 = rek kall for venstre subtre; opnavn2 = rek kall for høyre subtre; emit ( tempnavn = opnavn1 + opnavn2 ); return (tempnavn); case Assign: { varnavn = id. for v.s.-variabel (ligger i noden); opnavn = rek kall for venstre subtre; emit ( varnavn = opnavn ); return (varnavn); case ConstKind: { return (konstant-streng); // Emitter ingenting! case IdKind: { return (identifikator); // Emitter ingenting!
Nodeklasser for OO-utgave av abst.-synt.-tre for Tiny-språket. Merk: Dette er altså en fast subklasse-struktur i kompilatoren, og må ikke forveksles med det abstrakte syntaks-treet for et gitt program! TreeNode int lineno Program Stmt firststmt Stmt Stmt nextstmt Expr Char type IfStmt Expr cond Stmt thenstmts Stmt elsestmts RepStmt Stmt stmt Expr cond AssStmt Ident id Expr ex ReadStmt Ident id WriteStmt Expr ex Const Int value Kan også ha (gjerne virtuelle) metoder i nodene, f.eks: Ident String name BinOp Char op Expr left Expr right - dosemanalyses(); Gjør semantisk analyse av noden, og av subtreet det er rot i - generatecode(); Genererer kode for noden, og for subtreet det er rot i 16
Svarforslag for «String GenCodeTA()» Vi lager først en abstrakt «String GencodeTA();» i klassen Expr (eller gjerne i klassen TreeNode). Så en konkret en i hver av klassene Const, Ident og BinOp: I klassen Const: String GenCodeTA() { I klassen Ident: String GenCodeTA() { I klassen BinOp: String GenCodeTA(){
Svarforslag for «String GenCodeTA()» Vi lager først en abstrakt «String GencodeTA();» i klassen Expr (eller gjerne i klassen TreeNode). Så en konkret en i hver av klassene Const, Ident og BinOp: I klassen Const: String GenCodeTA() { return "" + value; // Ingen emit I klassen Ident: String GenCodeTA() { I klassen BinOp: String GenCodeTA(){
Svarforslag for «String GenCodeTA()» Vi lager først en abstrakt «String GenCodeTA();» i klassen Expr (eller gjerne i klassen TreeNode). Så en konkret en i hver av klassene Const, Ident og BinOp: I klassen Const: String GenCodeTA() { return "" + value; I klassen Ident: String GenCodeTA() {return name; // Ingen emit I klassen BinOp: String GenCodeTA(){
Svarforslag for «String GenCodeTA()» Vi lager først en abstrakt «String GenCodeTA();» i klassen Expr (eller gjerne i klassen TreeNode). Deretter en konkret en i hver av klassene Const, Ident og BinOp: I klassen Const: String GenCodeTA() { return "" + value; I klassen Ident: String GenCodeTA() {return name; I klassen BinOp: String GenCodeTA(){ String s1, s2; String t = NewTemp(); s1 = left.gencode(); s2 = right.gencode(); emit ( t + " = " + s1 + op + s2 ); return t;