Forum: Projeler Rhodeus Script RSS
Rhodeus Script 2.0
Sayfa:  1  2  sonraki 
Avatar
zekeriyadurmus #1
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Rhodeus Script 2.0
2.0'ın yapımına başlamış bulunmaktayım.

Salih hocama geçen gün bildirdiğim gibi hız konusunun çok da üzerine gitmeyeceğim(şimdilik). Ama şunu rahatlıkla belirtebilirim 1.sürümden daha hızlı :)

Geçen gün Rust[1] adında yeni bir programlama dili keşfettim. Mozilla geliştiriyormuş ve bu dilden de sentaks konusunda esinlenebileceğimizi düşündüm :)

Dille ilgili yaptığım bazı değişiklikler ve kararlar aşağıdaki gibidir.
  • Register based yerine stack based sanal makine oldu. Assemblynin push ve pop yöntemi kullanıldı.
  • Veriler struct içerisinde tutulmak yerine RhObject sınıfından türetiliyor.

Son değişiklikleri github sayfasına[2] yükledim.

[1] http://www.rust-lang.org/
[2] https://github.com/Rhodeus/Script2.0/

Zekeriya
Bilgi meraktan gelir...
Avatar
zekeriyadurmus #2
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Aşağıdaki 1 milyonluk boş bir döngünün çalışma hızı 6 kat arttırıldı.
  i=0
  while(i < 1000000) print(i++)
120 ms içerisinde bu kod çalışıyor.

Ayrıca parsera {} ifadelerini kullanma zorunluluğu kaldırılıyor. {} kullanılmazsa tek bir ifade belirtilebilir.

Zekeriya
Bilgi meraktan gelir...
Bu mesaj zekeriyadurmus tarafından değiştirildi; zaman: 2013-04-10, 13:34.
Avatar
Salih Dinçer #3
Üye Ock 2012 tarihinden beri · 1881 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #1
Merhaba Zekeriya,

Hız konusunda fazla oyalanmadan geliştirmeye devam etmek çok iyi bir karar oldu. Belki küçük bir öneri olabilir. Kodlar içerisinde gömülen hız ölçüm satırlarını debug { } kümesine alabilir veya version(test) { } gibi başka bir küme de kullanabiliriz. Böylece o satırlar -release sürümlerde derlenmemiş olacak.

zekeriyadurmus:
Dille ilgili yaptığım bazı değişiklikler ve kararlar aşağıdaki gibidir.
  • Register based yerine stack based sanal makine oldu. Assemblynin push ve pop yöntemi kullanıldı.
  • Veriler struct içerisinde tutulmak yerine RhObject sınıfından türetiliyor.
Az önce kodlara baktım ve anladığım gibi olmadığını gördüm. Ben D olanaklarıyla bir stack kurduğunu zannettimiştim. Meğer interpret() işlevi içerisinde assembly'nin pop ve push komutlarını kullanmışsın. Sanırım burada, ushort türünde bir değişkene (enum) sahip sınıfın adresini (içeriğini değil) stack'e atmış oluyorsun.

Peki sonra bunları pop ile aldığında işaretçinin gösterdiği nesneye ve tüm üyelerine erişebiliyor musun?

Bu arada RhOject sınıfında tam olarak ne işlemler yapılacak? Örneğin index() özelliği? Şu an hazır değiller sanırım ve bir tanesi için örnek verebilirsen kurguladığın çalışma sistemi hakkında daha fazla bilgi ipuçları elde edebiliriz.

Başarılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
zekeriyadurmus #4
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
hız ölçüm satırlarını debug { } kümesine alabilir veya version(test) { } gibi başka bir küme de kullanabiliriz. Böylece o satırlar -release sürümlerde derlenmemiş olacak.
Doğru diyorsunuz hocam. Debug içerisine aldım.

Peki sonra bunları pop ile aldığında işaretçinin gösterdiği nesneye ve tüm üyelerine erişebiliyor musun?
Kesinlikle erişebiliyoruz. Sonuçta nesne üzerinde hiçbir işlem yapmıyoruz sadece adresini push/pop ile saklayıp okuyoruz.

Bu arada RhOject sınıfında tam olarak ne işlemler yapılacak? Örneğin index() özelliği? Şu an hazır değiller sanırım ve bir tanesi için örnek verebilirsen kurguladığın çalışma sistemi hakkında daha fazla bilgi ipuçları elde edebiliriz.
RhObject içerisinde her bir veri türünün sahip olabileceği işlemler var mesela RhInt
a = 1
print(a[0])
Bu işlemi yapmak istediğinde RhInt üzerinde index metodu tanımlanmadığı için RhObject teki index metodu çağırılır ve oradan da ekrana hata mesajı verilir.

Index metodu rharray.d içerisinde aşağıdaki gibidir.

//RhArray.d
    override RhObject index(RhObject obj){
        return val[(cast(RhInt) obj).val];
    }
    override void indexEqual(RhObject key, RhObject value){
        val[(cast(RhInt) key).val] = value;
    }

Ama paraphrase işlemi yapılırken stack yönetimi ile ilgili sorun yaşıyorum. Kimi zaman elemanı stacktan alınması unutuluyor, kimi zaman ise fazladan alınıyor. Yorumlama işlemlerinin tam yapılması gerekiyor.

Zekeriya
Bilgi meraktan gelir...
Bu mesaj zekeriyadurmus tarafından değiştirildi; zaman: 2013-04-11, 02:30.
Avatar
zekeriyadurmus #5
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bir konuda görüşlerinizi almak isterim :)

i = 0
while (i++ <= 10) do
    print(i)
end
 
while (i++ <= 20) {
    print(i)
}
 
while (i++ <= 30)
    print(i)

Buradaki gibi 3 farklı while kullanımı olsun mu? Bazı programcılar { gibi özel karakterleri daha az kullanmak istiyorlar ben de onun için { ve } ye alternatif do ve end anahtar kelimelerini ekledim. { yerine do yazılabilir. Şu an bunu mümkün kıldım ama saçma bir fikir değildir umarım. Sizin bu konuda görüşleriniz nelerdir?

Zekeriya
Bilgi meraktan gelir...
Avatar
zekeriyadurmus #6
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Hatta biraz daha ileri gidiyorum...

while i++ <= 30
    print(i)

kullanımına da izin vereyim mi?

Zekeriya
Bilgi meraktan gelir...
acehreli (Moderatör) #7
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4396 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Ya do+end olsun ya da küme parantezleri; ikisi birden olursa karışıklık olabilir. Hangisi olursa olsun, kullanılmasının şart olması daha iyi. Yoksa kod yanlış okunabiliyor.

Son gösterdiğinde karışıklık şansı var mı? Satır sonuna kadar while'a dahil olarak mı kabul edeceksin? Yani aşağıdaki gibi değil tabii:
while (i++) <= 30
    print(i)

Eğer öyleyse dilin genelinde nasıl oluyorsa öyle olsun. Satır sonuna kadar diye başka kavramlar varsa tamam; yoksa parantezler daha iyi.

Tabii bunları bana değil, hedef kitlene sormalısın. :) Onlar ne isterler acaba?

Ali
Avatar
zekeriyadurmus #8
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Son gösterdiğinde karışıklık şansı var mı? Satır sonuna kadar while'a dahil olarak mı kabul edeceksin?
Hayır :)
while i++ <= 30 print(i)
Bu kodu bile çok rahat ayrıştırabilirim :)

Eğer öyleyse dilin genelinde nasıl oluyorsa öyle olsun. Satır sonuna kadar diye başka kavramlar varsa tamam; yoksa parantezler daha iyi.
Aslında sentaks şu şekilde olmuş oluyor;
while koşul kod
veya
while koşul { kod... }

Zekeriya
Bilgi meraktan gelir...
Avatar
zekeriyadurmus #9
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
i=0
while i++ <= 10 print(i) print("değişken")
Yazıldığında { } kullanılmadığı için 1 den 10 a kadarki sayıları ekrana yazdırır daha sonra değişken yazar

i=0
while i++ <= 10 {print(i) print("değişken")}
Bunda ise 1değişken 2değişken şeklinde yazar.

Bu kodu çok rahat bir şekilde ayrıştırıyor şu an.

Zekeriya
Bilgi meraktan gelir...
Avatar
Salih Dinçer #10
Üye Ock 2012 tarihinden beri · 1881 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
zekeriyadurmus:
i=0
while i++ <= 10 {print(i) print("değişken")}
Bunda ise 1değişken 2değişken şeklinde yazar.

Bu kodu çok rahat bir şekilde ayrıştırıyor şu an.
Bu 2.'si gerçekten çok hoş görünüyor. Elbette kısalık ve diğer dillere göre özgünlük önemli. Ama bunun ayarını belli kriterlere göre ayarlamalıyız. Yani temelde %50 özgünlük, %50 geleneksellik ise dilin kişiliğine ve yapısına uygun olacak her tür oran kaymaları (bir kefeden alıp diğerine verme) mübahtır...:)

Esprili yaklaştığım bu girişten sonra, konuyu teknik olarak inceleyelim:

Önce güzel parantezlerden bahsedeyim. Elbette her dilde kullanılmayan bu kümeleme olayı gerek D'nin ruhuna gerekse bir çok dile çok güzel yakışıyor. Özellikle OOP mantığında sadece { ... } işaretleri arasına kod yazarak bulunduğu state'in diğerlerini etkilememesi çok hoş bir şey. Bu ve benzeri nedenlerden dolayı bence kümelemeden hiç bir zaman vazgeçmeyelim. Ama bazı istisnaları olabilir:
i = 10
do print(i) while(i--)
Örnek koddan anlaşıldığı gibi, benim bazen while()'yerine do/while ikilisini bilinçli olarak kullandığım ve pratik bir şekilde güzel parantezlere ihtiyaç bıraktırmayan örnek kanımca güzel. Ama dikkat, tek satırda bazı şeyleri pratik şekilde ifade etmek istediğim için bana güzel geliyor olabilir. Ancak çoğunluk için kod okumayı zorlaştırabilir. O yüzden geleneksel kümeleme çoğu yerde abartılarak tek satıra parantez aç kullanılır ya. Belki kod okumayı kolaylaştırıyor olabilir ama pekala bir foreach'i şöyle yazmak da kodun okunabilirliliğini düşürmüyor, haksız mıyım?
foreach(data; datas) {
  print(data)
}
En iyisi orta karar sanki ama istisnaları da desteklemek lazım. Örneğin bunlardan biri de yukarıda ilk verdiğim kodda yer alan hem sorgu(if) hem de eksiltme(inc) komutunun olması önemli. Sanırım bu C'nin pratikliğinden gelen güzel bir olanak. Yani derleyici (tabi burada yorumlayıcı) döngü içinde değişkeni önce eksiltip sonra 0 olup olmadığına bakmasını istediğimi anlıyor. Zaten bizim her alan yapmak istediğimiz pratiklik ilkesi ile uyuşmuyor mu? Bu arada aklıma gelmişken:

Dil değişkenden önce ++ işaretleri ile sonraki arasında farkı anlayabiliyor mu? Her ne kadar birinin daha hızlı olduğu sebebiyle gelenekselleşen bir alışkanlık olsa da tek başına (tek satırda) kullanımlarda ikisi arasında hiç bir fark yok. Bunu D'nin assembly kodlarına bakarak tespit etmiştim. Yani her ikisi de tek başına inc i; gibi bir komut oluyor. Ama! Değişkeni ekrana yazarken veya yukarıdaki paragrafta anlattığım örnekteki gibi durumlarda öncesi ve sonrası arasında kritik sayılabilecek farkın ayırt edilmesi gerekiyor.

Özetlersek, kümelemeden ödün vermeyelim ama do/while ikilisinde olduğu gibi kümesiz de kullanabilmeliyiz. Ayrıca değişkenlerin öncesi ve sonrasında konulan dec/inc işaretlerinin farkını ortaya çıkarmalıyız.

Dip Not: Aslında D'nin ruhuna yakışan i.print() gibi bir özelliğini (UFCS) de ekleyebilseydik çok iyi olurdu. Hep arzuluyorum ya; RhS D'yi, temsilen de olsa onu yansıtan bir script olabilse. Belki bir süre sonra Ali hocam yurt dışında bunu tanıtarak çoğunluğun kullanımına vesile olur ve hatta dilin geliştiricileri bu script'i sahiplenerek resmi D script'i ilan edebilirler. Bunlar hep hayal ettiğim şeyler, bakarsınız olur...:)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
zekeriyadurmus #11
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bu 2.'si gerçekten çok hoş görünüyor. Elbette kısalık ve diğer dillere göre özgünlük önemli. Ama bunun ayarını belli kriterlere göre ayarlamalıyız. Yani temelde %50 özgünlük, %50 geleneksellik ise dilin kişiliğine ve yapısına uygun olacak her tür oran kaymaları (bir kefeden alıp diğerine verme) mübahtır...
Bu yapıyı ilk defa Rust dilinde gördüm çok hoşuma gitti o yüzden RhS ye uyguladım. Ama kullanıcı isterse zaten parantezleri de kullanabilir sonuçta while(((((i--))))) gibi ekstra parantezler ekleyerek kullanabilir. Bu ifadede sadece while den sonra parantez gelmeli zorunluluğunu ortadan kaldırmış oluyoruz.

Kümeleme karakterleri için;
if( true ) writeln(1); şeklinde bir ifade yapabiliyoruz C, D, php de ama rhs 1.0 da mümkün değil yani tek bir ifade için { } yazmak zorundasınız. 2.0 da bunu kaldırmaktan bahsediyordum. Koşul için de parantezleri kaldırdığımızda ortaya biraz değişik bir kod çıkıyor tabi bu şekilde olunca :)
if true writeln(1)
gibi :)

Dil değişkenden önce ++ işaretleri ile sonraki arasında farkı anlayabiliyor mu?
Maalesef şu an için bu mümkün değil ama D deki çalışma mantığını inceledikten sonra uygulayabilirim :) Şu anda ++i nin tam anlamıyla hangi kurallara göre çalıştığından bihaberim :)

Dip Not: Aslında D'nin ruhuna yakışan i.print() gibi bir özelliğini (UFCS) de ekleyebilseydik çok iyi olurdu. Hep arzuluyorum ya;
Aslında çok hoş olur bence ama o zaman şöyle bir soru geliyor aklıma;
Function x(z){
}
2.x()
"aa".x()
D de tür tanımlamaları olduğu için her tür doğru işlevle eşleşiyor. Burada karışıklık olmasın?
Ve bir de
Function toString(z){
}
toString(z) ile z.toString() farklı şeyler ifade ediyor. Bu dediğiniz şeyi yapabilirim ama tür tanımlamaları olmadığı için karışıklıklara sebep olmasın?

RhS D'yi, temsilen de olsa onu yansıtan bir script olabilse. Belki bir süre sonra Ali hocam yurt dışında bunu tanıtarak çoğunluğun kullanımına vesile olur ve hatta dilin geliştiricileri bu script'i sahiplenerek resmi D script'i ilan edebilirler. Bunlar hep hayal ettiğim şeyler, bakarsınız olur...
Bunu hiç düşünmemiştim, olmasını çok isterim ama D'nin bu anlamda DMDSCRIPT'i var.

Zekeriya
Bilgi meraktan gelir...
Bu mesaj zekeriyadurmus tarafından değiştirildi; zaman: 2013-04-12, 07:50.
acehreli (Moderatör) #12
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4396 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
zekeriyadurmus:
++i nin tam anlamıyla hangi kurallara göre çalıştığından

++i: i'yi arttır, ifadenin değeri olarak i'nin değerini kullan.

i++: i'nin şu andaki değerini sakla, i'yi arttır, ifadenin değeri olarak saklamış olduğun değeri kullan.

Ali
Avatar
Salih Dinçer #13
Üye Ock 2012 tarihinden beri · 1881 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yani Ali hocam şunu demek istiyor...

Eğer bu işleçler, değişkenden önce olursa tıpkı bulunduğu yerdeki anlamı gibi önce o değişkenin değeri 1 birim değişir. Tersinde ise sonra değişir. Bunu en iyi assembly komutları ile açıklayabiliriz. Örneğin bir int i varsayılan değeri (0) ile kuruluyor. Sonra hemen alt satırda bunu, writeln(++i); şeklinde ekrana yazdığımızı farz edelim. Assembly kodu üç aşağı beş yukarı şu şekilde olur:

inc    dword ptr -0Ch[EBP];
mov    EAX, -0Ch[EBP];
call   _D3std5stdio14__T7writelnTkZ7writelnFkZv@PC32;


Tersinde ise inc komutu call satırından hemen sonraya yerleştirilir. İşin esprisi aslında bu kadar basit. Tabi varyasyonları yok değil. Örneğin bir dizi tanımladık ama bu şekilde (dizi[++i];) kullandığımızda dizinin ilk elemanını değil 2.'sini çağırmış oluruz.

Bu konu çok temel ve bence olmazsa olmaz. Tabi teorik olarak olmasa da olur çünkü işimizi 2 satır ile de halledebiliriz. Ama öyle durumlar var ki (örneğin bir stack yapısında), işlevin return ile dönüşünü sağlarken, hem sayaçı (index'i) bir arttırıp hem de bunu geri döndürmek tek satırda yapabilmemiz bence büyük kolaylık.

Başarılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #14
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4396 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Salih Dinçer:
Tersinde ise inc komutu call satırından hemen sonraya yerleştirilir.

Temel türler için öyle açıklanabilir ama işin içine kullanıcı türleri gelince dilin bu davranışları açıkça belirlemesi gerekir.

Örneğin, senden alıntıladığım çözüm doğru olmaz çünkü işlem sıraları değişmiş olur:
    // Asıl kod
    writeln(i++);
 
    // Bir eşdeğeri
    {
        writeln(i);
        ++i;
    }
 
    // Başka eşdeğeri
    {
        auto eskiDeğer = i;
        ++i;
        writeln(eskiDeğer);
    }
Eğer i'nin türü bir struct veya class ise ve opUnary!"++" işlevinin yan etkisi varsa bu iki eşdeğer farklı sonuç üretebilir.

O yüzden dilin ifade kavramını tanımlaması (kabaca: değeri olan program yapısı) ve ++ gibi ifadelerin ne anlama geldiklerini açıkça belirlemesi gerekir.

Bu arada, yukarıda görüldüğü gibi post-increment işlecine aslında gerek yoktur. Olmasa, programcı yalnızca pre-increment ile yetinebilir ve istediği anlamı sağlayabilir.

return ile dönüşünü sağlarken, hem sayaçı (index'i) bir arttırıp hem de bunu geri döndürmek tek satırda yapabilmemiz bence büyük kolaylık.

Ben öyle kodları okumaya başından beri alışamadım. :) Aşağıdaki gibi kodları hiç anlamam:
*p++

Ali
Avatar
zekeriyadurmus #15
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Çok teşekkür ederim Ali hocam ve Salih hocam :)

Ben bu ++ özelliğini çok yanlış biliyormuşum :)

Haliyle rhs üzerinde de yanlış işlemiş oluyorum :)

print(i++) dediğinde opcode olarak aşağıdaki çıktıyı veriyor
load i
inc
loadparam
load print
call

https://github.com/Rhodeus/Script2.0/blob/master/test/loop… buradaki görmüş olduğunuz kodlar çalışıyor şu an :) Çok ilginç bir sentaks ortaya çıktı :)

Zekeriya
Bilgi meraktan gelir...
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  1  2  sonraki 
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-05-27, 12:14:52 (UTC -07:00)