Định nghĩa Menu

Một phần của tài liệu Nghiên cứu khả năng chuyển đổi giữa các đặc tả hình thức và ứng dụng trong kiểm chứng phần mềm (Trang 30)

5 Thực nghiệm

2.24 Định nghĩa Menu

2.8.2 Cú pháp và ngữ nghĩa2.8.2.1 Biến 2.8.2.1 Biến

OCaml là ngôn ngữ hằng nên biến thực chất là giá trị được đặt tên và không thể

thay đổi trong một phạm vi nào đó trong suốt quá trình chạy [14]. Điều này có

nghĩa là khi lập trình viên gán giá trị cho biến thì sau đó không thể thay đổi giá trị cho biến đó. OCaml cung cấp kiểu tham chiếu (mutable references), nó giống như là các con trỏ. Các biến tham chiếu này có thể thay đổi giá trị mà nó trỏ tới.

2.8.2.2 Kiểu dữ liệu cơ bản

Bảng 2.1: Các kiểu dữ liệu cơ bản của OCaml

Kiểu dữ liệu Mô tả

int Kiểu nguyên dương 31-bit float Kiểu số thực

bool Kiểu logic bao gồm true hoặc false char Kiểu kí tự

string Chuỗi ký tự unit Kiểu đặc biệt

OCaml cung cấp các kiểu dữ liệu cơ bản được liệt kê trong Bảng 2.1. Kiểu int chỉ sử dụng 32 bits tại vì nó sử dụng 1 bit để phân biệt giữa số nguyên và con trỏ. Nếu lập trình viên muốn sử dụng số nguyên 32-bit thì có thể sử dụng Int32 hoặc sổ nguyên 64-bit thì có thể sử dụng Int64.

2.8.2.3 Hàm

Hàm là một đối tượng dữ liệu nhận vào gồm có các tham số và trả về một đối

tượng dữ liệu có kiểu [14]. Một hàm có thể nhận và trả về một kiểu dữ liệu

Chương 2.Kiến thức cơ bản SimpleExpression: AdditiveExpr Expression: OrExpr Hình 2.25: Định nghĩa biểu thức.

nghĩa bằng cách sử dụng từ khóa let, f un hoặc f unction. Tuy nhiên, hàm yêu

cầu có ít nhất một tham số.

Hình 2.28 định nghĩa một hàm đơn giản nhất. Hàm có tên làmy f uncnhận

tham số là một kiểu unit và trả về giá trị là một kiểu int. Hàm được kết thúc

bằng hai dấu chấm phẩy. Hình 2.29 mô tả cách gọi hàm trong OCaml. Hàm phải có duy nhất một kiểu trả về, mặc dù kiểu trả về có thể là kiểu đa hình. Kiểu mà hàm trả về sẽ được trình biên dịch tự động đưa ra. Trình biên dịch tìm kiểu thông dụng nhất mà hàm có thể trả về và sau đó sử dụng kiểu đó.

2.8.2.4 Hàm mức cao

OCaml hỗ trợ hàm mức cao [14]. Điều này có nghĩa là hàm có thể nhận một hàm

khác làm tham số. Sở dĩ OCaml làm được điều này vì OCaml xem hàm như là

các lớp dữ liệu cơ bản. Hình 2.30 là ví dụ minh họa hàmbiggernhận ba tham số

đầu vào. Tham số f đầu tiên là một hàm có hai tham số. Hai tham số cuối cùng

x,yđược xem như là tham số của tham số f.

2.8.2.5 Hàm nặc danh

Hàm nặc danh là hàm không có tên, vì vậy hàm không được gán bất kỳ một

giá trị nào [14]. Hàm nặc danh rất hữu ích trong OCaml. Nhiều hàm sử dụng

các hàm khác như là đối số và hàm nặc danh là cách dễ dàng khai báo và đưa vào làm tham số cho các hàm khác. Thông thường, khai báo hàm nặc danh bằng

cách sử dụng từ khóa f unhoặc f unction. Hàmcomparedùng để so sánh hai giá

trị trong việc sắp xếp một danh sách. Hàm nhận vào hai số nguyên và trả về giá trị là 1 nếu giá trị thứ hai bé hơn giá trị thứ nhất. Hàm trả về giá trị là 0 nếu giá trị thứ hai bằng giá trị thứ nhất và trả về giá trị là -1 nếu giá trị thứ hai lớn hơn giá trị thứ nhất. Hàmcomparecó thể được cài đặt riêng biệt rồi sử dụng nó. Tuy nhiên, với hàm nặc danh có thể giúp khai báo và sử dụng trực tiếp chính nó. Hình 2.31 mô tả một hàm nặc danh.

Chương 2.Kiến thức cơ bản OrExpr: AndExpr OrExpr||AndExpr AndExpr: BitOrExpr

AndExpr&&BitOrExpr BitOrExpr: BitExclOrExpr BitOrExpr|BitExclOrExpr BitExclOrExpr: BitAndExpr BitExclOrExprBitAndExpr BitAndExpr: EqualityExpr

BitAndExpr&EqualityExpr EqualityExpr: RelationalExpr EqualityExpr==RelationalExpr EqualityExpr!==EqualityExpr RelationalExpr: ShiftExpr RelationalExpr<ShiftExpr RelationalExpr<=ShiftExpr RelationalExpr>ShiftExpr RelationalExpr>=ShiftExpr ShiftExpr: AdditiveExpr ShiftExpr»AdditiveExpr ShiftExpr«AdditiveExpr

Hình 2.26: Định nghĩa biểu thức (tiếp).

2.8.2.6 Hàm đệ quy

Hàm đệ quy là một phần cực kỳ quan trọng của OCaml [14]. Hiệu suất và Kích

thước mã nguồn của chương trình được cải tiến nhờ khả năng đệ quy đuôi trong OCaml. Hàm nặc danh không thể sử dụng đệ quy đuôi. Bởi vì hàm nặc danh không có tên nên không thể gọi hàm đó được. Hàm đệ quy được khai báo trong

OCaml bằng cách thêm từ khóa rec trước tên của hàm đó. Hàm đệ quy trong

OCaml là đệ quy đuôi nếu nó đảm bảo hai yêu cầu sau: hàm đệ quy không chứa try/with và giá trị trả về phải là giá trị không đổi. Ví dụ, hàm tính số Fibonacci không phải là hàm đệ quy đuôi [14]. Bởi vì, hàm tính số Fibonacci trả về giá trị là hàm yêu cầu tính giá trị Fibonacci tiếp theo. Hình 2.32 mô tả một hàm đệ quy tính số Fibonacci.

2.8.2.7 So sánh mẫu

OCaml cung cấp một chức năng so sánh mẫu tương tự với cấu trúcSW ITCH...

Chương 2.Kiến thức cơ bản AdditiveExpr: MultiplicativeExpr AdditiveExpr+MultiplicativeExpr AdditiveExpr-MultiplicativeExpr MultiplicativeExpr: UnaryExpr MultiplicativeExpr*UnaryExpr MultiplicativeExpr\UnaryExpr MultiplicativeExpr%UnaryExpr UnaryExpr: BaseExpr +BaseExpr -BaseExpr !BaseExpr BaseExpr: IntegerLiteral Variable ConstantIdentActionLabel #SetIdent @(SetIdent , Expression) (Expression)

Hình 2.27: Định nghĩa biểu thức (tiếp).

# l e t myfunc ( ) = 1 + 1 ; ;

v a l myfunc : u n i t −> i n t = <fun>

Hình 2.28: Ví dụ khai báo hàm.

giá trị đầu vào. Cấu trúc lệnh của so sánh mẫu được mô tả ở Hình 2.33. Trình

biên dịch OCaml sẽ so sánh expression với các patternn để đưa ra quyết định

thực hiệnexpressionn tương ứng. Ví dụ so sánh mẫu được mô tả ở Hình 2.34.

2.8.2.8 Đối tượng

OCaml là ngôn ngữ lập trình hàm được phát triển dựa trên ngôn ngữ CAML và

có thêm chức năng hướng đối tượng [14]. OCaml cung cấp đầy đủ các nguyên

lý của hướng đối tượng như: lớp, đối tượng, thừa kế, đa hình.

# myfunc 2 ; ;

− : i n t = 4

Chương 2.Kiến thức cơ bản # l e t b i g g e r f x y = f x y ; ; v a l b i g g e r : ( 'a −> 'b −> 'c ) −> 'a −> 'b −> 'c = <fun> # b i g g e r ( > ) 10 2 0 ; ; − : bool = f a l s e # b i g g e r ( < ) 10 2 0 ; ; − : bool = t r u e Hình 2.30: Ví dụ hàm mức cao. # L i s t . s o r t (fun x y −> i f x = y then −1 e l s e i f x < y then 1 e l s e 0 ) [ 1 ; 4 ; 9 ; 3 ; 2 ; 1 ] ; ; − : i n t l i s t = [ 9 ; 4 ; 3 ; 2 ; 1 ; 1 ] Hình 2.31: Ví dụ hàm nặc danh. # l e t r e c f i b n = i f ( n < 2 ) then 1 e l s e ( f i b ( n − 1 ) ) + ( f i b ( n − 2 ) ) ; ; v a l f i b : i n t −> i n t = <fun> # f i b 6 ; ; − : i n t = 13 Hình 2.32: Ví dụ hàm đệ quy.

match expression with | pattern1-> expression1 | pattern2-> expression2

...

| patternn-> expressionn

Hình 2.33: Cấu trúc lệnh của so sánh mẫu.

# l e t f i = match i with

| o −> " Zero "

| 3 −> " Three "

| _ −> " Neith er zero nor t h r e e " ; ;

Chương 2.Kiến thức cơ bản

2.9 OCamllex và OCamlyacc

2.9.1 OCamllex

Ocamllex [15] là bộ sinh dùng để sinh ra chương trình phân tích đoán nhận các

mẫu từ vựng trong tập tin đầu vào. Các biểu thức chính quy và các luật được đặc tả trong tập tin từ vựng. Ocamllex sẽ sinh ra tập tin mã nguồn OCaml dựa vào tập tin đặc tả này. Tập tin mã nguồn được sinh ra sẽ định nghĩa các hàm xử lý từ vựng [15]. Tập tin mã nguồn được dịch và liên kết lại để sinh ra tập tin có khả năng thực thi. Tập tin thực thi này khi chạy sẽ xử lý đầu vào của nó dựa vào các biểu thức chính quy. Khi nó tìm thấy một từ vựng nó sẽ thực thi đoạn mã nguồn OCaml tương ứng. Tập tin mã nguồn đặc tả từ vựng có đuôi mở rộng là .mll. Để biên dịch tập tin này sử dụng dòng lệnh:ocamllex∗.mll. Tập tin đặc tả từ vựng gồm có bốn thành phần: header,các định nghĩa, các luậtvàtrailer. Trong đó, các thành phầnheadervàruleslà cần thiết còn hai thành phần còn lại làrules vàtrailerlà tùy chọn. Cấu trúc tập tin đặc tả từ vựng được mô tả như Hình 2.35. Hình 2.36 là ví dụ mô tả một tập tin đặc tả từ vựng.

(* thành phần header *) { header }

(* thành phần định nghĩa *) let ident = regexp

let ...

(* thành phần luật *)

rule entrypoint [arg1... argn] = parse | pattern { action }

| ...

| pattern { action }

and entrypoint [arg1... argn] = parse ... and ... (* thành phần trailer *) { trailer } Hình 2.35: Cấu trúc tập tin đặc tả từ vựng. 2.9.2 OCamlyacc

Ocamlyacc [16] là bộ sinh dùng để sinh ra chương trình phân tích cú pháp bằng

ngôn ngữ OCaml từ một tập tin đặc tả văn phạm phi ngữ cảnh. Chương trình OCaml này sẽ có chức năng phân tích cú pháp cho tập tin dữ liệu đầu vào tuân thủ theo văn phạm đó. Tập tin mã nguồn đặc tả cú pháp có đuôi mở rộng là .mly. Để biên dịch tập tin này sử dụng dòng lệnh:ocamlyacc∗.mly. Tập tin đặc

Chương 2.Kiến thức cơ bản { l e t num_lines = r e f 0 l e t num_chars = r e f 0 } r u l e count = parse

| '\n' { i n c r num_lines ; i n c r num_chars ; count ←-

l e x b u f } | _ { i n c r num_chars ; count l e x b u f } | e o f { ( ) } { l e t main ( ) = l e t l e x b u f = Lexing . from_channel s t d i n i n count l e x b u f ; P r i n t f . p r i n t f " # o f l i n e s = %d , # o f c h a r s = %d\n " !←- num_lines ! num_chars l e t _ = P r i n t e x c . p r i n t main ( ) } Hình 2.36: Ví dụ tập tin đặc tả từ vựng.

tả cú pháp gồm có bốn thành phần: header,khai báo Ocamlyacc, luật văn phạmvà trailer. Cấu trúc tập tin đặc tả cú pháp được mô tả như Hình 2.37.

%{

Header (mã nguồn OCaml) %}

Khai báo Ocamlyacc %%

Các luật văn phạm %%

trailer (có thể có mã nguồn OCaml)

Chương 3 AGTool

3.1 Giới thiệu AGTool

Phương pháp kiểm chứng mô hình còn gặp phải vấn đề "bùng nổ không gian trạng thái". Một giả thuyết được đặt ra là thay vì kiểm chứng trên toàn bộ hệ thống, chúng ta sẽ kiểm chứng từng thành phần của hệ thống đó. Với giả thuyết này thì phương pháp kiểm chứng giả định-đảm bảo có tiềm năng trong việc giải quyết bài toán của phương pháp kiểm chứng mô hình. Để sử dụng được phương pháp kiểm chứng đảm bảo giả định, chúng ta cần sinh ra cho hệ thống

một giả định (Assumption). Và AGTool [7] là một trong những công cụ dùng để

thực hiện công việc sinh ra giả định đó. Hình 3.1 mô tả tổng quan về AGTool.

Hình 3.1: Mô hình công cụ kiểm chứng AGTool.

Các thành phần M1, M2 và thuộc tính Pcủa hệ thống được đặc tả bởi các

Chương 3.AGTool

(a) LTS của các thành phần đầu vào.

(b) Tập tin đặc tả các thành phần đầu vào.

Hình 3.2: Thành phần đầu vào của AGTool.

dạng LTS. AGTool được cài đặt bằng ngôn ngữ lập trình hàm OCaml. Hiện tại, AGTool tương tác với người dùng bằng giao diện dòng lệnh. Các thành phần đầu vào được đưa vào từ tệp văn bản. Dưới đây là một ví dụ minh họa cho đầu vào và đầu ra của AGTool. Hình 3.2a mô tả các thành phần của hệ thống kênh truyền tin dưới dạng các biểu đồ trực quan. Đầu vào gồm có hai thành phần

M1, M2 của hệ thống và thuộc tính P. Các thành phần này được đặc tả bằng

dưới dạng biểu diễn liệt kê. Hình 3.2b minh họa tập tin chứa các đặc tả đầu vào. AGTool sinh ra giả định từ đặc tả ở Hình 3.2b. Hình 3.3 mô tả kết quả sinh ra bởi AGTool.

Chương 3.AGTool

3.2 Hạn chế của AGTool

Với các chức năng của AGTool hiện tại thì nó còn tồn tại một vài nhược điểm để có thể đưa vào ứng dụng trong thực tế. Kiểu dữ liệu đầu vào được biểu diễn dưới dạng liệt kê, công việc này yêu cầu người dùng phải chuẩn tập tin đầu vào một cách tỉ mỉ, mất nhiều thời gian và dễ gây lỗi. Không những vậy, với các biểu diễn đầu vào và đầu ra dưới dạng liệt kê thì AGTool không thể sử dụng lại các đặc tả của các công cụ kiểm chứng phần mềm khác như LTSA.

Chương 4

Chuyển đổi giữa các dạng biểu diễn của LTS

LTSA là một công cụ nổi tiếng về kiểm chứng phần mềm tương tranh [3]. AGTool

có thể giao tiếp được với LTSA có ý nghĩa quan trọng trong việc ứng dụng nó vào trong thực tế. Các thành phần trong dữ liệu đầu vào của công cụ LTSA được đặc tả bởi ngôn ngữ FSP. Trong khi đó, AGTool nhận dữ liệu đầu vào và sinh ra kết quả (giả định) ở LF. Để AGTool và LTSA có thể giao tiếp, sử dụng lại các kết quả của nhau thì đầu vào và đầu ra của hai công cụ này phải sử dụng chung một kiểu dữ liệu. Vì vậy, các thành phần đầu vào và kết quả của AGTool phải được đặc tả bởi ngôn ngữ FSP. Trong chương này, luận văn đưa ra phương pháp

giải quyết hai bài toán chính là: chuyển đổi FSP sang LF và chuyển đổi từ LF

sang FSP. Ý tưởng của phương pháp này là thiết kế hai thành phần có chức năng chuyển đổi qua lại giữa FSP và LF. Sau đó, các thành phần này được tích hợp vào công cụ AGTool. Hình 4.1 mô tả kiến trúc của GUI-AGTool. Trong đó, các thành phần mới sẽ được phát triển và tích hợp với AGTool Core.

Chương 4.Chuyển đổi giữa các dạng biểu diễn của LTS

4.1 Chuyển đổi FSP sang LF

4.1.1 Ý tưởng

Hệ thống sẽ cài đặt một thành phần riêng được gọi làFSP Compiler. Thành phần

này có chức năng chuyển đổi dữ liệu FSP sang LF. Bài toán chuyển đổi FSP sang LF được mô tả bởi Hình 4.2. Dữ liệu FSP ở đầu vào được xử lý bởi thành phần

Hình 4.2: Cấu trúc thành phần chuyển đổi từ FSP sang LF.

FSP Compiler. Các thành phần trong dữ liệu đầu vào sẽ được chuyển đổi từ danh sách các hàm chuyển trạng thái sang kiểu dữ liệu LF bởi Thuật toán 4.1.

Danh sách list_transitions gồm các phần tử có định dạng là (start_state, list_sub_trans). Trong đó, start_state là trạng thái ban đầu, list_sub_trans là danh sách các tiến trình con. Tiến trình con này được định nghĩa bởi một nhãn và một trạng thái kết thúc –stop_state. Tương ứng với mỗi tiến trình con, ta thu được một phần tử gồm ba thành phần: (start_state, label, stop_state). Phần tử này chính là một hàm chuyển trạng thái. Phần tử khởi tạo là trạng thái bắt đầu

của hàm dịch chuyển đầu tiên trong danh sách list_transitions. Danh sách các

trạng tháil_statesđược xác định tại các dòng 3, 4 và 8, 9 của thuật toán. Tại các bước này, một trạng thái xuất hiện sẽ được kiểm tra. Nếu trạng thái này là trạng

thái mới thì nó được thêm vào danh sách l_states. Các hàm chuyển trạng thái

được thêm vào danh sáchl_transtại dòng 7 trong Thuật toán 4.1. FSP M biểu diễn một kênh truyền tin được đặc tả như Hình 4.3.

S0 = (ack2,ack1→ S0 | snd1→ S1 | snd2→ S2), S1 = (snd2,snd1,out1,ack2→S0), S2 = (snd2,snd1,out2,ack1→S0). Hình 4.3: FSP M.

Dựa vào việc phân tích từ vựng và phân tích cú pháp của M ta thu được list_transitions chứa các phần tử có kiểu là (start_state, list_sub_trans).

Chương 4.Chuyển đổi giữa các dạng biểu diễn của LTS

Thuật toán 4.1Thuật toán chuyển đổi FSP sang LF.

Đầu vào: list_transitions là danh sách các tiến trình con.

Đầu ra: listing_form là kiểu dữ liệu LF.

1: Khởi tạo l_states = empty, l_trans = empty, init_state = null {l_ states là danh sách rỗng chứa các trạng thái, l_ trans là danh sách rỗng chứa các hàm chuyển trạng thái, init_state là trạng thái khởi tạo}

2: for all(start_state, list_sub_trans) in list_transitionsdo

3: ifl_states.exists(start_state) = falsethen

4: l_states.add(start_state) {thêm phần tử start_state vào danh sách l_states}

Một phần của tài liệu Nghiên cứu khả năng chuyển đổi giữa các đặc tả hình thức và ứng dụng trong kiểm chứng phần mềm (Trang 30)

Tải bản đầy đủ (PDF)

(59 trang)