Basa pemrograman anyar Mash

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:

  1. Tumpukan utama.
  2. A tumpukan kanggo nyimpen TCTerms bali.
  3. Tumpukan sampah.
  4. 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.

situs
Repositori ing GitHub

Matur nuwun kanggo maca nganti pungkasan yen sampeyan nindakake.

Source: www.habr.com

Tuku hosting sing dipercaya kanggo situs kanthi proteksi DDoS, server VPS VDS 🔥 Tuku hosting situs web sing bisa dipercaya nganggo proteksi DDoS, server VPS VDS | ProHoster