--- /dev/null
+print('13 < 17: ')
+print(13 < 17)
+print('\n')
+print('17 < 17: ')
+print(17 < 17)
+print('\n')
+print('19 < 17: ')
+print(19 < 17)
+print('\n')
+print('13 > 17: ')
+print(13 > 17)
+print('\n')
+print('17 > 17: ')
+print(17 > 17)
+print('\n')
+print('19 > 17: ')
+print(19 > 17)
+print('\n')
+print('13 == 17: ')
+print(13 == 17)
+print('\n')
+print('17 == 17: ')
+print(17 == 17)
+print('\n')
+print('19 == 17: ')
+print(19 == 17)
+print('\n')
+print('13 <= 17: ')
+print(13 <= 17)
+print('\n')
+print('17 <= 17: ')
+print(17 <= 17)
+print('\n')
+print('19 <= 17: ')
+print(19 <= 17)
+print('\n')
+print('13 >= 17: ')
+print(13 >= 17)
+print('\n')
+print('17 >= 17: ')
+print(17 >= 17)
+print('\n')
+print('19 >= 17: ')
+print(19 >= 17)
+print('\n')
+print('13 != 17: ')
+print(13 != 17)
+print('\n')
+print('17 != 17: ')
+print(17 != 17)
+print('\n')
+print('19 != 17: ')
+print(19 != 17)
--- /dev/null
+13 < 17: true
+17 < 17: false
+19 < 17: false
+13 > 17: false
+17 > 17: false
+19 > 17: true
+13 == 17: false
+17 == 17: true
+19 == 17: false
+13 <= 17: true
+17 <= 17: true
+19 <= 17: false
+13 >= 17: false
+17 >= 17: true
+19 >= 17: true
+13 != 17: true
+17 != 17: false
+19 != 17: true
\ No newline at end of file
transformation.CMultiplicationExpression: 'multiply',
transformation.CIntegerDivisionExpression: 'integerDivide',
transformation.CModularDivisionExpression: 'modularDivide',
+ transformation.CEqualityExpression: 'equals',
+ transformation.CInequalityExpression: 'notEquals',
+ transformation.CGreaterThanExpression: 'greaterThan',
+ transformation.CLessThanExpression: 'lessThan',
+ transformation.CGreaterThanOrEqualExpression: 'greaterThanOrEqual',
+ transformation.CLessThanOrEqualExpression: 'lessThanOrEqual',
+ transformation.CAndExpression: 'and',
}
return 'builtin${}({}, {})'.format(
],
)
+FurEqualityExpression = collections.namedtuple(
+ 'FurEqualityExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+FurInequalityExpression = collections.namedtuple(
+ 'FurInequalityExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+FurLessThanOrEqualExpression = collections.namedtuple(
+ 'FurLessThanOrEqualExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+FurGreaterThanOrEqualExpression = collections.namedtuple(
+ 'FurGreaterThanOrEqualExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+FurLessThanExpression = collections.namedtuple(
+ 'FurLessThanExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+FurGreaterThanExpression = collections.namedtuple(
+ 'FurGreaterThanExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
def _integer_literal_expression_parser(index, tokens):
failure = (False, index, None)
return True, index, result
+def _equality_level_expression_parser(index, tokens):
+ failure = (False, index, None)
+
+ success, index, result = _addition_level_expression_parser(index, tokens)
+
+ if not success:
+ return failure
+
+ while success and index < len(tokens) and tokens[index].type == 'equality_level_operator':
+ success = False
+
+ if index + 1 < len(tokens):
+ success, try_index, value = _addition_level_expression_parser(index + 1, tokens)
+
+ if success:
+ result = {
+ '==': FurEqualityExpression,
+ '!=': FurInequalityExpression,
+ '>=': FurGreaterThanOrEqualExpression,
+ '<=': FurLessThanOrEqualExpression,
+ '>': FurGreaterThanExpression,
+ '<': FurLessThanExpression,
+ }[tokens[index].match](left=result, right=value)
+ index = try_index
+
+ return True, index, result
+
+
def _comma_separated_list_parser(index, tokens):
failure = (False, index, None)
expressions = []
- success, index, expression = _addition_level_expression_parser(index, tokens)
+ success, index, expression = _expression_parser(index, tokens)
if success:
expressions.append(expression)
success = False
if index + 1 < len(tokens):
- success, try_index, expression = _addition_level_expression_parser(index + 1, tokens)
+ success, try_index, expression = _expression_parser(index + 1, tokens)
if success:
expressions.append(expression)
return True, index, FurFunctionCallExpression(function=function, arguments=arguments)
-_expression_parser = _addition_level_expression_parser
+_expression_parser = _equality_level_expression_parser
def _assignment_statement_parser(index, tokens):
# TODO Use a FurSymbolExpression for the target? Maybe this is actually not a good idea
return result;
}
+Object builtin$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 builtin$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 builtin$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 builtin$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 builtin$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 builtin$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(Object base, Object exponent)
{
('open_parenthese', r'\('),
('close_parenthese', r'\)'),
('comma', r','),
- ('assignment_operator', r'='),
('integer_literal', r'\d+'),
('symbol', r'[a-z]+'),
('single_quoted_string_literal', r"'.*?'"),
+ ('equality_level_operator', r'(<=|>=|==|!=|<|>)'),
('addition_level_operator', r'(\+|-)'),
- ('multiplication_level_operator', r'(\*|//|%)'),
+ ('multiplication_level_operator', r'(\*|//|%)'),
+ ('assignment_operator', r'='),
]
_TOKEN_MATCHERS = list(map(_make_token_matcher, _TOKEN_MATCHERS))
),),
)
+ def test_tokenizes_equality_operator(self):
+ self.assertEqual(
+ tokenize('=='),
+ (Token(
+ type='equality_level_operator',
+ match='==',
+ index=0,
+ line=1,
+ ),),
+ )
+
+ def test_tokenizes_greater_than_or_equal_operator(self):
+ self.assertEqual(
+ tokenize('>='),
+ (Token(
+ type='equality_level_operator',
+ match='>=',
+ index=0,
+ line=1,
+ ),),
+ )
+
+ def test_tokenizes_less_than_or_equal_operator(self):
+ self.assertEqual(
+ tokenize('<='),
+ (Token(
+ type='equality_level_operator',
+ match='<=',
+ index=0,
+ line=1,
+ ),),
+ )
+
+ def test_tokenizes_greater_than_equal_operator(self):
+ self.assertEqual(
+ tokenize('>'),
+ (Token(
+ type='equality_level_operator',
+ match='>',
+ index=0,
+ line=1,
+ ),),
+ )
+
+ def test_tokenizes_less_than_equal_operator(self):
+ self.assertEqual(
+ tokenize('<'),
+ (Token(
+ type='equality_level_operator',
+ match='<',
+ index=0,
+ line=1,
+ ),),
+ )
+
+ def test_tokenizes_not_equal_operator(self):
+ self.assertEqual(
+ tokenize('!='),
+ (Token(
+ type='equality_level_operator',
+ match='!=',
+ index=0,
+ line=1,
+ ),),
+ )
+
def test_handles_trailing_newline(self):
self.assertEqual(
tokenize('print\n'),
],
)
+CEqualityExpression = collections.namedtuple(
+ 'CEqualityExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+CInequalityExpression = collections.namedtuple(
+ 'CInequalityExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+CGreaterThanOrEqualExpression = collections.namedtuple(
+ 'CGreaterThanOrEqualExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+CLessThanOrEqualExpression = collections.namedtuple(
+ 'CLessThanOrEqualExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+CGreaterThanExpression = collections.namedtuple(
+ 'CGreaterThanExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+CLessThanExpression = collections.namedtuple(
+ 'CLessThanExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+CAndExpression = collections.namedtuple(
+ 'CAndExpression',
+ [
+ 'left',
+ 'right',
+ ],
+)
+
+
CModularDivisionExpression = collections.namedtuple(
'CModularDivisionExpression',
[
],
)
+EQUALITY_LEVEL_TYPE_MAPPING = {
+ parsing.FurEqualityExpression: CEqualityExpression,
+ parsing.FurInequalityExpression: CInequalityExpression,
+ parsing.FurLessThanOrEqualExpression: CLessThanOrEqualExpression,
+ parsing.FurGreaterThanOrEqualExpression: CGreaterThanOrEqualExpression,
+ parsing.FurLessThanExpression: CLessThanExpression,
+ parsing.FurGreaterThanExpression: CGreaterThanExpression,
+}
+
+def transform_equality_level_expression(builtin_dependencies, symbol_list, expression):
+ # Transform expressions like 1 < 2 < 3 into expressions like 1 < 2 && 2 < 3
+ if type(expression.left) in EQUALITY_LEVEL_TYPE_MAPPING:
+ left = transform_equality_level_expression(
+ builtin_dependencies,
+ symbol_list,
+ expression.left
+ )
+
+ middle = left.right
+
+ right = transform_expression(
+ builtin_dependencies,
+ symbol_list,
+ expression.right,
+ )
+
+ # TODO Don't evaluate the middle expression twice
+ return CAndExpression(
+ left=left,
+ right=EQUALITY_LEVEL_TYPE_MAPPING[type(expression)](
+ left=middle,
+ right=right,
+ ),
+ )
+
+ return EQUALITY_LEVEL_TYPE_MAPPING[type(expression)](
+ left=transform_expression(builtin_dependencies, symbol_list, expression.left),
+ right=transform_expression(builtin_dependencies, symbol_list, expression.right),
+ )
+
BUILTINS = {
'false': [],
'pow': ['math.h'],
if type(expression) in LITERAL_TYPE_MAPPING:
return LITERAL_TYPE_MAPPING[type(expression)](value=expression.value)
+ if type(expression) in EQUALITY_LEVEL_TYPE_MAPPING:
+ return transform_equality_level_expression(builtin_dependencies, symbol_list, expression)
+
INFIX_TYPE_MAPPING = {
parsing.FurAdditionExpression: CAdditionExpression,
parsing.FurSubtractionExpression: CSubtractionExpression,