ריבועים מסמנים סוגריים. לדוגמה, כשרואים את הבלוק הבא, צריך להבין שהוא מייצג את הערך -(5 + 2)
ולא את הערך -5 + 2
, כי הערכים 5
ו-2
הם חלק מבלוק אחד, והערך -
הוא חלק מבלוק אחר.
אבל אם תוסיפו סוגריים לכל בלוק, הקוד יהיה קשה יותר לקריאה. השוואה בין (((5) * (2)) + (3))
לבין 5 * 2 + 3
. שני הביטויים האלה מביאים לאותה תוצאה (13
), אבל הביטוי השני קל יותר לקריאה.
כללי תעדוף הפעולות של Blockly עוזרים ליצור קוד עם מספר מינימלי של סוגריים, כדי לשפר את הקריאוּת שלו.
יצירת פלט 'תקין'
אם הקוד שנוצר לא צריך להיות קריא לבני אדם, אין צורך לדאוג לגבי צמצום של סוגריים. אפשר להשתמש ב-wrap לכל בלוק, וזו גישה טובה שתעזור לכם לוודא שהקוד שנוצר תמיד ייבדק בצורה נכונה.
כדי לוודא שהקוד תקין, תמיד מעבירים את הערך Order.ATOMIC
לקריאות ל-valueToCode
, ותמיד מחזירים את הערך Order.NONE
מתוך הגנרטור של קוד הבלוק.
יצירת סוגריים אופטימליים
צריך להוסיף סוגריים רק אם הקוד שנוצר שגוי בלעדיהם. המצב הזה מתרחש כשעדיפות האופרטור בבלוק החיצוני חזקה יותר מעדיפות האופרטור בבלוק הפנימי.
לדוגמה, בבלוק הבא יש אופרטור של הכחשה חד-ערך ואופרטור של חיבור. לשלילה החד-ערוצית יש עדיפות גבוהה יותר מאשר למבצע החיבור.
לכן, אם לא מוסיפים סוגריים, מקבלים את הערך -5 + 2
, והערך של -
מחושב לפני הערך של +
, שלא תואם לבלוק.
כדי להורות למחולל מתי להוסיף סוגריים, צריך לציין את מידת החוזק של האופרטורים השונים. אם הוא מזהה שהאופרטור החיצוני חזק יותר מהאופרטור הפנימי, הוא מוסיף סוגריים כדי להגן על האופרטור הפנימי.
valueToCode
מקבל את תעדוף האופרטור החיצוני, והטופלת המוחזרת מציינת את תעדוף האופרטור הפנימי.
דוגמה לבלוק שכולל שני אופרטורים:
import {javascriptGenerator, Order} from 'blockly/javascript';
javascriptGenerator.forBlock['negate_plus_two'] = function(block, generator) {
// valueToCode takes in the precedence of the outer operator.
const innerCode = generator.valueToCode(block, 'INNER', Order.UNARY_NEGATION);
const code = `-${innerCode} + 2`;
// The return tuple specifies the precedence of the inner operator.
return [code, Order.ADDITION];
}
קדימות של valueToCode
כשקוראים ל-valueToCode
כדי ליצור את הקוד של בלוק פנימי, מעבירים לו את תעדוף האופרטור החזק ביותר שפועל על הקוד של הבלוק הפנימי. זהו המפעיל מפניו צריך להגן על הקוד של הבלוק הפנימי.
לדוגמה, בבלוק הבא, גם אופרטור השלילה החד-ערךית וגם אופרטור החיבור פועלים על הקוד של הבלוק הפנימי. השלילה החד-ערך חזקה יותר, ולכן זו העדיפות שצריך להעביר ל-valueToCode
.
// The - is the strongest operator acting on the inner code.
const innerCode = generator.valueToCode(block, 'INNER', Order.UNARY_NEGATION);
const code = `-${innerCode} + 2`;
קדימות ההחזרה
כשמחזירים עדיפות ממחולל הקוד של הבלוק, צריך להחזיר את העדיפות של האופרטור החלש ביותר בקוד של הבלוק. זהו המשתנה שצריך להגן עליו.
לדוגמה, הבלוק הבא מכיל גם אופרטור של הכחשה חד-ערך וגם אופרטור של חיבור. התוספת חלשה יותר, ולכן זו העדיפות שצריך להחזיר ממחולל הקוד של הבלוק.
const code = `-${innerCode} + 2`;
// The + is the weakest operator in the block.
return [code, Order.ADDITION];
סדר הטיפוסים בני המנייה (enum)
כל מודול של יצירת שפה מגדיר enum של Order
שכולל את כל סדרי העדיפויות של השפה הזו.
לעדיפויות חזקות יותר יש ערכים נמוכים יותר של תמיכה, ולעדיפויות חלשות יותר יש ערכים גבוהים יותר של תמיכה. אפשר לחשוב על סדרי עדיפויות חזקים כ'מדורגים גבוה יותר' בעוצמה, ועל סדרי עדיפויות חלשים כ'מדורגים נמוך יותר' – כאילו הם לוחמים בתחרות.
כאן אפשר למצוא את המאפיינים של Order
לכל השפות המובנות:
סדרי עדיפויות מיוחדים
רוב סדרי העדיפויות במערכי הערכים של Order
בגנרטורים תואמים לסדרי העדיפויות שמוגדרים בשפות הטקסט שלהם. אבל יש שתי רמות עדיפות מיוחדות, Order.ATOMIC
ו-Order.NONE
.
Order.ATOMIC
היא העדיפות הגבוהה ביותר. הוא משמש במקרים הבאים:
- כדי לוודא שהקוד תמיד מופיע בסוגריים, מעבירים אותו ל-
valueToCode
. - הבלוק לא כולל אופרטורים, ולכן מחזירים אותו ממחולל הקוד של הבלוק.
Order.NONE
היא העדיפות החלשה ביותר. הוא משמש במקרים הבאים:
- אתם רוצים לוודא שהקוד תמיד מופיע בסוגריים, ולכן אתם מחזירים אותו ממחולל הקוד של הבלוק.
- אין אופרטורים שפועלים על בלוק פנימי, לכן מעבירים אותו אל
valueToCode
.