BAB III PERANCANGAN
3.1 Spesifikasi bahasa DOGI 3.1.1 Token Karakter-karakter yang diijinkan dipakai dalam bahasa DOGI adalah sembarang karakter selain karakter kontrol, dalam set karakter ASCII. DOGI tidak mendukung penggunaan karakter-karakter unicode. Carriage return, line feed, dan
tab dianggap sebagai white space. Frasa “sembarang karakter” yang digunakan selanjutnya akan selalu berarti “sembarang karakter dalam set karakter yang diijinkan bahasa DOGI”. A. Kata kunci Kata-kata kunci yang digunakan oleh DOGI adalah: package imports exports class access interface method property hidden
40
41 visible get set new kill begin end
B. Pengenal (identifier) Pengenal (identifier) dalam bahasa DOGI dimulai dengan huruf atau garis bawah atau @. Setiap karakter selanjutnya bisa merupakan salah satu dari huruf, garisbawah, @ maupun angka, tidak dibatasi panjangnya. Pengenal dalam bahasa DOGI tidak membedakan huruf besar maupun kecil (bersifat case-insensitive). Contoh nama-nama pengenal: dogi anjing si_manis @anak_dogi_1 bopi@home
C. Literal Literal merepresentasikan data. Bahasa DOGI mengenal tujuh macam literal, yaitu null, integer, floating-point, string, boolean, array dan code. Null Literal null tidak merepresentasikan data secara konkret. Null digunakan untuk menandai bahwa suatu nama tidak mereferensikan objek apa pun, walaupun itu
42 berarti nama tersebut mereferensikan sebuah objek – yaitu objek null sendiri. Null merupakan instansiasi dari kelas void. Dituliskan sebagai #null. Integer Literal integer merupakan representasi dari bilangan bulat. Literal integer sendiri terdiri dari dua macam representasi, yaitu desimal dan heksadesimal. Literal desimal terdiri dari barisan angka-angka yang panjangnya tidak dibatasi (walaupun aturan semantik akan membatasi nilainya, yang tergantung pada arsitektur komputer saat ini). Literal heksadesimal diawali dengan 0x, dilanjutkan dengan barisan angka maupun salah satu huruf a sampai f tanpa dibedakan huruf besar maupun kecil. Literal integer merupakan instansiasi dari kelas int. Graf sintaks untuk digit desimal, digit heksadesimal, dan literal integer dapat dilihat pada Gambar 3.1, Gambar 3.2, dan Gambar 3.3. digit
0 1 2 3 4 5 6 7 8 9
Gambar 3.1 Graf sintaks untuk digit
43 hexdigi t
digit A B C D E F
Gambar 3.2 Graf sintaks untuk digit heksadesimal
integer
digit 0
x
hexdigit
Gambar 3.3 Graf sintaks untuk literal integer
Contoh-contoh literal integer: 2152332 3154258763248678 0x42AB38C 0x32cFf
Floating-point Literal floating-point merupakan representasi dari bilangan real, dan instansiasi dari kelas real. Literal floating-point terdiri dari beberapa bagian, yaitu bagian integer, titik desimal, bagian pecahan dan eksponen. Pembentukan literal floating-point yang valid adalah • Bagian integer dan bagian pecahan terdiri dari satu atau lebih angka.
44 • Eksponen diawali huruf E atau e, diikuti langsung dengan angka-angka, atau bisa juga dengan plus atau minus, diikuti angka-angka. • Bagian integer diikuti langsung dengan eksponen, atau • Bagian integer diikuti dengan titik desimal, bagian pecahan, dan bisa diikuti oleh eksponen maupun tidak. Graf sintaks untuk literal floating-point dapat dilihat pada Gambar 3.4.
Floating-point
digit
.
digit
E
digit + -
Gambar 3.4 Graf sintaks untuk literal floating-point
Contoh-contoh literal floating-point: 124.12525 3.2 0.52e23 325.253e-004 5321124.4e+2
String Literal string adalah barisan sembarang karakter (kecuali tanda kutip ganda), di antara dua tanda kutip ganda (“). Backslash (\) digunakan sebagai karakter
escape, untuk menyatakan karakter kontrol ataupun karakter lainnya. Literal string merupakan instansiasi dari kelas string. Graf sintaks untuk karakter tunggal, karakter, dan string dapat dilihat pada Gambar 3.5, Gambar 3.6, Gambar 3.7, sedangkan daftar karakter escape dapat dilihat pada Tabel 3.1.
45 \b
Backspace
\t
Tabulasi
\n
line feed
\f
Form feed
\r
carriage return
\”
kutip ganda
\\
Backslash
\m##
mengulang karakter sebelumnya sebanyak ##
\u####
karakter unicode nomor ####
\0x##
karakter ASCII nomor ##
Tabel 3.1 Karakter-karakter escape yang berlaku
Contoh-contoh literal string: “Aku gigi mulut rumahku” “ \”Aku gigi mulut rumahku\” adalah string” “Aku\ngigi\nmulut\nrumahku\0x0D”
46 singlechar
! ... 0 ... 9 ... A ... Z ... a ... z ... ~
Gambar 3.5 Graf sintaks untuk karakter tunggal Char
\
u
hexdigit
0
x
hexdigit
hexdigit
hexdigit
hexdigit
hexdigit
m singlechar singlechar
Gambar 3.6 Graf sintaks untuk karakter String
“
“ char
Gambar 3.7 Graf sintaks untuk literal string
Boolean Literal boolean hanya ada dua, yaitu #true dan #false. Sesuai namanya, #true menunjukkan nilai benar, dan #false menunjukkan nilai salah. Kedua
47 literal ini merupakan instansiasi dari kelas bool. Pemberian tanda # mempermudah pembedaan dari nama objek. Array Literal array merepresentasikan array, dan merupakan instansiasi dari kelas array. Literal array dituliskan sebagai daftar yang dipisahkan tanda koma, dan dituliskan di antara tanda kurung kurawal. Graf sintaks untuk array dapat dilihat pada Gambar 3.8.
array
{
expr
} ,
Gambar 3.8 Graf sintaks untuk literal array
Contoh-contoh literal array: { 5, 2, 9, 4, 3, 2 } { console.writeln(3), Count()+2, 2+4*con_9, #false } { [ 5-f ], #true, { 5, 4, { 3, 2 }, 4 }, “abcde” }
Code Dalam bahasa DOGI terdapat tambahan literal yang lain, yaitu kode (code). Sifatnya seperti block pada SmallTalk. Literal kode yang dituliskan dalam sebuah metoda tidak akan dieksekusi, melainkan dianggap sebagai objek instansiasi dari kelas code. Penulisannya selalu berada di antara kata begin..end untuk kode dengan nol atau lebih statement, dan di antara [ .. ] untuk kode dengan nol atau satu statement. Kode tidak secara otomatis dieksekusi. Graf sintaks untuk kode dapat dilihat pada Gambar 3.9.
48 code
begin
exprList
[
exprList
expr
end
]
expr ;
Gambar 3.9 Graf sintaks untuk literal code
Contoh-contoh berikut adalah literal code: begin dogi makan; end begin out.write(“Guk!”); end
D. Pemisah Pemisah (separator) digunakan untuk memisahkan token-token. Daftar lengkap pemisah yang digunakan dapat dilihat pada Tabel 3.2 berikut. (
Berpasangan dengan ), digunakan untuk mengawali daftar parameter sebuah metoda, atau untuk memberikan presedensi bagi ekspresi
)
Merupakan penutup bagi (
{
Berpasangan dengan }, digunakan untuk mengawali suatu literal array
}
Merupakan penutup bagi {
[
Berpasangan dengan ], digunakan untuk indexer (dicadangkan), maupun code dengan satu ekspresi
]
Merupakan penutup bagi [ (dicadangkan)
<
Berpasangan dengan >, digunakan untuk mendaftar objek-objek lokal
49 dalam sebuah method. < juga digunakan sebagai operator. >
Merupakan penutup bagi <, juga digunakan sebagai operator.
;
Digunakan untuk memisahkan bagian-bagian dalam program DOGI
,
Pemisah dalam daftar
.
Titik desimal, juga digunakan sebagai qualifier bagi objek
Tabel 3.2 Pemisah dalam bahasa DOGI
E. Operator Operator adalah metoda. Operator tidak mendapat perlakuan khusus seperti pada bahasa-bahasa pemrograman lainnya. Operator hanyalah metoda yang diberi nama dengan simbol-simbol tertentu. Operator dibentuk dari satu atau sepasang simbol-simbol berikut dan masing-masing tidak didefinisikan. =
<
>
+
-
*
/
!
&
|
%
^
:
?
\
Pasangan operator /* dan */ tidak dapat dipakai karena sudah dipakai sebagai tanda awal dan akhir komentar. Contoh operator: + = += <<
50 F. White space Karakter-karakter yang termasuk white space adalah spasi, tabulasi, new line,
carriage return, dan line feed. Karakter-karakter tersebut diabaikan dalam proses kompilasi. G. Komentar Komentar dalam DOGI sama dengan yang dipakai pada bahasa C++. Ada dua jenis komentar, yaitu komentar satu baris, dan komentar bersarang (nested
comment). Komentar satu baris diawali dengan tanda //, dan karakter-karakter berikutnya merupakan komentar sampai baris tersebut berakhir. Komentar bersarang diawali tanda /* dan diakhiri dengan */, tidak harus dituliskan dalam baris yang sama. Graf sintaks untuk komentar dapat dilihat pada Gambar 3.10.
comment
/*
any character
//
singlechar
*/
↵
Gambar 3.10 Graf sintaks untuk komentar
Contoh komentar bersarang: /* Komentar komentar komentar komentar komentar komentar komentar komentar komentar komentar komentar komentar */
Contoh komentar satu baris: // Komentar satu baris
51 3.1.2 Struktur program Suatu program dalam bahasa DOGI dibentuk oleh daftar kelas, antarmuka kelas, dan antarmuka. Masing-masing deklarasi dipisahkan oleh tanda titik koma (;). Deklarasi-deklarasi tersebut disatukan dalam package, yang dituliskan dalam sebuah file kode sumber. Sebuah file kode sumber DOGI dapat memiliki lebih dari sebuah package. Graf sintaks untuk kode sumber dalam bahasa DOGI dapat dilihat pada Gambar 3.11.
source
package
;
Gambar 3.11 Graf sintaks untuk file program dalam bahasa DOGI
3.1.3 Package
Package adalah satuan paling kecil yang dapat dikompilasi secara mandiri. Sebuah package berisi daftar kelas, antarmuka kelas, dan antarmuka. Dituliskan dengan bentuk: package
begin end;
Sebuah package dapat mengimpor antarmuka-antarmuka kelas dari package lain dengan menuliskan dalam daftar deklarasi: imports . { , . } ;
Penulisan .* akan mengimpor semua nama yang diekspor oleh package yang dimaksud. Simbol-simbol yang dapat diimpor haruslah telah diekspor pada package yang bersangkutan, dengan menyebutkan:
52 exports { , } ;
Hanya antarmuka kelas (ditandai dengan kata kunci access) dan antarmuka (interface) yang dapat diekspor dan diimpor oleh sebuah package. Package tanpa nama adalah package yang tidak dapat diimpor oleh kelas manapun. Package tanpa nama adalah untuk package yang berisi program siap eksekusi, sehingga tidak perlu diimpor oleh kelas manapun. Kompiler DOGI untuk saat ini hanya mendukung satu package dalam sebuah file. Graf sintaks untuk package dapat dilihat pada Gambar 3.12.
packageHeader
package
packageItems
packageItem
package
packageHeader
packageItem
packageName
begin
packageItems
;
imports exports class access interface
Gambar 3.12 Graf sintaks untuk package
end
53 3.1.4 Kelas A. Deklarasi kelas Sebuah kelas dideklarasikan menggunakan kata kunci class, diikuti nama kelas induk, diikuti nama kelas yang akan dibuat. Bagian ini dinamakan class
declaration header, dan sudah cukup untuk mendeklarasikan sebuah kelas. class [ ( [ { , }] ) ]
Kelas yang dihasilkan dengan cara ini akan memiliki sifat sama persis dengan kelas induknya, yang memiliki visibilitas . Modifikasi terhadap anggota-anggota kelas dapat dituliskan setelah declaration header, diawali kata begin dan diakhiri kata end. begin end;
Graf sintaks untuk kelas dapat dilihat pada Gambar 3.13. Contoh deklarasi kelas: class binatang anjing … // anggota-anggota kelas di sini … end;
54
class
classHeader
classHeader
class
interfaceList
begin
baseAccessName
interfaceName
classMember
classMember
className
;
(
end
interfaceList
)
,
method field property
Gambar 3.13 Graf sintaks untuk class
B. Anggota-anggota kelas Sebuah kelas memiliki lima macam anggota (class member) yaitu: • Field, • Metoda (method), • Konstruktor, yaitu metoda khusus yang bertugas untuk menciptakan
instance. • Destruktor, yaitu metoda khusus untuk menghapus instance yang sudah dibuat. • Properti,
yaitu
antarmuka
terhadap
field/metoda
memperlakukannya sebagai nama objek. Setiap deklarasi anggota kelas dipisahkan dengan tanda titik koma (;).
dengan
55 C. Field Field dideklarasikan dengan bentuk umum [ field ] [*] { , [*] }
Penggunaan kata kunci field adalah optional. Tanda * dipakai sebagai tanda bahwa field yang bersangkutan tidak secara otomatis dialokasikan (dengan memanggil metoda new dari field yang bersangkutan), melainkan menunjuk pada #null. Graf sintaksnya seperti pada Gambar 3.14. field
field
accessName
*
fieldName ,
Gambar 3.14 Graf sintaks untuk field
Contoh: int umur; anjing * dogi; field kucing si_manis, * si_putih;
D. Metoda Deklarasi metoda memiliki dua bagian, yaitu method signature dan kode.
Method signature berupa nama kelas, diikuti nama metoda, diikuti daftar parameter yang dituliskan di antara tanda kurung. ( [ , … ] )
56 Deklarasinya berupa kata kunci method diikuti method signature. Jika diikuti dengan kode program, artinya metoda tersebut langsung diimplementasikan dalam kode-kode di dalamnya. Jika tidak, metoda tersebut dianggap sebagai metoda abstrak dan tidak boleh dipanggil sebelum diimplementasikan dalam kelas turunannya. Kode program dituliskan di antara kata kunci begin dan end seperti pada bahasa Pascal. Objek-objek lokal dapat dituliskan di antara signature dan kodenya, diapit tanda < dan >. method <method_signature> [ < , … > ] begin end;
Selain dengan cara menuliskan barisan kode-kodenya, DOGI memiliki alternatif penulisan definisi metoda dengan menuliskan ekspresinya secara langsung, jika kode hanya terdiri dari sebuah ekspresi saja. method <method_signature> [ < , … > ] = <ekspresi> ;
Dengan menambahkan titik pada nama metoda, metoda tersebut akan dianggap sebagai class method atau static method, yaitu metoda yang dikaitkan dengan nama kelas. Class method tidak dapat mengakses field yang dideklarasikan dalam kelas yang bersangkutan. Graf sintaks untuk metoda dapat dilihat pada Gambar 3.15.
57
method
method
methodSignature
<
localList begin
exprList
=
methodSignature
accessName
methodName
(
.new
declArgList
accessName
(
)
argName ,
localList
accessName
localName ,
;
Gambar 3.15 Graf sintaks untuk metoda
Contoh: method int jumlah (int a, int b) < int hasil > begin hasil = a + b; return (hasil); end; method real kuadrat (int x) = x * x; int .tipedata();
end
expr
.
kill
>
// ini class method
declArgList
)
58 E. Konstruktor Konstruktor adalah metoda khusus, berguna untuk menginstansiasikan sebuah kelas. Karena konstruktor adalah class method, maka nama konstruktor harus diawali titik. Konstruktor diijinkan untuk lebih dari satu dalam satu kelas, dibedakan berdasarkan signature-nya. Untuk field yang dialokasikan secara otomatis (tidak diberi tanda *), konstruktor akan mengalokasikan field tersebut dengan konstruktor .new() yang terdapat pada field tersebut. Graf sintaks untuk konstruktor dapat dilihat pada Gambar 3.15. method .new ( [ , … ] )
Contoh: method .new () begin … end; method .new (int A) begin … end;
F. Destruktor Berbeda dengan konstruktor, destruktor hanya diijinkan satu untuk setiap kelas, dan tidak menggunakan parameter. Destruktor digunakan untuk menghapus objek. Karena destruktor bukanlah class method, maka penamaannya tidak diawali tanda titik. Graf sintaks untuk destruktor dapat dilihat pada Gambar 3.15.
59 method kill ( )
Contoh: method kill() begin … end;
G. Properti Properti sebenarnya adalah penyingkatan dari penggunaan dua buah metoda yang berlaku sebagai getter (pengambil nilai) dan setter (pengeset nilai), disingkat penulisannya menjadi sebuah nama yang diperlakukan sebagai objek tunggal. Properti dapat dideklarasikan menggunakan salah satu dari penulisan ini: property = property [ get begin <definisi_get> end ] [ set begin <definisi_set> end] property [ get = <definisi_get> ] [ set = <definisi_set> ]
Graf sintaks untuk properti dapat dilihat pada Gambar 3.16. Contoh: property int Count=fCount; property TColor Color get = fColor set begin fColor = Color; return (fColor); end;
60 property
property
propertySignature
getter
setter
setter
getter
=
propertySignature
fieldName
accessName
getter
get
propertyDef
setter
set
propertyDef
propertyDef
<
begin =
localList
exprList
propertyName
>
end
expr
Gambar 3.16 Graf sintaks untuk properti
H. Akses (access) atau antarmuka kelas (class interface) Antarmuka kelas (class interface) atau disebut akses merupakan hal yang tidak terdapat dalam bahasa pemrograman OOP lainnya. Antarmuka kelas secara esensial merupakan visibilitas dari anggota-anggota kelas. Setiap anggota kelas yang didaftar dalam deklarasi class secara default memiliki visibilitas private, atau tidak dapat diakses oleh objek lain maupun kelas turunannya. Setiap anggota kelas yang didaftar dalam antarmuka kelas secara default memiliki visibilitas public. Visibilitas public juga dapat diperoleh dengan memberi awalan visible. Jika diberi awalan hidden, artinya anggota kelas yang
61 bersangkutan memiliki visibilitas protected. Selain yang didaftar dalam antarmuka kelas, anggota kelas bersifat private. Anggota-anggota yang dapat didaftar dalam antarmuka kelas hanya metoda dan properti saja (termasuk konstruktor dan destruktor). Field tidak dapat, untuk menjaga objek dari perubahan-perubahan yang tak terkendali. Setiap anggota yang hendak di-publish didaftarkan signature-nya tepat seperti yang telah didaftarkan di deklarasi kelasnya. Hanya saja tidak ada ketentuan bahwa nama parameter harus sama persis dengan yang telah dituliskan dalam deklarasi kelas. Antarmuka kelas atau akses dituliskan dengan header: access [ ]
Sebuah kelas dapat memiliki lebih dari satu antarmuka. Jika nama antarmuka kelas tidak disebutkan, atau bahkan antarmuka untuk sebuah kelas tidak dibuat, dianggap antarmuka untuk kelas tersebut sama dengan nama kelasnya. Untuk setiap kelas selalu terdapat satu antarmuka yang namanya sama dengan nama kelasnya. Untuk menurunkan sebuah kelas dari kelas lain, harus menyebutkan nama antarmukanya, dan bukan nama kelasnya. Anggota-anggota base class yang dapat diakses hanyalah yang disebutkan dalam antarmuka base class yang dipakai. Dengan demikian suatu kelas dapat memiliki banyak ‘muka’ untuk berhubungan dengan kelas lainnya. Hal ini berguna salah satunya untuk menghemat jumlah kelas yang harus dibuat. Dalam VCL Delphi, untuk setiap komponen kontrol biasanya terdapat
62 komponen abstraknya. Misalnya terdapat komponen TListView turunan TCustomListView, yang pada deklarasinya hanya mengubah visibilitas anggota-anggota TCustomListView yang protected menjadi published. Dengan antarmuka kelas, tidak perlu dilakukan hal seperti itu. Cukup dibuat dua buah antarmuka untuk TCustomListView, yaitu TCustomListView dengan semua anggotanya hidden, dan TListView dengan semua anggotanya visible. Penggunaan kata access dan bukan interface di sini dimaksudkan untuk mencadangkan dukungan abstraksi dengan interface. Bentuk umum deklarasi antarmuka kelas adalah: access [ ] begin end;
Graf sintaks untuk antarmuka kelas atau akses dapat dilihat pada Gambar 3.17.
access
accessHeader
accessHeader
accessMember
begin
access
accessMember
className
;
accessName
hiddenMember visibleMember
hiddenMember
hidden
propertySignature methodSignature
visibleMember
visible
propertySignature methodSignature
Gambar 3.17 Graf sintaks untuk antarmuka kelas
end
63 Contoh: class TWinControl TCustomListView property Items … ; property ViewStyle … ; end; access TCustomListView hidden Items; hidden ViewStyle; end; access TCustomListView TListView Items; ViewStyle; end; access TCustomListView TfixedStyleListView visible Items; hidden ViewStyle; end;
3.1.5 Ekspresi Walaupun DOGI, seperti halnya bahasa pemrograman OOP lainnya, masih menggunakan gaya imperatif, namun cara penulisan kode programnya dibuat sedemikian rupa sehingga dapat mudah dipahami. Setiap statement dalam DOGI merupakan sebuah ekspresi. Sebuah ekspresi merupakan operasi yang dilakukan terhadap sebuah objek, dengan mengirimkan pesan melalui metoda yang dimiliki objek tersebut. Satuan terkecil dari ekspresi hanya ada dua macam, yaitu objek dan metoda.
64 Suatu objek tunggal adalah elemen terkecil sebuah ekspresi. Objek tersebut dapat berupa objek dengan nama atau literal integer, floating-point, boolean, string,
null, code atau array. Graf sintaks objek tunggal dapat dilihat pada Gambar 3.20. Suatu term adalah bagian dari ekspresi yang dapat berupa objek, ekspresi lain di antara tanda kurung, properti dan pengiriman pesan. Berikut ini adalah kemungkinan bentuk-bentuk term. Graf sintaks untuk term dapat dilihat pada pada Gambar 3.19. ( <ekspresi> ) .<properti>
Pengiriman pesan dapat berbentuk satu dari: [ ] . <metoda> ( ) <metoda> ( ) . <metoda> ( )
Sebuah ekspresi dapat berupa sebuah term maupun pengiriman pesan ekspresi kepada sebuah term. Graf sintaks untuk ekspresi dapat dilihat pada Gambar 3.18. <metoda> <ekspresi_lain>
expr
term
method \
term
Gambar 3.18 Graf sintaks untuk ekspresi
65 term
sendMsg singleObject (
expr
term
sendMsg
)
property
term
[
argList
]
term
.
method
(
argList
method
(
argList
)
.
operator
)
term
Gambar 3.19 Graf sintaks untuk term singleObject
objectName className array code integer float string boolean null
Gambar 3.20 Graf sintaks untuk objek
Contoh-contoh ekspresi: dogi.duduk().salam(); console << ”Hello” + “ “ + “world!”; e = (29 * 94)+(24-3*c); if (a>b) then begin put() end else [ 4 ];
3.1.6 Package System
Package System berisi kelas-kelas dasar yang dipakai oleh DOGI. Package System tidak perlu diimpor secara eksplisit karena otomatis akan dipakai oleh kompiler DOGI. Setiap kelas dalam System memiliki dua buah antarmuka, yang
66 berbeda dengan awalan @. Antarmuka yang diberi awalan @ semua method dan propertinya bersifat hidden. Sebagai contoh, antarmuka void dan @void menunjuk pada kelas yang sama, berbeda dalam hal setiap anggota @void hidden dan ada anggota void yang bersifat visible. Selanjutnya hanya akan dibahas antarmuka yang bersifat visible. A. Kelas void Kelas void merupakan kelas induk dari semua kelas yang dibuat dalam program DOGI (seperi object dalam Java dan C#). Dinamakan void, dan bukan object, setidaknya dengan alasan-alasan berikut: • Pada C, C++ dan Java void adalah tipe data yang tidak mengandung apaapa. Perlakuan khusus terhadap void pada Java sepertinya tidak fair, karena sudah terdapat pembedaan kelas dengan tipe data, ditambah satu lagi “tipe data” void hanya untuk menunjukkan bahwa sebuah metoda tidak mengembalikan nilai. Karena itu dalam DOGI void dibuat sebagai kelas. Dan karena sifatnya yang tidak mengandung apa-apa, maka dibuatlah void sebagai kelas induk dari semuanya. Semua metoda dalam DOGI mengembalikan nilai. Jika tidak dituliskan secara eksplisit, nilai yang dikembalikan adalah #null. • Istilah object lebih bersifat konkret. Sedangkan kelas merupakan abstraksi. Dengan demikian, istilah object seharusnya lebih tepat digunakan sebagai nama instance, daripada nama kelas.
67 • Berdasarkan filosofi creatio ex nihilo, atau Allah menciptakan segala sesuatu dari tidak ada menjadi ada. Demikian juga setiap kelas diturunkan dari “ketiadaan” void. Konstruktor Kelas void memiliki hanya satu konstruktor, yang dipanggil tanpa parameter. Tugasnya adalah menciptakan sebuah objek dari kelas yang memanggilnya. Destruktor Destruktor kelas void bertugas untuk menghapus objek yang telah dibuat menggunakan konstruktor. Destruktor hanya akan menghapus objek yang bersangkutan jika reference count dari objek tersebut telah mencapai nol. Dengan kata lain, tidak ada lagi nama yang menunjuk objek tersebut. Metoda-metoda kelas void Metoda-metoda dalam kelas void diperlihatkan dalam Tabel 3.3. void self() void base() int refcount() int addRef() int release() void = (void) void assign(void) void assignTo(void) void applyTo(void, int)
void .refTo(void) void .->(void)
mengacu pada instance yang sedang aktif, dengan akses kepada metoda-metoda kelas aktif mengacu pada instance yang sedang aktif, dengan akses kepada metoda-metoda kelas induk mengembalikan jumlah reference count menambah reference count mengurangi reference count sama dengan assign(void) mengkopi objek lain menyediakan layanan jika objek lain berusaha mengkopi objek yang bersangkutan menyediakan layanan jika objek lain berusaha melakukan operasi terhadap objek yang bersangkutan mereferensikan nama pada suatu objek sama dengan refTo(void)
68 array : (void) void .return(void) _if .if(bool) _loop while(code cond) _loop loop(int n) _loop for(int i, int a, int b) _loop foreach(void x, array A)
menyediakan operasi bagi bentuk kondisi?a:b seperti pada bahasa C mengembalikan alur program pada metoda pemanggil, dan mengembalikan suatu objek menguji suatu kondisi, digunakan untuk seleksi perulangan dengan kondisi cond perulangan sebanyak nilai tertentu perulangan dengan counter i, dari nilai a hingga b perulangan dengan membaca array A dari awal hingga akhir array
Tabel 3.3 Daftar metoda yang terdapat dalam kelas void
B. Kelas data Kelas data dimaksudkan untuk menjadi kelas induk dari semua kelas yang bertugas menangani data atau bertindak sebagai tipe data. Kelas ini adalah turunan langsung dari void. C. Kelas number Kelas number dimaksudkan sebagai kelas induk dari kelas-kelas yang menangani bilangan, seperti int dan real. D. Kelas int Kelas int merupakan kelas yang bertugas menangani bilangan-bilangan
integer. Literal integer merupakan instansiasi dari kelas int. Kelas ini merupakan turunan langsung dari number. Metoda-metoda kelas int diperlihatkan pada Tabel 3.4. int + () int - () int + (int) real + (real) int – (int)
mengembalikan nilai tanpa perubahan mengembalikan nilai negatifnya menjumlahkan dengan bilangan integer menjumlahkan dengan bilangan real mengurangkan dengan bilangan integer
69 real – (real) int * (int) real * (real) real / (int) real / (real) bool == (int) bool != (int) bool > (int) bool < (int) bool >= (int) bool <= (int)
mengurangkan dengan bilangan real mengalikan dengan bilangan integer mengalikan dengan bilangan real membagi dengan bilangan integer membagi dengan bilangan real menguji kesamaan dengan integer lain menguji ketaksamaan dengan integer lain menguji apakah lebih besar dari integer lain menguji apakah lebih kecil integer lain menguji apakah lebih besar atau sama dengan integer lain menguji apakah lebih kecil atau sama dengan integer lain
Tabel 3.4 Daftar metoda yang terdapat dalam kelas int
E. Kelas bool Kelas bool adalah turunan dari data. Kelas ini berkaitan dengan literal
boolean pada bahasa DOGI. Metoda-metoda kelas bool diperlihatkan pada Tabel 3.5. bool ! () bool & (bool) bool bool bool void
| (bool) == (bool) != (bool) ? (void o)
void ? (array a)
mengembalikan negasi dari objek yang bersangkutan melakukan operasi konjungsi terhadap boolean lain melakukan operasi disjungsi terhadap boolean lain menguji kesamaan dengan boolean lain menguji ketaksamaan dengan boolean lain mengembalikan o jika objek bernilai benar, dan #null jika salah mengembalikan elemen pertama dari a jika kondisi benar, dan elemen kedua dari a jika kondisi salah
Tabel 3.5 Daftar metoda yang terdapat dalam kelas bool
F. Kelas real Kelas real digunakan untuk bilangan real, merupakan turunan dari kelas number.
70 Metoda-metoda kelas real diperlihatkan pada Tabel 3.6. real real real real real real real real real real bool bool bool bool bool
+ () - () + (int) + (real) – (int) – (real) * (int) * (real) / (int) / (real) == (real) != (real) > (real) < (real) >= (real)
bool <= (real)
mengembalikan nilai tanpa perubahan mengembalikan nilai negatifnya menjumlahkan dengan bilangan real menjumlahkan dengan bilangan real mengurangkan dengan bilangan real mengurangkan dengan bilangan real mengalikan dengan bilangan real mengalikan dengan bilangan real membagi dengan bilangan real membagi dengan bilangan real menguji kesamaan dengan real lain menguji ketaksamaan dengan real lain menguji apakah lebih besar dari real lain menguji apakah lebih kecil real lain menguji apakah lebih besar atau sama dengan real lain menguji apakah lebih kecil atau sama dengan real lain
Tabel 3.6 Daftar metoda yang terdapat dalam kelas real
G. Kelas string Kelas string merupakan turunan dari kelas data yang bertugas menangani data string. Metoda-metoda kelas string diperlihatkan pada tabel Tabel 3.8Tabel 3.7. int length() string + (string) bool == (string) bool != (string)
mengembalikan panjang string menggabungkan dengan string lain menguji kesamaan dengan string lain menguji ketaksamaan dengan string lain
Tabel 3.7 Daftar metoda yang terdapat dalam kelas string
H. Kelas array Kelas array merupakan turunan dari data yang berguna untuk menciptakan
array.
71 Metoda-metoda kelas array diperlihatkan pada tabel Tabel 3.8. int count() int setCount(int) void item(int i) void setItem(int i, void object)
mengembalikan banyaknya elemen array menentukan banyaknya elemen array mengembalikan elemen ke i mengganti elemen ke i dengan object
Tabel 3.8 Daftar metoda yang terdapat dalam kelas array
I. Kelas code Kelas code juga adalah turunan dari kelas data, ialah kelas yang menginstansiasikan semua kode yang ditulis dalam blok [ .. ] untuk kode yang hanya terdiri dari sebuah ekspresi, atau ditulis dalam blok begin..end untuk kode yang terdiri dari nol atau lebih ekspresi. Metoda-metoda kelas code diperlihatkan pada Tabel 3.9. code exec() void value() array else(code)
mengeksekusi kode mengembalikan hasil eksekusi kode membentuk array yang terdiri dari dua elemen bertipe code, untuk digunakan dalam struktur seleksi menggunakan if.
Tabel 3.9 Daftar metoda yang terdapat dalam kelas code
J. Kelas control Kelas control menurunkan kelas-kelas yang berguna dalam pembentukan struktur kontrol. Kelas control adalah turunan langsung dari kelas void. K. Kelas _if Kelas _if merupakan kelas turunan control yang bertugas untuk menangani struktur seleksi dengan menggunakan metoda if.
72 Kelas _if hanya memiliki sebuah metoda, yaitu then dalam dua bentuk, seperti diperlihatkan dalam Tabel 3.10. bool .then (code c) bool .then (array a)
jika bernilai benar, kerjakan c jika bernilai benar, kerjakan elemen pertama dari a, dan jika tidak, kerjakan elemen kedua dari a.
Tabel 3.10 Daftar metoda yang terdapat dalam kelas _if
L. Kelas _loop Kelas _loop merupakan kelas turunan control yang bertugas menangani struktur perulangan menggunakan metoda loop. Metoda-metoda kelas _loop diperlihatkan dalam Tabel 3.11. int .do(code)
melakukan perulangan terhadap kode yang diberikan, dan mengembalikan jumlah perulangan yang telah dilakukan
Tabel 3.11 Daftar metoda yang terdapat dalam kelas _loop
M. Kelas console Kelas console adalah turunan dari kelas void, ialah kelas yang bertugas untuk menangani input/output. Metoda-metoda kelas console diperlihatkan dalam Tabel 3.12. void void void void void void void void void
.<< (void) .>> (string) .>> (int) .>> (real) .>> (bool) .writeln (void) .readln (string) .readln (int) .readln (real)
void .readln (bool)
menuliskan suatu objek pada console membaca suatu string dari console membaca suatu integer dari console membaca suatu real dari console membaca suatu boolean dari console menuliskan suatu objek pada console (+newline) membaca suatu string dari console (+newline) membaca suatu integer dari console (+newline) membaca suatu real dari console (+newline) membaca suatu boolean dari console (+newline)
Tabel 3.12 Daftar metoda yang terdapat dalam kelas console
73
3.2 Perancangan kompiler DOGI Seperti telah disebutkan pada 1.2, untuk penyederhanaan perancangan kompiler, maka kompiler DOGI disatukan dengan eksekutornya (virtual machine). Kedua modul ini disatukan menjadi sebuah program. Untuk selanjutnya frasa “program DOGI” menunjuk pada program yang akan dibuat sebagai gabungan kompiler DOGI dan virtual machine. Program DOGI dibuat seluruhnya dengan C++, dengan bantuan program Flex untuk membuat scanner, serta Bison untuk membuat parser. Program DOGI versi Windows dikompilasi menggunakan Borland C++ 5.6.4 for Win32. Kompilasi dengan Minimalist GNU for Win32 versi 2.0.0 juga berhasil dilakukan. Untuk versi Linux dikompilasi menggunakan GNU C++ Compiler. 3.2.1 Spesifikasi rancangan Spesifikasi komputer yang digunakan dalam pembuatan dan pengujian program DOGI adalah: • Prosesor Pentium III 733 MHz • RAM 320MB • 2 Hard Disk berukuran 80GB dan 40GB • 2 Sistem operasi: a. Windows XP Professional Edition b. Linux dengan paket distribusi Mandrake 9.1 Program DOGI belum diuji dengan komputer dengan spesifikasi yang lain.
74 3.2.2 Antarmuka pemakai Program DOGI dijalankan dari command-line interpreter, dengan menuliskan: dogi { [] } []
Opsi yang disediakan adalah seperti diperlihatkan pada Tabel 3.13 (case-
insensitive). Jika kode sumber mengandung kesalahan, akan ditampilkan posisi dan jenis kesalahan yang terjadi. -i -s -e -d -v -x
menampilkan setiap instruksi yang sedang dieksekusi menampilkan state pada setiap eksekusi instruksi menampilkan isi stack pada setiap eksekusi instruksi gabungan dari -i, -s, dan -e menampilkan daftar isi package dalam file membuat dan mengeksekusi instance dari akses bernama
Tabel 3.13 Daftar opsi yang tersedia dalam program DOGI
3.2.3 Scanner Kode sumber scanner DOGI (dogi.lpp) dikompilasi dengan Flex untuk menghasilkan dogi.yy.cpp yang merupakan program dalam bahasa C++. Selanjutnya, dogi.yy.cpp dikompilasi menggunakan kompiler C++. Kode sumber scanner DOGI dapat dilihat pada Lampiran B. 3.2.4 Parser Kode sumber parser DOGI (dogi.ypp) dikompilasi dengan Bison untuk menghasilkan dogi.tab.hpp dan dogi.tab.cpp yang merupakan program dalam bahasa C++, untuk dikompilasi kembali dengan kompiler C++.
75 Kode sumber parser DOGI dapat dilihat pada Lampiran B, dan tata bahasanya dalam format BNF dapat dilihat pada Lampiran A. Dituliskan dalam format BNF dan bukan EBNF karena Bison hanya dapat mengenali BNF. 3.2.5 Aturan semantik tata bahasa DOGI Tidak setiap aturan semantik produksi tata bahasa DOGI akan dibahas di sini. Hanya definisi metoda dan ekspresi yang akan dibahas, karena merupakan bagian yang berhubungan erat dengan pembentukan kode antara. Setiap aturan semantik dideskripsikan dalam bentuk pseudocode. A. Definisi metoda dalam kelas Produksi methodCode → = expr methodCode → = … for index=number of arguments downto 1 do put POPA argumentindex endfor if (method is not class method) put POPCTX endif put KEEP … expr put RET
Produksi methodCode → begin exprList end methodCode → begin … for index=number of arguments downto 1 do put POPA argumentindex endfor
76 if (method is not class method) put POPCTX endif put KEEP … exprList end put PUSHN put RET
B. Ekspresi Baik expr, term, object, sendMsg maupun literal memiliki atributatribut sebagai berikut: • class untuk menyatakan tipe yang dikembalikan oleh nonterminalnonterminal tersebut. • instance untuk menyatakan apakah nonterminal adalah kelas atau
instance. Sedangkan method memiliki atribut instruction yang adalah instruksi yang diwakili oleh metoda yang bersangkutan secara langsung. Produksi expr → expr nextExprList expr → expr … put FLUSH … nextExprList
Produksi expr → term methodName expr if (term.class has method w/signature methodName(expr)) then if (term.instance = true) then
77 if (method is instruction) then put method.instruction else put CALL( term.class, index of method in term.class) endif else if (method is class method) then if (method is instruction) then put method.instruction else put CALL( term.class, index of method in term.class) endif else Error Message: Not class method. endif endif else Error Message: method not found. Endif
Produksi object → objectName if (objectName in localList) then put PUSHL (index of objectName in localList) object.class=class of objectName object.instance=true elseif (objectName in argList) then put PUSHA (index of objectName in argList) object.class=class of objectName object.instance=true
78 elseif (objectName in fieldList) then put PUSHO (index of objectName in fieldList) object.class=class of objectName object.instance=true elseif (objectName is className) then object.class=class of objectName object.instance=false else Error Message: objectName undeclared. Endif
Produksi object → integer put PUSHI integer.value
Produksi object → floatingPoint put PUSHF floatingPoint.value
Produksi object → boolean put PUSHB boolean.value
Produksi object → string put PUSHS string.value
Produksi object → code put PUSHC code.address
79 Produksi sendMsg → term . methodName (sendArgList) if (term.class has method w/signature methodName(sendArgList)) then if (term.instance = true) then if (method is instruction) then put method.instruction else put CALL( term.class, index of method in term.class) endif else if (method is class method) then if (method is instruction) then put method.instruction else put CALL( term.class, index of method in term.class) endif else Error Message: Not class method. endif endif else Error Message: method not found. Endif
Produksi sendMsg → methodName (sendArgList) dan sendMsg → . methodName (sendArgList) if (current.class has method w/signature methodName(sendArgList)) then
80 if (method is not class method) then put SELF endif if (method is instruction) then put method.instruction else put CALL( current.class, index of method in current.class) endif else Error Message: method not found. Endif
Produksi sendMsg → operatorName object if (object.class has method w/signature operatorName()) then if (method is instruction) then put method.instruction else put CALL( object.class, index of method in object.class) endif else Error Message: method not found. Endif
C. Literal code Produksi code → begin exprList end code → begin …
81 push current address to address stack put PUSHC (current address+4) put JMP (-1) … exprList end put FLUSH put PUSHN put RETC addr = pop address stack replace code at addr+3 with current address
Produksi code → [ expr ] code → begin … push current address to address stack put PUSHC (current address+4) put JMP (-1) … exprList end put RETC addr = pop address stack replace code at addr+3 with current address
3.3 Perancangan DOGIVM (DOGI Virtual Machine) 3.3.1 Instruksi-instruksi dasar DOGIVM Instruksi-instruksi yang terdapat pada DOGIVM diperlihatkan pada Tabel 3.14. Panjang instruksi menyatakan panjang instruksi dalam satuan doubleword (32 bit), jumlah pop menyatakan banyaknya anggota stack yang diambil oleh instruksi tersebut, dan return menyatakan banyaknya objek yang didorong oleh instruksi tersebut ke dalam stack.
82
instruksi
panjang (double word)
jumlah pop
return
NOP PUSH o PUSHL l PUSHA a PUSHI i PUSHF f PUSHB b PUSHS s PUSHC a
1 2 2 2 2 2 2 2 2
PUSHN POP o POPL l
1 2 2
1 1
POPA a
2
1
POPCTX
1
1
JMP a IFENTRY
2 1
1
1
IFT IFTE
1 1
2 2
1 1
LOOP LOOPW
1 1
1
1 1
LOOPI
1
1
1
LOOPA
1
2
1
LOOPF
1
3
1
LOOPDO CALL c m CALLC a NEW c m KILL RET RETC ENDX END KEEP FLUSH
1 3 2 3 1 1 1 1 1 1 1
2
1
1
1 1
DISCONST
1
1
1
ADD
1
2
1
1 1 1 1 1 1 1 1 1
1 *
deskripsi tidak ada operasi dorong objek o ke dalam stack dorong objek lokal l ke dalam stack dorong objek argumen a ke dalam stack dorong objek integer bernilai i ke dalam stack dorong objek real bernilai f ke dalam stack dorong objek boolean bernilai b ke dalam stack dorong objek string bernilai s ke dalam stack dorong objek code yang menunjuk alamat a ke dalam stack dorong objek null ke dalam stack ambil objek dari stack dan asosiasikan ke objek o ambil objek dari stack dan asosiasikan ke objek lokal l ambil objek dari stack dan asosiasikan ke objek argumen a ambil objek dari stack dan asosiasikan ke objek konteks lompat ke alamat a buat suatu instance _if berdasarkan kondisi yang diberikan objek pada puncak stack jalankan kode pada puncak stack jika benar pilih kode yang akan dijalankan dari array pada puncak stack buat suatu instance _loop buat suatu instance _loop berdasarkan yang diberikan objek pada puncak stack buat suatu instance _loop berdasarkan jumlah yang diberikan objek pada puncak stack buat suatu instance _loop berdasarkan array yang diberikan objek pada puncak stack, dan objek di bawahnya untuk menampung elemen array buat suatu instance _loop berdasarkan batas yang diberikan objek pada puncak stack dan objek di bawahnya eksekusi kode yang ada pada puncak stack memanggil metoda m dari kelas c mengeksekusi kode pada alamat a membuat instance dari kelas c dengan konstruktor m mendealokasikan objek pada puncak stack kembali pada alamat pemanggil (CALL) kembail pada alamat pemanggil (CALLC) menandai akhir dari kode menandai akhir dari kode menandai stack dengan pembatas menghapus isi stack dari puncak hingga pembatas yang dibuat dengan KEEP mengembalikan #true jika objek pada puncak stack dibuat dari literal mengembalikan hasil penjumlahan dari dua objek
83
SUB
1
2
1
MUL
1
2
1
DIV
1
2
1
NEG
1
1
1
POS AND
1 1
1 2
1 1
OR
1
2
1
NOT
1
1
1
ASSIGN REFTO ADDREF RELEASE REFCOUNT BASE SELF ALTER CMPE
1 1 1 1 1 1 1 1 1
2 2 1 1 1 1 1 2 2
1 1 1 1 1 1 1 1 1
CMPNE
1
2
1
CMPG
1
2
1
CMPL
1
2
1
CMPGE
1
2
1
CMPLE
1
2
1
SLEN ARRSCNT ARRGCNT
1 1 1
1 2 1
1 1 1
ARRSITEM ARRGITEM CONOUT CONIN
1 1 1 1
3 2 1 1
1 1 1 1
CONOUTN
1
1
1
pada puncak stack mengembalikan hasil pengurangan dari dua objek pada puncak stack mengembalikan hasil perkalian dari dua objek pada puncak stack mengembalikan hasil pembagian dari dua objek pada puncak stack mengembalikan negasi dari objek pada puncak stack (bilangan) tidak ada operasi mengembalikan hasil operasi and dari dua objek pada puncak stack mengembalikan hasil operasi or dari dua objek pada puncak stack mengembalikan negasi dari objek pada puncak stack (boolean) mengkopi dua objek pada puncak stack mereferensikan nama objek pada objek lain menambah reference count mengurangi reference count mengembalikan reference count mendorong instance ke dalam stack mendorong instance ke dalam stack mendorong array berisi dua objek pada puncak stack membandingkan dua objek pada puncak stack, dan mengembalikan #true jika keduanya sama, dan #false jika sebaliknya membandingkan dua objek pada puncak stack, dan mengembalikan #true jika keduanya tidak sama, dan #false jika sebaliknya membandingkan dua objek pada puncak stack, dan mengembalikan #true jika nilai objek pertama > nilai objek kedua, dan #false jika sebaliknya membandingkan dua objek pada puncak stack, dan mengembalikan #true jika nilai objek pertama < nilai objek kedua, dan #false jika sebaliknya membandingkan dua objek pada puncak stack, dan mengembalikan #true jika nilai objek pertama ≥ nilai objek kedua, dan #false jika sebaliknya membandingkan dua objek pada puncak stack, dan mengembalikan #true jika nilai objek pertama ≤ nilai objek kedua, dan #false jika sebaliknya mengembalikan panjang string pada puncak stack mengeset jumlah elemen array pada puncak stack mengembalikan jumlah elemen array pada puncak stack mengeset elemen array pada puncak stack mengembalikan elemen array pada puncak stack mencetak representasi dari objek pada puncak stack membaca representasi objek dari console dan mendorongnya ke dalam stack mencetak representasi dari objek pada puncak stack (+newline)
84 CONINN
1
1
1
CDEXEC CDVAL CDELSE CDQT
1 1 1 1
1 1 2 2
1 1 1 1
CDQTE
1
2
1
membaca representasi objek dari console dan mendorongnya ke dalam stack mengeksekusi kode yang terdapat pada puncak stack mengembalikan nilai yang dihasilkan oleh kode membentuk array berisi dua objek pada puncak stack mengembalikan objek pada puncak stack jika bernilai benar mengembalikan objek pertama pada array pada puncak stack jika bernilai benar
Tabel 3.14 Daftar instruksi DOGIVM
3.3.2 Siklus eksekusi instruksi Siklus eksekusi kode antara DOGI diperlihatkan dalam Gambar 3.21. Instruksi CALL • Dorong state konteks ke dalam state stack • Kosongkan state konteks, • Set posisi pada state konteks pada alamat metoda Instruksi RET • Pop state konteks dari state stack 3.3.3 State Suatu state dalam DOGIVM terdiri dari: • Sebuah daftar semua objek yang diinstansiasikan sejak program berjalan, • Sebuah state konteks – yaitu informasi mengenai posisi eksekusi, instance yang sedang aktif, semua field yang terdapat pada instance tersebut, argumen-argumen metoda yang sedang dieksekusi, dan objek-objek lokal metoda tersebut,
85 • Sebuah state stack yang menyimpan state konteks ketika ada pemanggilan suatu metoda, • Sebuah stack evaluasi, yang berisi objek-objek untuk digunakan dalam evaluasi, dan objek hasil evaluasi suatu ekspresi.
86
start
Reset posisi & kosongkan stack
Ambil instruksi
Tidak
Eksekusi instruksi
Majukan posisi pembacaan
Stack kosong?
Ya selesai
Gambar 3.21 Siklus fetch-execute DOGIVM