2010-07-21 29 views
7

Xin chào tất cả mọi người Tôi hiện đang triển khai một ngôn ngữ lập trình đơn giản cho trải nghiệm học tập nhưng tôi cần một số lời khuyên. Hiện tại tôi đang thiết kế phiên dịch của tôi và tôi đã gặp vấn đề.Thực hiện một máy ảo dựa trên ngăn xếp cho một tập hợp con của C

Ngôn ngữ của tôi là tập hợp con của C và tôi gặp sự cố liên quan đến việc triển khai trình thông dịch chồng. Trong ngôn ngữ sau đây sẽ biên dịch:

somefunc() 
{ 
    1 + 2; 
} 

main() 
{ 
    somefunc(); 
} 

Bây giờ đây là được rồi nhưng khi "1 + 2" được tính kết quả được đẩy lên một chồng và sau đó trở về chức năng nhưng vẫn có một số trên stack, và không nên có. Làm thế nào tôi có thể giải quyết vấn đề này?

Tôi đã nghĩ về việc lưu "trạng thái" của ngăn xếp trước khi gọi hàm và khôi phục "trạng thái" sau khi gọi hàm. Ví dụ, lưu số lượng các phần tử trên stack, sau đó thực thi mã hàm, trả về và sau đó bật từ stack cho đến khi chúng ta có cùng số phần tử như trước (hoặc có thể +1 nếu hàm trả về một cái gì đó).

Bất kỳ ý tưởng nào? Cảm ơn mọi lời khuyên!

Trả lời

8

Câu hỏi hay! Một trong những sở thích của tôi là viết trình biên dịch cho các ngôn ngữ đồ chơi, vì vậy kudo cho hương vị lập trình tuyệt vời của bạn.

An tuyên bố biểu thức là nơi mã trong câu lệnh chỉ đơn giản là một biểu thức. Điều này có nghĩa là bất kỳ điều gì trong biểu mẫu <expression> ;, bao gồm những thứ như bài tập và cuộc gọi chức năng, nhưng không phải là if s, while s hoặc return s. Bất kỳ câu lệnh biểu thức nào sẽ có giá trị còn lại trên ngăn xếp ở cuối, mà bạn nên loại bỏ.

1 + 2 là một tuyên bố biểu hiện, nhưng như vậy là những:

  • x = 5;
    Việc chuyển nhượng biểu lá giá trị 5 trên stack từ kết quả của một bài tập là giá trị của các trái toán hạng tay. Sau khi tuyên bố được hoàn tất, bạn bật tắt các giá trị không sử dụng 5.

  • printf("hello world!\n");
    printf() trả về số lượng ký tự. Bạn sẽ có giá trị này còn lại trên stack, do đó, pop nó khi tuyên bố kết thúc.

Tuyên bố biểu thức hiệu quả sẽ để lại giá trị trên ngăn xếp trừ khi loại biểu thức là void. Trong trường hợp đó, bạn có các trường hợp đặc biệt là void và không bật bất kỳ thứ gì sau đó hoặc đẩy giá trị "void" giả mạo lên ngăn xếp để bạn luôn có thể bật một giá trị.

+0

trong biểu diễn AST của tôi, tôi có một nút gọi là "ASTStmtExpr" chỉ cho điều này! Tôi nghĩ rằng tôi bắt đầu hiểu, loại ... Đây là những gì tôi không chắc chắn về: Do những hạn chế của những bình luận trả lời tôi có để dán một snipplet: \t trống Compiler :: lần (const ASTStmtExpr & expr_stmt, std :: shared_ptr func) \t \t { \t \t \t expr_stmt.expr() -> chấp nhận (* này, func); \t \t} Bạn đang nói rằng tôi nên thêm một OP_POP sau này, và cho những thứ như bài tập tôi sẽ đẩy một giả "Nil" đối tượng để nó sau đó sẽ được xuất hiện? –

+0

Xin lỗi tôi không biết các ý kiến ​​không được định dạng –

+1

Đối với các bài tập không, bạn không đẩy giá trị giả, vì bạn sẽ có kết quả của bài tập trên ngăn xếp đã có. Một nhiệm vụ chỉ là một biểu thức sử dụng toán tử '=', không khác với '+' hoặc '-' trừ' = 'có một tác dụng phụ của việc gán cho một biến. Nếu không nó hoạt động giống như tất cả các nhà khai thác khác. –

2

Bạn sẽ cần một trình phân tích cú pháp thông minh hơn. Khi bạn thấy một biểu thức có giá trị không được sử dụng thì bạn cần phát ra POP.

+0

Xin chào, cảm ơn bạn đã trả lời. Tôi vẫn còn trong giai đoạn của các trình biên dịch mã hóa cho trẻ sơ sinh và tôi đã nghĩ về việc tối ưu hóa như thế này, nhưng không thể tìm ra giải pháp khả thi: (Có lẽ tôi sẽ thử lại, một lần nữa cảm ơn !! –

0

Đây là cơ hội quan trọng về tối ưu hóa học tập. bạn có một hàm thực hiện phép tính số nhưng số nguyên, kết quả toán học int thậm chí không được sử dụng theo bất kỳ cách nào, hình dạng hoặc hình thức nào.

Để trình biên dịch của bạn tối ưu hóa chức năng đi sẽ làm giảm rất nhiều bytecode được tạo và thực hiện không có gì!

Các vấn đề liên quan