return result;
}
-{% for od in operator_declarations %}
-Object operator${{ od.name }}(Object left, Object right)
+{% for id in infix_declarations %}
+Object operator${{ id.name }}(Object left, Object right)
{
- assert(left.type == {{ od.input_type.upper() }});
- assert(right.type == {{ od.input_type.upper() }});
+ assert(left.type == {{ id.in_type.upper() }});
+ assert(right.type == {{ id.in_type.upper() }});
Object result;
- result.type = {{ od.result_type.upper() }};
- result.instance.{{ od.result_type.lower() }} = left.instance.{{ od.input_type.lower() }} {{ od.c_operator }} right.instance.{{ od.input_type.lower() }};
+ result.type = {{ id.out_type.upper() }};
+ result.instance.{{ id.out_type.lower() }} = left.instance.{{ id.in_type.lower() }} {{ id.operator }} right.instance.{{ id.in_type.lower() }};
return result;
}
{% endfor %}
-Object operator$equals(Object left, Object right)
-{
- assert(left.type == INTEGER);
- assert(right.type == INTEGER);
-
- Object result = { BOOLEAN, { left.instance.integer == right.instance.integer } };
- return result;
-}
-
-Object operator$notEquals(Object left, Object right)
-{
- assert(left.type == INTEGER);
- assert(right.type == INTEGER);
-
- Object result = { BOOLEAN, { left.instance.integer != right.instance.integer } };
- return result;
-}
-
-Object operator$greaterThan(Object left, Object right)
-{
- assert(left.type == INTEGER);
- assert(right.type == INTEGER);
-
- Object result = { BOOLEAN, { left.instance.integer > right.instance.integer } };
- return result;
-}
-
-Object operator$lessThan(Object left, Object right)
-{
- assert(left.type == INTEGER);
- assert(right.type == INTEGER);
-
- Object result = { BOOLEAN, { left.instance.integer < right.instance.integer } };
- return result;
-}
-
-Object operator$greaterThanOrEqual(Object left, Object right)
-{
- assert(left.type == INTEGER);
- assert(right.type == INTEGER);
-
- Object result = { BOOLEAN, { left.instance.integer >= right.instance.integer } };
- return result;
-}
-
-Object operator$lessThanOrEqual(Object left, Object right)
-{
- assert(left.type == INTEGER);
- assert(right.type == INTEGER);
-
- Object result = { BOOLEAN, { left.instance.integer <= right.instance.integer } };
- return result;
-}
-
{% if 'pow' in builtins %}
Object builtin$pow$implementation(Environment* parent, size_t argc, Object* args)
{
],
)
-EQUALITY_LEVEL_OPERATOR_TO_FUNCTION_NAME_MAPPING = {
- '==': 'equals',
- '!=': 'notEquals',
- '<=': 'lessThanOrEqual',
- '>=': 'greaterThanOrEqual',
- '<': 'lessThan',
- '>': 'greaterThan',
-}
-
-def transform_comparison_level_expression(accumulators, expression):
- # Transform expressions like 1 < 2 < 3 into expressions like 1 < 2 && 2 < 3
- if isinstance(expression.left, parsing.FurInfixExpression) and expression.left.order == 'comparison_level':
- left = transform_comparison_level_expression(
- accumulators,
- expression.left
- )
-
- middle = left.right
-
- right = transform_expression(
- accumulators,
- expression.right,
- )
-
- # TODO Don't evaluate the middle expression twice
- return CFunctionCallForFurInfixOperator(
- name='and',
- left=left,
- right=CFunctionCallForFurInfixOperator(
- name=EQUALITY_LEVEL_OPERATOR_TO_FUNCTION_NAME_MAPPING[expression.operator],
- left=middle,
- right=right,
- ),
- )
-
- return CFunctionCallForFurInfixOperator(
- name=EQUALITY_LEVEL_OPERATOR_TO_FUNCTION_NAME_MAPPING[expression.operator],
- left=transform_expression(accumulators, expression.left),
- right=transform_expression(accumulators, expression.right),
- )
-
BUILTINS = {
'false': [],
'pow': ['math.h'],
symbol_list_index=accumulators.symbol_list.index(expression.value),
)
-CInfixOperatorDeclaration = collections.namedtuple(
- 'CInfixOperatorDeclaration',
+CInfixDeclaration = collections.namedtuple(
+ 'CInfixDeclaration',
[
'name',
- 'input_type',
- 'result_type',
- 'c_operator',
+ 'in_type',
+ 'out_type',
+ 'operator',
],
)
INFIX_OPERATOR_TO_DECLARATION = {
- '+': CInfixOperatorDeclaration(name='add', input_type='INTEGER', result_type='INTEGER', c_operator='+'),
- '-': CInfixOperatorDeclaration(name='subtract', input_type='INTEGER', result_type='INTEGER', c_operator='-'),
- '*': CInfixOperatorDeclaration(name='multiply', input_type='INTEGER', result_type='INTEGER', c_operator='*'),
- '//': CInfixOperatorDeclaration(name='integerDivide', input_type='INTEGER', result_type='INTEGER', c_operator='/'),
- '%': CInfixOperatorDeclaration(name='modularDivide', input_type='INTEGER', result_type='INTEGER', c_operator='%'),
- 'and': CInfixOperatorDeclaration(name='and', input_type='BOOLEAN', result_type='BOOLEAN', c_operator='&&'),
- 'or': CInfixOperatorDeclaration(name='or', input_type='BOOLEAN', result_type='BOOLEAN', c_operator='||'),
+ '+': CInfixDeclaration(name='add', in_type='integer', out_type='integer', operator='+'),
+ '-': CInfixDeclaration(name='subtract', in_type='integer', out_type='integer', operator='-'),
+ '*': CInfixDeclaration(name='multiply', in_type='integer', out_type='integer', operator='*'),
+ '//': CInfixDeclaration(name='integerDivide', in_type='integer', out_type='integer', operator='/'),
+ '%': CInfixDeclaration(name='modularDivide', in_type='integer', out_type='integer', operator='%'),
+ 'and': CInfixDeclaration(name='and', in_type='boolean', out_type='boolean', operator='&&'),
+ 'or': CInfixDeclaration(name='or', in_type='boolean', out_type='boolean', operator='||'),
+ '==': CInfixDeclaration(name='equals', in_type='integer', out_type='boolean', operator='=='),
+ '!=': CInfixDeclaration(name='notEquals', in_type='integer', out_type='boolean', operator='!='),
+ '<=': CInfixDeclaration(name='lessThanOrEqual', in_type='integer', out_type='boolean', operator='<='),
+ '>=': CInfixDeclaration(name='greaterThanOrEqual', in_type='integer', out_type='boolean', operator='>='),
+ '<': CInfixDeclaration(name='lessThan', in_type='integer', out_type='boolean', operator='<'),
+ '>': CInfixDeclaration(name='greaterThan', in_type='integer', out_type='boolean', operator='>'),
}
+def transform_comparison_level_expression(accumulators, expression):
+ accumulators.operator_set.add(INFIX_OPERATOR_TO_DECLARATION[expression.operator])
+
+ # Transform expressions like 1 < 2 < 3 into expressions like 1 < 2 && 2 < 3
+ if isinstance(expression.left, parsing.FurInfixExpression) and expression.left.order == 'comparison_level':
+ left = transform_comparison_level_expression(
+ accumulators,
+ expression.left
+ )
+
+ middle = left.right
+
+ right = transform_expression(
+ accumulators,
+ expression.right,
+ )
+
+ # TODO Don't evaluate the middle expression twice
+ return CFunctionCallForFurInfixOperator(
+ name='and',
+ left=left,
+ right=CFunctionCallForFurInfixOperator(
+ name=INFIX_OPERATOR_TO_DECLARATION[expression.operator].name,
+ left=middle,
+ right=right,
+ ),
+ )
+
+ return CFunctionCallForFurInfixOperator(
+ name=INFIX_OPERATOR_TO_DECLARATION[expression.operator].name,
+ left=transform_expression(accumulators, expression.left),
+ right=transform_expression(accumulators, expression.right),
+ )
+
def transform_infix_expression(accumulators, expression):
if expression.order == 'comparison_level':
return transform_comparison_level_expression(accumulators, expression)