מודולה-2

מוֹדוּלה־2 (באנגלית: Modula-2) היא שפת תכנות מערכות מובנת ופרוצדורלית עם טיפוסיות חזקה וסטטית שפותחה על ידי ניקלאוס וירת בין השנים 1977–1988 במכון הטכנולוגי של ציריך.<ref name=":1"></ref> מודולה־2 הורחבה במקור מפסקל,<ref></ref> והיא ירשה את הפיתוח של מודולה.<ref></ref> מודולה־2 באה לתת מענה מקיף לכל החסרונות של פסקל.<ref name=":1" /><ref></ref><ref name=":1guide" group="א">Programming in Modula-2, Preface, pp. 3–5</ref><ref name=":0report" group="ב">Report, Introduction, pp. 133–134</ref>

== היסטוריה ==
בשנת 1976 וירת ביקר במעבדת פארק, היכן שתפס את ההשראה לפיתוח של מודולה־2 משפת התכנות מֶסַה.<ref name=":1guide" group="א" /><ref name=":1" />
בשנת 1980 [[DISER Lilith היה המחשב הראשון שהושק עם מערכת הפעלה שפותחה במודולה־2.<ref name=":1" />]]
בשנת 1977 וירת התחיל את הפיתוח של מודולה־2 כהמשך לפיתוח של מודולה, וכתחליף לפסקל.<ref name=":1guide" group="א" /> מודולה הראשונה הייתה שפת תכנות נסיונית, והיא מעולם לא פותחה מעבר לשלבי הניסוי שלה אחרי שנת 1975. וירת תכנן את מודולה־2 שתהיה שפת תכנות מערכות ושפת תכנות כללית במחשבי DISER Lilith.<ref name=":1" /><ref name=":1guide" group="א" /> תחביר השפה היה דומה יותר לזה של מודולה מאשר לפסקל, לכן וירת החליט לקרוא לה מודולה־2.<ref name=":1guide" group="א" />

בשנת 1978 פורסמה המהדורה הראשונה של הדו"ח של אפיון השפה.<ref></ref>

בשנת 1979 נוצר היישום השימושי הראשון של השפה עבור מחשבי ה־PDP-11 בשימוש פנימי של המכון הטכנולוגי של ציריך.<ref name=":1guide" group="א" />

בשנת 1980 פורסמה המהדורה השנייה של הדו"ח של האפיון השפה.<ref></ref><ref name=":1guide" group="א" />

בשנת 1981 מהדר השפה שוחרר בפעם הראשונה לציבור הרחב.<ref name=":1guide" group="א" /> מיד לאחר מכן השפה צברה פופולריות ונוצר עניין ציבורי בפרסום מדריך רשמי עבור השפה.<ref name=":1guide" group="א" />

בשנת 1982 פורסמה הגרסה הראשונה של מדריך השפה מאת ניקלאוס וירת על ידי הוצאת שפרינגר.<ref></ref>

בשנת 1983 פורסמה הגרסה השנייה של השפה (PIM2).<ref></ref>

בין השנים 1983–1985 וירת החליט לפתח מהדר משלו עבור השפה. המהדר של וירת היה מהיר ויעיל בהרבה מהמהדרים שהוצעו עד כה לשפה.<ref name=":1" /><ref name=":0wirth"></ref>

בשנת 1985 פורסמה הגרסה השלישית של השפה (PIM3).<ref></ref>

בשנת 1988 פורסמה הגרסה הרביעית של השפה (PIM4).<ref name=":12wirth"></ref> 

בשנת 1989 וירת פרסם מאמר בו התייחס לתכנות מונחה עצמים במודולה־2, למרות שבמקור לא עוצבה לכך. במאמר וירת הציע פתרון לחיקוי הורשה במודולה־2 באמצעות היכולת של השפה להתעלם מאכיפת טיפוסיות בתכנות מערכות.<ref></ref>

בשנת 1996 ארגון התקינה הבין־לאומי (ISO) פרסם תקן מקיף לשפת התכנות מודולה־2. מכיוון שהיו בו שינויים מזעריים אך מחייבים בשפה, הוא נחשב לניב נוסף של השפה.<ref></ref>

בשנת 2010 שוחררה הגרסה הראשונה של המימוש החופשי GNU Modula-2 עבור המהדר GCC לציבור הרחב מטעם מיזם גנו.<ref name=":5" />

בשנת 2011 שוחררה הגרסה הראשונה של המהדר החינמי ADW Modula-2 לציבור הרחב אחרי שירש את הפיתוח של המהדר Stony Brook Modula-2.<ref name=":3" />

=== תיעוד ===
מדריך השפה יצא לאור בארבע מהדורות בין השנים 1982–1988. המהדורות שיקפו על שינויים בשפה. סקירת השפה פורסמה באופן חופשי לקהל הרחב בגרסת PDF מתוך מדריך השפה. הסקירה כוללת בה אפיון מלא של השפה.<ref group="א">Programming in Modula-2, Report on the Programming Language Modula-2, pp. 133–156</ref> גרסת ה־PDF שפרסמה הוצאת שפרינגר כוללת בה גם את ארבעת הנספחים האחרונים בספר: הגדרת תחביר השפה בסימון EBNF ,<ref name=":7guide" group="א">Programming in Modula-2, The Syntax of Modula-2, pp. 157–160</ref> תיאור ספריית הליבה של מודולה־2,<ref group="א">Programming in Modula-2, Appendix 2: Standard Utility Modules, pp. 161–169</ref> טבלת תוי ASCII,<ref group="א">Programming in Modula-2, Appendix 3: The ASCII Character Set, p. 170</ref> ותרשימי זרימה לתחביר השפה.<ref group="א">Programming in Modula-2, Appendix 4: Syntax Diagrams, pp. 171–180</ref>

== דוגמאות ==
=== שלום, עולם! ===
<syntaxhighlight lang="modula2" line="1">
MODULE HelloWorld
 IMPORT InOut;
BEGIN
 InOut.WriteString("Hello, world!");
 InOut.WriteLn;
END HelloWorld.
</syntaxhighlight>

=== מחלק משותף מרבי ===

הדוגמה הבאה מוצאת את המחלק המשותף המריבי בין המונה <code>a</code> למכנה <code>b</code> בשבר פשוט שהמשתמש קולט לתוכם, ואז מדפיסה אותו במסוף.<ref name=":12guide" group="א">Programming in Modula-2, A First Example, pp. 11–13</ref>
<syntaxhighlight lang="modula2" line="1">
MODULE GCD
 FROM InOut IMPORT ReadInt, WriteString, WriteLn, WriteInt;
 VAR a, b: INTEGER;
BEGIN
 WriteString("a = "); ReadInt(a); WriteLn;
 WriteString("b = "); ReadInt(b); WriteLn;
 WHILE a # b DO
 IF a > b THEN
 a := a - b
 ELSE
 b := b - a
 END
 END;
 WriteString("GCD = ");
 WriteInt(a, 6);
 WriteLn;
END GCD.
</syntaxhighlight>

== עיצוב ==
וירת עיצב את מודולה־2 כדי לתת מענה מקיף לכל החסרונות של פסקל, והכתיר אותה להיות היורשת.<ref name=":1guide" group="א" /><ref name=":0report" group="ב" /> מודולה־2 היא שפת תכנות מערכות, ולמרות זאת, המודלריות שלה מאפשרת לתוכניות לעבור הידור מוצלח בלי שינויים נוספים עבור ארכיטקטורות מחשבים שונות, מכיוון שיישום השפה (המהדר והמודולים שלו) דואג לספק מודולים מערכתיים עם ממשק זהה ויישום מותאם לכל ארכיטקטורה שהוא מכיר בה. מודולים מערכתיים אלה עוברים הידור נפרד ובלתי־תלוי בשאר התוכנית של המשתמש. אחריות זו מוטלת על יישום השפה.<ref name=":0report" group="ב" /> חידושיה המרכזיים של מודולה־2 על פני פסקל הם:

# פִּירְקָן<ref></ref> (או ) כיחידת קוד מקור שעוברת הידור נפרד משאר הקוד.<ref name=":1guide" group="א" /><ref name=":0report" group="ב" />
# תחביר חינוכי ואחיד שמעודד את למידת השפה תוך כדי הקריאה.<ref name=":1guide" group="א" /><ref name=":0report" group="ב" />
# שִׁגְרַת הֶמְשֵׁךְ <ref></ref> (או ) כמנגנון ליישום וניהול תהליכים בו־זמניים .<ref></ref><ref name=":1guide" group="א" /><ref name=":0report" group="ב" />
# גישה למבני נתונים ללא אכיפת טיפוסיות בתכנות מערכות. זה שימוש בעיקר לפיתוח מערכת ההפעלה של DISER Lilith.<ref name=":1guide" group="א" />

=== תחום הכרזה ===
כמו שפות אימפרטיביות אחרות, גם מודולה־2 משתמשת בתחום הכרזה לקסיקלי. כלומר, שמות משתנים חייבים להיות מוכרזים לפני השימוש בהם באותו התחום.<ref name=":12guide" group="א" /><ref group="ב">Report, Declarations and Scope Rules, pp. 135–136</ref> בנוסף, על מנת להשתמש במשתנה בביטוי, חייבים להקצות לו ערך כלשהו.<ref name=":3guide" group="א">Programming in Modula-2, Statements and Expressions, pp. 19–21</ref>

=== טיפוסי נתונים ===
מודולה־2 מכירה בשישה טיפוסי נתונים : מספר שלם, מספר טבעי, מספר ממשי, בוליאני (אמת או שקר), תו, ומערך ביטים .<ref name=":2guide" group="א">Programming in Modula-2, Elementary Data Types, pp. 28–35</ref> לא ניתן לשנות טיפוס של משתנה לאחר הכרזתו, וניסיון להקצות ערך שאינו הולם את טיפוסיות המשתנה יגרום לשגיאת הידור עוד לפני הריצה של התוכנית.<ref name=":2guide" group="א" /> אי לכך, מודולה־2 היא שפת תכנות עם טיפוסיות חזקה וסטטית. בנוסף, טיפוס הנתונים של המשתנה מגדיר את הפעולות האפשריות עליו.<ref name=":2guide" group="א" /> מודולה־2 מאפשרת למתכנת להגדיר הרכבות של טיפוסי נתונים מתקדמים יותר בעזרת ששת הטיפוסים הבסיסיים.<ref name=":2guide" group="א" /> לא רק משתנים נושאים עימם טיפוסיות, אלא גם קבועים, פונקציות, ותוצאות של פעולות.<ref name=":2guide" group="א" /> בנוסף, מודולה־2 לא מבצעת המרת טיפוסים בלי הוראה מפורשת. לדוגמה, פעולת חשבון בין מספר טבעי ומספר ממשי תדרוש המרה מפורשת של אחד מהם לטיפוס של האחר בעזרת <code>FLOAT(n)</code> או <code>TRUNC(x)</code>.<ref name=":2guide" group="א" />
{| class="wikitable mw-collapsible"
|+טיפוסי הנתונים הבסיסיים של מודולה־2<ref name=":2guide" group="א" /><ref name=":5report" group="ב">Report, Basic Types, pp. 137</ref><ref name=":2"></ref><ref></ref>
!סיווג
!שם
!פעולות
!בתים
!טווח ערכים מותר
|-
| rowspan="2" |מספר שלם
|<code>INTEGER</code>
| rowspan="4" |חיבור <code>+</code>, חיסור <code>-</code>, כפל <code>*</code>, חילוק שלמים <code>DIV</code>, ושארית <code>MOD</code>.
|2
|<math>-2^{15} \leq n \in \mathbb{Z} \leq 2^{15}-1</math>
|-
|<code>LONGINT</code>
|4
|<math>-2^{31} \leq n \in \mathbb{Z} \leq 2^{31}-1</math>
|-
| rowspan="2" |מספר טבעי
|<code>CARDINAL</code>
|2
|<math>0 \leq n \in \mathbb{N} \leq 2^{16}-1</math>
|-
|<code>LONGCARD</code>
|4
|<math>0 \leq n \in \mathbb{N} \leq 2^{32}-1</math>
|-
| rowspan="2" |מספר ממשי
|<code>REAL</code>
| rowspan="2" |ארבע פעולות חשבון: <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>.
|4
|<math>8.43 \times 10^{-37} \leq x \in \mathbb{R} \leq 3.37 \times 10^{38}</math>
|-
|<code>LONGREAL</code>
|8
|<math>4.19 \times 10^{-307} \leq x \in \mathbb{R} \leq 1.67 \times 10^{308}</math>
|-
|בוליאני
|<code>BOOLEAN</code>
|שלילה <code>NOT</code> (או <code>~</code>), וגם <code>AND</code> (או <code>&</code>), ואו <code>OR</code>.
|1
|<code>TRUE</code> או <code>FALSE</code>
|-
| rowspan="2" |תו
| rowspan="2" |<code>CHAR</code>
| rowspan="2" |להמיר תו למספר סידורי <code>ORD("c")</code>, להמיר מספר סידורי לתו <code>CHR(n)</code>.
|1
|במקור תו ASCII.
|-
|2
|מהדרים חדשים מציעים Unicode.
|-
|מערך ביטים
|<code>BITSET</code>
|איחוד <code>+</code>, הפרש <code>-</code>, חיתוך <code>*</code>, והפרש סימטרי <code>/</code>.
|2
|מערך ערכי <code>CARDINAL</code> מ־0 עד 15.
|}

=== מודלריות ===
אחד מחידושיה המרכזיים של מודולה־2 הוא פיצול התוכנית למודולים כיחידות קוד מקור שעוברות הידור נפרד.<ref name=":1guide" group="א" /><ref name=":0report" group="ב" /> במודולה־2, מודול מוגדר בשני רבדים: הכרזת הממשק, ויישום המודול.<ref name=":0report" group="ב" /> בדומה לשפת C, הכרזת הממשק של המודול נמצאת בקובץ נפרד שמכריז על השגרות הזמינות באותו מודול, על סוגי המשתנים שהן קולטות ופולטות. הכרזת המודול היא שימושית בעיקר למהדר, ואין צורך לספק אותה למשתמש התוכנית. לעומת זאת, יישום המודול עובר הידור לשפת מכונה כי הוא מכיל בו קוד אימפרטיבי שמתאר את אופן הפעולה והביצוע של השגרות והתכנית.<ref name=":0report" group="ב" />

== תחביר ==
התחביר של מודולה־2 מורכב מפקודות אימפרטיביות. פקודות מופרדות בעזרת נקודה ופסיק <code>;</code>, ולעיתים קרובות הן גם מכילות ביטויים שעוברים חישוב. פקודות וביטויים מורכבים מאסימונים שנוצרים מרצף תווי ASCII. המהדר מבצע בדיקת דקדוק תחבירי, ניתוח סמנטי, וניתוח לקסיקלי, ואז מתרגם פקודות לשפת סף. אסימונים מוכרים מייצגים בין היתר מילים שמורות, ערכים, מחרוזות, הערות, מזהים (שמות של משתנים, קבועים, שגרות, ומודולים), פעולות, ופיסוק.<ref group="ב">Report, Syntax, p. 134</ref><ref name=":1report" group="ב">Report, Vocabulary and Representation, pp. 134–135</ref><ref name=":22guide" group="א" />

=== אסימוני השפה ===
{| class="wikitable mw-collapsible"
|+אסימונים במודולה־2<ref name=":22guide" group="א">Programming in Modula-2, Representation of Modula Programs, pp. 16–18</ref><ref name=":1report" group="ב" />
! colspan="3" |סיווג
!הגדרה
!דוגמה
|-
|מזהה
| colspan="2" |שם משתנה
|רצף של תווי אותיות אלף־בת לטיניות וסיפרות עשרוניות, כשהתו הראשון מוכרח להיות אות.
|<code>i8MyPi</code>
|-
| rowspan="6" |ערך
| rowspan="3" |מספר שלם
|עשרוני
|רצף סיפרות עשרוניות.
|<code>2016</code>
|-
|אוקטלי
|רצף סיפרות עשרוניות בטווח 0–7 ותו <code>B</code> עוקב.
|<code>7B</code>
|-
|הקסדצימלי
|רצף סיפרות עשרוניות ואותיות מ־<code>A</code> עד <code>F</code> ותו <code>H</code> עוקב.
|<code>FFFFFFH</code>
|-
| rowspan="2" |מספר ממשי
|שבר עשרוני
|רצף סיפרות עשרוניות עם נקודה עשרונית.
|<code>1.25</code>
|-
|כתיב מדעי
|רצף סיפרות עשרוניות עם נקודה עשרונית, התו <code>E</code>, סימן <code>+</code> או <code>-</code> ורצף ספרות עשרוניות נוסף.
|<code>4.0E-10</code>
|-
| colspan="2" |מחרוזת
|רצף תווים שנפתח ונסגר בתו <code>"</code>, או שנפתח ונסגר בתו <code>'</code>.
|<code>"Hello world"</code>

<code>'Hello world'</code>
|-
| rowspan="3" |תחביר
| colspan="2" |פעולה
|כל הופעה של תו המייצג פעולה (ראה פעולות).
|<code>+</code>
|-
| colspan="2" |מילה שמורה
|כל רצף תווים שיוצר מילה מרשימת המילים השמורות.
|<code>IF</code>
|-
| colspan="2" |הערה
|כל רצף שנפתח ב־ ונסגר ב־.
|<code>(* Comment *)</code>
|}

=== מילים שמורות ===
למודולה־2 קיימות ארבעים מילים שמורות.<ref name=":22guide" group="א" /><ref name=":1report" group="ב" />
<syntaxhighlight lang="modula2">
AND ELSIF LOOP REPEAT
ARRAY END MOD RETURN
BEGIN EXIT MODULE SET
BY EXPORT NOT THEN
CASE FOR OF TO
CONST FROM FOR TYPE
DEFINITION IF POINTER UNTIL
DIV IMPLEMENTATION PROCEDURE VAR
DEFINITION IMPORT QUALIFIED WHILE
ELSE DEFINITION RECORD WITH
</syntaxhighlight>

=== פקודות וביטויים ===
בדומה לשפות תכנות רבות, פקודות במודולה־2 מאפשרות תכנות אימפרטיבי בכך שהן מורות בקרת זרימה והקצאת ביטויים לתוך משתנים, בעוד שהביטויים עצמם הם רצפים של פעולות ואופרנדים שעוברים חישוב לפי סדר פעולות מתמטי, או סדר פעולות שהמתכנת מגדיר בעזרת סוגריים עגולים.<ref name=":3guide" group="א" /> מודולה־2 מכירה באחד־עשרה סוגי פקודות:<ref name=":3guide" group="א" />

# הקצאה (קליטת ערך למשתנה) <code>:=</code>
# קריאת שגרה
# שינוי תחום משתנים <code>WITH</code>
# שמונה פקודות לבקרת זרימה:
## תנאי <code>IF</code>
## מִקְרֶה<ref></ref> <code>CASE</code>
## חזרה <code>RETURN</code>
## יציאה ידנית מלולאה <code>EXIT</code>
## וארבעה סוגי לולאות:
### לולאה אין־סופית <code>LOOP</code>
### לולאת <code>WHILE</code>
### לולאת <code>REPEAT</code>
### לולאת <code>FOR</code>

==== קבועים ====
מודולה־2 מאפשרת למתכנת להכריז ערכים קבועים. ערכים אלה אינם משתנים במהלך התוכנית, וערכם נקבע על ידי המהדר לפני הריצה של התוכנית. הכרזה של קבוע נעשית בעזרת הסימן <code>=</code>, והמילה <code>CONST</code> מאפשרת הכרזה של כמה קבועים ברצף כמו בדוגמה למטה.<ref name=":4guide" group="א">Programming in Modula-2, Constant and Variable Declarations, p. 36</ref><ref group="ב">Report, Constant Declarations, p. 136</ref>
<syntaxhighlight lang="modula2">
CONST PI = 3.14159;
 E = 2.71828;
 N = 16;
 M = N - 1;
</syntaxhighlight>

==== משתנים ====
הכרזה של משתנה נעשית בעזרת הסימן <code>:</code> כשמשמאל שם המשתנה, ומימין טיפוס המשתנה. בדומה לקבועים, ניתן להכריז מספר משתנים ברצף בעזרת המילה <code>VAR</code>.<ref name=":4guide" group="א" />
<syntaxhighlight lang="modula2">
VAR i, j, k: INTEGER;
 x, y, z: REAL;
 c: CHAR;
</syntaxhighlight>

=== בקרת זרימה ===
מהיותה שפת תכנות מבנית, חלק מסוגי הפקודות יכולות להכיל בתוכן תת־פקודות. לדוגמה, תנאי <code>IF</code> יכול להיות מוכל בתוך תנאי <code>IF</code> אחר, שגם הוא יכול להיות מוכל בתוך לולאת <code>WHILE</code>, וכך בעצם נוצרת בקרת זרימה.<ref name=":3guide" group="א" /> במודולה־2, הסימן נקודה ופסיק <code>;</code> הוא מפריד בין פקודות ומגדיר את סדר הביצוע בתוכנית.<ref name=":3guide" group="א" />

===== לולאות =====
מודולה־2 מציעה ארבעה סוגי לולאות: <code>LOOP</code>, <code>WHILE</code>, <code>REPEAT</code>, ו־<code>FOR</code>.<ref name=":0guide" group="א">Programming in Modula-2, Control Structures, pp. 22–27</ref> כמו בשפות אחרות, הלולאות <code>WHILE</code>, <code>REPEAT</code>, ו־<code>FOR</code> הן תלויות בתנאי כלשהו.<ref name=":0guide" group="א" /> לעומת זאת, הלולאה <code>LOOP</code> היא אין־סופית ומתקיימת ללא תנאים. לכן, היא דורשת יציאה ידנית באמצעות הפקודה <code>EXIT</code> בתוכה.<ref name=":6report" group="ב">Report, Loop Statements, p. 147</ref><ref name=":0guide" group="א" /> ובכל אופן, הפקודה <code>EXIT</code> יודעת לעצור לולאה מכל סוג.<ref name=":3report" group="ב">Report, Return and Exit Statements, pp. 147–148</ref> דוגמה ללולאת <code>LOOP</code>:<ref name=":0guide" group="א" /><ref name=":6report" group="ב" />
<syntaxhighlight lang="modula2">
LOOP
 IF i < n THEN
 i := i + 1
 ELSE
 EXIT
 END
END
</syntaxhighlight>
בלולאת <code>WHILE</code>, כל עוד התנאי מתקיים, הלולאה תמשיך לחזור על עצמה. דוגמה ללולאת <code>WHILE</code>:<ref name=":0guide" group="א" /><ref name=":7report" group="ב">Report, While Statements, pp. 145–146</ref>
<syntaxhighlight lang="modula2">
WHILE i < n DO
 i := i + 1
END
</syntaxhighlight>
בלולאת <code>REPEAT</code>, הבדיקה נעשית בסוף המחזור, והמחזור הראשון מתקיים ללא תנאי. התנאי לעצירה צריך להתקיים על מנת שהלולאה תיעצר. דוגמה ללולאת <code>REPEAT</code>:<ref name=":0guide" group="א" /><ref name=":8report" group="ב">Report, Repeat Statements, p. 146</ref>
<syntaxhighlight lang="modula2">
REPEAT
 i := i + 1
UNTIL i = n
</syntaxhighlight>
בלולאת <code>FOR</code> ישנה הכרזה של משתנה ייעודי. ברירת המחדל, הלולאה מקדמת את המשתנה שלה ב־1 כל מחזור, אבל אפשר להגדיר את קצב ההתקדמות או להפוך אותה להתקדמות שלילית בעזרת <code>BY</code> בפקודת <code>FOR</code>:<ref name=":5guide" group="א">Programming in Modula-2, The Data Structure Array, pp. 37–46</ref><ref name=":9report" group="ב">Report, For Statements, pp. 146–147</ref>
<syntaxhighlight lang="modula2">
FOR i := 0 TO -n BY -1 DO
 (* Statements *)
END
</syntaxhighlight>
===== תנאים =====
במודולה־2, הפקודה <code>IF</code> מאפשרת בקרת זרימה לפי תנאים. אם התנאי הראשון נכשל, ניתן לשרשר מספר תנאים נוספים אחריו בעזרת <code>ELSIF</code>, ומצב ברירת מחדל באמצעות <code>ELSE</code>.<ref group="ב">Report, If Statements, p. 145</ref><ref name=":0guide" group="א" /> חשוב לציין שבשרשרת תנאים הבדיקה היא לפי סדר הופעתם. לכן, ברגע שתנאי אחד מתקיים, כל השאר אחריו מדולגים.<ref name=":0guide" group="א" /> תחביר של תנאי מלא יראה כך:
<syntaxhighlight lang="modula2">
IF n = 0 THEN
 (* n equals 0 *)
ELSIF n = 1 THEN
 (* n equals 1 *)
ELSIF n > 1 THEN
 (* n is greater than 1 *)
ELSE
 (* n is lesser than 0 *)
END
</syntaxhighlight>

=== מבני נתונים ===
מודולה־2 מציעה שמונה סוגים בסיסיים של טיפוסי נתונים:

# טיפוס ערך (לדוגמה, משתנה המחזיק בו ערך של מספר ממשי)<ref name=":5report" group="ב" /><ref name=":2" />
# <ref name=":0hebrew" /><ref name=":6guide" group="א" /><ref name=":10report" group="ב" />
# <ref name=":11report" group="ב">Report, Subrange Types, pp. 137–138</ref>
# מערך<ref name=":5guide" group="א" /><ref name=":2report" group="ב">Report, Array Types, p. 138</ref>
# רשומה<ref></ref><ref name=":12report" group="ב">Report, Record Types, pp. 138–139</ref>
# קבוצה (דומה למושג קבוצה במתמטיקה)<ref group="ב">Report, Set Types, p. 139</ref>
# מצביע<ref group="ב">Report, Pointer Types, p. 140</ref>
# טיפוס פונקציה (טיפוס נתונים שיודע להחזיק בו כתובת של פונקציה או שגרה באופן דומה לתכנות פונקציונלי)<ref group="ב">Report, Procedure Types, p. 140</ref><ref></ref>

בעזרת הטיפוסים הבסיסיים בשפה ניתן להרכיב טיפוסי נתונים חדשים עבור מבני נתונים מורכבים יותר כגון מערך דו־ממדי. לאחר הכרזת הטיפוסים החדשים ניתן להמשיך להרכיב בעזרתם טיפוסים מורכבים אף יותר.<ref group="ב">Report, Type Declarations, pp. 136–140</ref>

==== מערכים ====
באופן דומה להכרזת משתנים, הכרזת מערכים תיעשה בעזרת המילה <code>ARRAY</code>, טווח האיברים מוגדר בעזרת שתי נקודות <code>..</code> בין סוגריים מרובעים, וטיפוסיות האיברים תבוא בסוף הפקודה אחרי המילה <code>OF</code>.<ref name=":5guide" group="א" /><ref name=":2report" group="ב" /> גישה למערכים נעשית בעזרת סוגריים מרובעים <code>A[i]</code>, ובמערכים רב־ממדיים מפרידים בין הממדים בעזרת פסיק <code>,</code>: <code>A[i, j]</code>.<ref name=":5guide" group="א" /><ref name=":2report" group="ב" /> שלא כמו בשפות אחרות, הקצאה בין משתנים שמחזיקים מערכים היא בפועל מעתיקה את המערך בינם ולא רק את המצביע. מתכנת מתחיל היה עושה זאת בעזרת לולאה, ומעתיק איבר־איבר, אך במודולה־2 מספיק להקצות את כל המערך למשתנה חדש, והוא למעשה יוצר מערך נפרד עם אותם איברים.<ref name=":5guide" group="א" />
<syntaxhighlight lang="modula2">
VAR A: ARRAY [0 .. N-1] OF INTEGER;
</syntaxhighlight>
במודולה־2 אפשר להכריז על מערכים רב־ממדיים לאיברים מאותו טיפוס בעזרת שני תחבירים:<ref name=":5guide" group="א" />
<syntaxhighlight lang="modula2">
VAR A: ARRAY [1 .. N], [1 .. M] OF INTEGER;
</syntaxhighlight>
<syntaxhighlight lang="modula2">
VAR A: ARRAY [1 .. N] OF
 ARRAY [1 .. M] OF INTEGER;
</syntaxhighlight>
==== טיפוסי נמנים ====

במודולה־2 ניתן להגדיר <ref name=":0hebrew"></ref> בעזרת רשימת מזהים בסוגריים עגולים.<ref name=":6guide" group="א">Programming in Modula-2, Enumeration Types, p. 64</ref><ref name=":10report" group="ב">Report, Enumerations, p. 137</ref> בדומה לטיפוס התו (<code>CHAR</code>), ניתן לבקש את המספר הסידורי של כל איבר במניה בעזרת הפונקציה <code>ORD(item)</code>.<ref name=":6guide" group="א" /> בנוסף, הטיפוס הבוליאני (<code>BOOLEAN</code>) במודולה־2 הוא מקרה פרטי של טיפוס נמנים מהצורה: <code>1=BOOLEAN = (FALSE, TRUE)</code>.<ref name=":6guide" group="א" /> השימוש בטיפוסי נמנים הוא כשאר הטיפוסים בשפה. כלומר, משתנה מאותו טיפוס נמנים יכול להכיל בו אחד מהפריטים במנייה.<ref name=":6guide" group="א" />
<syntaxhighlight lang="modula2">
TYPE messageType = (error, warning, info);
 messagePriority = (prompt, monitor, log);
 messageBell = (beep, visual, sound);
</syntaxhighlight>

==== טווח משנה ====
במודולה־2 ניתן להגדיר טיפוס נתונים חדש שמגביל את טווח הערכים המותר בטיפוס ערכי בלתי־רציף (כלומר, טיפוס מספרי שאינו מספר ממשי) או טיפוס נמנים קיים. לדוגמה, טווח משנה אופייני של ימי עסקים וסוף שובע בישראל בתוך ימי השבוע יוגדר כך:<ref name=":11report" group="ב" />
<syntaxhighlight lang="modula2">
(* Describing working days and weekend days in Israel via enum subranges. *)
TYPE Days = (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday);
 WorkingDays = Days [Sunday .. Thursday];
 WeekendDays = Days [Friday .. Saturday];
</syntaxhighlight>

==== רשומות ====
רשומה היא טיפוס הנתונים הגמיש ביותר בשפה, והיא מאפשרת למתכנת להגדיר טיפוס נתונים חדש המורכב מכמה טיפוסי נתונים שונים בתוך הרשומה בעזרת ”שדות.“ שדות גם יכולים להכיל בהם רשומות באופן מקונן.<ref name=":12report" group="ב" /> בעזרת רשומות ניתן לתאר בשפה טיפוסי נתונים מגוונים הן לשימוש רב־תכליתי ומופשט כגון עץ בינארי, והן לשימוש מסוים כגון פרטי לקוחות. לדוגמה, רשומה פשוטה המתארת ייצוג צבע תוגדר בעזרת רשומה המורכבת משלושה שדות, שכל אחד מהם מכיל ערך מטיפוס טווח משנה של מספר שלם:
<syntaxhighlight lang="modula2">
(* Record type describing an RGB color. *)
TYPE Color = RECORD
 R: INTEGER [0..255];
 G: INTEGER [0..255];
 B: INTEGER [0..255];
END
</syntaxhighlight>
בנוסף, במודולה־2 ניתן להגדיר זמינות של שדות על פי הערכים שנמצאים בשאר השדות.<ref name=":12report" group="ב" /> לדוגמה, לכל אדם קיים תאריך לידה, אך רק לאדם שנפטר קיים תאריך פטירה:
<syntaxhighlight lang="modula2">
TYPE Date = RECORD
 Day: INTEGER [1..31];
 Month: INTEGER [1..12];
 Year: INTEGER;
END;
Person = RECORD
 Born: Date;
 CASE IsAlive: BOOLEAN OF
 FALSE: Died: Date;
 END;
END;
</syntaxhighlight>

=== שגרות ===

מהיותה שפת תכנות פרוצדורלית, מודולים במודולה־2 עשויים להגדיר תת־תוכניות ולייצא אותם כפקודות עם שמות ייחודיים ופרמטרים. פקודות כאלה נקראות שִגְרוֹת והן מוגדרות בעזרת המילה <code>PROCEDURE</code>.<ref group="א">Programming in Modula-2, Procedures, pp. 47–48</ref><ref name=":4report" group="ב">Report, Procedure Declarations, pp. 148–150</ref><ref name=":0"></ref> שגרה היא בגדר ”“ אם היא מחזירה ערך כלשהו, אחרת היא בגדר ”.“<ref name=":4report" group="ב" /><ref name=":0" /> פונקציות מחזירת ערך בעזרת הפקודה <code>RETURN</code>.<ref name=":3report" group="ב" /> לכן, ביטויים מתייחסים אליהן כאל ערכים שטרם חושבו.<ref name=":4report" group="ב" /><ref name=":0" /> שגרות יודעות להכריז על משתנים מקומיים בקטע הפנימי שנמצא בין ה־<code>PROCEDURE</code> וה־<code>BEGIN</code>.<ref name=":4report" group="ב" /><ref name=":0" /> דוגמה לפונקציה ריבועית פשוטה <math>f(x)=x^2</math> כך ש־<math>f:\R \rightarrow \R</math> (כלומר, פונקציה שמקבלת ומחזירה מספרים ממשיים):
<syntaxhighlight lang="modula2">
PROCEDURE f(x: REAL): REAL;
BEGIN
 RETURN x * x;
END f
</syntaxhighlight>
במודולה־2, הפעלת פונקציות מחייבת שימוש בסוגריים עגולים אפילו בהיעדר פרמטרים. לדוגמה,. לעומת זאת, אין צורך בכתיב עם סוגריים עגולים בציווים שלא מקבלים פרמטרים. לדוגמה, <code>MinimizeWindow</code>.<ref name=":4report" group="ב" /><ref name=":0" /> בנוסף, שגרות יודעות לקבל שני סוגים של פרמטרים: ”,“ ו”.“ פרמטר מסוג ”משתנה“ מוכרז בעזרת המילה <code>VAR</code> לפניו, והוא בפועל מצביע למשתנה שנמצא מחוץ לתחום השגרה. לפיכך, פרמטר כזה גורם ל”תופעות לוואי“ במשתנה המקורי שנשלח אל השגרה.<ref name=":4report" group="ב" /><ref name=":0" /> דוגמה לשגרת ציווי שמבצעת העלאה בריבוע בעזרת פרמטר מסוג ”משתנה“:
<syntaxhighlight lang="modula2">
PROCEDURE Square(VAR x: REAL);
BEGIN
 x := x * x;
END Square
</syntaxhighlight>
במודולה־2 קיימות 19 שגרות בסיסיות שהן זמינות בכל חלקי הקוד. מתוכן 12 הן פונקציות ו־7 הן ציווים.<ref name=":4report" group="ב" />
{| class="wikitable mw-collapsible"
|+שגרות ופונקציות סטנדרטיות במודולה־2<ref name=":4report" group="ב" />
!סיווג
!קריאה
!משמעות
!מקבלת
!מחזירה
|-
| rowspan="11" |פונקציה
|<code>ABS(x)</code>
|ערך מוחלט
| colspan="2" |מספר (בדרך כלל ממשי או שלם)
|-
|<code>CAP(ch)</code>
|אות רישית
| colspan="2" |תו
|-
|<code>CHR(n)</code>
|המרת מספר סידורי לתו
|מספר טבעי
|תו
|-
|<code>FLOAT(n)</code>
|המרת מספר שלם למספר ממשי
|מספר שלם
|מספר ממשי
|-
|<code>HIGH(a)</code>
|האינדקס האחרון במערך
|מערך
|מספר טבעי
|-
|<code>MAX(T)</code>
|הערך המרבי מהטיפוס <code>T</code>
| colspan="2" rowspan="2" |<code>T</code>
|-
|<code>MIN(T)</code>
|הערך המזערי מהטיפוס <code>T</code>
|-
|<code>ORD(ch)</code>
|המרת תו למספר סידורי
|תו
| rowspan="2" |מספר טבעי
|-
|<code>SIZE(T)</code>
|אורך בזיכרון (במספר הבתים) הדרוש לערך מהטיפוס <code>T</code>
|<code>T</code>
|-
|<code>TRUNC(x)</code>
|המרת מספר ממשי למספר שלם
|מספר ממשי
|מספר שלם
|-
|<code>VAL(T, n)</code>
|החזרת הפריט ה־<code>n</code> מהטיפוס <code>T</code> (בדרך כלל טיפוס נמנים); זהה ל־<code>CHR(n)</code> אם <code>T</code> הוא <code>CHAR</code>
|<code>T</code>, מספר טבעי
|<code>T</code>
|-
| rowspan="7" |ציווי
|<code>DEC(x)</code>
|הקטנה ב־<code>1</code>; בשפות תכנות רבות קיימת הפעולה <code>--</code> במקום
| colspan="2" rowspan="4" |מספר, תו, או טיפוס נמנים
|-
|<code>DEC(x, n)</code>
|הקטנה ב־<code>n</code>; בשפות תכנות רבות קיימת הפעולה <code>-=</code> במקום
|-
|<code>INC(x)</code>
|הגדלה ב־<code>1</code>; בשפות תכנות רבות קיימת הפעולה <code>++</code> במקום
|-
|<code>INC(x, n)</code>
|הגדלה ב־<code>n</code>; בשפות תכנות רבות קיימת הפעולה <code>+=</code> במקום
|-
|<code>EXCL(s, i)</code>
| colspan="3" |הוצאת הפריט <code>i</code> מהקבוצה <code>s</code>
|-
|<code>INCL(s, i)</code>
| colspan="3" |הכללת הפריט <code>i</code> בקבוצה <code>s</code>
|-
|<code>HALT</code>
| colspan="3" |יציאה מהתוכנית (סיום ריצה)
|}

=== פעולות ===
בשונה מכתיב מתמטי, במודולה־2 שני סימוני פעולות לא יכולים לבוא זה מיד אחר זה באופן רציף, ובמקרה כזה חובה להשתמש בסוגריים כדי לבודד את סדר הפעולות. לדוגמה, <code>x * -1</code> נחשב ביטוי לא חוקי במודולה־2. במקום זאת, יש לכתוב <code>x * (-1)</code>.<ref name=":3guide" group="א" /> בנוסף, לא ניתן לרמוז על פעולת כפל בין משתנים וערכים. לדוגמה, <code>2n</code> (<math>2n</math>) נחשב ביטוי לא חוקי. במקום זאת, חובה לכתוב את הביטוי במלואו. כלומר, <code>2 * n</code>.<ref name=":3guide" group="א" />
{| class="wikitable mw-collapsible"
|+סימני פעולות במודולה־2<ref name=":7guide" group="א" /><ref></ref>
! colspan="2" |סיווג
!אופרנדים
!פעולה
! colspan="2" |סימן
|-
| rowspan="20" |בינארי
|הקצאה (קלט)
| colspan="2" |קליטת ערך למשתנה
|<code>:=</code>
| rowspan="2" |<math>=</math>
|-
| rowspan="9" |יוחסה (פלט)
| rowspan="6" |מספרים
|שווה ל־
|<code>==</code>
|-
|לא שווה ל־
|<code>#</code>או <code><></code>
|<math>\neq</math>
|-
|גדול מ־
|<code>></code>
|<math>></math>
|-
|קטן מ־
|<code><</code>
|<math><</math>
|-
|גדול או שווה ל־
|<code>>=</code>
|<math>\geq</math>
|-
|קטן או שווה ל־
| rowspan="2" |<code><=</code>
|<math>\leq</math>
|-
| rowspan="2" |קבוצות
|מוכל ב־
|<math>\sube</math>
|-
|מכיל את
|<code>>=</code>
|<math>\supe</math>
|-
|ערך וקבוצה
|שייך ל־
|<code>IN</code>
|<math>\in</math>
|-
| rowspan="2" |לוגיקה (פלט)
| rowspan="2" |אמת או שקר
|וגם
|<code>&</code> או <code>AND</code>
|<math>\and</math>
|-
|או
|<code>OR</code>
|<math>\or</math>
|-
| rowspan="4" |חשבון (פלט)
| rowspan="4" |מספרים
|חיבור
|<code>+</code>
|<math>+</math>
|-
|חיסור
|<code>-</code>
|<math>-</math>
|-
|כפל
|<code>*</code>
|<math>\times</math>
|-
|חילוק
|<code>/</code>
|<math>\div</math>
|-
| rowspan="4" |חשבון קבוצות (פלט)
| rowspan="4" |קבוצות
|איחוד
|<code>+</code>
|<math>\cup</math>
|-
|חיתוך
|<code>*</code>
|<math>\cap</math>
|-
|הפרש
|<code>-</code>
|<math>\smallsetminus</math>
|-
|הפרש סימטרי
|<code>/</code>
|<math>\Delta</math>
|-
| rowspan="2" |אונארי
|לוגיקה (פלט)
|אמת או שקר
|לא
|<code>~</code> או <code>NOT</code>
|<math>\neg</math>
|-
|חשבון (פלט)
|מספר
|סימן שלילי
|<code>-</code>
|<math>-</math>
|}

=== מודולים ===

תוכניות במודולה־2 בנויות מרכיבים שעוברים הידור נפרד זה אחר זה לפי קשר התלות בינם. כל רכיב כזה נכתב בקובץ נפרד, ובמונחי השפה הוא מכונה ”מודול.“ לפיכך, מבנה המודול הוא גם השלד הבסיסי של כל קובץ קוד מקור בשפה. הקטע הבא מתאר את מבנה המודול במודולה־2.<ref name=":12guide" group="א" /> בסוף מודול תמיד מופיעה נקודה.
<syntaxhighlight lang="modula2">
MODULE MyModule
 (* Import Lists *)
 (* Declarations *)
BEGIN
 (* Statements *)
END MyModule.
</syntaxhighlight>

== מהדרים ==
במשך השנים מאז הופעתה בשנת 1983 פותחו עשרות מהדרים ומימושים שונים לשפה. נכון לשנת 2021, קיימים שני מימושים מרכזיים שזמינים לציבור הרחב ונמצאים תחת פיתוח ותחזוקה מתמדת: המימוש של מיזם גנו והמימוש של ADW. כמו כן, גם מעצב השפה, ניקלאוס וירת, פיתח מימוש משלו עבור השפה בין השנים 1983–1985.<ref name=":1" /><ref name=":0wirth" />

=== GNU Modula-2 ===
GNU Modula-2 הוא מימוש חופשי ומקיף עבור מודולה־2 עם המהדר GCC מטעם מיזם גנו.<ref name=":4"></ref><ref></ref> הגרסה הראשונה של המימוש שוחררה לציבור בשנת 2010.<ref name=":5"></ref> המהדר מצטיין במיוחד בממשק בין מודולה־2 לשפת C.<ref name=":4" /> בנוסף, המימוש חוצה פלטפורמות ותומך גם בארכיטקטורות מחשבים פחות מוכרות כמו ARM ו־AVR לתכנות משובצות.<ref name=":4" />

=== ADW Modula-2 ===
ADW Modula-2 הוא מהדר חינמי עבור מודולה־2.<ref name=":3" /> הגרסה הראשונה של המהדר שחוררה בשנת 2011 אחרי שירש את הפיתוח של מימוש קודם, Stony Brook Modula-2.<ref name=":3"></ref> המהדר תומך אך ורק בחלונות (32 או 64 סיביות).<ref name=":3" /> כמו כן, באתר הבית של ADW Modula-2 ניתן למצוא מדריך מקיף לשפה, דוגמאות והסברים לשימוש במהדר.<ref></ref> נכון לשנת 2021 הוא נמצא תחת פיתוח פעיל, ויוצאת לו גרסה חדשה כאחת לשנתיים.<ref name=":3" />

== ראו גם ==
* פסקל - שפת התכנות שממנה הורחבה מודולה־2.<ref name=":1" />
* עדה - שפת תכנות עילית ממשפחת פסקל שפותחה במיוחד עבור צבא ארצות הברית; גם היא הושפעה מאחותה, מודולה־2.
* לואה - שפת תכנות דינמית עכשוויות וידידותית, למרות שאינה ממשפחת פסקל, היא תפסה השראה רבה ממודולה־2.<ref></ref>

== לקריאה נוספת ==

== קישורים חיצוניים ==
* 
* 
* 
* 
* [https://rosettacode.org/wiki/Category:Modula-2 דגימות קוד של מודולה־2 ב־RosettaCode] (באנגלית)

== הערות שוליים ==
=== מדריך השפה מהדורה רביעית ===

=== סקירת השפה ===

=== מקורות נוספים ===

קטגוריה:שפות תכנות