Nei Programméiersprooch Mash

Zënter e puer Joer hunn ech probéiert meng eegen Programméierungssprooch z'entwéckelen. Ech wollt menger Meenung no déi einfachst, voll funktionell a praktesch Sprooch erstellen.

An dësem Artikel wëll ech d'Haaptstadien vu menger Aarbecht ervirhiewen an, fir unzefänken, dat erstallt Konzept vun der Sprooch an hir éischt Ëmsetzung beschreiwen, un deem ech am Moment schaffen.

Ech soen am Viraus datt ech de ganze Projet am Free Pascal geschriwwen hunn, well ... Programmer op et kënne fir eng grouss Zuel vu Plattformen zesummegesat ginn, an de Compiler selwer produzéiert ganz optimiséiert Binären (ech sammelen all Komponente vum Projet mam O2 Fändel).

Sprooch Runtime

Als éischt ass et derwäert iwwer déi virtuell Maschinn ze schwätzen, déi ech hu misse schreiwen fir zukünfteg Uwendungen a menger Sprooch ze lafen. Ech hu beschloss eng Stackarchitektur ëmzesetzen, vläicht, well et deen einfachste Wee war. Ech hunn keen eenzegen normalen Artikel fonnt wéi ech dat op Russesch maachen, also nodeems ech mech mat dem engleschsproochege Material vertraut hunn, hunn ech mech gesat fir mäin eegene Vëlo ze designen an ze schreiwen. Als nächst wäert ech meng "fortgeschratt" Iddien an Entwécklungen an dëser Matière presentéieren.

Stack Ëmsetzung

Natierlech, uewen um VM ass de Stack. A menger Ëmsetzung funktionnéiert et a Blocken. Wesentlech ass dëst eng einfach Array vu Pointer an eng Variabel fir den Index vun der Spëtzt vum Stack ze späicheren.
Wann et initialiséiert gëtt, gëtt eng Array vun 256 Elementer erstallt. Wann méi Zeigefanger op de Stack gedréckt ginn, erhéicht seng Gréisst mat den nächsten 256 Elementer. Deementspriechend, wann Dir Elementer aus dem Stack erofhuelen, gëtt seng Gréisst ugepasst.

De VM benotzt verschidde Stacks:

  1. Haapt Stack.
  2. E Stack fir Retourpunkten ze späicheren.
  3. Dreckstipp Stack.
  4. Probéieren / fänken / endlech Spär Handler Stack.

Konstanten a Variablen

Dësen ass einfach. Konstanten ginn an engem separaten klenge Stéck Code gehandhabt a sinn an zukünfteg Uwendungen iwwer statesch Adressen verfügbar. Variablen sinn eng Rei vu Pointer vun enger gewësser Gréisst, den Zougang zu sengen Zellen gëtt duerch Index duerchgefouert - d.h. statesch Adress. Variablen kënnen op d'Spëtzt vum Stack gedréckt ginn oder vun do gelies ginn. Eigentlech, well Wärend eis Variabelen am Wesentlechen Zeiger op Wäerter am VM Erënnerung späicheren, gëtt d'Sprooch dominéiert andeems se mat impliziten Zeeche schaffen.

Gerempels Sammelstécker

A mengem VM ass et semi-automatesch. Déi. den Entwéckler selwer entscheet wéini de Gerempels Sammler ruffen. Et funktionnéiert net mat engem normale Zeigerteller, wéi am Python, Perl, Ruby, Lua, etc. Et gëtt duerch e Markersystem ëmgesat. Déi. wann eng Variabel soll e temporäre Wäert zougewisen ginn, engem Zeigefanger picken op dëse Wäert op de Stack Sammelstécker dobäi. An Zukunft leeft de Sammler séier duerch déi scho virbereet Lëscht vu Pointer.

Ëmgank probéieren / fänken / endlech blockéiert

Wéi an all modern Sprooch ass Ausnahmshandhabung e wichtege Bestanddeel. De VM Kär ass an engem Try..catch Block gewéckelt, deen zréck an d'Code-Ausféierung kënnt nodeems se eng Ausnahm gefaangen hunn, andeems Dir e puer Informatioun doriwwer op de Stack dréckt. Am Applikatiounscode kënnt Dir probéieren / fänken / endlech Blocks vum Code definéieren, déi Entréespunkte beim Fang (Ausnahmshandter) an endlech / Enn (Enn vum Block) uginn.

Multithreading

Et gëtt um VM Niveau ënnerstëtzt. Et ass einfach a praktesch ze benotzen. Et funktionnéiert ouni Ënnerbriechungssystem, sou datt de Code an e puer Threads e puer Mol méi séier soll ausgefouert ginn.

Extern Bibliothéike fir VMs

Et gëtt kee Wee ouni dëst ze maachen. VM ënnerstëtzt Importer, ähnlech wéi et an anere Sproochen ëmgesat gëtt. Dir kënnt en Deel vum Code am Mash schreiwen an en Deel vum Code an Mammesproochen, da verlinkt se an eng.

Iwwersetzer vun héijer Mash Sprooch op Bytecode fir VMs

Mëttelstuf Sprooch

Fir séier en Iwwersetzer aus enger komplexer Sprooch an de VM Code ze schreiwen, hunn ech fir d'éischt eng Zwëschesprooch entwéckelt. D'Resultat war en Assembler-ähnlechen schreckleche Spektakel, deen et kee besonnesche Punkt ass hei ze berücksichtegen. Ech wäert nëmme soen datt op dësem Niveau den Iwwersetzer déi meescht Konstanten a Variabelen veraarbecht, hir statesch Adressen an d'Adressen vun den Entréespunkte berechent.

Iwwersetzer Architektur

Ech hunn net déi bescht Architektur fir d'Ëmsetzung gewielt. Den Iwwersetzer baut kee Codebaum, wéi aner Iwwersetzer maachen. Hie kuckt am Ufank vun der Struktur. Déi. wann de Stéck Code, deen parséiert gëtt, ausgesäit wéi "während <Conditioun>:", dann ass et offensichtlech datt dëst e While Loop Konstrukt ass a muss als While Loop Konstrukt veraarbecht ginn. Eppes wéi e komplexe Schalterfall.

Dank dëser architektonescher Léisung huet sech den Iwwersetzer net ganz séier erausgestallt. Wéi och ëmmer, d'Liichtegkeet vu senger Ännerung ass wesentlech eropgaang. Ech hunn déi néideg Strukture méi séier bäigefüügt wéi mäi Kaffi ofkille konnt. Voll OOP Support gouf a manner wéi enger Woch implementéiert.

Äre Code optimiséieren

Hei hätt ee selbstverständlech besser kënnen ëmgesat ginn (a wäert ëmgesat ginn, awer méi spéit, soubal een dorops kënnt). Bis elo weess den Optimizer nëmme wéi een onbenotzten Code, Konstanten an Importer vun der Versammlung ofschneiden. Och verschidde Konstanten mam selwechte Wäert ginn duerch een ersat. Dat ass alles.

Sprooch Mash

Basis Konzept vun Sprooch

D'Haaptidee war déi funktionellst an einfachst Sprooch z'entwéckelen. Ech mengen, datt d'Entwécklung hir Aufgab mat engem Knall këmmert.

Code Blocks, Prozeduren a Funktiounen

All Konstruktiounen an der Sprooch gi mat engem Colon opgemaach. : a sinn vum Bedreiwer zougemaach Enn.

Prozeduren a Funktiounen ginn als proc respektiv func deklaréiert. D'Argumenter sinn an parentheses opgezielt. Alles ass wéi déi meescht aner Sproochen.

Bedreiwer zréck Dir kënnt e Wäert vun enger Funktioun zréckginn, Bedreiwer briechen erlaabt Iech d'Prozedur / Funktioun ze verloossen (wann et ausserhalb vun de Schleifen ass).

Beispill Code:

...

func summ(a, b):
  return a + b
end

proc main():
  println(summ(inputln(), inputln()))
end

Ënnerstëtzt Designs

  • Loops: fir..Enn, iwwerdeems..Enn, bis..Enn
  • Konditioune: wann..[sous..]end, switch..[case..end..][else..]end.
  • Methoden: proc <name>():... end, func <name>():... end
  • Label & goo: <Numm>:, sprangen <Numm>
  • Enumen Opzielungen a konstante Arrays.

Verännerlechen

Den Iwwersetzer kann se automatesch bestëmmen, oder wann den Entwéckler var schreift ier se se definéieren.

Code Beispiller:

a ?= 10
b ?= a + 20

var a = 10, b = a + 20

Global a lokal Variablen ginn ënnerstëtzt.

OOP

Gutt, mir sinn op dat leckerst Thema komm. Mash ënnerstëtzt all objektorientéiert Programméierungsparadigmen. Déi. Klassen, Ierfschaft, Polymorphismus (dorënner dynamesch), dynamesch automatesch Reflexioun an Introspektioun (voll).

Ouni weider Ado ass et besser just Code Beispiller ze ginn.

Eng einfach Klass a mat deem schaffen:

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

Ausgang: 30.

Ierfschaft a Polymorphismus:

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

Ausgang: 60.

Wat iwwer dynamesche Polymorphismus? Jo, dat ass Reflexioun!:

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

Ausgang: 60.

Loosst eis elo e Moment huelen fir introspektéiere fir einfach Wäerter a Klassen:

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

Wäert Ausgang: richteg, richteg.

Iwwer Aufgab Bedreiwer an explizit Hiweiser

Den ?= Bedreiwer gëtt benotzt fir eng Variabel e Pointer op e Wäert an der Erënnerung ze ginn.
Den = Bedreiwer ännert e Wäert an der Erënnerung mat engem Zeiger vun enger Variabel.
An elo e bëssen iwwer explizit Hiweiser. Ech hunn se an d'Sprooch bäigefüügt fir datt se existéieren.
@<Variabel> - huelt en explizit Zeechner op eng Variabel.
?<Variabel> - kritt eng Variabel mam Zeiger.
@= - gitt e Wäert un eng Variabel duerch en explizit Zeeche drop.

Beispill Code:

uses <bf>
uses <crt>

proc main():
  var a = 10, b
  b ?= @a
  PrintLn(b)
  b ?= ?b
  PrintLn(b)
  b++
  PrintLn(a)
  InputLn()
end

Wäert erausginn: eng Zuel, 10, 11.

Probéiert ..[fangen..][endlech..]end

Beispill Code:

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

Pläng fir d'Zukunft

Ech kucken a kucken weider op GraalVM & Truffle. Meng Runtime Ëmfeld huet keen JIT Compiler, also wat d'Performance ugeet, ass et de Moment nëmme kompetitiv mam Python. Ech hoffen datt ech fäeg sinn JIT Compilatioun op Basis vu GraalVM oder LLVM ëmzesetzen.

repository

Dir kënnt mat den Entwécklungen spillen an de Projet selwer verfollegen.

Websäit
Repository op GitHub

Merci fir d'Liesen bis zum Schluss wann Dir et gemaach hutt.

Source: will.com

Kaaft zouverlässeg Hosting fir Site mat DDoS Schutz, VPS VDS Server 🔥 Kaaft zouverléissegt Websäithosting mat DDoS-Schutz, VPS VDS Server | ProHoster