10. kodutöö: AKTK interpretaator
Olles kirjutanud grammatika ja loonud AST-i, oleme lõpuks jõudnud nii kaugele, et saame hakata käivitama AKTK programme! Hetkel piirdume interpreteerimisega, milleks on vaja implementeerida järgnev klass:
package week10;
public class AktkInterpreter {
	public static void run(String program) {
		// TODO: käivita antud AKTK kood
	}
}
Kodutöö mall on avalikus repos. Etteantud on abiklass week10.AktkInterpreterBuiltins, mis sisaldab AKTK "standardteeki", st. neid funktsioone, mis on kõigile AKTK programmidele alati kättesaadavad.
Vihjed
- Programmi lähtekoodist on kõigepealt vaja saada selle AST.
- AST-i läbimiseks/väärtustamiseks oleme lisanud AstVisitorliidese.
- Kuna avaldiste väärtusteks võivad olla nii täisarvud kui ka sõned, siis väärtustava visitor-i tagastustüübiks sobib Object. Väärtuse puudumisel saab tagastadanull.
- Pane tähele, et AKTK abstraktne süntaksipuu ühtlustab tavapärased infiksoperaatsioonid ja harilikud funktsiooni väljakutsed ühe nimetaja alla (FunctionCall) — interpreteerimisel tuleks neil vahet teha. Selle tarvis on klassiFunctionCalllisatud abimeetodidisComparisonOperatorjaisArithmeticOperation— kui need meetodid tagastavadfalse, on tegemist hariliku funktsiooniväljakutsega.
- Muutujatega töötamiseks on vaja väärtuskeskkonda.
- Kuigi AKTK programmides võib (aga ei pruugi!) esineda muutujate jms tüüpe, võib neid hetkel ignoreerida ja alati lähtuda väärtuste endi tüüpidest.
- Sisseehitatud funktsioone on kõige paindlikum käivitada reflection-i abil. Näiteks järgneva koodiga saab AktkInterpreterBuiltinsklassist sõne kujul oleva nime ja argumentide tüüpide järgi leida vastava meetodi ning selle soovitud argumentidel käivitada ja tagastatud väärtuse saada:try { Integer argument = 42; Method method = AktkInterpreterBuiltins.class .getDeclaredMethod("print", new Class<?>[]{argument.getClass()}); Object returnValue = method.invoke(null, new Object[]{argument}); } catch (Exception e) { throw new RuntimeException(e); }Rohkem infot: https://docs.oracle.com/javase/tutorial/reflect/.
- If ja while lause tingimuses loeme vääraks täisarvu 0 ja tõeseks kõiki muid täisarve.
- Võib eeldada, et kõik funktsioonid on defineeritud globaalses skoobis, st funktsioone skoopima ei pea.
- Sisseehitatud funktsioonide korral tuleb arvestada üledefineerimisega (overloading), sest printfunktsiooni saab kasutada nii arvulise kui ka tekstilise argumendiga. AKTK-s defineeritud funktsioonide korral üledefineerimist toetada pole vaja.
- Kui jääd hätta AKTK funktsioonide return-lausete implementeerimisega, siis ühe võimalusena uuri, kuidas toimub funktsioonist väärtuse väljaandmine Pascalis.