Í nokkur ár reyndi ég fyrir mér að þróa mitt eigið forritunarmál. Ég vildi búa til, að mínu mati, einfaldasta, fullkomlega virka og þægilegasta tungumálið sem mögulegt er.
Í þessari grein vil ég draga fram helstu stig vinnu minnar og til að byrja með lýsa skapaðri hugmynd um tungumálið og fyrstu útfærslu þess sem ég er að vinna að núna.
Leyfðu mér að segja fyrirfram að ég skrifaði allt verkefnið í Free Pascal, vegna þess að... hægt er að setja saman forrit á því fyrir gríðarlegan fjölda kerfa og þýðandinn sjálfur framleiðir mjög bjartsýni tvöfalda (ég safna öllum hlutum verkefnisins með O2 fánanum).
Tungumál keyrslutími
Fyrst af öllu, það er þess virði að tala um sýndarvélina sem ég þurfti að skrifa til að keyra framtíðarforrit á mínu tungumáli. Ég ákvað að innleiða stafla arkitektúr, kannski, vegna þess að það var auðveldasta leiðin. Ég fann ekki eina eðlilega grein um hvernig á að gera þetta á rússnesku, svo eftir að hafa kynnt mér ensku efnið settist ég að því að hanna og skrifa mitt eigið hjól. Næst mun ég kynna „háþróaðar“ hugmyndir mínar og þróun í þessu máli.
Stafla útfærsla
Augljóslega er staflan efst á VM. Í útfærslu minni virkar það í kubbum. Í meginatriðum er þetta einfalt úrval af ábendingum og breyta til að geyma vísitöluna efst á staflanum.
Þegar það er frumstillt er búið til fylki af 256 þáttum. Ef fleiri ábendingum er ýtt á staflann eykst stærð hans um næstu 256 þætti. Í samræmi við það, þegar þættir eru fjarlægðir úr staflanum, er stærð hans aðlöguð.
VM notar nokkra stafla:
- Aðalstafla.
- Stafla til að geyma skilapunkta.
- Sorphirðustafla.
- Prófaðu/grípa/lokaðu loksins stjórnandastafla.
Fastar og breytur
Þessi er einföld. Stöður eru meðhöndlaðar í sérstökum litlum kóða og eru fáanlegar í framtíðarforritum með kyrrstæðum heimilisföngum. Breytur eru fylki ábendinga af ákveðinni stærð, aðgangur að frumum hennar fer fram með vísitölu - þ.e. kyrrstætt heimilisfang. Hægt er að ýta breytum efst í staflann eða lesa þaðan. Reyndar vegna þess Þó að breyturnar okkar geymi í raun ábendingar að gildum í VM minni, þá er tungumálið einkennist af því að vinna með óbeinum ábendingum.
Rusla safnari
Í VM mínum er hann hálfsjálfvirkur. Þeir. framkvæmdaraðili ákveður sjálfur hvenær hann hringir í sorphirðu. Það virkar ekki með því að nota venjulegan benditeljara, eins og í Python, Perl, Ruby, Lua o.s.frv. Það er útfært í gegnum merkjakerfi. Þeir. þegar breytu er ætlað að fá tímabundið gildi er bendi á þetta gildi bætt við sorphirðustaflann. Í framtíðinni rennur safnarinn fljótt í gegnum þegar tilbúinn lista yfir ábendingar.
Meðhöndlun reyna/fanga/loka blokkir
Eins og á hverju nútímamáli er meðhöndlun undantekninga mikilvægur þáttur. VM kjarnanum er pakkað inn í try..catch blokk, sem getur farið aftur í keyrslu kóða eftir að hafa náð undantekningu með því að ýta einhverjum upplýsingum um hana inn í stafla. Í forritakóða geturðu skilgreint reyndu/veiða/loka kóðablokka, tilgreina aðgangsstaði við afla (undantekningastjórnun) og loks/lok (lok reitsins).
Fjölþráður
Það er stutt á VM stigi. Það er einfalt og þægilegt í notkun. Það virkar án truflanakerfis, þannig að kóðinn ætti að vera keyrður í nokkrum þræði nokkrum sinnum hraðar, í sömu röð.
Ytri bókasöfn fyrir VM
Það er engin leið að vera án þessa. VM styður innflutning, svipað og það er útfært á öðrum tungumálum. Þú getur skrifað hluta kóðans í Mash og hluta kóðans á móðurmáli og tengt þá síðan í eitt.
Þýðandi úr Mash tungumáli á háu stigi yfir í bækikóða fyrir VM
Millimál
Til að skrifa fljótt þýðanda úr flóknu tungumáli yfir í VM kóða þróaði ég fyrst millimál. Niðurstaðan var hræðilegt sjónarspil sem líkist assembler og það er enginn sérstakur tilgangur að íhuga hér. Ég segi bara að á þessu stigi vinnur þýðandinn flestar fasta og breytur, reiknar út kyrrstæð heimilisföng þeirra og heimilisföng inngangsstaða.
Þýðandi arkitektúr
Ég valdi ekki besta arkitektúrinn til útfærslu. Þýðandinn byggir ekki kóðatré eins og aðrir þýðendur gera. Hann lítur á upphaf byggingarinnar. Þeir. ef kóðastykkið sem verið er að þátta lítur út eins og “meðan <skilyrði>:”, þá er augljóst að þetta er while lykkja smíði og þarf að vinna sem while lykkju smíði. Eitthvað eins og flókið skiptimál.
Þökk sé þessari byggingarlausn reyndist þýðandinn ekki vera mjög fljótur. Hins vegar hefur auðvelt að breyta því verulega. Ég bætti nauðsynlegum mannvirkjum hraðar en kaffið mitt gat kólnað. Fullur OOP stuðningur var innleiddur á innan við viku.
Kóða hagræðingu
Hér hefði auðvitað mátt útfæra það betur (og kemur til framkvæmda, en seinna, um leið og maður kemst að). Enn sem komið er veit fínstillingarmaðurinn aðeins hvernig á að klippa ónotaðan kóða, fasta og innflutning frá samsetningunni. Einnig er nokkrum föstum með sama gildi skipt út fyrir einn. Það er allt og sumt.
Mash tungumál
Grunnhugtak tungumál
Meginhugmyndin var að þróa sem hagnýtasta og einfaldasta tungumálið. Ég held að þróunin ráði við verkefni sitt með glæsibrag.
Kóðablokkir, verklag og aðgerðir
Allar smíðar í tungumálinu eru opnaðar með tvípunkti. : og eru lokaðar af rekstraraðila enda.
Verklag og aðgerðir eru lýstar sem proc og func, í sömu röð. Rökin eru skráð innan sviga. Allt er eins og flest önnur tungumál.
Rekstraraðili aftur þú getur skilað gildi frá falli, rekstraraðila brjóta gerir þér kleift að hætta aðferð/aðgerð (ef hún er utan lykkjunnar).
Dæmi um kóða:
...
func summ(a, b):
return a + b
end
proc main():
println(summ(inputln(), inputln()))
end
Stutt hönnun
- Lykkjur: fyrir..enda, meðan..enda, þar til..enda
- Skilyrði: ef..[annar..]enda, skipta..[máli..end..][else..]end.
- Aðferðir: proc <name>():... end, func <name>():... end
- Label & goto: <nafn>:, hoppa <nafn>
- Telja upp talningar og fastar fylkingar.
Variables
Þýðandinn getur ákvarðað þær sjálfkrafa, eða ef verktaki skrifar var áður en hann skilgreinir þær.
Dæmi um kóða:
a ?= 10
b ?= a + 20
var a = 10, b = a + 20
Alþjóðlegar og staðbundnar breytur eru studdar.
OOP
Jæja, við erum komin að ljúffengasta efninu. Mash styður allar hlutbundnar forritunaraðferðir. Þeir. flokka, erfðir, fjölbreytni (þar á meðal dýnamískt), kraftmikla sjálfvirka endurspeglun og sjálfsskoðun (full).
Án frekari ummæla er betra að gefa bara kóðadæmi.
Einfaldur flokkur og vinna með hann:
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
Mun gefa út: 30.
Erfðir og fjölbreytni:
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
Mun gefa út: 60.
Hvað með dynamic polymorphism? Já, þetta er spegilmynd!:
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
Mun gefa út: 60.
Nú skulum við taka smá stund til að skoða einföld gildi og flokka:
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
Mun gefa út: satt, satt.
Um verkefnastjóra og skýrar ábendingar
?= stjórnandinn er notaður til að úthluta breytu bendi á gildi í minni.
The = rekstraraðili breytir gildi í minni með því að nota bendi frá breytu.
Og nú aðeins um skýrar ábendingar. Ég bætti þeim við tungumálið þannig að þau væru til.
@<breytu> — taktu skýran bendil á breytu.
?<breytu> — fáðu breytu með bendili.
@= — úthlutaðu gildi til breytu með skýrum bendili á hana.
Dæmi um kóða:
uses <bf>
uses <crt>
proc main():
var a = 10, b
b ?= @a
PrintLn(b)
b ?= ?b
PrintLn(b)
b++
PrintLn(a)
InputLn()
end
Mun gefa út: einhver tala, 10, 11.
Prófaðu..[grípa..][loksins..]end
Dæmi um kóða:
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
Áætlanir fyrir framtíðina
Ég held áfram að skoða og skoða GraalVM & Truffle. Runtime umhverfið mitt er ekki með JIT þýðanda, svo hvað varðar afköst er það sem stendur aðeins samkeppnishæft við Python. Ég vona að ég geti innleitt JIT samantekt byggða á GraalVM eða LLVM.
geymsla
Þú getur leikið þér með þróunina og fylgst með verkefninu sjálfur.
Þakka þér fyrir að lesa til enda ef þú gerðir það.
Heimild: www.habr.com