def test_lookup_from_inner_env(): """The `extend` function returns a new environment extended with more bindings.""" env = Environment({"foo": 42}) env = env.extend({"bar": True}) assert_equals(42, env.lookup("foo")) assert_equals(True, env.lookup("bar"))
def test_lookup_on_missing_raises_exception(): """When looking up an undefined symbol, an error should be raised. The error message should contain the relevant symbol, and inform that it has not been defined.""" with assert_raises_regexp(DiyLangError, "my-missing-var"): empty_env = Environment() empty_env.lookup("my-missing-var")
def test_lookup_on_missing_raises_exception(): """TEST 4.2: When looking up an undefined symbol, an error should be raised. The error message should contain the relevant symbol, and inform that it has not been defined. """ with assert_raises_regexp(DiyLangError, "my-missing-var"): empty_env = Environment() empty_env.lookup("my-missing-var")
def test_lookup_from_inner_env(): """TEST 4.3: The `extend` function returns a new environment extended with more bindings. Tip: The Dictionary class has a convenient .update method. """ env = Environment({"foo": 42}) env = env.extend({"bar": True}) assert_equals(42, env.lookup("foo")) assert_equals(True, env.lookup("bar"))
def test_lookup_deeply_nested_var(): """TEST 4.4: Extending overwrites old bindings to the same variable name.""" env = Environment({"a": 1}).extend({"b": 2}).extend({"c": 3}). \ extend({"foo": 100}) assert_equals(100, env.lookup("foo"))
def test_define_with_nonsymbol_as_variable(): """TEST 4.13: Defines should evaluate the argument before storing it in the environment. """ env = Environment() evaluate(parse("(define x (+ 1 41))"), env) assert_equals(42, env.lookup("x"))
def test_define_should_evaluate_the_argument(): """TEST 4.13: Defines should evaluate the argument before storing it in the environment. """ env = Environment() evaluate(parse("(define x (+ 1 41))"), env) assert_equals(42, env.lookup("x"))
def test_extend_returns_new_environment(): """The extend method should create a new environment, leaving the old one unchanged.""" env = Environment({"foo": 1}) extended = env.extend({"foo": 2}) assert_equals(1, env.lookup("foo")) assert_equals(2, extended.lookup("foo"))
def test_extend_returns_new_environment(): """TEST 4.5: The extend method should create a new environment, leaving the old one unchanged.""" env = Environment({"foo": 1}) extended = env.extend({"foo": 2}) assert_equals(1, env.lookup("foo")) assert_equals(2, extended.lookup("foo"))
def test_simple_lookup(): """TEST 4.1: An environment should store variables and provide lookup. Tip: Implement this in the lookup() method in types.py. """ env = Environment({"var": 42}) assert_equals(42, env.lookup("var"))
def test_creating_list_with_cons_does_not_modify_initial_list(): """TEST 6.2.1: The `cons` functions prepends an element to the front of a list without modifying the intial list.""" env = Environment({"initial_list": [1, 2, 3]}) result = evaluate(parse("(cons 0 initial_list)"), env) assert_equals(parse("(0 1 2 3)"), result) assert_equals([1, 2, 3], env.lookup("initial_list"))
def test_define(): """Test of simple define statement. The `define` form is used to define new bindings in the environment. A `define` call should result in a change in the environment. What you return from evaluating the definition is not important (although it affects what is printed in the REPL).""" env = Environment() evaluate(parse("(define x 1000)"), env) assert_equals(1000, env.lookup("x"))
def test_define(): """TEST 4.10: Test of simple define statement. The `define` form is used to define new bindings in the environment. A `define` call should result in a change in the environment. What you return from evaluating the definition is not important (although it affects what is printed in the REPL). """ env = Environment() evaluate(parse("(define x 1000)"), env) assert_equals(1000, env.lookup("x"))
def test_calling_very_simple_function_in_environment(): """A call to a symbol corresponds to a call to its value in the environment. When a symbol is the first element of the AST list, it is resolved to its value in the environment (which should be a function closure). An AST with the variables replaced with its value should then be evaluated instead.""" env = Environment() evaluate(parse("(define add (lambda (x y) (+ x y)))"), env) assert_is_instance(env.lookup("add"), Closure) result = evaluate(parse("(add 1 2)"), env) assert_equals(3, result)
def test_calling_very_simple_function_in_environment(): """TEST 5.12: A call to a symbol corresponds to a call to its value in the environment. When a symbol is the first element of the AST list, it is resolved to its value in the environment (which should be a function closure). An AST with the variables replaced with its value should then be evaluated instead. """ env = Environment() evaluate(parse("(define add (lambda (x y) (+ x y)))"), env) assert_is_instance(env.lookup("add"), Closure) result = evaluate(parse("(add 1 2)"), env) assert_equals(3, result)
def test_set_changes_environment_in_place(): """TEST 4.6: When calling `set` the environment should be updated""" env = Environment() env.set("foo", 2) assert_equals(2, env.lookup("foo"))
def test_lookup_deeply_nested_var(): """Extending overwrites old bindings to the same variable name.""" env = Environment({"a": 1}).extend({"b": 2}).extend({"c": 3}).extend({"foo": 100}) assert_equals(100, env.lookup("foo"))
def test_set_changes_environment_in_place(): """When calling `set` the environment should be updated""" env = Environment() env.set("foo", 2) assert_equals(2, env.lookup("foo"))
def test_simple_lookup(): """An environment should store variables and provide lookup.""" env = Environment({"var": 42}) assert_equals(42, env.lookup("var"))