def test_with_vars_and_calls(self):
     self.assert_generates_ast('''
         a as Int = 5 ** 0.7
         b as Float = 0.2 * sqrt(2) * a / blah(a*sqrt(2))
         ''',
         [
             Definition(
                 Declaration(_('a'), _t('Int')),
                 MathExpression([Integer(5), _op('**'), Float(0.7)])
             ),
             Definition(
                 Declaration(_('b'), _t('Float')),
                 MathExpression([
                     Float(0.2),
                     _op('*'),
                     Call(_('sqrt'), [Integer(2)]),
                     _op('*'),
                     _('a'),
                     _op('/'),
                     Call(_('blah'),
                          [MathExpression([
                              _('a'),
                              _op('*'),
                             Call(_('sqrt'), [Integer(2)])
                          ])]
                     )
                 ])
             )
         ])
    def test_recursion(self):
        self.assert_generates_ast('''
            bear as Function(emma as Heifer*, bertram as Bull*) -> Calf*:
                return malloc(sizeof(Calf))

            bear_n as Function(n as Int, emma as Heifer*, bertram as Bull*):
                if not n:
                    return
                else:
                    bear(eve, adam)
                    return bear_n(n-1)
        ''',
        [
            Function(
                _('bear'),
                FunctionHeader(
                    _t('Calf', True),
                    [
                        Declaration(_('emma'), _t('Heifer', True)),
                        Declaration(_('bertram'), _t('Bull', True))
                    ],
                ),
                Block([Return(Call(_('malloc'), [Call(_('sizeof'), [_('Calf')])]))])
            ),
            Function(
                _('bear_n'),
                FunctionHeader(
                    None,
                        [
                            Declaration(_('n'), _t('Int')),
                            Declaration(_('emma'), _t('Heifer', True)),
                            Declaration(_('bertram'), _t('Bull', True))
                        ],
                    ),
                    Block([
                        If(
                            Condition([_op('not'), _('n')]),
                            Block([Return(None)]),
                            Block([
                                Call(_('bear'), [_('eve'), _('adam')]),
                                Return(
                                    Call(
                                        _('bear_n'),
                                        [MathExpression([_('n'), _op('-'), Integer(1)])]
                                    )
                                )
                            ])
                        )
                    ])
            )
        ])
    def test_definition(self):
        self.assert_generates_ast('''
            foo as Function(a as Int, b as Float, c as Bool, d as Bool, e as Bool, f as Bool) -> String:
                if a:
                    return a
                if c and e and (d or e) or (f):
                    return a
                else:
                    return b

            foo2 as Function():
                return 0
            ''',
            [
                Function(
                    _('foo'),
                    FunctionHeader(
                        _t('String'),
                        [
                            Declaration(_('a'), _t('Int')),
                            Declaration(_('b'), _t('Float')),
                            Declaration(_('c'), _t('Bool')),
                            Declaration(_('d'), _t('Bool')),
                            Declaration(_('e'), _t('Bool')),
                            Declaration(_('f'), _t('Bool'))
                        ]
                    ),
                    Block([
                        If(
                            Condition([_('a')]),
                            Block([Return(_('a'))])
                        ),
                        If(
                            Condition([
                                _('c'), _op('and'),
                                _('e'), _op('and'),
                                ExpressionContainer([Condition([_('d'), _op('or'), _('e')])]),
                                _op('or'),
                                ExpressionContainer([_('f')])
                            ]),
                            Block([Return(_('a'))]),
                            Block([Return(_('b'))])
                        )
                    ])
                ),
                Function(
                    _('foo2'),
                    FunctionHeader(None, []),
                    Block([Return(Integer(0))])
                )
            ])
 def test_basic(self):
     self.assert_generates_ast('''
         while a < b:
             do_something()
     ''',
     [
         WhileLoop(
             Condition([_('a'), _op('<'), _('b')]),
             Block([
                 Call(_('do_something'), [])
             ])
         )
     ])
 def test_multiple(self):
     self.assert_generates_ast('''
         a as Int = 5 * 8
         b as Float = 10 * 3.14
         b = 10 / 5.678
         b = 5 * 5 + 1
         b = 5 * 3 + (2 * 7)
         7 + (3 ^ (2 + 1) / 5 ** 7 * (8/9)) - 9 * (5 - 3)
     ''',
     [
         Definition(
             Declaration(_('a'), _t('Int')),
             MathExpression([Integer(5), _op('*'), Integer(8)]),
         ),
         Definition(
             Declaration(_('b'), _t('Float')),
             MathExpression([Integer(10), _op('*'), Float(3.14)])
         ),
         Assignment(_('b'),
             MathExpression([Integer(10), _op('/'), Float(5.678)])
         ),
         Assignment(_('b'),
             MathExpression([Integer(5), _op('*'), Integer(5), _op('+'), Integer(1)])
         ),
         Assignment(_('b'),
             MathExpression([
                 Integer(5),
                 _op('*'),
                 Integer(3),
                 _op('+'),
                 ExpressionContainer([
                     MathExpression([
                         Integer(2), _op('*'), Integer(7)
                     ])
                 ])
             ])
         ),
         MathExpression([
             Integer(7),
             _op('+'),
             ExpressionContainer([
                 MathExpression([
                     Integer(3),
                     _op('**'),
                     ExpressionContainer([
                         MathExpression([Integer(2), _op('+'), Integer(1)])
                     ]),
                     _op('/'),
                     Integer(5),
                     _op('^'),
                     Integer(7),
                     _op('*'),
                     ExpressionContainer([
                         MathExpression([Integer(8), _op('/'), Integer(9)])
                     ]),
                 ]),
             ]),
             _op('-'),
             Integer(9),
             _op('*'),
             ExpressionContainer([
                 MathExpression([Integer(5), _op('-'), Integer(3)])
             ])
         ])
     ])