{% macro params(compute) -%}
{% set input = compute.input %}
{% set args = namespace(index=0, dict={}) %}
{% if 'input' in compute %}
{% for key,variable in input|dictsort %}
{% if key != 'value' -%}
{{- ", " if args.index > 0 -}}{{- numconv(variable) }} {{ key -}}
{%- set args.index = args.index + 1 -%}
{%- endif %}
{% endfor %}
{%- endif %}
{% if 'return' in compute and compute.return is iterable and compute.return is not string %}
{# In C languages, you pass in array as a parameter #}
{% for key,var in compute.variables|dictsort %}
    {% set x=args.dict.__setitem__(key, var) %}
{% endfor %}
{{- ", " if args.index > 0 -}}{{numconv(args.dict[compute.return[0]])}} * returnArray
{%- endif %}
{%- endmacro %}

{% macro variables(vars) -%}
{% if vars %}
{% for key,var in vars|dictsort %}
    {{ numconv(var) }} {{key}}; // Variable declaration
{% endfor %}
{% endif %}
{%- endmacro %}

{% macro registerSize(registers, name) %}
{% for key,register in registers|dictsort %}
{% if key == name %}{{numtype(register.length)}}{% endif %}
{% endfor %}
{% endmacro %}

{% macro returnType(compute) -%}
{# Create a dictionary of all the variables #}
{% set vars = namespace(dict={}) %}
{% if 'variables' in compute %}
{% for key,var in compute.variables|dictsort %}
    {% set x=vars.dict.__setitem__(key, var) %}
{% endfor %}
{% endif %}
{% if compute.return is iterable and compute.return is not string %}
{# In C languages, you do not return arrays. Rather the arg is an array #}
void
{%- else -%}
{# Render a single var type #}
{{ numconv(vars.dict[compute.return]) }}
{%- endif %}
{%- endmacro %}

{% macro numconv(cyan) -%}
{%- if cyan == 'int8' -%}
char
{%- elif cyan == 'uint8' -%}
uint8_t
{%- elif cyan == 'int16' -%}
short
{%- elif cyan == 'uint16' -%}
uint16_t
{%- elif cyan == 'int32' -%}
long
{%- elif cyan == 'uint32' -%}
uint32_t
{%- elif cyan == 'float32' -%}
float
{%- elif cyan == 'float64' -%}
double
{%- else -%}
{# Raise an error and take a guess #}
/* ERROR UNDEFINED TYPE */ long double
{%- endif -%}
{%- endmacro %}

{% macro numtype(len, sign) -%}
{%- if sign -%}
{%- if len <= 8 %}
char
{%- elif len <= 16 %}
short
{%- elif len <= 32 %}
long
{%- else %}
long long
{%- endif %}
{%- else %}
{%- if len <= 8 %}
uint8_t
{%- elif len <= 16 %}
uint16_t
{%- elif len <= 32 %}
uint32_t
{%- else %}
uint64_t
{%- endif %}
{%- endif %}
{%- endmacro %}

{% macro recursiveAssignLogic(logicalStep, keys) -%}
{% for key in keys -%}
{# Perform a recursive summation from an array of logical steps #}
{% if key == 'sum' -%}
    ({%- for step in logicalStep[key] -%}
    {% if step is iterable and step is not string -%}
    {{ recursiveAssignLogic(step, step.keys()) -}}
    {%- else -%}
    {{step}}
    {%- endif %}
    {{- "+" if not loop.last -}}
    {%- endfor -%})
{%- endif %}
{# Perform a recursive difference from an array of logical steps #}
{% if key == 'difference' -%}
    ({%- for step in logicalStep[key] -%}
    {% if step is iterable and step is not string -%}
    {{ recursiveAssignLogic(step, step.keys()) -}}
    {%- else -%}
    {{step}}
    {%- endif %}
    {{- "-" if not loop.last -}}
    {%- endfor -%})
{%- endif %}
{# Perform a recursive product from an array of logical steps #}
{% if key == 'product' -%}
    ({%- for step in logicalStep[key] -%}
    {% if step is iterable and step is not string -%}
    {{ recursiveAssignLogic(step, step.keys()) -}}
    {%- else -%}
    {{step}}
    {%- endif %}
    {{- "*" if not loop.last -}}
    {%- endfor -%})
{%- endif %}
{# Perform a recursive division from an array of logical steps #}
{% if key == 'division' -%}
    ({%- for step in logicalStep[key] -%}
    {% if step is iterable and step is not string -%}
    {{ recursiveAssignLogic(step, step.keys()) -}}
    {%- else -%}
    {{ step }}
    {%- endif %}
    {{- "/" if not loop.last -}}
    {%- endfor -%})
{%- endif %}
{# Perform a recursive modulus from an array of logical steps #}
{% if key == 'modulus' -%}
    ({%- for step in logicalStep[key] -%}
    {% if step is iterable and step is not string -%}
    (int) {{ recursiveAssignLogic(step, step.keys()) -}}
    {%- else -%}
    {#- Need to do a cast to int, may lose precision -#}
    (int) {{ step }}
    {%- endif %}
    {{- "%" if not loop.last -}}
    {%- endfor -%})
{%- endif %}
{# Perform a bitwise OR from an array of logical steps #}
{% if key == 'bitwiseOr' -%}
    ({%- for step in logicalStep[key] -%}
    {% if step is iterable and step is not string -%}
    {{ recursiveAssignLogic(step, step.keys()) -}}
    {%- else -%}
    {{ step }}
    {%- endif %}
    {{- "|" if not loop.last -}}
    {%- endfor -%})
{%- endif %}
{# Perform a bitwise AND from an array of logical steps #}
{% if key == 'bitwiseAnd' -%}
    ({%- for step in logicalStep[key] -%}
    {% if step is iterable and step is not string -%}
    {{ recursiveAssignLogic(step, step.keys()) -}}
    {%- else -%}
    {{ step }}
    {%- endif %}
    {{- "&" if not loop.last -}}
    {%- endfor -%})
{%- endif %}
{# Perform a power operation #}
{% if key == 'power' -%}
    pow({{logicalStep[key][0]}}, {{logicalStep[key][1]}})
{%- endif %}
{# Perform an arc tangent operation #}
{% if key == 'arc tangent' -%}
    atan({{logicalStep[key]}})
{%- endif %}
{# Bitwise ops #}
{%- if key == 'bitShiftLeft' -%}
    ({{logicalStep.var}} << {{logicalStep.bits}})
{%- endif %}
{%- if key == 'bitShiftRight' -%}
    ({{logicalStep.var}} >> {{logicalStep.bits}})
{%- endif %}
{%- endfor %}
{%- endmacro %}