diff --git a/README.md b/README.md index db31fef..130bf62 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,33 @@ Repositori ini terdiri atas 2 cabang utama: - `main`: berisi kode spesifikasi Gara untuk versi Gara yang telah dirilis untuk khalayak umum - `lokal`: berisi kode spesifikasi untuk versi Gara yang sedang dalam tahap pengembangan + +## Konvensi Penulisan + +- Gunakan `sidang` dan kelas yang akan disidang +- Gunakan `tentang` dan metode/perilaku yang akan disidang +- Gunakan `saat` untuk menyidang perilaku yang sangat spesifik +- Gunakan `ia` untuk melakukan penyidangan tingkah laku sesuai kondisi +- Fungsi statis dideskripsikan dengan tanda `#`: + + ```gr + tentang("#dariKata/1", fn () { + ia("dapat berkata-kata", fn () { + // ... + }) + }) + ``` + +- Fungsi instansi dideskripsikan dengan tanda "." +- Fungsi yang sedang dites perlu dideskripsikan aritasnya, misal: `#baru/1`, `.desimal/1` +- Untuk ekspektasi masalah, gunakan `coba` - `tahan` sebagai berikut: + + ```gr + tuntut coba { + sesuatuYangBermasalah() + salah + } tahan (e) { + tuntut e.pesan == "pesan" + } == benar + ``` +- Tes fungsi diurutkan secara alfabetis diff --git a/sidang_coba.gr b/sidang_coba.gr index f74dd64..5009a05 100644 --- a/sidang_coba.gr +++ b/sidang_coba.gr @@ -95,7 +95,7 @@ sidang("Ekspresi coba", fn () { } tuntut masalah1.pesan() == "objek tipe Kelas tidak memiliki metode `baru` yang bisa dipanggil" - tuntut masalah2.pesan() == "hanya bisa dipanggil dengan 1 argumen" + tuntut masalah2.pesan() == "aripicu hanya bisa dipicu dengan 1 argumen" }) ia("variabel pengenal pada blok penahan bisa shadowing variabel dengan pengenal yang sama", fn () { diff --git a/sidang_deret.gr b/sidang_deret.gr index b967c51..5118eba 100644 --- a/sidang_deret.gr +++ b/sidang_deret.gr @@ -33,7 +33,7 @@ sidang(Deret, fn () { [].awal(1) } tahan (e) { tuntut e itu MasalahArgumen - tuntut e.pesan().berisi?("`awal` hanya bisa dipanggil dengan tanpa argumen") + tuntut e.pesan().berisi?("`awal` hanya bisa dipicu dengan tanpa argumen") benar } diff --git a/sidang_fungsi.gr b/sidang_fungsi.gr index 544e82b..970d4d1 100644 --- a/sidang_fungsi.gr +++ b/sidang_fungsi.gr @@ -207,7 +207,7 @@ sidang(Fungsi, fn () { salah } tahan (e) { tuntut e itu MasalahArgumen - tuntut e.pesan() == "hanya bisa dipanggil dengan 2 argumen" + tuntut e.pesan() == "aripicu hanya bisa dipicu dengan 2 argumen" } == benar }) diff --git a/sidang_integer.gr b/sidang_integer.gr index a60ece7..7498ace 100644 --- a/sidang_integer.gr +++ b/sidang_integer.gr @@ -18,6 +18,45 @@ sidang(Integer, fn () { tuntut !(satu itu Kelas) }) + tentang("penggunaan tanda hubung `_`", fn () { + ia("bisa dilakukan ditengah angka", fn () { + tuntut 1_2 == 12 + tuntut 123_000 == 123000 + tuntut 123_0 == 1230 + tuntut 123_456_789 == 123456789 + }) + + ia("tidak bisa dilakukan diawal angka", fn () { + tuntut coba { + _123 + salah + } tahan (e) { + tuntut e.pesan == "pengenal `_123` tidak ditemukan atau belum terdefinisikan" + benar + } == benar + }) + + ia("tidak bisa dilakukan diakhir angka", fn () { + tuntut coba { + eval!("123_") + salah + } tahan (e) { + tuntut e.pesan == "angka `123_` tidak dimengerti" + benar + } == benar + }) + + ia("tidak bisa bersambungan", fn () { + tuntut coba { + eval!("1__2") + salah + } tahan (e) { + tuntut e.pesan == "angka `1__2` tidak dimengerti" + benar + } == benar + }) + }) + ia(".mutlak() mengutus nilai non-negatif", fn () { tuntut 5.mutlak() == 5 tuntut -5.mutlak() == 5 diff --git a/sidang_kata.gr b/sidang_kata.gr index f0e42be..17808f9 100644 --- a/sidang_kata.gr +++ b/sidang_kata.gr @@ -152,7 +152,7 @@ sidang(Kata, fn () { ia(".cari(arg1) menemukan posisi dimana Kata dapat ditemukan dalam Kata untuk pertama kalinya", fn () { tuntut coba { "".cari(1) } tahan (e) { e.pesan().berisi?("tidak dapat menerima Integer") } - tuntut coba { "".cari("1", "2") } tahan (e) { e.pesan().berisi?("`cari` hanya bisa dipanggil dengan 1 argumen") } + tuntut coba { "".cari("1", "2") } tahan (e) { e.pesan().berisi?("`cari` hanya bisa dipicu dengan 1 argumen") } tuntut "foobar".cari("") == 0 tuntut "foobar".cari("foo") == 0 @@ -227,7 +227,7 @@ sidang(Kata, fn () { }) ia(".kecil() menjadikan seluruh karakter berhuruf kecil", fn () { - tuntut coba { "".kecil(1) } tahan (e) { e.pesan().berisi?("`kecil` hanya bisa dipanggil dengan tanpa argumen") } + tuntut coba { "".kecil(1) } tahan (e) { e.pesan().berisi?("`kecil` hanya bisa dipicu dengan tanpa argumen") } tuntut "ABC".kecil() == "abc" tuntut "Abc".kecil() == "abc" @@ -280,7 +280,7 @@ sidang(Kata, fn () { }) ia(".panjang() memberi informasi jumlah karakter dalam kata", fn () { - tuntut coba { "".panjang(1) } tahan (e) { e.pesan().berisi?("`panjang` hanya bisa dipanggil dengan tanpa argumen") } + tuntut coba { "".panjang(1) } tahan (e) { e.pesan().berisi?("`panjang` hanya bisa dipicu dengan tanpa argumen") } tuntut "".panjang() == 0 tuntut "1".panjang() == 1 @@ -309,7 +309,7 @@ sidang(Kata, fn () { }) ia(".rapi() menghapus seluruh karakter spasi diawal dan diakhir Kata", fn () { - tuntut coba { "".rapi(1) } tahan (e) { e.pesan().berisi?("`rapi` hanya bisa dipanggil dengan tanpa argumen") } + tuntut coba { "".rapi(1) } tahan (e) { e.pesan().berisi?("`rapi` hanya bisa dipicu dengan tanpa argumen") } tuntut " Gara ".rapi() == "Gara" tuntut " G a r a ".rapi() == "G a r a" diff --git a/sidang_kelas.gr b/sidang_kelas.gr index 7090362..1865edb 100644 --- a/sidang_kelas.gr +++ b/sidang_kelas.gr @@ -25,6 +25,42 @@ sidang(Kelas, fn () { tuntut a.a == 12 }) + tentang("sifat `tetap`", fn () { + ia("membuat kelas tidak bisa diperkaya setelah pendefinisian", fn () { + tidakAda!(fn () { A }) + + kelas tetap A { + ada a + } + + ada a = A.baru + tuntut a.a == nil + + tuntut coba { + kelas A { ada b } + salah + } tahan (e) { + tuntut e.pesan == "kelas `A` tidak dapat diperkaya karena telah bersifat tetap" + benar + } == benar + }) + + ia("tidak bisa disematkan pada kelas yang telah terdefinisikan", fn () { + tidakAda!(fn () { A }) + + kelas A {} + tuntut A.tetap? == salah + + tuntut coba { + kelas tetap A {} + salah + } tahan (e) { + tuntut e.pesan == "dilarang menambahkan sifat tetap ke kelas `A` yang telah didefinisikan" + benar + } == benar + }) + }) + tentang("nama", fn () { ia("harus diawali huruf kapital", fn () { tuntut coba { @@ -81,6 +117,19 @@ sidang(Kelas, fn () { tuntut 1.kelas() != Angka }) + tentang(".tetap?", fn () { + ia("mengutus `benar` jika kelas bersifat tetap", fn () { + tidakAda!(fn () { A }) + tidakAda!(fn () { B }) + + kelas tetap A {} + kelas B {} + + tuntut A.tetap? == benar + tuntut B.tetap? == salah + }) + }) + tentang("metode", fn () { ia("bisa dipanggil dengan ini", fn () { tidakAda!(fn () { A }) @@ -1010,7 +1059,7 @@ sidang(Kelas, fn () { salah } tahan (e) { tuntut e itu Masalah - tuntut e.pesan() == "`sapa` adalah metode pribadi kelas Penyapa yang hanya bisa dipanggil dari dalam" + tuntut e.pesan() == "`sapa` adalah metode pribadi kelas Penyapa yang hanya bisa dipicu dari dalam" benar } == benar @@ -1045,7 +1094,7 @@ sidang(Kelas, fn () { A.baru().b() salah } tahan (e) { - tuntut e.pesan() == "`a` adalah metode pribadi kelas A yang hanya bisa dipanggil dari dalam" + tuntut e.pesan() == "`a` adalah metode pribadi kelas A yang hanya bisa dipicu dari dalam" benar } == benar }) diff --git a/sidang_kelas_penurunan.gr b/sidang_kelas_penurunan.gr index 4f7d7c3..fb1e73e 100644 --- a/sidang_kelas_penurunan.gr +++ b/sidang_kelas_penurunan.gr @@ -32,7 +32,37 @@ sidang("Penurunan `kelas`", fn () { tuntut A2.moyang.berisi?(Objek) == benar }) - tentang("kelas telah terdefinisikan", fn () { + ia("bisa bersifat tetap", fn () { + tidakAda!(fn () { A }) + tidakAda!(fn () { B }) + + kelas A { ada a = "a" } + kelas tetap B -> A { ada b = "b" } + + tuntut B.tetap? + ada b = B.baru + tuntut b.a == "a" + tuntut b.b == "b" + }) + + saat("menurun dari kelas yang bersifat tetap", fn () { + ia("tidak bisa dilakukan", fn () { + tidakAda!(fn () { A }) + tidakAda!(fn () { B }) + + kelas tetap A {} + + tuntut coba { + kelas B -> A {} + salah + } tahan (e) { + tuntut e.pesan == "kelas punca `A` tidak dapat diturunkan karena telah bersifat tetap" + benar + } == benar + }) + }) + + saat("kelas telah terdefinisikan", fn () { ia("bermasalah jika kelas punca berbeda", fn () { tuntut coba { kelas Masalah -> Riil {} @@ -390,7 +420,7 @@ sidang("Penurunan `kelas`", fn () { B.baru().a() salah } tahan (e) { - tuntut e.pesan == "`a` adalah metode pribadi kelas B yang hanya bisa dipanggil dari dalam" + tuntut e.pesan == "`a` adalah metode pribadi kelas B yang hanya bisa dipicu dari dalam" benar } == benar }) @@ -547,7 +577,7 @@ sidang("Penurunan `kelas`", fn () { B.a() salah } tahan (e) { - tuntut e.pesan == "`a` adalah fungsi statis bersifat pribadi kelas B yang hanya bisa dipanggil dari dalam" + tuntut e.pesan == "`a` adalah fungsi statis bersifat pribadi kelas B yang hanya bisa dipicu dari dalam" benar } == benar }) diff --git a/sidang_kelas_statis.gr b/sidang_kelas_statis.gr index 71448eb..64e870c 100644 --- a/sidang_kelas_statis.gr +++ b/sidang_kelas_statis.gr @@ -664,7 +664,7 @@ sidang("Statis pada `kelas`", fn () { A.b() salah } tahan (e) { - tuntut e.pesan() == "`b` adalah fungsi statis bersifat pribadi kelas A yang hanya bisa dipanggil dari dalam" + tuntut e.pesan() == "`b` adalah fungsi statis bersifat pribadi kelas A yang hanya bisa dipicu dari dalam" benar } == benar }) @@ -745,7 +745,7 @@ sidang("Statis pada `kelas`", fn () { A.baru() salah } tahan (e) { - tuntut e.pesan() == "`baru` adalah fungsi statis bersifat pribadi kelas A yang hanya bisa dipanggil dari dalam" + tuntut e.pesan() == "`baru` adalah fungsi statis bersifat pribadi kelas A yang hanya bisa dipicu dari dalam" benar } == benar }) diff --git a/sidang_operator.gr b/sidang_operator.gr index 727fc41..53fd8cd 100644 --- a/sidang_operator.gr +++ b/sidang_operator.gr @@ -1333,4 +1333,223 @@ sidang("Operator", fn () { }) }) }) + + tentang("|> (operasi salur)", fn () { + ia("dapat digunakan tanpa argumen tambahan", fn () { + ada tambah5 = fn (arg1) { arg1 + 5 } + ada a = 1 |> fn (arg1){ arg1 + 5 }() |> tambah5() + tuntut a == 11 + }) + + ia("dapat digunakan dengan fungsi statis dalam kelas", fn () { + tidakAda!(fn () { Matku }) + + kelas Matku { + fn sta tambah(a1, a2) { a1 + a2 } + fn sta kurang(a1, a2) { a1 - a2 } + fn sta kali(a1, a2) { a1 * a2 } + fn sta bagi(a1, a2) { a1 / a2 } + fn sta tambah5(a1) { a1 + 5 } + } + + ada angka = 1 + |> Matku.tambah5() + |> Matku.kali(2) + |> Matku.kurang(2) + |> Matku.kali(3) + |> Matku.bagi(10) + + tuntut angka == 3 + }) + + ia("memiliki precedence yang rendah", fn () { + tuntut (1 + 2 |> fn(a) { a + 1 }()) == 4 + tuntut (!benar |> fn (b) { !b }()) == benar + tuntut (!benar |> fn (b) { !b }() |> fn (b) { nil }()) == nil + }) + + ia("dapat melempar masalah", fn () { + tuntut coba { + 1 + nil |> fn (x){ x }() + salah + } tahan (e) { + tuntut e.pesan == "tidak dapat menerima Nirdefinisi" + benar + } == benar + + tuntut coba { + 1 |> fn (x){ x + nil }() + salah + } tahan (e) { + tuntut e.pesan == "tidak dapat menerima Nirdefinisi" + benar + } == benar + }) + + saat("sisi kanan bukan fungsi", fn () { + ia("akan bermasalah", fn () { + tuntut coba { + 1 |> Kelas + salah + } tahan (e) { + tuntut e.pesan == "sisi kanan operasi salur (`|>`) harus pemanggilan aripicu" + benar + } == benar + }) + }) + + saat("sisi kanan adalah fungsi yang tidak menerima argumen", fn () { + ia("akan bermasalah", fn () { + tuntut coba { + 1 |> fn(){}() + salah + } tahan (e) { + tuntut e.pesan == "aripicu hanya bisa dipicu dengan tanpa argumen" + benar + } == benar + + tuntut coba { + 1 |> fn antahBerantah(){}() + salah + } tahan (e) { + tuntut e.pesan == "`antahBerantah` hanya bisa dipicu dengan tanpa argumen" + benar + } == benar + }) + }) + + saat("digunakan dengan kondisi bercabang", fn () { + saat("digunakan dengan ekspresi jika-lain", fn () { + saat("cabang memiliki satu pernyataan", fn () { + ia("bisa dilakukan tanpa masalah", fn () { + ada a = 1 |> jika (benar) { fn(n){n+1}() } lain { fn(n){n+2}() } + tuntut a == 2 + + ada a = 1 |> jika (salah) { fn(n){n+1}() } lain { fn(n){n+2}() } + tuntut a == 3 + }) + }) + + saat("cabang memiliki lebih dari satu pernyataan", fn () { + ia("tidak bisa dilakukan", fn () { + tuntut coba { + ada a = 1 |> jika (benar) { ada a; fn(n){n+1}() } lain { ada b; fn(n){n+2}() } + salah + } tahan (e) { + tuntut e.pesan == "cabang kondisi untuk operasi salur hanya dapat berisi satu pernyataan" + benar + } == benar + }) + }) + }) + saat("digunakan dengan operasi tigas (?:)", fn () { + saat("tidak memiliki cabang alternatif", fn () { + ia("bermasalah", fn () { + tuntut coba { + eval!("1 ? benar") + salah + } tahan (e) { + tuntut e.pesan == "seharusnya menjumpai `:`, tapi malah `UJUNG`" + benar + } == benar + }) + }) + + ia("bisa dilakukan tanpa masalah", fn () { + ada fnA = fn (n) { n + 3 }, + fnB = fn (n) { n + 5 }, + fnC = fn (n) { n + 7 }, + fnD = fn (n) { n + 11 }, + fnE = fn (n) { n + 13 }, + fnF = fn (n) { n + 17 } + + ada a = 1 + 1 |> benar ? fnA() : fnB() + tuntut a == 5 + + ada a = 1 + 1 |> salah ? fnA() : fnB() + tuntut a == 7 + + ada a = 1 + 1 + |> salah ? fnA() : fnB() + |> 1 == 1 ? fnC() : fnD() + + tuntut a == 14 + + ada a = 1 + 1 + |> salah ? fnA() : fnB() + |> salah ? fnC() : fnD() + |> 1 == 1 ? fnE() : fnF() + + tuntut a == 31 + + ada a = 1 + 1 + |> salah ? fnA() : fnB() + |> salah ? fnC() : fnD() + |> 1 != 1 ? fnE() : fnF() + + tuntut a == 35 + }) + + saat("kondisi dinegasikan", fn () { + ia("tetap bisa dioperasikan dengan benar", fn () { + tuntut !benar ? "0" : "1" == "1" + tuntut !salah ? "0" : "1" == "0" + }) + }) + }) + }) + }) + + tentang("?: (operasi tigas)", fn () { + ia("mengutus cabang benar jika benar", fn () { + tuntut 1 ? "1" : "0" == "1" + + ada x = fn () { benar } + tidakAda!(fn () { A }) + kelas A { fn sta x() { benar }} + + tuntut 1 && (benar || salah) && benar && (x() && A.x()) ? "1" : "0" == "1" + }) + + ia("mengutus cabang salah jika salah", fn () { + tuntut nil ? "1" : "0" == "0" + + ada x = fn () { salah } + tidakAda!(fn () { A }) + kelas A { fn sta x() { salah }} + + tuntut 1 && (benar || salah) && benar && (x() && A.x()) && salah ? "1" : "0" == "0" + }) + + ia("bisa multi-baris", fn () { + ada a = 1 == 1 ? + "1" : "0" + + tuntut a == "1" + + ada a = 1 == 2 ? + "1" : + "0" + + tuntut a == "0" + + ada a = 2 == 2 + ? "1" + : "0" + + tuntut a == "1" + }) + + saat("digunakan dengan operasi penempatan", fn () { + ada a = 1 > 0 ? "1" : "0" + tuntut a == "1" + + ada a = 1 > 2 ? "1" : "2" + tuntut a == "2" + + ada a = 4 > 3 ? "0" : "1", b = 3 > 4 ? "0" : "1" + tuntut a == "0" + tuntut b == "1" + }) + }) }) diff --git a/sidang_rangkap_pabrik.gr b/sidang_rangkap_pabrik.gr index 7d183dc..309d0c9 100644 --- a/sidang_rangkap_pabrik.gr +++ b/sidang_rangkap_pabrik.gr @@ -10,7 +10,7 @@ sidang(Rangkap::Pabrik, fn () { salah } tahan (e) { tuntut e itu MasalahMetode - tuntut e.pesan == "`baru` adalah fungsi statis bersifat pribadi kelas Rangkap::Pabrik yang hanya bisa dipanggil dari dalam" + tuntut e.pesan == "`baru` adalah fungsi statis bersifat pribadi kelas Rangkap::Pabrik yang hanya bisa dipicu dari dalam" benar } == benar }) diff --git a/sidang_refleksi.gr b/sidang_refleksi.gr index 468f3e8..13db291 100644 --- a/sidang_refleksi.gr +++ b/sidang_refleksi.gr @@ -50,6 +50,8 @@ sidang(Refleksi, fn () { saat("metode belum terdefinisikan", fn () { ia("akan didefinisikan", fn () { + tidakAda!(fn () { A }) + kelas A {} ada a1 = A.baru() ada a2 = A.baru() @@ -62,6 +64,25 @@ sidang(Refleksi, fn () { tuntut a1.hmm != a2.hmm }) + saat("kelas bersifat tetap", fn () { + ia("dapat didefinisikan", fn () { + tidakAda!(fn () { A }) + + kelas tetap A {} + tuntut A.tetap? + + ada a1 = A.baru() + ada a2 = A.baru() + + Refleksi.terapkan!(a1, "hmm", fn () { "hmma1" }) + Refleksi.terapkan!(a2, "hmm", fn () { "hmma2" }) + + tuntut a1.hmm == "hmma1" + tuntut a2.hmm == "hmma2" + tuntut a1.hmm != a2.hmm + }) + }) + ia("termasuk dalam daftar metode objek tersebut", fn () { ada a = 123 tuntut a.metode.berisi?("a") == salah @@ -163,6 +184,26 @@ sidang(Refleksi, fn () { tuntut A.baru().a() == "A" }) + saat("kelas bersifat tetap", fn () { + ia("bisa ditimpa", fn () { + tidakAda!(fn () { A }) + + kelas tetap A { + fn a() { "A" } + } + + tuntut A.tetap? == benar + + ada a = A.baru() + tuntut a.a() == "A" + + Refleksi.terapkan!(a, "a", fn () { "a" }) + tuntut a.a() == "a" + + tuntut A.baru().a() == "A" + }) + }) + saat("metode asal berupa metode pribadi", fn () { ia("menjadi dapat diakses secara umum", fn () { tidakAda!(fn () { A }) @@ -209,6 +250,20 @@ sidang(Refleksi, fn () { }) saat("membayangi fungsi statis", fn () { + ia("tidak dapat dilakukan jika kelas bersifat tetap", fn () { + tidakAda!(fn () { A }) + + kelas tetap A {} + + tuntut coba { + Refleksi.terapkan!(A, "a", fn () { "A" }) + salah + } tahan (e) { + tuntut e.pesan == "dilarang melakukan penerapan pada kelas `A` yang bersifat tetap" + benar + } == benar + }) + ia("dapat menggantikan pemanggilan fungsi statis", fn () { tidakAda!(fn () { A }) diff --git a/sidang_riil.gr b/sidang_riil.gr index d586bb5..87128c6 100644 --- a/sidang_riil.gr +++ b/sidang_riil.gr @@ -10,6 +10,45 @@ sidang("Riil", fn () { tuntut Riil.PI >= 3.14 }) + tentang("penggunaan tanda hubung `_`", fn () { + ia("bisa dilakukan ditengah angka", fn () { + tuntut 123_456.789 == 123456.789 + tuntut 123.456_789 == 123.456789 + tuntut 123.45_67_89 == 123.456789 + tuntut 12_3.45_67_89 == 123.456789 + }) + + ia("tidak bisa dilakukan diawal angka", fn () { + tuntut coba { + eval!("_123.456") + salah + } tahan (e) { + tuntut e.pesan == "seharusnya menjumpai `IDENTITAS`, tapi malah `INTEGER`" + benar + } == benar + }) + + ia("tidak bisa dilakukan diakhir angka", fn () { + tuntut coba { + eval!("123.456_") + salah + } tahan (e) { + tuntut e.pesan == "angka `123.456_` tidak dimengerti" + benar + } == benar + }) + + ia("tidak bisa bersambungan", fn () { + tuntut coba { + eval!("123.45__6") + salah + } tahan (e) { + tuntut e.pesan == "angka `123.45__6` tidak dimengerti" + benar + } == benar + }) + }) + tentang(".desimal(arg1)", fn () { ada angka = 12650.5011872336272724 ada angkaAsli = 12650.5011872336272724 diff --git a/sidang_sintaksis.gr b/sidang_sintaksis.gr index f2a1683..cf24fc7 100644 --- a/sidang_sintaksis.gr +++ b/sidang_sintaksis.gr @@ -20,7 +20,7 @@ sidang("Sintaksis", fn () { salah } tahan (e) { tuntut e itu MasalahEksekusi - tuntut e.pesan() == "bukan fungsi: 2" + tuntut e.pesan() == "bukan fungsi: \"2\"" } })