Pawn (ngôn ngữ lập trình)

PAWN (tiền nhiệm là Small-C) là một ngôn ngữ lập trình "mã nguồn mở" được sử dụng trên nhiều nền tảng.

Cú pháp của ngôn ngữ gần giống với C nhưng khác kiểu. Không có con trỏ, toàn bộ các chương trình được quản lý bên trong một abstract machine (hay máy ảo) của PAWN để đảm bảo kiểm tra các chỉ số của mảng cũng như bảo vệ chương trình khỏi bị tràn bộ nhớ. Trình biên dịch Pawn tạo ra mã P (hoặc "bytecode").

== Công dụng ==
Pawn là ngôn ngữ được điều chỉnh phù hợp với các máy có tài nguyên hạn chế, nó đã được dùng trong một số kỹ thuật nhúng như của vệ tinh ESTCube-1 hoặc phổ biến hơn là trong các máy chủ trò chơi SA-MP ("San Andreas - Multiplayer").

== Phần tử trong PAWN ==
Giống như bất kỳ ngôn ngữ lập trình khác, PAWN cũng có những đặc tính riêng.

// main() là hàm chính của mọi chương trình, nó sẽ được thực thi đầu tiên
main()

=== Biến ===
Kiểu của các biến trong PAWN hạn chế hơn so với C và cách khai báo của chúng cũng khác.

Để khai báo một biến, chúng ta sử dụng từ khóa "new" theo sau là tên của biến.

Nếu không có xác định kiểu, mặc định biến sẽ được xem như kiểu số nguyên.

main()

=== Cấu trúc điều kiện ===
Chúng ta sẽ phân biệt hai cấu trúc điều khiển chính: "if" cũng như "switch".

Dạng đầu tiên của cấu trúc này được định nghĩa trong một so sánh điều kiện đơn giản dưới đây:

hand()
Tuy nhiên, chúng ta cũng có thể xử lý phủ định của biểu thức trước đó bằng từ khóa "else".

hand()
Từ khóa cuối cùng cho phép kiểm tra một biểu thức nếu biểu thức trước đó trả về giá trị "false": "else if".

hand()

Lưu ý: bằng cách sử dụng "else" ở cuối, tôi kiểm tra xem một trong các điều kiện trước nó đã được thỏa mãn hay không.

Cấu trúc điều kiện luôn bắt đầu bằng "if" trong mọi trường hợp.

==== Cấu trúc "switch" ====
Cấu trúc điều kiện "switch" được sử dụng trong trường hợp bạn phải kiểm tra lần lượt các giá trị của một biến. Bạn có thể sử dụng cấu trúc "if" và "else if" để có công dụng tương tự.

Tuy nhiên, cấu trúc "switch" sẽ phù hợp hơn trong trường hợp này. Thay vì sử dụng nhiều lệnh "else if", chúng ta sẽ sử dụng từ khóa "case" để kiểm tra giá trị của biến.

hand()

=== Cấu trúc lặp ===
Cấu trúc lặp (hoặc vòng lặp) lặp lại một hoặc nhiều lệnh một số lần nhất định.

Chúng ta cần phân biệt hai cấu trúc lặp chính, mỗi cấu trúc này được đặc trưng bởi số lần lặp xác định.

==== Vòng lặp "for" ====
Vòng lặp "for" sẽ thực thi các lệnh lồng nhau một số lần nhất định.

Trong một vòng lặp như vậy, chúng ta thường sử dụng một "bước nhảy". Nó đặc biệt hữu ích khi một lệnh phải được lặp lại nhiều lần và ta cần một cách để kiểm soát số lần lặp.
hand()
==== Vòng lặp "while" ====
Vòng lặp "while" là một vòng lặp không xác định.

Vòng lặp này thường được đặt với một điều kiện không để kiểm tra số lần lặp.

Vòng lặp này không nhất thiết phải có một "bước nhảy" như vòng lặp "for".

hand()
==== Vòng lặp "do..while" ====
Vòng lặp "do..while" cũng không xác định.

Khác với vòng lặp "while", vòng lặp "do..while" sẽ thực thi lệnh trước khi kiểm tra điều kiện lần đầu tiên.

Điều này đảm bảo sẽ luôn có ít nhất một lần lặp. Nó đặc biệt được sử dụng trong kiểm tra đầu vào người dùng.

/* Chương trình tính tổng N số nguyên dương đầu tiên (N được nhập bởi người dùng) */
hand()

=== Hàm / thủ tục ===
Trong thuật toán, chúng ta thường phân biệt hàm của thủ tục bằng sự tồn tại hay không của giá trị trả về. Trong C, chúng ta phân biệt bằng từ khóa đặt trước định nghĩa hàm (void hoặc một kiểu dữ liệu).
Trong PAWN, hai khái niệm này thường bị nhầm lẫn vì nó không phân biệt rõ ràng.

==== Khai báo một hàm ====
Khai báo một hàm trong PAWN được thực hiện như sau:

hand()
multiply(a, b) // nhân số nguyên a với b

Tương tự, nếu bạn muốn trả về dữ liệu của một kiểu khác ngoài số nguyên, bạn chỉ cần xác định kiểu trước khi khai báo:

bool:AreEquals(a, b) // hàm này trả về true hoặc false

Tuy nhiên, sẽ cần phải xác định kiểu dữ liệu mà hàm trả về nếu nó khác với kiểu mặc định (số nguyên). Do đó, bạn sẽ cần tạo ra một tiêu đề (header) của hàm trước khi gọi nó. Chúng ta sẽ có:

forward bool:AreEquals(a, b); // tạo một tiêu đề bằng cách gọi từ khóa forward

hand()
bool:AreEquals(a, b)

==== Truyền tham số ====
Một hàm có thể (hoặc không) truyền đối số trong khai báo hàm của nó.
Ngôn ngữ PAWN cung cấp hai kiểu truyền tham số cho hàm.

Kiểu đầu tiên là truyền tham số theo giá trị, nó sẽ tạo ra một bản sao của biến được truyền làm tham số khi gọi hàm.
Giá trị của biến bản sao không thể ảnh hưởng đến giá trị của biến ban đầu.

hand()
square(value)

Kiểu truyền tham số này được ưu tiên cho việc xử lý giá trị của một biến hoặc chỉ đọc giá trị của nó.

Tuy nhiên, nếu muốn thay đổi giá trị của biến được truyền làm tham số, chúng ta sẽ phải sử dụng kiểu truyền tham số thứ hai: theo tham chiếu.
Kiểu truyền tham số này là thay vì truyền giá trị của biến để tạo ra một biến khác, thì sẽ truyền địa chỉ bộ nhớ của nó, từ đó cho phép thay đổi trực tiếp biến trong bộ nhớ.

hand()
square(&value) // dùng dấu & để truyền tham số theo tham chiếu

Kiểu truyền tham số này được ưu tiên khi chúng ta cần phải trả về nhiều giá trị từ một hàm (ví dụ: chuyển đổi giây thành định dạng hh-mm-ss).