SEN2001 · 3. hafta · Describing Syntax and Semantics II

Semantik: attribute grammar ve weakest precondition

Static semantics için attribute grammar (synthesized, inherited, intrinsic), dinamik semantiğin üç yöntemi ve axiomatic semantics ile weakest precondition hesabı.

static semanticsattribute grammarsynthesized attributeinherited attributeintrinsic attributepredicateoperational semanticsdenotational semanticsaxiomatic semanticspreconditionpostconditionweakest preconditionassignment axiomloop invariant

Sözdizimi (syntax) bir programın biçimini tanımlar; ama “değişken kullanılmadan önce bildirilmeli” ya da “int’e real atanamaz” gibi kurallar BNF ile yazılamaz. Bu sayfa iki şeyi kapsar: bu kuralları yazmak için attribute grammar ve programın anlamını (semantics) tanımlamak için üç yöntem. Sınavda en sık çıkan iki soru tipi: attribute grammar ile tip kontrolü yapmak ve weakest precondition hesaplamak.

Altın kurallar:

  1. Synthesized yukarı, inherited aşağı akar.
  2. Önce look-up, sonra expected_type, sonra actual_type, en son predicate.
  3. Weakest precondition sondan başa hesaplanır. Postcondition’daki değişkenin yerine atamanın sağ tarafını yaz.
  4. Negatif sayıyla bölünce eşitsizlik yön değiştirir.

Static semantics

Bazı kurallar derleme zamanında kontrol edilir ama context-free grammar ile ifade edilemez ya da edilmesi çok zahmetlidir:

  • Java’da float bir değer int değişkene atanamaz.
  • Tüm değişkenler kullanılmadan önce bildirilmeli.
  • Ada’da bir alt programın sonundaki end adı, başındaki adla aynı olmalı.

Bunlara static semantics denir: anlamla ilgili ama çalıştırmadan, derleme zamanında kontrol edilebilen kurallar. Adı “semantics” olsa da aslında sözdizimine yakındır.

Attribute grammar

Attribute grammar, bir CFG’ye üç şey ekler:

  • Attribute’lar: her sembole bağlı değerler (actual_type, expected_type).
  • Semantic function’lar (attribute computation functions): her kurala bağlı, attribute’ların nasıl hesaplandığını söyleyen kurallar.
  • Predicate’ler: kuralın geçerli olması için doğru olması gereken koşullar. Biri false olursa static semantics hatası var.

Üç tür attribute var:

TürAkış yönüÖrnek
SynthesizedÇocuklardan ebeveyne, yukarı<expr>.actual_type operandlardan hesaplanır
InheritedEbeveynden/kardeşten çocuğa, aşağı veya yana<expr>.expected_type, kardeşi <var>’dan gelir
IntrinsicYapraklarda, dışarıdanlook-up(<var>.string) symbol table’dan

Tip kontrolü örneği

1. <assign> -> <var> = <expr>
   <expr>.expected_type <- <var>.actual_type
2. <expr> -> <var>[2] + <var>[3]
   <expr>.actual_type <- if (<var>[2].actual_type = int) and
                            (<var>[3].actual_type = int) then int else real
   predicate: <expr>.actual_type == <expr>.expected_type
3. <expr> -> <var>
   <expr>.actual_type <- <var>.actual_type
   predicate: <expr>.actual_type == <expr>.expected_type
4. <var> -> A | B | C
   <var>.actual_type <- look-up(<var>.string)

Köşeli parantezli indisler (<var>[2]) aynı nonterminal’in farklı örneklerini ayırır. A = B + C için A real, B real, C int olsun:

adım                                   değer
1. <var>.actual_type <- look-up(A)     real      (intrinsic)
2. <expr>.expected_type <- real        real      (inherited)
3. <var>[2] = look-up(B), <var>[3]     real, int (intrinsic)
4. <expr>.actual_type                  real      (synthesized: ikisi de int değil)
5. predicate real == real              TRUE

A int, B int, C real olsaydı: expected int, actual real, predicate false. Bu gramer otomatik dönüşüm (coercion) yapmaz; A real, B int, C int bile hata verir çünkü actual int, expected real.

Bağlamdan bağımsız olmayan dil

anbncna^n b^n c^n dili CFG ile yazılamaz. Attribute grammar ile kolay:

<S> -> <A> <B> <C>      predicate: <A>.size == <B>.size == <C>.size
<A> -> a | <A>[2] a     <A>.size <- 1  |  <A>.size <- <A>[2].size + 1
(B ve C için aynı)

CFG kısmı a+b+c+ biçimini kabul eder. aabbcc geçer; aabbc sözdizimsel olarak doğru ama predicate false.

Dinamik semantik: üç yöntem

YöntemAnlam neyle tanımlanırKim kullanır
OperationalProgramın (sanal) bir makinede çalışırken yaptığı durum değişiklikleriDil kılavuzları, öğretim
DenotationalHer yapıyı matematiksel bir nesneye/fonksiyona eşlemekTeorik çalışma, kanıt, derleyici üretimi
Axiomaticİfadelerden önce ve sonra doğru olan mantık önermeleriProgram doğrulama

Operational semantics

Yüksek seviyeli bir yapının anlamını, daha basit ve iyi bilinen bir dile çevirerek verir. C’nin for döngüsü:

for (expr1; expr2; expr3) { ... }

        expr1;
loop:   if expr2 == 0 goto out
        ...
        expr3;
        goto loop
out:    ...

Okuyan biri for’u bilmese de if ve goto’yu biliyorsa anlamı çözer.

Denotational semantics

Her sözdizimsel yapı için bir matematiksel fonksiyon tanımlanır. İkili sayı örneği:

M_bin('0') = 0
M_bin('1') = 1
M_bin(<bin_num> '0') = 2 * M_bin(<bin_num>)
M_bin(<bin_num> '1') = 2 * M_bin(<bin_num>) + 1

101 için: ‘1’ → 1, ‘10’ → 2, ‘101’ → 5. 10110 için 22. Programlarda durum (state) değişkenlerin değerlerinden oluşur; her ifade bir durumdan başka bir duruma giden fonksiyondur.

Axiomatic semantics

Bir ifade S için şu üçlüye Hoare triple denir:

{P}  S  {Q}\{P\}\; S \;\{Q\}

P precondition (önkoşul), Q postcondition (sonkoşul). Anlamı: S çalışmadan önce P doğruysa, S bittiğinde Q doğrudur. Q verildiğinde, Q’yu garanti eden en az kısıtlayıcı önkoşula weakest precondition denir.

Atama aksiyomu

x=Ex = E ataması ve postcondition Q için:

wp(x=E, Q)=Qx→Ewp(x = E,\ Q) = Q_{x \to E}

Q’daki her x yerine E yaz, sadeleştir. Örnek: x = 2 * y - 3 {x > 7}:

2y−3>7  ⇒  2y>10  ⇒  y>52y - 3 > 7 \;\Rightarrow\; 2y > 10 \;\Rightarrow\; y > 5

Kontrol etmeyi alışkanlık yap: y = 6 → x = 9 > 7 doğru; y = 5 → x = 7, 7 > 7 yanlış. Sınır doğru dışlanmış.

TUZAK · negatif katsayı. a = -2 * b + 4 {a < 0}: −2b+4<0⇒−2b<−4⇒b>2-2b + 4 < 0 \Rightarrow -2b < -4 \Rightarrow b > 2. Eşitsizliğin iki tarafını -2’ye bölünce yön döner. b < 2 yazan yanar. Bir değer deneyerek kontrol et: b = 3 → a = -2 < 0, doğru.

Sıralı ifadeler

S1; S2S_1;\ S_2 için önce S2S_2‘nin weakest precondition’ını bul, o S1S_1‘in postcondition’ı olur:

y = x + 4;
x = y * 2;
{x < 20}

adım 1 (son atama):  2y < 20      →  y < 10
adım 2 (ilk atama):  x + 4 < 10   →  x < 6
sonuç: {x < 6}

Seçim

if B then S1 else S2 için:

wp=(B∧wp(S1,Q))∨(¬B∧wp(S2,Q))wp = (B \wedge wp(S_1, Q)) \vee (\neg B \wedge wp(S_2, Q))

if (x > 0) y = x - 1; else y = x + 1; {y > 0}: then dalı x > 1 verir (x > 0 ile birleşince yine x > 1). Else dalı x > -1 verir; x ≤ 0 ile birleşince tam sayılarda sadece x = 0. Cevap: x > 1 veya x = 0.

Daha güçlü önkoşul da geçerli

{x > 5} x = x - 3 {x > 0} geçerli bir üçlüdür, ama weakest değil. Weakest x > 3. Rule of consequence: P’ ⇒ P ise ve {P} S {Q} geçerliyse, {P’} S {Q} de geçerlidir. Yani weakest precondition’dan daha güçlü her önkoşul işe yarar; daha zayıfı yaramaz (x ≥ 3 için x = 3 → 0 > 0 yanlış).

Döngüler

while B do S için weakest precondition doğrudan hesaplanamaz; bir loop invariant (döngü değişmezi) I bulmak gerekir. I döngüden önce doğru olmalı, her turdan sonra da doğru kalmalı ve döngü bittiğinde (I∧¬BI \wedge \neg B) Q’yu gerektirmeli. Invariant bulmak tümevarıma benzer ve genelde vizede yüzeysel sorulur: “invariant nedir, hangi üç koşulu sağlamalı?”

Sık yapılan hatalar

YanlışDoğrusu
wp’yi baştan sona hesaplamakSondaki postcondition’dan geriye git
-2’ye bölünce yönü korumakNegatifle bölünce < ↔ >
Synthesized = aşağı akarSynthesized yukarı, inherited aşağı
expected_type synthesizedKardeşten geldiği için inherited
“Daha güçlü önkoşul geçersiz”Geçerli, ama weakest değil
Static semantics çalışma zamanındaDerleme zamanında kontrol edilir
Attribute grammar = CFGCFG + attribute + function + predicate
Denotational = makinede çalıştırmakO operational; denotational matematiksel fonksiyon

Kendini test et

Sınavdaki gibi İngilizce sorular. Önce kâğıt kalemle çöz, sonra cevabı aç.

Soru 1orta

Using the type-checking attribute grammar below, does the predicate hold for A = B + C when A is int, B is int and C is real?

1. <assign> -> <var> = <expr>
   <expr>.expected_type <- <var>.actual_type
2. <expr> -> <var>[2] + <var>[3]
   <expr>.actual_type <- if (<var>[2].actual_type = int) and
                            (<var>[3].actual_type = int) then int else real
   predicate: <expr>.actual_type == <expr>.expected_type
3. <expr> -> <var>
   <expr>.actual_type <- <var>.actual_type
   predicate: <expr>.actual_type == <expr>.expected_type
4. <var> -> A | B | C
   <var>.actual_type <- look-up(<var>.string)
Cevabı göster
No, the predicate fails

Sıra: önce yapraklar look-up ile tip alır (A int, B int, C real). Kural 1: expected_type ← A'nın tipi = int. Kural 2: iki operand da int değil → actual_type = real. Predicate: real == int → false. Derleyici bunu derleme zamanında tip hatası olarak bildirir.

Soru 2orta

Same grammar: does the predicate hold for A = B + C when A is real, B is int and C is int?

Cevabı göster
No

actual_type: iki operand da int → int. expected_type: A'nın tipi real. int == real değil → predicate false. Bu gramer coercion yapmaz, tipler birebir aynı olmalı. (A real, B real, C int durumunda ise actual = real, expected = real → true.)

Soru 3kolay

In the grammar above, classify actual_type, expected_type, and the type that look-up returns for a <var> leaf.

Cevabı göster
actual_type: synthesized; expected_type: inherited; look-up result: intrinsic

Synthesized: bilgi çocuklardan ebeveyne, yukarı akar (<expr>.actual_type operandlardan hesaplanır). Inherited: bilgi ebeveynden ya da kardeşten aşağı/yana akar (<expr>.expected_type, kardeşi <var>'dan gelir). Intrinsic: yapraktaki değer dışarıdan, symbol table'dan gelir.

Soru 4orta

An attribute grammar for anbncna^n b^n c^n uses <S> -> <A> <B> <C>, where each of <A>, <B>, <C> has a synthesized attribute size and the predicate is A.size = B.size = C.size. Which strings pass both syntax and the predicate? aabbcc, aabbc, abc, aabcc, abca

Cevabı göster
aabbcc and abc

CFG kısmı a+ b+ c+ biçimini kabul eder, sayıları predicate kontrol eder. aabbcc: 2,2,2 ✔. abc: 1,1,1 ✔. aabbc: 2,2,1 ✘ (predicate false). aabcc: 2,1,2 ✘. abca: biçim bozuk, syntax hatası. Bu dil context-free değildir; CFG tek başına üretemez, attribute grammar'ın gücü burada.

Soru 5kolay

Compute the weakest precondition: x = 2 * y - 3 {x > 7}

Cevabı göster
{y > 5}

Atama aksiyomu: postcondition'da x yerine 2y - 3 yaz. 2y−3>7⇒2y>10⇒y>52y - 3 > 7 \Rightarrow 2y > 10 \Rightarrow y > 5. Kontrol: y = 6 → x = 9 > 7 ✔; y = 5 → x = 7, 7 > 7 değil ✔ (sınır dışlandı).

Soru 6orta

Compute the weakest precondition of the sequence: y = x + 4; x = y * 2; {x < 20}

Cevabı göster
{x < 6}

Sondan başa çalış. Son atama: 2y<20⇒y<102y < 20 \Rightarrow y < 10. Bu, ilk atamanın postcondition'ı olur. İlk atama: x+4<10⇒x<6x + 4 < 10 \Rightarrow x < 6. Kontrol: x = 5 → y = 9 → x = 18 < 20 ✔; x = 6 → y = 10 → x = 20 ✘.

Soru 7zor

Compute the weakest precondition: a = -2 * b + 4 {a < 0}

Cevabı göster
{b > 2}

−2b+4<0⇒−2b<−4-2b + 4 < 0 \Rightarrow -2b < -4. Negatif sayıya bölünce eşitsizlik yön değiştirir: b>2b > 2. Kontrol: b = 3 → a = -2 < 0 ✔; b = 2 → a = 0 ✘. En sık yapılan hata işaret çevirmeyi unutup b < 2 yazmak.

Soru 8zor

For integer x, compute the weakest precondition: if (x > 0) y = x - 1; else y = x + 1; {y > 0}

Cevabı göster
{x > 1 or x = 0}

Seçim kuralı: (x>0∧wp1)∨(x≤0∧wp2)(x > 0 \wedge wp_1) \vee (x \le 0 \wedge wp_2). Then dalı: x−1>0⇒x>1x - 1 > 0 \Rightarrow x > 1; x > 0 ile birlikte x > 1. Else dalı: x+1>0⇒x>−1x + 1 > 0 \Rightarrow x > -1; x ≤ 0 ile birlikte tam sayılarda sadece x = 0. Sonuç: x > 1 veya x = 0. (Gerçel sayılarda else kısmı −1<x≤0-1 < x \le 0 olurdu.)

Soru 9orta

Which preconditions make the triple {P} x = x - 3 {x > 0} valid? (a) x > 0 (b) x > 3 (c) x > 5 (d) x >= 3

Cevabı göster
(b) and (c)

Weakest precondition x > 3. Geçerli olan her P bunu gerektirmeli (P ⇒ x > 3). x > 5 daha güçlü (stronger) ama geçerli. x > 0 ve x ≥ 3 geçersiz: x = 3 için sonuç 0, 0 > 0 değil. Weakest = geçerli olanların en az kısıtlayıcısı.

Soru 10orta

Using the denotational rules below, compute MbinM_{bin} of 10110.

M_bin('0') = 0
M_bin('1') = 1
M_bin(<bin_num> '0') = 2 * M_bin(<bin_num>)
M_bin(<bin_num> '1') = 2 * M_bin(<bin_num>) + 1
Cevabı göster
22

Soldan sağa birikir: '1' → 1; '10' → 2·1 = 2; '101' → 2·2 + 1 = 5; '1011' → 2·5 + 1 = 11; '10110' → 2·11 = 22. Denotational semantics her sözdizimsel yapıyı matematiksel bir nesneye (burada bir tam sayıya) eşler.

Soru 11kolay

Name the dynamic semantics method described: (a) meaning is the sequence of state changes when the program runs on a virtual machine; (b) meaning is a mathematical function from states to states; (c) meaning is given by logical assertions before and after statements.

Cevabı göster
(a) operational (b) denotational (c) axiomatic

Operational: programı daha basit bir makine diline çevirip çalıştırmak gibi düşün, dil kılavuzları ve öğretimde kullanılır. Denotational: en titiz yöntem, matematiksel fonksiyonlar. Axiomatic: önkoşul/sonkoşul önermeleri, amaç program doğrulama (verification).

Soru 12orta

Compute the weakest precondition: b = a + 1; a = 3 * b; {a > 12}

Cevabı göster
{a > 3}

Son atama: 3b>12⇒b>43b > 12 \Rightarrow b > 4. İlk atama: a+1>4⇒a>3a + 1 > 4 \Rightarrow a > 3. Dikkat: sondaki a ile baştaki a aynı değişken ama farklı anlardaki değerleri; sondan başa giderken her atama kendi değişkenini değiştirir.

Doğrulama: Attribute grammar tip kontrolleri, a^n b^n c^n predicate'i ve denotational ikili sayı değerleri node ile hesaplandı; her weakest precondition cevabı -50..50 aralığındaki tüm tam sayılarla programın kendisi çalıştırılarak kaba kuvvetle karşılaştırıldı (verify/SEN2001/03a.mjs).

Deftere not kartı

static semantics: CFG'nin yazamadığı derleme zamanı kuralları (tip uyumu, önce bildir) attribute grammar = CFG + attribute'lar + semantic function'lar + predicate'ler synthesized: aşağıdan YUKARI (actual_type) inherited: yukarıdan AŞAĞI/yana (expected_type) intrinsic: yaprakta, symbol table'dan (look-up) sıra: look-up → expected aşağı → actual yukarı → predicate operational = sanal makinede durum değişimi (kılavuz) denotational = matematiksel fonksiyon (en titiz) axiomatic = {P} S {Q}, doğrulama wp(x = E, Q) = Q'da x yerine E yaz, sadeleştir sıralı ifade: SONDAN BAŞA if: (B and wp(then)) or (not B and wp(else)) negatifle bölünce eşitsizlik döner daha güçlü önkoşul da geçerli; weakest = en az kısıtlayıcı