# functions from SICP Python 4.1.1
def evaluate(component, env):
  if is_literal(component):
    return literal_value(component)
  elif is_name(component):
    return lookup_symbol_value(symbol_of_name(component), env)
  elif is_application(component):
    return apply(evaluate(function_expression(component), env),
                          llist_of_values(arg_expressions(component),
                                          env))
  elif is_operator_combination(component):
    return evaluate(operator_combination_to_application(component),
                    env)
  elif is_conditional(component):
    return eval_conditional(component, env)
  elif is_lambda_expression(component):
    return make_function(lambda_parameter_symbols(component),
                         make_return_statement(lambda_body(component)),
                         env)
  elif is_sequence(component):
    return eval_sequence(sequence_statements(component), env)
  elif is_return_statement(component):
    return eval_return_statement(component, env)
  elif is_function_definition(component):
    return evaluate(function_def_to_assignment(component), env)
  elif is_assignment(component):
    return eval_assignment(component, env)
  else:	return error("unknown syntax -- evaluate", component)
def apply(fun, arguments):
    if is_primitive_function(fun):
        return apply_primitive_function(fun, arguments)
    elif is_compound_function(fun):
        body = function_body(fun)
        locals = local_variables(body)
	unassigneds = llist_of_unassigned(locals)
        result = evaluate(body,
                          extend_environment(
                              append(function_parameters(fun),
			             locals),
                              append(arguments,
			             unassigneds),
                              function_environment(fun)))
        return (return_value_content(result)
                if is_return_value(result)
                else None)
    else:
        return error("unknown function type -- apply", fun)
def map(fun, items):
    return (None if is_none(items)
            else pair(fun(head(items)),
                      map(fun, tail(items))))
def llist_of_values(exps, env):
    return map(lambda arg: evaluate(arg, env), exps)
def eval_conditional(component, env):
    if is_truthy(evaluate(conditional_predicate(component), env)):
        return (evaluate(conditional_consequent(component), env)            
    else: return evaluate(conditional_alternative(component), env))
def eval_sequence(stmts, env):
    for_each(lambda stmt: evaluate(stmt, env), stmts)	    
    return None
def eval_return_statement(component, env):
    return make_return_value(evaluate(return_expression(component),
                                      env))
def eval_assignment(component, env):
    value = evaluate(assignment_value_expression(component), env)
    assign_symbol_value(assignment_symbol(component), value, env)
    return value
def eval_declaration(component, env):
    assign_symbol_value(
        declaration_symbol(component),
        evaluate(declaration_value_expression(component), env),
        env)
    return None

