def evaluate(self, s, value, insert=None):
        """Expression evaluator.

        * For expressions, returns the value of the expression.

        * For Blocks, returns a generator (or the empty list []).

        """
        assert not isinstance(value, kurt.Script)

        if insert and insert.unevaluated:
            return value

        if isinstance(value, kurt.Block):
            if value.type.shape == "hat":
                return []

            if value.type not in self.COMMANDS:
                if getattr(value.type, '_workaround', None):
                    value = value.type._workaround(value)
                    if not value:
                        raise kurt.BlockNotSupported(value.type)
                else:
                    raise kurt.BlockNotSupported(value.type)

            f = self.COMMANDS[value.type]

            args = [self.evaluate(s, arg, arg_insert)
                    for (arg, arg_insert)
                    in zip(list(value.args), value.type.inserts)]
            value = f(s, *args)

            def flatten_generators(gen):
                for item in gen:
                    if inspect.isgenerator(item):
                        for x in flatten_generators(item):
                            yield x
                    else:
                        yield item
            if inspect.isgenerator(value):
                value = flatten_generators(value)

            if value is None:
                value = []

        if insert:
            if isinstance(value, basestring):
                value = unicode(value)

                if insert.shape in ("number", "number-menu", "string"):
                    try:
                        value = float(value)
                    except (TypeError, ValueError):
                        if insert.shape == "number":
                            value = 0

            if isinstance(value, float) and value == int(value):
                value = int(value)

            if insert.kind in ("spriteOrStage", "spriteOrMouse", "stageOrThis",
                               "spriteOnly", "touching"):
                if value not in ("mouse-pointer", "edge"):
                    value = (self.project.stage if value == "Stage"
                             else self.project.get_sprite(value))
            elif insert.kind == "var":
                if value in s.variables:
                    value = s.variables[value]
                else:
                    value = s.project.variables[value]
            elif insert.kind == "list":
                if value in s.lists:
                    value = s.lists[value]
                else:
                    value = s.project.lists[value]
            elif insert.kind == "sound":
                for sound in s.sounds:
                    if sound.name == value:
                        value = sound
                        break

        return value
Expression evaluator.

        * For expressions, returns the value of the expression.

        * For Blocks, returns a generator (or the empty list []).