Skip to content

Commit

Permalink
Add support for logical AND / OR operations (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
anubh-v authored Feb 11, 2020
1 parent e9a1e64 commit faaaa98
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 4 deletions.
51 changes: 51 additions & 0 deletions evaluator.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,55 @@ function analyze_sequence(stmts) {

}

/* BOOLEAN OPERATIONS (&& and ||) */

function is_boolean_operation(stmt) {
return is_tagged_list(stmt, "boolean_operation");
}

function name_of_boolean_op(stmt) {
return head(tail(head(tail(stmt))));
}

function boolean_op_left_arg(stmt) {
return list_ref(head(tail(tail(stmt))), 0);
}

function boolean_op_right_arg(stmt) {
return list_ref(head(tail(tail(stmt))), 1);
}

function analyze_boolean_op(stmt) {
const left_hand_expr_func = analyze(boolean_op_left_arg(stmt));
const right_hand_expr_func = analyze(boolean_op_right_arg(stmt));

return name_of_boolean_op(stmt) === "&&"
? analyze_logical_and(left_hand_expr_func, right_hand_expr_func)
: analyze_logical_or(left_hand_expr_func, right_hand_expr_func);
}

function analyze_logical_and(left_hand_expr_func, right_hand_expr_func) {
return (env, succeed, fail) => {
left_hand_expr_func(env,
(val, fail2) => {
val ? right_hand_expr_func(env, succeed, fail2)
: succeed(false, fail2);
},
fail);
};
}

function analyze_logical_or(left_hand_expr_func, right_hand_expr_func) {
return (env, succeed, fail) => {
left_hand_expr_func(env,
(val, fail2) => {
val ? succeed(true, fail2)
: right_hand_expr_func(env, succeed, fail2);
},
fail);
};
}

/* FUNCTION APPLICATION */

// The core of our evaluator is formed by the
Expand Down Expand Up @@ -750,6 +799,8 @@ function analyze(stmt) {
? analyze_require(stmt)
: is_application(stmt)
? analyze_application(stmt)
: is_boolean_operation(stmt)
? analyze_boolean_op(stmt)
: error(stmt, "Unknown statement type in analyze");
}

Expand Down
31 changes: 27 additions & 4 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ function test_subfunction() {
assert_equal(120, final_result);
}

function test_binary_boolean_operations() {
parse_and_eval("true && (false || true) && (true && false);");
assert_equal(false, final_result);
}

function test_shortcircuiting() {
parse_and_eval("function foo() { return foo(); }\
true || foo();"
);

assert_equal(true, final_result);
parse_and_eval("function foo() { return foo(); }\
false && foo();"
);

assert_equal(false, final_result);
}

/* 1.2 Test Non-Deterministic Functionality */

/**
Expand Down Expand Up @@ -64,14 +82,18 @@ function test_nondet_require() {
return low > high ? amb() : amb(low, int_between(low + 1, high)); \
} \
function is_divisible_by_3(x) { return (x % 3) === 0;} \
let integer = int_between(4, 10); \
require(is_divisible_by_3(integer)); \
function is_even(x) { return (x % 2) === 0;} \
function is_one(x) { return x === 1;}\
let integer = int_between(1, 12); \
require(is_one(integer) || (is_even(integer) && is_divisible_by_3(integer))); \
integer;"
);

assert_equal(1, final_result);
try_again();
assert_equal(6, final_result);
try_again();
assert_equal(9, final_result);
assert_equal(12, final_result);
try_again();
assert_equal(null, final_result);
}
Expand Down Expand Up @@ -117,7 +139,8 @@ run(
test_assignment,
test_conditional_expressions,
test_function,
test_subfunction,
test_subfunction,
test_shortcircuiting,
test_nondet_empty,
test_nondet_infinite,
test_nondet_require,
Expand Down

0 comments on commit faaaa98

Please sign in to comment.