Wis pirang-pirang taun aku nyoba ngembangake basa pamrograman dhewe. Aku pengin nggawe, miturut pendapatku, basa sing paling gampang, fungsional lan trep.
Ing artikel iki, aku pengin nyorot tahapan utama karyaku lan, kanggo miwiti, njlèntrèhaké konsep basa sing digawé lan implementasine sing pisanan, sing saiki lagi ditindakake.
Ayo kula ngomong sadurunge aku nulis kabeh proyek ing Free Pascal, amarga ... program ing bisa nyawiji kanggo nomer ageng platform, lan compiler dhewe mrodhuksi binar banget optimized (Aku ngumpulake kabeh komponen saka project karo flag O2).
Runtime basa
Kaping pisanan, sampeyan kudu ngomong babagan mesin virtual sing kudu daktulis kanggo mbukak aplikasi ing mangsa ngarep ing basaku. Aku mutusaké kanggo ngleksanakake arsitektur tumpukan, mbok menawa, amarga iku cara paling gampang. Aku ora nemu siji artikel normal babagan carane nindakake iki ing basa Rusia, supaya sawise familiarize dhewe karo materi basa Inggris, aku lungguh mudhun kanggo ngrancang lan nulis sepedha dhewe. Salajengipun kula badhe ngaturaken gagasan lan pangrembakanipun ingkang “maju” wonten ing bab punika.
Implementasi tumpukan
Temenan, ing ndhuwur VM ana tumpukan. Ing implementasine saya kerjane ing blok. Ateges iki minangka array prasaja penunjuk lan variabel kanggo nyimpen indeks ing ndhuwur tumpukan.
Nalika diwiwiti, susunan 256 unsur digawe. Yen pointer liyane di-push menyang tumpukan, ukuran mundhak dening 256 unsur sabanjuré. Mulane, nalika mbusak unsur saka tumpukan, ukurane disetel.
VM nggunakake sawetara tumpukan:
- Tumpukan utama.
- A tumpukan kanggo nyimpen TCTerms bali.
- Tumpukan sampah.
- Coba / nyekel / pungkasanipun mblokir tumpukan handler.
Konstanta lan Variabel
Iki prasaja. Konstanta ditangani ing potongan kode cilik sing kapisah lan kasedhiya ing aplikasi mangsa ngarep liwat alamat statis. Variabel minangka susunan penunjuk kanthi ukuran tartamtu, akses menyang sel kasebut ditindakake kanthi indeks - i.e. alamat statis. Variabel bisa di-push menyang ndhuwur tumpukan utawa diwaca saka ing kono. Bener, amarga Nalika variabel kita ateges nyimpen pointer menyang nilai ing memori VM, basa kasebut didominasi kanthi nggarap penunjuk implisit.
Pengumpul sampah
Ing VM sandi iku semi-otomatis. Sing. pangembang dhewe nemtokaken nalika nelpon kolektor uwuh. Ora bisa nggunakake counter pointer biasa, kaya ing Python, Perl, Ruby, Lua, etc. Iki dileksanakake liwat sistem marker. Sing. nalika variabel dimaksudaké kanggo diutus Nilai sak wentoro, pitunjuk kanggo Nilai iki ditambahake menyang tumpukan kolektor uwuh kang. Ing mangsa ngarep, kolektor cepet mbukak dhaptar pitunjuk sing wis disiapake.
Nangani nyoba / nyekel / pungkasanipun pamblokiran
Kaya ing basa modern, penanganan pengecualian minangka komponen penting. Inti VM kebungkus ing try..pemblokiran nyekel, kang bisa bali menyang eksekusi kode sawise keno pangecualian dening push sawetara informasi bab iku ing tumpukan. Ing kode aplikasi, sampeyan bisa nemtokake nyoba / nyekel / pungkasan pamblokiran kode, nuduhake titik entri ing nyekel (pengecualian handler) lan pungkasan / pungkasan (mburi blok).
Multithreading
Didhukung ing tingkat VM. Iku prasaja lan trep kanggo nggunakake. Kerjane tanpa sistem interrupt, supaya kode kudu dieksekusi ing sawetara thread kaping pirang-pirang luwih cepet, mungguh.
Pustaka eksternal kanggo VM
Ora ana cara kanggo nindakake tanpa iki. VM ndhukung impor, padha karo carane dileksanakake ing basa liyane. Sampeyan bisa nulis bagéan saka kode ing Mash lan bagéan saka kode ing basa pribumi, banjur nyambung menyang siji.
Penerjemah saka basa Mash tingkat dhuwur menyang bytecode kanggo VM
basa madya
Kanggo cepet nulis penerjemah saka basa kompleks menyang kode VM, aku pisanan ngembangake basa penengah. Asil ana tontonan elek kaya assembler sing ora ana titik tartamtu ing considering kene. Aku mung bakal ngomong yen ing tingkat iki penerjemah ngolah paling konstanta lan variabel, ngetung alamat statis lan alamat titik entri.
Arsitèktur penerjemah
Aku ora milih arsitektur paling apik kanggo implementasine. Penerjemah ora nggawe wit kode, kaya sing ditindakake dening penerjemah liyane. Dheweke katon ing awal struktur. Sing. yen potongan kode sing diurai katon kaya "nalika <kondisi>:", mula jelas yen iki minangka konstruksi loop while lan kudu diproses minangka konstruksi loop while. Soko kaya switch-kasus Komplek.
Thanks kanggo solusi arsitektur iki, penerjemah ora cepet banget. Nanging, ease saka modifikasi wis tambah akeh. Aku nambahake struktur sing dibutuhake luwih cepet tinimbang kopiku bisa adhem. Dhukungan OOP lengkap ditindakake kurang saka seminggu.
Optimasi kode
Ing kene, mesthine bisa ditindakake kanthi luwih apik (lan bakal ditindakake, nanging mengko, sanalika bisa ditindakake). Nganti saiki, pangoptimal mung ngerti carane ngilangi kode, konstanta lan impor sing ora digunakake saka perakitan. Uga, sawetara konstanta kanthi nilai sing padha diganti karo siji. Mekaten.
Basa mash
Konsep dhasar basa
Ide utama yaiku ngembangake basa sing paling fungsional lan prasaja. Aku sing pembangunan copes karo sawijining tugas karo bang.
Blok kode, prosedur lan fungsi
Kabeh konstruksi ing basa dibukak nganggo titik loro. : lan ditutup dening operator ends.
Prosedur lan fungsi diumumake minangka proc lan func. Argumentasi kasebut kadhaptar ing kurung. Kabeh kaya basa liyane.
Operator bali sampeyan bisa bali Nilai saka fungsi, operator break ngijini sampeyan kanggo metu saka prosedur / fungsi (yen njaba puteran).
Kode sampel:
...
func summ(a, b):
return a + b
end
proc main():
println(summ(inputln(), inputln()))
end
Desain sing Didhukung
- Loops: kanggo..pungkasan, nalika..pungkasan, nganti..pungkasan
- Kondisi: yen..[liyane..]pungkasan, ganti..[kasus..akhir..][liyane..]pungkasan
- Metode: proc <name>():... end, func <name>():... end
- Label & goto: <jeneng>:, mlumpat <jeneng>
- Enumerations Enum lan susunan pancet.
Variabel
Penerjemah bisa nemtokake kanthi otomatis, utawa yen pangembang nulis var sadurunge nemtokake.
Tuladha kode:
a ?= 10
b ?= a + 20
var a = 10, b = a + 20
Variabel global lan lokal didhukung.
OOP
Inggih, kita wis teka menyang topik sing paling enak. Mash ndhukung kabeh paradigma pemrograman berorientasi obyek. Sing. kelas, warisan, polimorfisme (kalebu dinamis), refleksi otomatis dinamis lan introspeksi (lengkap).
Tanpa ado maneh, luwih becik menehi conto kode.
Kelas sing prasaja lan nggarap:
uses <bf>
uses <crt>
class MyClass:
var a, b
proc Create, Free
func Summ
end
proc MyClass::Create(a, b):
$a = new(a)
$b = new(b)
end
proc MyClass::Free():
Free($a, $b)
$rem()
end
func MyClass::Summ():
return $a + $b
end
proc main():
x ?= new MyClass(10, 20)
println(x->Summ())
x->Free()
end
Bakal output: 30.
Warisan lan polimorfisme:
uses <bf>
uses <crt>
class MyClass:
var a, b
proc Create, Free
func Summ
end
proc MyClass::Create(a, b):
$a = new(a)
$b = new(b)
end
proc MyClass::Free():
Free($a, $b)
$rem()
end
func MyClass::Summ():
return $a + $b
end
class MyNewClass(MyClass):
func Summ
end
func MyNewClass::Summ():
return ($a + $b) * 2
end
proc main():
x ?= new MyNewClass(10, 20)
println(x->Summ())
x->Free()
end
Bakal output: 60.
Kepiye babagan polimorfisme dinamis? Ya, iki refleksi!:
uses <bf>
uses <crt>
class MyClass:
var a, b
proc Create, Free
func Summ
end
proc MyClass::Create(a, b):
$a = new(a)
$b = new(b)
end
proc MyClass::Free():
Free($a, $b)
$rem()
end
func MyClass::Summ():
return $a + $b
end
class MyNewClass(MyClass):
func Summ
end
func MyNewClass::Summ():
return ($a + $b) * 2
end
proc main():
x ?= new MyClass(10, 20)
x->Summ ?= MyNewClass::Summ
println(x->Summ())
x->Free()
end
Bakal output: 60.
Saiki ayo sedhela kanggo introspeksi nilai lan kelas sing prasaja:
uses <bf>
uses <crt>
class MyClass:
var a, b
end
proc main():
x ?= new MyClass
println(BoolToStr(x->type == MyClass))
x->rem()
println(BoolToStr(typeof(3.14) == typeReal))
end
Bakal output: bener, bener.
Babagan operator assignment lan pitunjuk eksplisit
Operator ?= digunakake kanggo nemtokake variabel pointer menyang nilai ing memori.
Operator = ngganti nilai ing memori nggunakake pointer saka variabel.
Lan saiki sethitik babagan pitunjuk eksplisit. Aku ditambahake menyang basa supaya padha ana.
@<variabel> - njupuk pointer eksplisit menyang variabel.
?<variable> — entuk variabel kanthi pointer.
@= - nemtokake nilai menyang variabel kanthi pointer eksplisit.
Kode sampel:
uses <bf>
uses <crt>
proc main():
var a = 10, b
b ?= @a
PrintLn(b)
b ?= ?b
PrintLn(b)
b++
PrintLn(a)
InputLn()
end
Bakal output: sawetara nomer, 10, 11.
Coba..[nyekel..][akhire..]pungkas
Kode sampel:
uses <bf>
uses <crt>
proc main():
println("Start")
try:
println("Trying to do something...")
a ?= 10 / 0
catch:
println(getError())
finally:
println("Finally")
end
println("End")
inputln()
end
Rencana kanggo masa depan
Aku terus ndeleng lan ndeleng GraalVM & Truffle. Lingkungan runtime saya ora duwe compiler JIT, mula saka segi kinerja saiki mung kompetitif karo Python. Mugi sing aku bakal bisa kanggo ngleksanakake kompilasi JIT adhedhasar GraalVM utawa LLVM.
gudang
Sampeyan bisa muter karo pembangunan lan tindakake project dhewe.
Matur nuwun kanggo maca nganti pungkasan yen sampeyan nindakake.
Source: www.habr.com
