Last active
March 12, 2023 21:22
-
-
Save aanastasiou/ddcc9dc58a29a6a8027585314d0f757d to your computer and use it in GitHub Desktop.
A simple stack language expressed in Rascal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module stacklang_list::stacklang_list | |
// A very simple stack language | |
// | |
// The stack is represented as a list with the top of the stack extending the list from the left. | |
// For example, to add two numbers: eval([add(), push(1), push(1)]) | |
import IO; | |
// Symbols | |
data s_sym = push(int a) | | |
pop() | | |
add() | | |
mul() | | |
sub() | | |
div() | | |
check() | // Equivalent of IF ("if" is a reserved word in rascal) | |
check_while()| // Equivalent of WHILE ("while" is a reserved word in rascal) | |
resume(); // Equivalent of THEN/REPEAT for IF/WHILE | |
// Program (as a list of symbols) | |
alias s_prog = list[s_sym]; | |
// Evaluation rules | |
// Math operations | |
s_prog eval([add(), push(int a), push(int b)]) = eval([push(a+b)]); | |
s_prog eval([*rest, add(), push(int a), push(int b)]) = eval([*rest, push(a+b)]); | |
s_prog eval([*rest, sub(), push(int a), push(int b)]) = eval([*rest, push(b-a)]); | |
s_prog eval([sub(), push(int a), push(int b)]) = eval([push(b-a)]); | |
s_prog eval([*rest, mul(), push(int a), push(int b)]) = eval([*rest, push(a*b)]); | |
s_prog eval([mul(), push(int a), push(int b)]) = eval([push(a*b)]); | |
s_prog eval([*rest, div(), push(int a), push(int b)]) = eval([*rest, push(b/a)]); | |
s_prog eval([div(), push(int a), push(int b)]) = eval([push(b/a)]); | |
// Conditional execution | |
s_prog eval([resume(), *true_branch, check(), push(int condition)]) = condition!=0?eval([*true_branch,push(condition)]):eval([push(condition)]); | |
s_prog eval([*rest, resume(), *true_branch, check(), push(int condition)]) = condition!=0?eval([*rest, *true_branch, push(condition)]):eval([*rest, push(condition)]); | |
// Iteration (using while) | |
s_prog eval([resume(), *true_branch, check_while(), push(int condition)]) = condition!=0?eval([resume(), *true_branch, check_while(),*true_branch, push(condition)]):eval([push(condition)]); | |
s_prog eval([*rest, resume(), *true_branch, check_while(), push(int condition)]) = condition!=0?eval([*rest, resume(), *true_branch, check_while(), *true_branch, push(condition)]):eval([*rest, push(condition)]); | |
// Pop | |
s_prog eval([pop(), push(int a)]) = eval([]); | |
s_prog eval([*rest, pop(), push(int a)]) = eval([*rest]); | |
// Propagate forms that do not have evaluation rules. | |
default s_prog eval(s_prog e) = e; | |
// TESTS | |
// Math operations | |
test bool simple_add() = eval([add(), push(1), push(1)]) == [push(2)]; | |
test bool rest_add() = eval([add(), push(1), add(), push(1), push(1)]) == [push(3)]; | |
test bool simple_sub() = eval([sub(), push(1), push(2)]) == [push(1)]; | |
test bool rest_sub() = eval([sub(), push(1), sub(), push(1), push(2)]) == [push(0)]; | |
test bool simple_mul() = eval([mul(), push(3), push(2)]) == [push(6)]; | |
test bool rest_mul() = eval([mul(), push(6), mul(), push(3), push(2)]) == [push(36)]; | |
test bool simple_div() = eval([div(), push(3), push(9)]) == [push(3)]; | |
test bool rest_div() = eval([div(), push(3), div(), push(3), push(9)]) == [push(1)]; | |
// Stack operations | |
// Pop | |
test bool simple_pop() = eval([pop(), push(2)]) == []; | |
test bool rest_pop() = eval([push(122), pop(), push(2)]) == [push(122)]; | |
// Conditional | |
test bool simple_check() = eval([resume(), push(0), check(), push(1)]) == [push(0), push(1)]; | |
test bool rest_check() = eval([push(0), resume(), push(0), check(), push(1)]) == [push(0), push(0), push(1)]; | |
// Iteration | |
test bool simple_check_while() = eval([resume(), sub(), push(1), check_while(), push(10)]) == [push(0)]; | |
test bool rest_check_while() = eval([push(0), resume(), sub(), push(1), check_while(), push(10)]) == [push(0), push(0)]; | |
//Nested iteration | |
test bool nested_check_while() = eval([resume(), pop(), resume(), sub(), push(1), check_while(), push(2), sub(), push(1), check_while(), push(2)]) == [push(0)]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment