מבוא מהיר לתחביר Pascal Script

מדריך זה מכסה את עקרונות התחביר המרכזיים של Pascal Script בסיסי כפי שהוא משמש במודול התסריטים לרוחב מערכת Hyper.
המדריך מסייע לעבור מהאופי הדינמי של JavaScript אל הסביבה המובנית של Pascal Script.
  • התחביר אינו רגיש לאותיות גדולות/קטנות כלל.
  • פקודות מסתיימות בנקודה-פסיק (;).   ירידות שורה אינן משפיעות על ביצוע הקוד.
  • בלוקים של קוד יש לתחום ב- begin ... end במקום { ... }.
  • תוכניות, פרוצדורות ופונקציות חייבות להצהיר על כל המשתנים לפני השימוש.
  • השמה למשתה תבוצע בסימן :=.
  • הערה בשורה אחת:
    // זו הערה
  • הערה מרובת שורות:
    { זו הערת בלוק }

תוכן העניינים

סוגי נתונים נתמכים

בשונה מ-let או var ב-JavaScript, פסקל דורש הגדרות טיפוס מפורשות. להלן הטיפוסים המובנים הזמינים במנוע הסקריפטים:
טיפוס תיאור מינימום מקסימום
Integer מספר שלם עם סימן, 32-ביט. -2147483648 2147483647
Int64 / LongInt מספר שלם עם סימן, 64-ביט. -9223372036854775808 9223372036854775807
Word מספר שלם ללא סימן, 16-ביט. 0 65535
Cardinal / LongWord מספר שלם ללא סימן, 32-ביט. 0 4294967295
Double מספר בנקודה צפה בדיוק כפול (Double-precision), עד 15 ספרות אחרי הנקודה. 2.23e-308 1.79e+308
String מחרוזת Ansi או Unicode.
Char תו Unicode יחיד (16-ביט).
Boolean דגל TRUE/FALSE.
Variant טיפוס כללי שיכול לאחסן כל ערך או אובייקט.

סימנים ומשמעותם

סימני הפיסוק בפסקל פועלים לפי כללים נוקשים ושונים מתחביר C-style של JavaScript.
סימן תיאור
:= השמה: קובע ערך למשתנה (ב-JS משתמשים ב-=).
= שוויון: אופרטור השוואה המשמש בתנאים (ב-JS משתמשים ב-==).
<> אי-שוויון: לא שווה (ב-JS משתמשים ב-!=).
< , > , <= , >= אופרטורי השוואה: קטן, גדול, קטן או שווה, גדול או שווה.
' ' גרשיים בודדים: ליטרלים של מחרוזות חייבים להשתמש בגרשיים בודדים.

אופרטורים

פעולות לוגיות ואריתמטיות משתמשות לעיתים במילות מפתח במקום בסימנים.
אופרטור תיאור
+ חיבור מספרים או שרשור מחרוזות.
- , * , / חיסור, כפל, חילוק (/ מחזיר תוצאה בנקודה צפה).
DIV חילוק שלם (מחזיר את המספר השלם ללא שארית).
MOD השארית לאחר חילוק שלם (ב-JS: %).
NOT NOT לוגי (ב-JS: !).
AND / OR AND / OR לוגיים (ב-JS: && ו-||).
XOR XOR לוגי (אמת רק כאשר האופרנדים שונים).
SHL / SHR הזזה ביטית שמאלה / ימינה.

הצהרת משתנים (var) וקבועים (const)

ב-Pascal Script, משתנים מוכרזים לפני השימוש בתוך בלוק var, עם טיפוסים מפורשים. קבועים מוכרזים בתוך בלוק const ואינם ניתנים לשינוי בזמן ריצה.
סדר טיפוסי ביחידת סקריפט הוא:
const -> var -> begin ... end;
const
  MAX_RETRIES = 3;
  APP_NAME = 'Pascal Demo';

var
  counter: Integer;
  userName: String;
  isReady: Boolean;

begin
  counter := 0;
  userName := 'Dana';
  isReady := True;

  ShowMessage(APP_NAME + ' / retries: ' + IntToStr(MAX_RETRIES));
end;
// Multiple variables of the same type in one line
var
  x, y, z: Integer;
begin
  x := 10;
  y := 20;
  z := x + y;
end;

תנאי IF

השתמש ב-if ... then ... else לביצוע מותנה. השתמש בסוגריים להבהרה בביטויים מורכבים.
חשוב: אל תשים נקודה-פסיק (;) ממש לפני else.
var
  age: Integer;
  isMember: Boolean;
begin
  age := 21;
  isMember := True;

  if (age >= 18) and (isMember = True) then
    ShowMessage('Access granted')
  else
    ShowMessage('Access denied');
end;
// Else-if style (nested if in else branch)
if score >= 90 then
  grade := 'A'
else if score >= 80 then
  grade := 'B'
else
  grade := 'C';

בלוקי קוד: Begin...End מול שורה יחידה

ב-JavaScript, סוגריים מסולסלים { } מקבצים פקודות. בפסקל משתמשים ב-begin וב-end.
  • שורה יחידה: אם IF או לולאה מכילים רק פקודה אחת, begin/end הם אופציונליים.
  • בלוק מרובה שורות: מספר פקודות חייבות להיות עטופות בבלוק begin...end;.
  • כלל ה-Else: אסור לשים נקודה-פסיק לפני מילת המפתח else.
// Single line example
IF X > 10 Then
  DoSomething;

// Block example
if (X <= 10) and (Y <> 0) then
  Begin
    X:= X + 1;
    Y:= 0;
  End;

איטרציה (לולאות)

כל משתני הבקרה של הלולאה (כמו i) חייבים להיות מוכרזים בבלוק var לפני שהלולאה מתחילה.

For

משמש אך ורק לספירה בטווח.
var
  i: Integer;
begin
  for i := 1 to 5 do
    begin
      ShowMessage('Iteration: ' + IntToStr(i));
    end;

  for i := 5 downto 1 do
    begin
      ShowMessage('Countdown: ' + IntToStr(i));
    end;
end;

While

חוזר כל עוד התנאי נשאר True.
while (CurrentValue <= MaxLimit) do
  begin
    CurrentValue := CurrentValue + Step;
  end;

Repeat...Until

דומה ל-do...while ב-JS; תמיד מבצע לפחות פעם אחת ועוצר כאשר התנאי הופך ל-True.
repeat
  ExecuteTask;
until (IsFinished = True);

Case (מקביל ל-switch)

Case הוא המקביל בפסקל ל-switch ב-JavaScript. משתמשים בו כדי לבחור בקלות בין מספר ענפים.
var
  dayNumber: Integer;
  dayName: String;
begin
  dayNumber := 3;

  case dayNumber of
    1: dayName := 'Sunday';
    2: dayName := 'Monday';
    3: dayName := 'Tuesday';
    4: dayName := 'Wednesday';
    5: dayName := 'Thursday';
    6: dayName := 'Friday';
    7: dayName := 'Saturday';
  else
    dayName := 'Unknown';
  end;
end;
נתמך גם Case המבוסס על מחרוזת:
var
  commandText: String;
begin
  commandText := 'start';

  case LowerCase(commandText) of
    'start': ShowMessage('Starting...');
    'stop': ShowMessage('Stopping...');
    'pause': ShowMessage('Paused.');
  else
    ShowMessage('Unknown command: ' + commandText);
  end;
end;

מערך (Array)

מערכים מאחסנים מספר ערכים מאותו טיפוס במיקומים ממוספרים (indexed).
var
  scores: array[0..4] of Integer;
  i: Integer;
begin
  scores[0] := 10;
  scores[1] := 20;
  scores[2] := 30;
  scores[3] := 40;
  scores[4] := 50;

  for i := 0 to 4 do
    ShowMessage('Score #' + IntToStr(i) + ': ' + IntToStr(scores[i]));
end;

TRY

השתמש ב-Try...Except כדי ללכוד ולטפל בשגיאות בזמן ריצה.
var
  x, y, z: Integer;
begin
  x := 10;
  y := 0;

  try
    z := x div y;
    ShowMessage('Result: ' + IntToStr(z));
  except
    ShowMessage('An error occurred: division by zero.');
  end;
end;

השתמש ב-Try...Finally כאשר קוד ניקוי חייב לרוץ בין אם מתרחשת שגיאה ובין אם לא.
var
  started: Boolean;
begin
  started := False;

  try
    started := True;
    ShowMessage('Starting task...');
    ExecuteTask;
  finally
    if started then
      ShowMessage('Cleanup completed.');
  end;
end;

פרוצדורות מול פונקציות

פרוצדורה מבצעת פעולות. פונקציה מחזירה ערך.
procedure LogMessage(msg: String);
begin
  ShowMessage(msg);
end;

function AddNumbers(a, b: Integer): Integer;
begin
  Result := a + b;
end;

var
  sum: Integer;
begin
  LogMessage('Calculating...');
  sum := AddNumbers(7, 5);
  ShowMessage('Sum = ' + IntToStr(sum));
end;
ניתן גם ליצור תתי-שגרות מקוננות (local) בתוך פרוצדורה/פונקציה אחרת. יש להצהיר על עוזרים מקומיים לפני ה-begin החיצוני.
function BuildWelcomeMessage(userName: String): String;
  function NormalizeName(const rawName: String): String;
  begin
    NormalizeName := Trim(rawName);
  end;
begin
  Result := 'Hello, ' + NormalizeName(userName);
end;

begin
  ShowMessage(BuildWelcomeMessage('  Yaniv  '));
end;

העברת פרמטרים

פרמטרים רגילים מועברים לפי ערך. פרמטרים מסוג var מועברים לפי הפניה (reference).
procedure IncreaseByValue(x: Integer);
begin
  x := x + 1;
end;

procedure IncreaseByRef(var x: Integer);
begin
  x := x + 1;
end;

var
  n: Integer;
begin
  n := 10;
  IncreaseByValue(n);
  ShowMessage('After value call: ' + IntToStr(n)); // 10

  IncreaseByRef(n);
  ShowMessage('After var call: ' + IntToStr(n)); // 11
end;

כלי עזר למחרוזות

עוזרי מחרוזות נפוצים הם פשוטים ובעלי טיפוסים חזקים.
var
  s: String;
begin
  s := '  Pascal Script  ';

  ShowMessage('Length: ' + IntToStr(Length(s)));
  ShowMessage('Trim: [' + Trim(s) + ']');
  ShowMessage('Upper: ' + UpperCase(s));
  ShowMessage('Lower: ' + LowerCase(s));
  ShowMessage('Pos of Script: ' + IntToStr(Pos('Script', s)));
  ShowMessage('Copy 1..6: ' + Copy(Trim(s), 1, 6));
end;

יסודות תאריך/שעה

ערכי תאריך/שעה הם מטופסים וקלים לעיצוב/פורמט.
var
  nowValue: TDateTime;
begin
  nowValue := Now;

  ShowMessage('Date: ' + DateToStr(Date));
  ShowMessage('Time: ' + TimeToStr(Time));
  ShowMessage('Now: ' + DateTimeToStr(nowValue));
  ShowMessage('Custom: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', nowValue));
end;

המרת טיפוסים

המרות הן מפורשות. השתמש בגרסאות Try כאשר קלט משתמש עלול להיות לא תקין.
var
  s: String;
  n: Integer;
  f: Double;
begin
  s := '42';
  n := StrToInt(s);
  f := StrToFloat('3.14');

  ShowMessage('IntToStr: ' + IntToStr(n));
  ShowMessage('FloatToStr: ' + FloatToStr(f));

  if TryStrToInt('abc', n) then
    ShowMessage('Converted: ' + IntToStr(n))
  else
    ShowMessage('Invalid integer input.');
end;

רשומות (Records)

Record הוא מבנה נתונים מטופס, הדומה ל"צורת אובייקט" פשוטה ב-JavaScript.
type
  TUser = record
    Name: String;
    Age: Integer;
    Active: Boolean;
  end;

var
  user: TUser;
begin
  user.Name := 'Dana';
  user.Age := 28;
  user.Active := True;

  ShowMessage('User: ' + user.Name + ', age ' + IntToStr(user.Age));
end;