වසර ගණනාවක් මම මගේම ක්රමලේඛන භාෂාවක් සංවර්ධනය කිරීමට උත්සාහ කළෙමි. මට අවශ්ය වූයේ, මගේ මතය අනුව, හැකි තරම් සරල, සම්පූර්ණ ක්රියාකාරී සහ පහසු භාෂාවක් නිර්මාණය කිරීමටයි.
මෙම ලිපියෙන් මට මගේ කාර්යයේ ප්රධාන අදියර ඉස්මතු කිරීමට අවශ්ය වන අතර, ආරම්භ කිරීමට, මා දැනට වැඩ කරමින් සිටින භාෂාවේ නිර්මාණය කරන ලද සංකල්පය සහ එහි පළමු ක්රියාත්මක කිරීම විස්තර කරන්න.
මම සම්පූර්ණ ව්යාපෘතිය ලිව්වේ ෆ්රී පැස්කල් වලින් බව කලින්ම කියන්නම්, මොකද... එහි ඇති වැඩසටහන් විශාල වේදිකා සංඛ්යාවක් සඳහා එකලස් කළ හැකි අතර, සම්පාදකය විසින්ම ඉතා ප්රශස්ත ද්විමය ද්විමය නිෂ්පාදනය කරයි (මම ව්යාපෘතියේ සියලුම සංරචක O2 ධජය සමඟ එකතු කරමි).
භාෂා ධාවන කාලය
පළමුවෙන්ම, මගේ භාෂාවෙන් අනාගත යෙදුම් ධාවනය කිරීමට මට ලිවීමට සිදු වූ අතථ්ය යන්ත්රය ගැන කතා කිරීම වටී. ස්ටැක් ගෘහ නිර්මාණ ශිල්පයක් ක්රියාත්මක කිරීමට මම තීරණය කළෙමි, සමහර විට එය පහසුම ක්රමය වූ බැවිනි. රුසියානු භාෂාවෙන් මෙය කරන්නේ කෙසේද යන්න පිළිබඳ එකදු සාමාන්ය ලිපියක් මට හමු නොවීය, එබැවින් ඉංග්රීසි භාෂා ද්රව්ය සමඟ මා හුරුපුරුදු වූ පසු, මම මගේම බයිසිකලයක් සැලසුම් කිරීමට සහ ලිවීමට වාඩි වී සිටියෙමි. ඊළඟට මම මේ කාරණය සම්බන්ධයෙන් මගේ "උසස්" අදහස් සහ වර්ධනයන් ඉදිරිපත් කරමි.
ස්ටැක් ක්රියාත්මක කිරීම
පැහැදිලිවම, VM එකේ උඩින්ම තියෙන්නේ Stack එක. මගේ ක්රියාත්මක කිරීමේදී එය බ්ලොක් වල ක්රියා කරයි. අත්යවශ්යයෙන්ම මෙය සරල පොයින්ටර් මාලාවක් වන අතර තොගයේ මුදුනේ දර්ශකය ගබඩා කිරීම සඳහා විචල්යයකි.
එය ආරම්භ කරන විට, මූලද්රව්ය 256 ක අරාවක් නිර්මාණය වේ. තවත් පොයින්ටර් තොගය මතට තල්ලු කළහොත්, එහි විශාලත්වය ඊළඟ මූලද්රව්ය 256 කින් වැඩි වේ. ඒ අනුව, තොගයෙන් මූලද්රව්ය ඉවත් කරන විට, එහි ප්රමාණය සකස් කර ඇත.
VM අට්ටි කිහිපයක් භාවිතා කරයි:
- ප්රධාන තොගය.
- ආපසු ලකුණු ගබඩා කිරීම සඳහා තොගයක්.
- කසළ එකතු කරන්නාගේ තොගය.
- හැන්ඩ්ලර් තොගය උත්සාහ කරන්න/අල්ලා ගන්න/අවසානයේ අවහිර කරන්න.
නියතයන් සහ විචල්යයන්
මෙය සරලයි. නියතයන් වෙනම කුඩා කේත කැබැල්ලකින් හසුරුවන අතර අනාගත යෙදුම්වල ස්ථිතික ලිපින හරහා ලබා ගත හැක. විචල්ය යනු යම් ප්රමාණයක දර්ශක සමූහයකි, එහි සෛල වෙත ප්රවේශය දර්ශකය මගින් සිදු කෙරේ - i.e. ස්ථිතික ලිපිනය. විචල්යයන් තොගයේ ඉහළට තල්ලු කර හෝ එතැන් සිට කියවිය හැක. ඇත්ත වශයෙන්ම, මන්ද අපගේ විචල්යයන් අත්යවශ්යයෙන්ම VM මතකයේ අගයන් වෙත පොයින්ටර් ගබඩා කරන අතර, භාෂාව ව්යංග දර්ශක සමඟ වැඩ කිරීමෙන් ආධිපත්යය දරයි.
කුණු එකතුකරන්නා
මගේ VM එකේ ඒක Semi-automatic. එම. කසළ එකතු කරන්නා අමතන්නේ කවදාද යන්න සංවර්ධකයා විසින්ම තීරණය කරයි. එය Python, Perl, Ruby, Lua යනාදී ලෙස සාමාන්ය පොයින්ටර් කවුන්ටරයක් භාවිතයෙන් ක්රියා නොකරයි. එය සලකුණු පද්ධතියක් හරහා ක්රියාත්මක වේ. එම. විචල්යයකට තාවකාලික අගයක් පැවරීමට අදහස් කරන විට, මෙම අගයට දර්ශකයක් කුණු එකතු කරන්නාගේ තොගයට එකතු වේ. අනාගතයේදී, එකතු කරන්නා ඉක්මනින් දැනටමත් සකස් කර ඇති දර්ශක ලැයිස්තුව හරහා ගමන් කරයි.
හැසිරවීම උත්සාහ කිරීම/අල්ලා ගැනීම/අවසානයේ අවහිර කිරීම්
ඕනෑම නවීන භාෂාවක මෙන්, ව්යතිරේක හැසිරවීම වැදගත් අංගයකි. VM හරය ට්රයි..කැච් බ්ලොක් එකකින් ඔතා ඇති අතර, එය පිළිබඳ තොරතුරු තොගය මතට තල්ලු කිරීමෙන් ව්යතිරේකයක් අල්ලා ගැනීමෙන් පසු කේත ක්රියාත්මක කිරීමට ආපසු යා හැක. යෙදුම් කේතය තුළ, ඔබට උත්සාහ/අල්ලා ගැනීම/අවසාන වශයෙන් කේත බ්ලොක් නිර්වචනය කළ හැකිය, අල්ලාගැනීමේදී (ව්යතිරේක හසුරුවන්නා) සහ අවසානයේ/අවසානයේ (බ්ලොක් එකේ අවසානය) ඇතුළත් කිරීමේ ස්ථාන සඳහන් කරන්න.
බහු කියවීම
එය VM මට්ටමින් සහය දක්වයි. එය භාවිතා කිරීමට පහසු සහ සරල ය. එය බාධා පද්ධතියකින් තොරව ක්රියා කරයි, එබැවින් කේතය පිළිවෙලින් කිහිප වතාවක් වේගයෙන් නූල් කිහිපයකින් ක්රියාත්මක කළ යුතුය.
VM සඳහා බාහිර පුස්තකාල
මේක නැතුව කරන්න විදිහක් නෑ. VM වෙනත් භාෂාවලින් ක්රියාත්මක කරන ආකාරයටම, ආනයන සඳහා සහය දක්වයි. ඔබට කේතයේ කොටසක් Mash සහ කේතයේ කොටසක් ස්වදේශීය භාෂාවෙන් ලිවිය හැක, ඉන්පසු ඒවා එකකට සම්බන්ධ කරන්න.
උසස් මට්ටමේ Mash භාෂාවේ සිට VM සඳහා බයිට් කේතය දක්වා පරිවර්තකය
අතරමැදි භාෂාව
සංකීර්ණ භාෂාවකින් පරිවර්තකයෙකු ඉක්මනින් VM කේතයට ලිවීමට, මම මුලින්ම අතරමැදි භාෂාවක් නිර්මාණය කළෙමි. මෙහි ප්රතිඵලය වූයේ එකලස් කරන්නෙකු වැනි බිහිසුණු සංදර්ශනයක් වන අතර මෙහි සලකා බැලීමේ විශේෂ කරුණක් නොමැත. මෙම මට්ටමේදී පරිවර්තකයා බොහෝ නියතයන් සහ විචල්යයන් ක්රියාවට නංවා, ඒවායේ ස්ථිතික ලිපින සහ ප්රවේශ ලක්ෂ්යවල ලිපිනයන් ගණනය කරන බව පමණක් මම කියමි.
පරිවර්තක ගෘහ නිර්මාණ ශිල්පය
මම ක්රියාත්මක කිරීම සඳහා හොඳම ගෘහ නිර්මාණ ශිල්පය තෝරා ගත්තේ නැත. පරිවර්තකයා වෙනත් පරිවර්තකයන් කරන ආකාරයට කේත ගසක් ගොඩනඟන්නේ නැත. ඔහු ව්යුහයේ ආරම්භය දෙස බලයි. එම. විග්රහ කරන කේත කොටස “while <condition>:” ලෙස දිස්වන්නේ නම්, මෙය while loop construct එකක් වන අතර while loop construct ලෙස සැකසිය යුතු බව පැහැදිලිය. සංකීර්ණ ස්විච්-කේස් එකක් වගේ දෙයක්.
මෙම වාස්තු විද්යාත්මක විසඳුමට ස්තූතිවන්ත වන්නට, පරිවර්තකයා ඉතා වේගවත් නොවන බව පෙනී ගියේය. කෙසේ වෙතත්, එහි වෙනස් කිරීමේ පහසුව සැලකිය යුතු ලෙස වැඩි වී ඇත. මම මගේ කෝපි සිසිල් කිරීමට වඩා වේගයෙන් අවශ්ය ව්යුහයන් එකතු කළා. සම්පූර්ණ OOP සහාය සතියකට අඩු කාලයකදී ක්රියාත්මක විය.
කේත ප්රශස්තකරණය
මෙන්න, ඇත්ත වශයෙන්ම, එය වඩා හොඳින් ක්රියාත්මක කළ හැකිව තිබුණි (සහ ක්රියාත්මක වනු ඇත, නමුත් පසුව, යමෙකු එය වටා ගිය වහාම). මෙතෙක්, ප්රශස්තකාරකය දන්නේ එකලස් කිරීමෙන් භාවිතා නොකළ කේතය, නියතයන් සහ ආනයනය කපා හරින ආකාරය පමණි. එසේම එකම අගයක් ඇති නියතයන් කිහිපයක් එකකින් ප්රතිස්ථාපනය වේ. එච්චරයි.
මෑෂ් භාෂාව
භාෂාව පිළිබඳ මූලික සංකල්පය
ප්රධාන අදහස වූයේ හැකි තරම් ක්රියාකාරී හා සරල භාෂාවක් වර්ධනය කිරීමයි. මම හිතන්නේ සංවර්ධනය එහි කර්තව්යය සමඟ සාර්ථකව කටයුතු කරන බවයි.
කේත අවහිර කිරීම්, ක්රියා පටිපාටි සහ කාර්යයන්
භාෂාවේ ඇති සියලුම ඉදිකිරීම් මහා බඩවැලකින් විවෘත වේ. : සහ ක්රියාකරු විසින් වසා ඇත අවසානය.
ක්රියා පටිපාටි සහ කාර්යයන් පිළිවෙලින් proc සහ func ලෙස ප්රකාශ කර ඇත. තර්ක වරහන් තුළ ලැයිස්තුගත කර ඇත. සෑම දෙයක්ම වෙනත් බොහෝ භාෂා මෙන් ය.
ක්රියාකරු ආපසු ඔබට ශ්රිතයක්, ක්රියාකරු වෙතින් අගයක් ආපසු ලබා දිය හැක බිඳීම ක්රියා පටිපාටිය / කාර්යයෙන් පිටවීමට ඔබට ඉඩ සලසයි (එය ලූපයෙන් පිටත නම්).
උදාහරණ කේතය:
...
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>:, <name> පනින්න
- Enum ගණනය කිරීම් සහ නියත අරා.
විචල්යයන්
පරිවර්තකයාට ඒවා ස්වයංක්රීයව තීරණය කළ හැකිය, නැතහොත් සංවර්ධකයා ඒවා අර්ථ දැක්වීමට පෙර var ලියන්නේ නම්.
කේත උදාහරණ:
a ?= 10
b ?= a + 20
var a = 10, b = a + 20
ගෝලීය සහ දේශීය විචල්යයන් සඳහා සහය දක්වයි.
OOP
හොඳයි, අපි වඩාත් රසවත් මාතෘකාවට පැමිණ ඇත. Mash සියළුම වස්තු-නැඹුරු වැඩසටහන්කරණ සුසමාදර්ශ සඳහා සහය දක්වයි. එම. පන්ති, උරුමය, බහුරූපතාව (ගතික ඇතුළුව), ගතික ස්වයංක්රීය පරාවර්තනය සහ අභ්යන්තර විමර්ශනය (සම්පූර්ණ).
තවදුරටත් කතා නොකර, කේත උදාහරණ පමණක් ලබා දීම වඩා හොඳය.
සරල පන්තියක් සහ එය සමඟ වැඩ කිරීම:
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
ප්රතිදානය වනු ඇත: සත්ය, සත්ය.
පැවරුම් ක්රියාකරුවන් සහ පැහැදිලි දර්ශක ගැන
විචල්යයක් මතකයේ අගයකට පොයින්ටරයක් පැවරීමට ?= ක්රියාකරු භාවිතා කරයි.
The = ක්රියාකරු විචල්යයකින් පොයින්ටරයක් භාවිතයෙන් මතකයේ අගයක් වෙනස් කරයි.
දැන් පැහැදිලි ඉඟි ගැන ටිකක්. මම ඒවා භාෂාවට එකතු කළේ ඒවා පවතින නිසා.
@<variable> — විචල්යයකට පැහැදිලි දර්ශකයක් ගන්න.
?<variable> — Pointer මගින් විචල්යයක් ලබා ගන්න.
@= — විචල්යයකට පැහැදිලි දර්ශකයක් මඟින් අගයක් ලබා දෙන්න.
උදාහරණ කේතය:
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 සම්පාදකයක් නොමැත, එබැවින් කාර්ය සාධනය අනුව එය දැනට තරඟකාරී වන්නේ Python සමඟ පමණි. GraalVM හෝ LLVM මත පදනම්ව JIT සම්පාදනය ක්රියාත්මක කිරීමට මට හැකි වනු ඇතැයි මම බලාපොරොත්තු වෙමි.
ගබඩාව
ඔබට වර්ධනයන් සමඟ සෙල්ලම් කර ව්යාපෘතිය ඔබම අනුගමනය කළ හැකිය.
ඔබ එසේ කළේ නම් අවසානය දක්වා කියවීමට ස්තූතියි.
මූලාශ්රය: www.habr.com