Toto je starší verze dokumentu!


Domácí úkol č. 6: Virtuální stroj

  • Úkol zadán: 1. 12. 2014
  • Odevzdávání naostro možné od: 5. 12. 2014
  • Absolutní konec odevzdávání: 23. 1. 2015
  • Odevzdáváte soubory: command.h, command.cpp, virtualMachine.h, virtualMachine.cpp, client.h a client.cpp

Doplnění zadání (zobrazeno podtrženě):

  • zatim nic

Představení úkolu

Za virtuální stroj je v jednom ze svých významů považován software, který nad nějakou počítačovou platformou vytváří jednotné virtuální prostředí pro běh aplikací. Virtuální stroj skrývá rozdíly mezi různými hardwarovýmí platformami, definuje sadu instrukcí, vytváří jednotnou abstraktní vrstvu nad různými operačními systémy, efektivně překládá virtuální instrukce na skutečné instrukce procesoru, poskytuje podporu pro vyšší programovací jazyky (např. způsob voláni podprogramů, OOP).

Výhody použiti virtuálního stroje:

  • jednodužší vývoj software a jeho připrava pro použití
  • společné požadavky vyšších programovacích jazyků stačí implementovat jednou, např.
  • podprogramy, objekty, jmenné prostory (namespaces)
  • uzávěry (closures) a navazování (continuations)
  • správu paměti
  • snadnější spolupráce mezi vyššími programovacími jazyky
  • způsob volání podprogramů a metod
  • reprezentace základnich typů (řetězců, polí, objektů, …)
  • kód s částmi v různých jazycích běží jako jeden program
  • možnost nastavit bezpečnostní opatření a kvóty
  • např. tenhle program se může připojivat k jiným počítačům v síti, ale nemůže přistupovat k lokálním souborům
  • ladění, analýza a optimalizování programů jsou jednodužší
  • možnost použít dynamické optimalizace, tj. využit informace, které jsou známý až za běhu programu, ne při jeho psaní

Mezi nejznámější virtuální stroje patří např. JVM (Java Virtual Machine).

Exitují dva typy virtuálních strojů a to zásobníkový a registrový. Nás bude zajímat ten první.

Zadání

Vaším úkolem bude napsat 3 třídy včetně hlavičkových souborů. Třída Client bude sloužit k ovládání virtuálního stroje - skrze třídu Client se budou ukládat a provádět instrukce Command uložené v Queue (ke stažení níže). Z toho plyne, že třída Command bude sloužit k uložení samotných instrukcí pro VirtualMachine.

Stáhněte si queue.h

Požadavky

třída Client

slouží k ovládání VirtualMachine přes prostředníka Queue. Tento prostředník je však zapomnětlivý a zapamatuje si maximálně 6 instrukcí pro virtuální stroj, proto s tím počítejte! Client nemá vlastní paměť. Vaším úkolem bude napsat metody:

  • void add(Command* command) - na vstup příjde ukazatel na třídu Command, které uloží do Queue.
  • void add(vector<Command*> comm) - na vstup příjde vector ukazatelů na třídu Command, které uloží do Queue (pozor, aby jich nebylo moc). Příklad:
Client c;
VirtualMachine* v = new VirtualMachine;
c.add(new Command(v, &VirtualMachine::add, 3));
  • void run() - Vezme Commandy uložené v Queue a provede je.
  • void clear() - smaže poslední vložený Command do Queue.
  • int load(const string& path, VirtualMachine* v) - Commandy vyparsuje ze souboru a uloží, cesta k souboru bude metodě load předána v argumentu. V souboru na každém řádku bude jeden příkaz bez jakýchkoliv mezer. V případě, že příkaz vyžaduje parametr, tak na řádku bude jediná mezera a to mezi příkazem a parametrem. Jakýkoliv jiný formát je chybný, příkaz se neprovede a vypíše na výstup vhodnou chybovou hlášku. Příkazy se i v případě nevalidního vstupu ukládají - poslední uložený příkaz je příkaz před prvním nevalidním příkazem. Stejně tak je formát chybný, pokud bude parametr tam, kde být nemá nebo naopak. V linuxu standardně končí soubory znakem nového řádku (i zde). Nemůžete předpokládat, že v souboru budou pouze validní příkazy. V případě zjištění nevalidního vstupu nebo jiné chyby metoda vrátí 1, jinak 0. Soubor může vypadat např. takto:
add 4
add 2
add 1
plus
minus
add 8
print
Pokud je fronta plná a příjde požadavek na zařazení dalšího příkazu, je proveden nejstarší příkaz ve frontě a teprve poté je přidán nový příkaz.
třída Command

slouží k uložení instrukce pro VirtualMachine Vaším úkolem bude napsat metody:

  • kontruktor - na vstup dostane ukazatel na VirtualMachine, dále metodu, kterou má VirtualMachine udělat a dále může, ale nemusí dostat parametr pro metodu VirtualMachinu. V případě, že přijde metoda add bez parametru, program vypíše vhodnou chybovou hlášku, na parametr uloží 0 a pokračuje dál. V případě, že přijde jiná metoda s parametrem, tak se tento parametr ignoruje.
  • přetížit operátor () - tak aby se volali Commandy ve VirtualMachine (aby šlo zavolat some_command()).
třída VirtualMachine

je samotný zásobníkový virtuální stroj, takže mimo instrukcí má i vlastní paměť (reprezentovaná např. pomocí vector<int>).

  • void plus(int) - sečte dvě poslední čísla na zásobníku, součet uloží opět nahoru (sčítané (násobené, apod.) čísla na zásobníku nezůstávají)
  • void minus(int) - odečte předposlední číslo od posledního a výsledek uloží
  • void divide(int) - poslední číslo děleno předposlední číslo v celých číslech, uložit, v případě dělení 0 se nic neprovede, pouze vypsat vhodnou chybovou hlášku.
  • void multiply(int) - součin dvou posledních čísel, opět uložit
  • void add(int n) - přidá číslo na zásobník
  • void print(int) - vytiskne celý zásobník, poslední vypsané číslo bude to nahoře na zásobníku, všechna čísla budou na jednom řádku a mezi čísly bude mezera (za posledním číslem mezera nebude), příklad výstupu:
c.add(new Command(v, &VirtualMachine::add, 5));
c.add(new Command(v, &VirtualMachine::add, 4));
c.add(new Command(v, &VirtualMachine::add, 3));
c.add(new Command(v, &VirtualMachine::add, 8));
c.add(new Command(v, &VirtualMachine::add, 3));
c.add(new Command(v, &VirtualMachine::plus));
c.add(new Command(v, &VirtualMachine::print));
výstup potom bude:
5 4 3 11

Poznámky

  • Při řešení plného Queue nemůžete všechny Commandy jednoduše provést a pokračovat s prázdnou Queue. Nebylo by možné potom zavolat clear(). Queue proto musí být stále plná až do zavolání run().
  • Pokud načítání ze souboru (v client::load) proběhne správně, tak spuštění commandů (client::run) proběhne v client::load a ne v mainu.
  • soubor main.cpp neodevzdávate, pokud nějaký vytvoříte, tak slouží pouze k vašemu testování
  • příklad, jak by se mohlo v mainu testovat:
  Client c;
	VirtualMachine* v = new VirtualMachine;
	vector<Command*> com;
	com.push_back(new Command(v, &VirtualMachine::add, 1));
	com.push_back(new Command(v, &VirtualMachine::add, 5));
	com.push_back(new Command(v, &VirtualMachine::add, 9));
	com.push_back(new Command(v, &VirtualMachine::add, 8));
	com.push_back(new Command(v, &VirtualMachine::minus));
	com.push_back(new Command(v, &VirtualMachine::plus));
	com.push_back(new Command(v, &VirtualMachine::multiply));
	com.push_back(new Command(v, &VirtualMachine::add, 3));
	com.push_back(new Command(v, &VirtualMachine::add, 3));
	com.push_back(new Command(v, &VirtualMachine::print));
	c.add(com);
	c.add(new Command(v, &VirtualMachine::add, 3));
	c.run();
 

Autor: Úlohu připravil Jan Bilík. Podporu pro řešení úlohy poskytuje Lukáš Ručka, v případě nejasností jej kontaktujte na diskuzním fóru nebo na 359687@mail.muni.cz.

QR Code
QR Code public:pb161_fall14_hw06 (generated for current page)