Skip to content

Instantly share code, notes, and snippets.

@aanastasiou
Last active March 12, 2023 21:22
Show Gist options
  • Save aanastasiou/ddcc9dc58a29a6a8027585314d0f757d to your computer and use it in GitHub Desktop.
Save aanastasiou/ddcc9dc58a29a6a8027585314d0f757d to your computer and use it in GitHub Desktop.
A simple stack language expressed in Rascal
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