    # This file is a testcase for the highlighting of Crystal code
    # It's not executable code, but a collection of code snippets
    #

    require "lib_z"
    require "./digest"

    module Digest::Adler32
      def self.initial : UInt32
        LibZ.adler32(0, nil, 0).to_u32
      end

      def self.checksum(data) : UInt32
        update(data, initial)
      end

      def self.update(data, adler32 : UInt32) : UInt32
        slice = data.to_slice
        LibZ.adler32(adler32, slice, slice.size).to_u32
      end

      def self.combine(adler1 : UInt32, adler2 : UInt32, len) : UInt32
        LibZ.adler32_combine(adler1, adler2, len).to_u32
      end
    end

    struct BigRational
      Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], BigRational
      Number.expand_div [Float32, Float64], BigRational
    end

    module Crystal::Repl::Closure
      VAR_NAME = ".closure_var"
      ARG_NAME = ".closure_arg"
    end

    class FunctionType
      getter arg_types : Array(ArgType)
      getter return_type : ArgType

      @@cvar = 3
      @ivar = 7

      def initialize(@arg_types, @return_type)
      end

      def //(other : Int::Unsigned) : BigInt
        check_division_by_zero other
        unsafe_floored_div(other)
      end

      def //(other : Int) : BigInt
        check_division_by_zero other

        if other < 0
          (-self).unsafe_floored_div(-other)
          @cvar += 1
        else
          unsafe_floored_div(other)
         @ivar += 10
        end
      end
    end

    require "llvm/enums/atomic"
    struct Atomic(T)
      # Creates an Atomic with the given initial value.
      def compare_and_set(cmp : T, new : T) : {T, Bool}
        {% if T.union? && T.union_types.all? { |t| t == Nil || t < Reference } %}
          address, success = Ops.cmpxchg(pointerof(@value).as(LibC::SizeT*), LibC::SizeT.new(cmp.as(T).object_id), LibC::SizeT.new(new.as(T).object_id), :sequentially_consistent, :sequentially_consistent)
          {address == 0 ? nil : Pointer(T).new(address).as(T), success}
        {% elsif T < Reference %}
          # Use addresses again (but this can't return nil)
          address, success = Ops.cmpxchg(pointerof(@value).as(LibC::SizeT*), LibC::SizeT.new(cmp.as(T).object_id), LibC::SizeT.new(new.as(T).object_id), :sequentially_consistent, :sequentially_consistent)
          {Pointer(T).new(address).as(T), success}
        {% else %}
          Ops.cmpxchg(pointerof(@value), cmp, new, :sequentially_consistent, :sequentially_consistent)
        {% end %}
      end

      def swap(value : T)
        {% if T.union? && T.union_types.all? { |t| t == Nil || t < Reference } || T < Reference %}
          address = Ops.atomicrmw(:xchg, pointerof(@value).as(LibC::SizeT*), LibC::SizeT.new(value.as(T).object_id), :sequentially_consistent, false)
          Pointer(T).new(address).as(T)
        {% else %}
          Ops.atomicrmw(:xchg, pointerof(@value), value, :sequentially_consistent, false)
        {% end %}
      end
    end

    class Deque(T)
      include Indexable::Mutable(T)

      @start = 0
      protected setter size
      private getter buffer

      def initialize(size : Int, value : T)
        if size < 0
          raise ArgumentError.new("Negative deque size: #{size}")
        end
        @size = size.to_i
        @capacity = size.to_i

        unless @capacity == 0
          @buffer = Pointer(T).malloc(@capacity, value)
        end
      end

      # Returns a new `Deque` that has this deque's elements cloned.
      # That is, it returns a deep copy of this deque.
      #
      # Use `#dup` if you want a shallow copy.
      def clone
        {% if T == ::Bool || T == ::Char || T == ::String || T == ::Symbol || T < ::Number::Primitive %}
          Deque(T).new(size) { |i| self[i].clone.as(T) }
        {% else %}
          exec_recursive_clone do |hash|
            clone = Deque(T).new(size)
            each do |element|
              clone << element.clone
            end
            clone
          end
        {% end %}
      end

      def delete_at(index : Int) : T
        unless 0 <= index < @size
          raise IndexError.new
        end
        return shift if index == 0

        if index > @size // 2
          # Move following items to the left, starting with the first one
          # [56-01234] -> [6x-01235]
          dst = rindex
          finish = (@start + @size - 1) % @capacity
          loop do
            src = dst + 1
            src -= @capacity if src >= @capacity
            @buffer[dst] = @buffer[src]
            break if src == finish
            dst = src
          end
          (@buffer + finish).clear
        end

      end

      def each(& : T ->) : Nil
        halfs do |r|
          r.each do |i|
            yield @buffer[i]
          end
        end
      end

      def pop : T
        pop { raise IndexError.new }
      end

      macro [](*args)
        array = uninitialized Array(Int32)
        {% for arg, i in args %}
          array.to_unsafe[{{i}}] = {{arg}}
        {% end %}
        array
      end

        def message : String
            case self
            when SUCCESS        then "No error occurred. System call completed successfully."
            when TXTBSY         then Errno::ETXTBSY
            when NOTCAPABLE     then Errno::ENOTCAPABLE
            else                     Errno::EINVAL
            end
        end

        enum Signal
            KILL = 0
            BILL = 101
        end

    end

      # :nodoc:
    module Ops
        # Defines methods that directly map to LLVM instructions related to atomic operations.

        @[Primitive(:cmpxchg)]
        def self.cmpxchg(ptr : T*, cmp : T, new : T, success_ordering : LLVM::AtomicOrdering, failure_ordering : LLVM::AtomicOrdering) : {T, Bool} forall T
        end

        @[Primitive(:atomicrmw)]
        def self.atomicrmw(op : LLVM::AtomicRMWBinOp, ptr : T*, val : T, ordering : LLVM::AtomicOrdering, singlethread : Bool) : T forall T
        end
    end

    @[Link("z")]
    lib LibZ
      alias Char = LibC::Char
      alias SizeT = LibC::SizeT

      fun zlibVersion : Char*
      fun crc32_combine(crc1 : ULong, crc2 : ULong, len : Long) : ULong

      alias AllocFunc = Void*, UInt, UInt -> Void*
      alias FreeFunc = (Void*, Void*) ->

      struct ZStream
        next_in : Bytef*
        avail_in : UInt
        next_out : Bytef*
        total_out : ULong
        msg : Char*
        state : Void*
        zalloc : AllocFunc
        zfree : FreeFunc
        opaque : Void*
        data_type : Int
        adler : Long
      end

      # error codes
      enum Error
        OK            =  0
        VERSION_ERROR = -6
      end

      enum Flush
        NO_FLUSH      = 0
        TREES         = 6
      end

      MAX_BITS      = 15

      fun deflateInit2 = deflateInit2_(stream : ZStream*, level : Int32, method : Int32,
                                       window_bits : Int32, mem_level : Int32, strategy : Int32,
                                       version : UInt8*, stream_size : Int32) : Error
      fun deflate(stream : ZStream*, flush : Flush) : Error
      fun deflateSetDictionary(stream : ZStream*, dictionary : UInt8*, len : UInt) : Int

      fun inflateInit2 = inflateInit2_(stream : ZStream*, window_bits : Int32, version : UInt8*, stream_size : Int32) : Error
      fun inflate(stream : ZStream*, flush : Flush) : Error
      fun inflateSetDictionary(stream : ZStream*, dictionary : UInt8*, len : UInt) : Error
    end