// Souffle - A Datalog Compiler
// Copyright (c) 2016, The Souffle Developers. All rights reserved
// Licensed under the Universal Permissive License v 1.0 as shown at:
// - https://opensource.org/licenses/UPL
// - <souffle root>/licenses/SOUFFLE-UPL.txt

//
//	Forward circuit evaluation
// 	Yield the value of each wire, given the input wire assignments
//


.type Var <: symbol
.type Bool <: symbol

//bitwise gates
.decl g_and(res : Var, o1 : Var, o2 : Var)
.input g_and()
.decl g_or(res : Var, o1 : Var, o2 : Var)
.input g_or()
.decl g_not(res : Var, o1 : Var)
.input g_not()

//the input values for wires
.decl set_input(x : Var, y : Bool)
.input set_input()
//querying a wire's value
.decl g_assignment(x : Var, y : Bool)
.output g_assignment()

g_assignment(x, "true") :-
	set_input(x, "true");
	g_and(x, o1, o2), g_assignment(o1, "true"), g_assignment(o2, "true");
	g_or(x, o1, _), g_assignment(o1, "true");
	g_or(x, _, o2), g_assignment(o2, "true");
 	g_not(x, o1), g_assignment(o1, "false").

g_assignment(x, "false") :-
	set_input(x, "false");
	g_and(x, o1, _), g_assignment(o1, "false");
 	g_and(x, _, o2), g_assignment(o2, "false");
	g_or(x, o1, o2), g_assignment(o1, "false"), g_assignment(o2, "false"),
	g_not(x, o1), g_assignment(o1, "true").

//same as g_assignment, however only outputs non-inputs
.decl yield_outs(x : Var, val : Bool)
.output yield_outs()
yield_outs(x, val) :-
	!set_input(x, _), g_assignment(x, val).
