చాలా సంవత్సరాలుగా నేను నా స్వంత ప్రోగ్రామింగ్ లాంగ్వేజ్ని అభివృద్ధి చేయడంలో నా చేతిని ప్రయత్నించాను. నేను నా అభిప్రాయం ప్రకారం, అత్యంత సరళమైన, పూర్తిగా పనిచేసే మరియు అనుకూలమైన భాషను సృష్టించాలనుకుంటున్నాను.
ఈ వ్యాసంలో నేను నా పని యొక్క ప్రధాన దశలను హైలైట్ చేయాలనుకుంటున్నాను మరియు ప్రారంభించడానికి, నేను ప్రస్తుతం పని చేస్తున్న భాష యొక్క సృష్టించిన భావన మరియు దాని మొదటి అమలు గురించి వివరించాలనుకుంటున్నాను.
నేను మొత్తం ప్రాజెక్ట్ను ఫ్రీ పాస్కల్లో రాశాను అని ముందుగానే చెబుతాను, ఎందుకంటే... దానిపై ప్రోగ్రామ్లను భారీ సంఖ్యలో ప్లాట్ఫారమ్ల కోసం సమీకరించవచ్చు మరియు కంపైలర్ చాలా ఆప్టిమైజ్ చేసిన బైనరీలను ఉత్పత్తి చేస్తుంది (నేను ప్రాజెక్ట్ యొక్క అన్ని భాగాలను O2 ఫ్లాగ్తో సేకరిస్తాను).
భాష రన్టైమ్
అన్నింటిలో మొదటిది, నా భాషలో భవిష్యత్ అనువర్తనాలను అమలు చేయడానికి నేను వ్రాయవలసిన వర్చువల్ మెషీన్ గురించి మాట్లాడటం విలువైనది. నేను స్టాక్ ఆర్కిటెక్చర్ని అమలు చేయాలని నిర్ణయించుకున్నాను, బహుశా ఇది సులభమైన మార్గం. రష్యన్ భాషలో దీన్ని ఎలా చేయాలనే దానిపై నేను ఒక్క సాధారణ కథనాన్ని కనుగొనలేదు, కాబట్టి ఆంగ్ల భాషా మెటీరియల్తో నాకు పరిచయం అయిన తర్వాత, నేను నా స్వంత సైకిల్ రూపకల్పన మరియు వ్రాయడానికి కూర్చున్నాను. తదుపరి నేను ఈ విషయంలో నా "అధునాతన" ఆలోచనలు మరియు అభివృద్ధిని ప్రదర్శిస్తాను.
స్టాక్ అమలు
సహజంగానే, VM ఎగువన స్టాక్ ఉంది. నా అమలులో ఇది బ్లాక్లలో పనిచేస్తుంది. ముఖ్యంగా ఇది పాయింటర్ల యొక్క సాధారణ శ్రేణి మరియు స్టాక్ పైభాగంలోని సూచికను నిల్వ చేయడానికి వేరియబుల్.
ఇది ప్రారంభించబడినప్పుడు, 256 మూలకాల శ్రేణి సృష్టించబడుతుంది. మరిన్ని పాయింటర్లను స్టాక్పైకి నెట్టినట్లయితే, దాని పరిమాణం తదుపరి 256 మూలకాల ద్వారా పెరుగుతుంది. దీని ప్రకారం, స్టాక్ నుండి మూలకాలను తొలగించేటప్పుడు, దాని పరిమాణం సర్దుబాటు చేయబడుతుంది.
VM అనేక స్టాక్లను ఉపయోగిస్తుంది:
- ప్రధాన స్టాక్.
- రిటర్న్ పాయింట్లను నిల్వ చేయడానికి ఒక స్టాక్.
- చెత్త కలెక్టర్ స్టాక్.
- హ్యాండ్లర్ స్టాక్ని ప్రయత్నించండి/క్యాచ్ చేయండి/చివరిగా బ్లాక్ చేయండి.
స్థిరాంకాలు మరియు వేరియబుల్స్
ఇది సరళమైనది. స్థిరాంకాలు ప్రత్యేక చిన్న కోడ్లో నిర్వహించబడతాయి మరియు స్టాటిక్ చిరునామాల ద్వారా భవిష్యత్ అప్లికేషన్లలో అందుబాటులో ఉంటాయి. వేరియబుల్స్ అనేది ఒక నిర్దిష్ట పరిమాణంలోని పాయింటర్ల శ్రేణి, దాని కణాలకు ప్రాప్యత సూచిక ద్వారా నిర్వహించబడుతుంది - అనగా. స్థిర చిరునామా. వేరియబుల్స్ స్టాక్ పైభాగానికి నెట్టవచ్చు లేదా అక్కడ నుండి చదవవచ్చు. నిజానికి, ఎందుకంటే మా వేరియబుల్స్ తప్పనిసరిగా VM మెమరీలో విలువలకు పాయింటర్లను నిల్వ చేస్తున్నప్పుడు, అవ్యక్త పాయింటర్లతో పని చేయడం ద్వారా భాష ఆధిపత్యం చెలాయిస్తుంది.
వ్యర్థాలు సేకరించువాడు
నా VMలో ఇది సెమీ ఆటోమేటిక్. ఆ. చెత్త సేకరించేవారిని ఎప్పుడు పిలవాలో డెవలపర్ స్వయంగా నిర్ణయిస్తారు. ఇది పైథాన్, పెర్ల్, రూబీ, లువా మొదలైన వాటిలో సాధారణ పాయింటర్ కౌంటర్ ఉపయోగించి పని చేయదు. ఇది మార్కర్ సిస్టమ్ ద్వారా అమలు చేయబడుతుంది. ఆ. ఒక వేరియబుల్కు తాత్కాలిక విలువను కేటాయించాలని భావించినప్పుడు, ఈ విలువకు ఒక పాయింటర్ చెత్త సేకరించేవారి స్టాక్కు జోడించబడుతుంది. భవిష్యత్తులో, కలెక్టర్ ఇప్పటికే సిద్ధం చేసిన పాయింటర్ల జాబితా ద్వారా త్వరగా నడుస్తుంది.
ప్రయత్నించండి/క్యాచ్/చివరిగా బ్లాక్లను నిర్వహించడం
ఏదైనా ఆధునిక భాషలో వలె, మినహాయింపు నిర్వహణ అనేది ఒక ముఖ్యమైన భాగం. VM కోర్ ట్రై..క్యాచ్ బ్లాక్లో వ్రాప్ చేయబడింది, ఇది స్టాక్పై కొంత సమాచారాన్ని నెట్టడం ద్వారా మినహాయింపును క్యాచ్ చేసిన తర్వాత కోడ్ అమలుకు తిరిగి రావచ్చు. అప్లికేషన్ కోడ్లో, మీరు ట్రై/క్యాచ్/చివరిగా కోడ్ బ్లాక్లను నిర్వచించవచ్చు, క్యాచ్ (మినహాయింపు హ్యాండ్లర్) మరియు చివరగా/ముగింపు (బ్లాక్ ముగింపు) వద్ద ఎంట్రీ పాయింట్లను పేర్కొనవచ్చు.
మల్టీథ్రెడింగ్
దీనికి VM స్థాయిలో మద్దతు ఉంది. ఇది ఉపయోగించడానికి సులభమైనది మరియు సౌకర్యవంతంగా ఉంటుంది. ఇది అంతరాయ వ్యవస్థ లేకుండా పనిచేస్తుంది, కాబట్టి కోడ్ అనేక థ్రెడ్లలో వరుసగా అనేక రెట్లు వేగంగా అమలు చేయబడాలి.
VMల కోసం బాహ్య లైబ్రరీలు
ఇది లేకుండా చేయడానికి మార్గం లేదు. VM ఇతర భాషలలో ఎలా అమలు చేయబడుతుందో అదే విధంగా దిగుమతులకు మద్దతు ఇస్తుంది. మీరు కోడ్లో కొంత భాగాన్ని మాష్లో మరియు కొంత భాగాన్ని స్థానిక భాషల్లో వ్రాసి, ఆపై వాటిని ఒకదానికి లింక్ చేయవచ్చు.
VMల కోసం హై-లెవల్ మాష్ భాష నుండి బైట్కోడ్కు అనువాదకుడు
ఇంటర్మీడియట్ భాష
సంక్లిష్ట భాష నుండి VM కోడ్లోకి అనువాదకుడిని త్వరగా వ్రాయడానికి, నేను మొదట ఇంటర్మీడియట్ భాషను అభివృద్ధి చేసాను. ఫలితంగా అసెంబ్లర్ లాంటి భయంకరమైన దృశ్యం ఏర్పడింది, ఇక్కడ ప్రత్యేకంగా పరిగణించాల్సిన అవసరం లేదు. ఈ స్థాయిలో అనువాదకుడు చాలా స్థిరాంకాలు మరియు వేరియబుల్స్ను ప్రాసెస్ చేస్తాడు, వాటి స్టాటిక్ చిరునామాలు మరియు ఎంట్రీ పాయింట్ల చిరునామాలను లెక్కిస్తాడని మాత్రమే నేను చెబుతాను.
అనువాదకుల నిర్మాణం
నేను అమలు కోసం ఉత్తమ నిర్మాణాన్ని ఎంచుకోలేదు. ఇతర అనువాదకులు చేసినట్లుగా అనువాదకుడు కోడ్ ట్రీని నిర్మించడు. అతను నిర్మాణం ప్రారంభంలో చూస్తాడు. ఆ. అన్వయించబడిన కోడ్ ముక్క “while <condition>:” లాగా కనిపిస్తే, ఇది కాసేపు లూప్ నిర్మాణమని మరియు కాసేపు లూప్ నిర్మాణంగా ప్రాసెస్ చేయబడాలని స్పష్టంగా తెలుస్తుంది. సంక్లిష్టమైన స్విచ్-కేస్ లాంటిది.
ఈ నిర్మాణ పరిష్కారానికి ధన్యవాదాలు, అనువాదకుడు చాలా వేగంగా లేడని తేలింది. అయితే, దాని సవరణ సౌలభ్యం గణనీయంగా పెరిగింది. నేను నా కాఫీని చల్లబరుస్తుంది కంటే వేగంగా అవసరమైన నిర్మాణాలను జోడించాను. పూర్తి OOP మద్దతు ఒక వారంలోపు అమలు చేయబడింది.
కోడ్ ఆప్టిమైజేషన్
ఇక్కడ, వాస్తవానికి, ఇది మెరుగ్గా అమలు చేయబడి ఉండవచ్చు (మరియు అమలు చేయబడుతుంది, కానీ తరువాత, దాని చుట్టూ చేరిన వెంటనే). ఇప్పటివరకు, ఆప్టిమైజర్కు అసెంబ్లీ నుండి ఉపయోగించని కోడ్, స్థిరాంకాలు మరియు దిగుమతులను ఎలా కత్తిరించాలో మాత్రమే తెలుసు. అలాగే, ఒకే విలువ కలిగిన అనేక స్థిరాంకాలు ఒకదానితో భర్తీ చేయబడతాయి. అంతే.
భాష మాష్
భాష యొక్క ప్రాథమిక భావన
సాధ్యమయ్యే అత్యంత క్రియాత్మకమైన మరియు సరళమైన భాషను అభివృద్ధి చేయడం ప్రధాన ఆలోచన. అభివృద్ధి దాని పనిని చప్పుడుతో ఎదుర్కుంటుందని నేను భావిస్తున్నాను.
కోడ్ బ్లాక్లు, విధానాలు మరియు విధులు
భాషలోని అన్ని నిర్మాణాలు కోలన్తో తెరవబడతాయి. : మరియు ఆపరేటర్ ద్వారా మూసివేయబడతాయి ముగింపు.
విధానాలు మరియు విధులు వరుసగా ప్రోక్ మరియు ఫంక్గా ప్రకటించబడ్డాయి. వాదనలు కుండలీకరణాల్లో జాబితా చేయబడ్డాయి. అన్నీ ఇతర భాషల మాదిరిగానే ఉంటాయి.
ఆపరేటర్ తిరిగి మీరు ఫంక్షన్, ఆపరేటర్ నుండి విలువను తిరిగి ఇవ్వవచ్చు విరామం ప్రక్రియ/ఫంక్షన్ నుండి నిష్క్రమించడానికి మిమ్మల్ని అనుమతిస్తుంది (ఇది లూప్ల వెలుపల ఉంటే).
నమూనా కోడ్:
...
func summ(a, b):
return a + b
end
proc main():
println(summ(inputln(), inputln()))
end
మద్దతు ఉన్న డిజైన్లు
- లూప్స్: కోసం..ముగింపు, అయితే..ముగింపు, వరకు..ముగింపు
- షరతులు: if..[else..]end, switch..[case..end..][else..]end
- పద్ధతులు: proc <name>():... end, func <name>():... end
- లేబుల్ & గోటో: <name>:, జంప్ <పేరు>
- ఎన్యుమరేషన్లు మరియు స్థిరమైన శ్రేణులు.
వేరియబుల్స్
అనువాదకుడు వాటిని స్వయంచాలకంగా గుర్తించగలడు లేదా డెవలపర్ వాటిని నిర్వచించే ముందు var వ్రాస్తే.
కోడ్ ఉదాహరణలు:
a ?= 10
b ?= a + 20
var a = 10, b = a + 20
గ్లోబల్ మరియు లోకల్ వేరియబుల్స్కు మద్దతు ఉంది.
OOP
బాగా, మేము చాలా రుచికరమైన అంశానికి వచ్చాము. మాష్ అన్ని ఆబ్జెక్ట్-ఓరియెంటెడ్ ప్రోగ్రామింగ్ నమూనాలకు మద్దతు ఇస్తుంది. ఆ. తరగతులు, వారసత్వం, పాలిమార్ఫిజం (డైనమిక్తో సహా), డైనమిక్ ఆటోమేటిక్ రిఫ్లెక్షన్ మరియు ఆత్మపరిశీలన (పూర్తి).
మరింత ఆలస్యం చేయకుండా, కోడ్ ఉదాహరణలు ఇవ్వడం మంచిది.
ఒక సాధారణ తరగతి మరియు దానితో పని చేయడం:
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
విల్ అవుట్పుట్: 30.
వారసత్వం మరియు పాలిమార్ఫిజం:
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
విల్ అవుట్పుట్: 60.
డైనమిక్ పాలిమార్ఫిజం గురించి ఏమిటి? అవును, ఇది ప్రతిబింబం!:
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
విల్ అవుట్పుట్: 60.
ఇప్పుడు సాధారణ విలువలు మరియు తరగతుల కోసం ఆత్మపరిశీలన చేసుకోవడానికి కొంత సమయం తీసుకుందాం:
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
విల్ అవుట్పుట్: నిజం, నిజం.
అసైన్మెంట్ ఆపరేటర్లు మరియు స్పష్టమైన పాయింటర్ల గురించి
?= ఆపరేటర్ అనేది ఒక వేరియబుల్ను మెమరీలోని విలువకు పాయింటర్ని కేటాయించడానికి ఉపయోగించబడుతుంది.
వేరియబుల్ నుండి పాయింటర్ ఉపయోగించి = ఆపరేటర్ మెమరీలో విలువను మారుస్తుంది.
మరియు ఇప్పుడు స్పష్టమైన పాయింటర్ల గురించి కొంచెం. నేను వాటిని ఉనికిలో ఉండేలా భాషకు జోడించాను.
@<variable> — వేరియబుల్కు స్పష్టమైన పాయింటర్ను తీసుకోండి.
?<variable> — పాయింటర్ ద్వారా వేరియబుల్ పొందండి.
@= — వేరియబుల్కు స్పష్టమైన పాయింటర్ ద్వారా విలువను కేటాయించండి.
నమూనా కోడ్:
uses <bf>
uses <crt>
proc main():
var a = 10, b
b ?= @a
PrintLn(b)
b ?= ?b
PrintLn(b)
b++
PrintLn(a)
InputLn()
end
విల్ అవుట్పుట్: కొంత సంఖ్య, 10, 11.
ప్రయత్నించండి..[పట్టుకోండి..][చివరకు..]ముగింపు
నమూనా కోడ్:
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
భవిష్యత్తు కోసం ప్రణాళికలు
నేను GraalVM & Truffleని చూస్తూనే ఉంటాను. నా రన్టైమ్ వాతావరణంలో JIT కంపైలర్ లేదు, కాబట్టి పనితీరు పరంగా ఇది ప్రస్తుతం పైథాన్తో మాత్రమే పోటీగా ఉంది. నేను GraalVM లేదా LLVM ఆధారంగా JIT సంకలనాన్ని అమలు చేయగలనని ఆశిస్తున్నాను.
రిపోజిటరీ
మీరు అభివృద్ధితో ఆడవచ్చు మరియు ప్రాజెక్ట్ను మీరే అనుసరించవచ్చు.
మీరు చదివితే చివరి వరకు చదివినందుకు ధన్యవాదాలు.
మూలం: www.habr.com