from langkit.dsl import ASTNode, Bool, T
from langkit.expressions import DynamicVariable, Literal, Property, Self

from utils import emit_and_print_errors


dyn_var = DynamicVariable('dyn_var', Bool)


def run(name, expr, calling_expr=True):
    """
    Emit and print the errors we get for the below grammar with "expr" as
    a property in BarNode.
    """

    print('== {} =='.format(name))

    class FooNode(ASTNode):
        pass

    class Example(FooNode):
        p = Property(expr)
        calling = Property(calling_expr)

    emit_and_print_errors(lkt_file='foo.lkt')
    print('')


# Test proper validation for default arguments
run('Bad tuple', lambda a=(Bool, ): a)
run('Bad expr', lambda a=(Bool, Bool): a)
run('Bad type', lambda a=(Bool, 1): a)
run('Bad Self use', lambda a=(T.FooNode, Self): a)
run('Bad dynamic variable use', lambda a=(Bool, dyn_var): a)

# Test proper validation for argument passing with default arguments
run('Missing argument (1)',
    lambda a=Bool, b=(Bool, True): a.and_then(b),
    Self.p())
run('Missing argument (2)',
    lambda a=Bool, b=(Bool, True): a.and_then(b),
    Self.p(b=True))

run('Bad keyword argument',
    lambda a=Bool, b=(Bool, True): a.and_then(b),
    Self.p(a=1, b=True))

run('Too many arguments (1)',
    lambda a=Bool, b=(Bool, True): a.and_then(b),
    Self.p(True, False, b=False))
run('Too many arguments (2)',
    lambda a=Bool, b=(Bool, True): a.and_then(b),
    Self.p(True, a=False, b=False))
run('Too many arguments (3)',
    lambda a=Bool, b=(Bool, True): a.and_then(b),
    Self.p(True, False, c=False))
run('Too many arguments (4)',
    lambda a=Bool, b=(Bool, True): a.and_then(b),
    Self.p(True, False, 1, a=False))

run('Non-literal argument',
    lambda a=(Bool, Literal(True).equals(False)): a,
    Self.p)

print('Done')
