module Sol class LambdaExpression < Expression attr_reader :args , :body , :clazz def initialize( args , body , clazz = nil) @args , @body = args , body raise "no bod" unless @body @clazz = clazz end # because of normalization (of send), slot_definition is called first, # to assign the block to a variable. # # This means we do the compiler here (rather than to_slot, which is in # fact never called) def to_slot_definition(compiler) compile(compiler) unless @parfait_block return SlotMachine::SlotDefinition.new(SlotMachine::LambdaConstant.new(parfait_block(compiler)) , []) end # create a block, a compiler for it, compile the block and add the compiler(code) # to the method compiler for further processing def compile( compiler ) parfait_block = self.parfait_block(compiler) block_compiler = SlotMachine::BlockCompiler.new( parfait_block , compiler.get_method ) head = body.to_slot( block_compiler ) block_compiler.add_code(head) compiler.add_method_compiler(block_compiler) end def each(&block) block.call(self) @body.each(&block) end def to_s(depth=0) "Block #{args} #{body}" end # create the parfait block (parfait representation of the block, a Callable similar # to CallableMethod) def parfait_block(compiler) return @parfait_block if @parfait_block @parfait_block = compiler.create_block( make_arg_type , make_frame(compiler)) end private def make_arg_type( ) type_hash = {} @args.each {|arg| type_hash[arg] = :Object } Parfait::Type.for_hash( type_hash ) end def make_frame(compiler) type_hash = {} @body.each do |node| next unless node.is_a?(LocalVariable) or node.is_a?(LocalAssignment) next if compiler.in_scope?(node.name) type_hash[node.name] = :Object end Parfait::Type.for_hash( type_hash ) end end end