# Copyright (C) 2021 Jasper den Ouden.
#
# This is free software: you can redistribute it and/or modify
# it under the terms of the Affero GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
from type_stack_calc.extractor import Extractor, StopMarker
def list_flatten(gen):
for el in gen:
if type(el) == list:
for r_el in list_flatten(el): yield r_el
else:
yield el
def filter_none(lst): return [el for el in lst if el is not None]
class IfBlock:
"""`if_block.py`: `{..if..} {..else..} (..cond..).if` provider."""
def __init__(self, cond, yes, no, ret_stack):
self.cond, self.yes, self.no = map(filter_none, [cond, yes, no])
self.stack = ret_stack
def extract_cond(self, extractor, gen):
lst = []
e_c = Extractor((lst.append, extractor[1]))
gen = reversed(self.cond)
for el in gen:
if el is not None:
e_c._extract_1(gen, el)
self.cond = list_flatten(lst) # Remainder can stay.
def extract(self, extractor, gen, _obj):
self.extract_cond(extractor, gen)
if len(self.stack) > 0: # TODO permit multi-output stuff or not?
assert len(self.stack) == 1
tmp = extractor.tmp_var('if', self.stack[0])
if deffer := getattr(tmp, 'deffer', None):
extractor[1](deffer)
if getattr(tmp, 'key', "")[:1] == '~':
extractor[0](StopMarker)
else:
extractor[0](tmp)
self.yes = [*self.yes, *tmp.setter] # internals extracted later)
self.no = [*self.no, *tmp.setter]
extractor[1](self) # Thing itself extracts outside.
def extract_top(self, extractor, gen, _obj):
self.extract_cond(extractor, gen)
extractor[0](self) # Already on top, just place.
# .yes and .no is done by `extracted_to_c`.
def to_c(self, tc, _gen):
wfile, prep = tc[:2]
wfile(prep + "if(")
tc.new_context(prep + " ", '(').c(self.cond)
wfile(") {")
body_tc = tc.new_context(prep + " ", ';')
body_tc.extract_n_c(self.yes)
if any(self.no): # Only do non-empty elses.
wfile(prep + "} else {")
body_tc.extract_n_c(self.no)
wfile(prep + "}")
else:
wfile(prep + "}")