Example #1
0
def test_basic_recursion():
    implementation = function(
        [parameter_name],
        conditional(
            (invoke(GREATER_THAN, parameter_name, integer(1)),
             invoke(
                 MULTIPLY, parameter_name,
                 invoke(function_name,
                        invoke(SUBTRACT, parameter_name, integer(1))))),
            (boolean(True), integer(1))))

    environment = Environment.create_standard()
    environment.define(function_name, limp.evaluate(implementation,
                                                    environment))

    data = [
        (1, 1),
        (2, 2),
        (3, 6),
        (4, 24),
        (5, 120),
        (6, 720),
    ]
    for parameter, expected_result in data:
        source_code = invoke(function_name, integer(parameter))
        result = limp.evaluate(source_code, environment)
        yield assert_equal, expected_result, result
Example #2
0
def test_executing_something_a_fixed_number_of_times():
    for iterations in range(ARBITRARY_ITERATION_LIMIT):
        my_function = MagicMock()
        environment = Environment.create_standard()
        environment.define(FUNCTION_NAME, my_function)
        code = invoke(TIMES, integer(iterations), symbol(FUNCTION_NAME))
        limp.evaluate(code, environment)
        yield (assert_equal, iterations, my_function.call_count)
Example #3
0
def test_iterating_a_fixed_number_of_times():
    my_function = MagicMock()
    environment = Environment.create_standard()
    environment.define(FUNCTION_NAME, my_function)
    code = invoke(ITERATE, integer(ARBITRARY_ITERATION_LIMIT),
                  symbol(FUNCTION_NAME))
    limp.evaluate(code, environment)
    for i in range(ARBITRARY_ITERATION_LIMIT):
        yield (my_function.assert_any_call, i)
Example #4
0
def test_miscellaneous_strings_remain_unmodified():
    data = [
        "[]",
        "()",
        "[ ]",
    ]
    for string_ in data:
        source_code = string(string_)
        yield assert_equal, string_, limp.evaluate(source_code)
Example #5
0
def test_looping_functions():
    FUNCTION_NAME = 'my_function'
    ARBITRARY_ITERATION_LIMIT = 100

    # test 'times' function
    for iterations in range(ARBITRARY_ITERATION_LIMIT):
        my_function = MagicMock()
        environment = Environment.create_standard()
        environment.define(FUNCTION_NAME, my_function)
        limp.evaluate(f'(times {iterations} {FUNCTION_NAME})', environment)
        yield assert_equals, iterations, my_function.call_count

    # test 'iterate' function
    my_function = MagicMock()
    environment = Environment.create_standard()
    environment.define(FUNCTION_NAME, my_function)
    limp.evaluate(f'(iterate {ARBITRARY_ITERATION_LIMIT} {FUNCTION_NAME})',
                  environment)
    for i in range(iterations):
        yield my_function.assert_any_call, i
Example #6
0
def test_accessing_attributes():
    environment = Environment.create_standard()
    environment.define('object', limp.evaluate(object_code))

    data = [
        ('{age: 90}.age', 90),
        ('{name:"Bob" age:200}.age', 200),
        ('object.name', "Blarg Smith"),
        ('object.age', 1337),
        ('object.interests', ["food", "limp", "THPS"]),
        ('object.address', {
            "house-number": 420,
            "street": "earth street"
        }),
        ('object.address.street', "earth street"),
        ('{profiles: {byxor: {is-cool: true}}}.profiles.byxor.is-cool', True),
    ]

    for source_code, expected_result in data:
        result = limp.evaluate(source_code, environment)
        yield assert_equals, expected_result, result
Example #7
0
def test_lists_are_immutable():
    LIST = 'my-list'
    LIST_VALUE = [1, 2, 3]

    environment = Environment.create_standard()
    environment.define(LIST, LIST_VALUE)

    invocations = [
        invoke(APPEND_ELEMENT, LIST, integer(1)),
        invoke(CONCATENATE, LIST, list_of(string("foo"), string("bar"))),
        invoke(MAP, TEMPORARY_MAP_FUNCTION, LIST),
        invoke(FILTER, TEMPORARY_FILTER_FUNCTION, LIST),
        invoke(REDUCE, TEMPORARY_REDUCE_FUNCTION, LIST),
        invoke(FIRST_ELEMENT, LIST),
        invoke(LAST_ELEMENT, LIST),
        invoke(ALL_BUT_FIRST, LIST),
        invoke(ALL_BUT_LAST, LIST),
        invoke(PREPEND_ELEMENT, LIST, string("foo")),
    ]
    for invocation in invocations:
        limp.evaluate(invocation, environment)

    yield assert_equal, LIST_VALUE, environment.resolve(LIST)
Example #8
0
def test_ascii_literals_remain_unmodified():
    LOWEST_ORDINAL = 32
    HIGHEST_ORDINAL = 126
    ORDINALS = lambda: range(LOWEST_ORDINAL, HIGHEST_ORDINAL + 1)

    EXCLUSIONS = [
        Syntax.STRING_DELIMITER,
        Syntax.ESCAPE_SEQUENCE,
    ]

    for ordinal in ORDINALS():
        character = chr(ordinal)
        if not character in EXCLUSIONS:
            source_code = string(character)
            yield assert_equal, character, limp.evaluate(source_code)
Example #9
0
def test_name_shadowing_is_handled_for_function_parameters():
    variable_name = 'n'
    original_value = 0
    function_name = "number"
    function_definition = f"(define {function_name} (function ({variable_name}) {variable_name}))"

    environment = Environment.create_empty()
    environment.define(variable_name, original_value)

    run = lambda code: limp.evaluate(code, environment)
    variable_is_unchanged = lambda: (assert_equal, original_value,
                                     run(variable_name))
    run(function_definition)

    run(f"({function_name} 1)")

    yield variable_is_unchanged()
Example #10
0
def main(bot, author_id, source_code, thread_id, thread_type, **kwargs):
    def send(message):
        bot.sendMessage(str(message),
                        thread_id=thread_id,
                        thread_type=thread_type)

    def send_error(info, error):
        full_error_message = f'{type(error).__name__}: {error}'
        send(f'{info} {full_error_message}')

    try:
        environment = limp.environment.create_standard()
        environment.define('send', send)
        result = limp.evaluate(source_code, environment)
        send(result)
    except (SyntaxError, NameError) as error:
        send_error('You got a', error)
    except Exception as error:
        send_error('Something unexpected happened', error)
        send("It's possible that it's your fault.")
Example #11
0
def test_getting_symbols():
    environment = Environment.create_standard()

    environment.define_multiple({
        'x': 10,
        'y': 20,
        'z': 30,
        'foo': 100,
    }.items())

    data = [
        ('x',   10),
        ('y',   20),
        ('z',   30),
        ('foo', 100),
    ]

    for source_code, expected_result in data:
        result = limp.evaluate(source_code, environment)
        yield assert_equal, expected_result, result
Example #12
0
import limp
import limp.environment as Environment
from nose.tools import assert_equal
from tests.syntax import *

ENVIRONMENT = Environment.create_empty()
EVALUATE = lambda code: limp.evaluate(code, ENVIRONMENT)

ARBITRARY_NAME = "arbitrary"
ARBITRARY_VALUES = [0, 1, "value"]


def test_function_parameters_can_shadow_globally_defined_variables():
    REUSABLE_NAME = ARBITRARY_NAME
    OUTER_VALUE, INNER_VALUE = ARBITRARY_VALUES[:2]

    ENVIRONMENT.define(REUSABLE_NAME, OUTER_VALUE)

    SHADOWING_FUNCTION = function([REUSABLE_NAME], REUSABLE_NAME)
    EVALUATE(invoke(SHADOWING_FUNCTION, string(INNER_VALUE)))

    yield (assert_equal, OUTER_VALUE, EVALUATE(REUSABLE_NAME))
Example #13
0
 def the_test():
     for source_code, expected_result in data:
         print("--------------------------")
         print(source_code)
         result = limp.evaluate(source_code)
         yield assert_equals, expected_result, result
Example #14
0
def test_inequality():
    for a, b, expected_equality in DATA:
        source_code = invoke(ARE_NOT_EQUAL, a, b)
        yield assert_equal, limp.evaluate(source_code), not expected_equality
Example #15
0
def test_standard_library():
    data = [

        # Mathematical functions
        ('(+ 1 1)', 2),
        ('(+ 2 3)', 5),
        ('(- 1 1)', 0),
        ('(- 4 2)', 2),
        ('(* 2 3)', 6),
        ('(* 4 1)', 4),
        ('(/ 4 2)', 2),
        ('(/ 1 2)', 0.5),
        ('(// 1 2)', 0),
        ('(// 5 2)', 2),
        ('(** 2 3)', 8),
        ('(** 0 0)', 1),
        ('(sqrt 144)', 12),
        ('(sqrt 0)', 0),
        ('(sqrt 1)', 1),
        ('(! 0)', 1),
        ('(! 1)', 1),
        ('(! 4)', 24),
        ('(! 7)', 5040),
        ('(% 4 4)', 0),
        ('(% 5 6)', 5),
        ('(% 3 1)', 0),

        # Comparison functions on integers
        ('(> 1 0)', True),
        ('(> 1 1)', False),
        ('(> 0 1)', False),
        ('(> 9999 321)', True),
        ('(> -10 -20)', True),
        ('(>= 1 0)', True),
        ('(>= 1 1)', True),
        ('(>= 0 1)', False),
        ('(>= 9999 321)', True),
        ('(>= -10 -20)', True),
        ('(< 10 11)', True),
        ('(< 11 11)', False),
        ('(< 12 10)', False),
        ('(< 100 4321)', True),
        ('(< -99 -12)', True),
        ('(<= 10 11)', True),
        ('(<= 11 11)', True),
        ('(<= 12 10)', False),
        ('(<= 100 4321)', True),
        ('(<= -99 -12)', True),

        # Integer equality function
        ('(= 9 9)', True),
        ('(= 4 5)', False),
        ('(= 1 1)', True),

        # String equality function
        ('(= "" "")', True),
        ('(= "a" "a")', True),
        ('(= "ab" "ab")', True),
        ('(= "car" "avan")', False),
        ('(= "tayne" "mayne")', False),

        # Boolean equality function
        ('(= true false)', False),
        ('(= false true)', False),
        ('(= true true)', True),
        ('(= false false)', True),

        # Boolean functions
        ('(not true)', False),
        ('(not false)', True),
        ('(not (not true))', True),
        ('(not (not false))', False),
        ('(and true true)', True),
        ('(and true false)', False),
        ('(and false true)', False),
        ('(and false false)', False),
        ('(or true true)', True),
        ('(or true false)', True),
        ('(or false true)', True),
        ('(or false false)', False),
        ('(xor true true)', False),
        ('(xor true false)', True),
        ('(xor false true)', True),
        ('(xor false false)', False),

        # String functions
        ('(concatenate "foo" "bar")', "foobar"),
        ('(concatenate "hello" " there")', "hello there"),
        ('(concatenate "a" "b" "c" "d")', "abcd"),
        ('(concatenate "x" "y" "z" "?")', "xyz?"),
        ('(string 123)', "123"),
        ('(string 999)', "999"),
        ('(string 0)', "0"),
        ('(strip " x ")', "x"),
        ('(strip " abc ")', "abc"),
        ('(strip " x \t\n")', "x"),
        ('(strip "hello \n\t\n there")', "hello \n\t\n there"),
        ('(length "")', 0),
        ('(length "a")', 1),
        ('(length "ab")', 2),
        ('(length "abc")', 3),
        ('(length "tayne")', 5),
        ('(in "" "")', True),
        ('(in "a" "a")', True),
        ('(in "abc" "abcde")', True),
        ('(in "bc" "abcde")', True),
        ('(in "car" "car is red")', True),
        ('(in "a" "b")', False),
        ('(in "abacus" "b")', False),
        ('(in "self-respect" "php-programmers")', False),
        ('(repeat "" 10)', ""),
        ('(repeat "a" 5)', "aaaaa"),
        ('(repeat "hey " 3)', "hey hey hey "),
        ('(repeat "racecar" 3)', "racecarracecarracecar"),
        ('(reverse "")', ""),
        ('(reverse "abc")', "cba"),
        ('(reverse "lol")', "lol"),
        ('(reverse "jesus")', "susej"),
        ('(lowercase "abc")', "abc"),
        ('(lowercase "AbC")', "abc"),
        ('(lowercase "LIMP 2017")', "limp 2017"),
        ('(lowercase "Byxor")', "byxor"),
        ('(uppercase "abc")', "ABC"),
        ('(uppercase "AbC")', "ABC"),
        ('(uppercase "LIMP 2017")', "LIMP 2017"),
        ('(uppercase "Byxor")', "BYXOR"),

        # Easter egg definitions
        ('bizkit', "Keep ROLLIN ROLLIN ROLLIN ROLLIN whaaat!"),
    ]
    for source_code, expected_result in data:
        yield (assert_equals, expected_result, limp.evaluate(source_code))