diff --git a/main.py b/main.py index 0194570..c222f00 100755 --- a/main.py +++ b/main.py @@ -67,6 +67,7 @@ symbol_to_name = { "==": "nxor", "|!": "orn", "&!": "andn", + "?:": "ternary", }; def determine_available_operators(args): @@ -201,6 +202,8 @@ def calculate_simplifications(args, available_operators): return extract_variables(inner); case (_, left, right): return extract_variables(left) + extract_variables(right); + case (_, cond, true, false): + return extract_variables(cond) + extract_variables(true) + extract_variables(false); case _: print(exp); assert(not "TODO"); @@ -225,6 +228,10 @@ def calculate_simplifications(args, available_operators): '==': lambda x, y: ~(x ^ y), # nxor } + ternary_operators = { + '?:': lambda x, y, z: (x & y) | (~x & z), # ternary + }; + def print_status(): numerator = 65536 - todo_count[0]; denominator = 65536 @@ -307,6 +314,29 @@ def calculate_simplifications(args, available_operators): consider(binary_truthtable, binary_expression, binary_cost); + # consider ternary operators: + for name, function in sorted(ternary_operators.items()): + if name in available_operators: + s = sorted(lookup.items()); + for a_truthtable, a_expression in s: + for b_truthtable, b_expression in s: + # x ? y : z + ternary_truthtable = function( + my_truthtable, a_truthtable, b_truthtable) & M; + ternary_expression = (name, + my_expression, a_expression, b_expression); + ternary_cost = 1 + my_cost + \ + costs[a_truthtable] + costs[b_truthtable]; + + consider(ternary_truthtable, ternary_expression, \ + ternary_cost); + + # y ? x : z + # assert(not "TODO"); + + # z ? y : z + # assert(not "TODO"); + return costs, lookup pathname = "simplifications.bin" @@ -393,7 +423,7 @@ def parse(text): self.tokendata = self.text[self.position]; self.position += 1; - case "(" | ")": + case "(" | ")" | "?" | ":": self.tokenkind = self.text[self.position]; self.position += 1; @@ -551,8 +581,30 @@ def parse(text): return left; + def parse_ternary(tokenizer): + exp = parse_ors(tokenizer); + + if tokenizer.tokenkind in ("?", ): + cond = exp; + + tokenizer.next(); + + true = parse_ors(tokenizer); + + if tokenizer.tokenkind != ":": + raise BaseException("expecting ':' in ternary expression, " + "found: '{tokenizer.tokenkind}'!"); + + tokenizer.next(); + + false = parse_ternary(tokenizer); + + return ("?:", cond, true, false); + else: + return exp; + def parse_root(tokenizer): - return parse_ors(tokenizer); + return parse_ternary(tokenizer); tokenizer = Tokenizer(text); @@ -608,6 +660,10 @@ def evaluate(expr): case ("!&", left, right): return ~(evaluate(left) & evaluate(right)) & M; + case ("?:", cond, left, right): + cond = evaluate(cond); + return (cond & evaluate(left)) | (~cond & evaluate(right)); + case _: print(f'expr = {expr}'); assert(not "TODO");