#!/usr/bin/ruby
class Func
  def init(opename, ope)
    @opename = opename
    @ope = ope
  end

  def header1
    print "module gms_assign\n"
    print "  use datatype\n"
    print "  use mem_manager\n"
    print "  implicit none\n"
    print "  integer :: ix, iy, iz\n\n"
    print "  interface assignment(", @ope, ")\n"
  end

  def header2(out1, in1)
    if  out1.index(in1) != nil || out1 == "xyz" then 
      print "    module procedure ", @opename, "_", out1, "_", in1, "\n"
    end
  end

  def  header3
    print "  end interface\n"
    print "contains\n\n"
  end

  def output(out1, in1)
    if not out1.index(in1) != nil || out1 == "xyz"  then return end


    if in1.index("x") != nil then 
      xr = "ix"
      else 
      xr = "1"
    end

    if in1.index("y") != nil then 
      yr = "iy"
      else 
      yr = "1"
    end

    if in1.index("z") != nil then 
      zr = "iz"
      else 
      zr = "1"
    end

    if out1.index("x") != nil then 
      xl = "ix"
      else 
      xl = "1"
    end

    if out1.index("y") != nil then 
      yl = "iy"
      else 
      yl = "1"
    end

    if out1.index("z") != nil then 
      zl = "iz"
      else 
      zl = "1"
    end




#begin function output
    print "  subroutine ",@opename,"_", out1, "_", in1, "(output, input)\n"
      print "    type(var_", out1, "), intent(inout) :: output \n"
      print "    type(var_", in1, "), intent(in) :: input \n\n"

    
#+++++++++  GRID CHECK!!!!

    if xl == "ix"  && xr == "ix"
      print "    if ( input%grid(1) /= output%grid(1) ) stop \"(",@ope,")grid violation\"\n"
    end

    if yl == "iy"  && yr == "iy"
      print "    if ( input%grid(2) /= output%grid(2) ) stop \"(",@ope,")grid violation\"\n"
    end

    if zl == "iz"  && zr == "iz"
      print "    if ( input%grid(3) /= output%grid(3) ) stop \"(",@ope,")grid violation\"\n"
    end

 print "\n"

#=========GET NEW ID

      if in1 == out1 then

      print "    linked_counter_", out1,"( output%id ) = linked_counter_", out1,"( output%id ) -1 \n\n"

	print "    if ( linked_counter_",out1,"( output%id ) == 0 ) then \n"
	print "       free_mask_", out1, "( output%id ) = .true. \n"
	print "    end if \n\n"


	print"    output%id = input%id \n\n"

	print "       linked_counter_",out1,"( input%id ) = linked_counter_",out1,"( input%id ) + 1 \n\n"

	print "    if( free_mask_",out1,"( input%id )  ) then \n"
	print "       free_mask_", out1, "( input%id ) = .false.\n"
	print "    end if \n\n"

#	print "    call garbege_collect_", out1, "\n\n"
	print "    call garbege_collect\n\n"

	elsif out1.index(in1) != nil || out1 == "xyz" then


########  START CALC
    if out1.index("z")!= nil then
      print "    do iz = lb_axis3, ub_axis3\n"
    end

    if out1.index("y")!= nil then
      print "      do iy = lb_axis2, ub_axis2\n"
    end

    if out1.index("x")!= nil then
      print "        do ix = lb_axis1, ub_axis1\n"
    end

    print "\n"

      print "        work_", out1
      print "(", xl, ", ", yl, ", ",  zl,", output%id) & \n"
      print "                      = work_", in1
      print "(", xr, ", ", yr, ", ",  zr,", input%id)  \n"
      print "\n"

    if out1.index("z") != nil then
      print "        end do\n"
    end

    if out1.index("y") != nil then
      print "      end do\n"
    end

    if out1.index("x") != nil then
      print "    end do\n"
    end
#==============  END CALC
    print"\n"
#	print "    call garbege_collect_", out1, "\n"
#	print "    call garbege_collect_", in1, "\n\n"
	print "    call garbege_collect\n\n"
	else
	print "      stop \"extend error (=)\" \n\n"
      end


    print "  end subroutine ",@opename,"_", out1, "_", in1, "\n\n"
  end

  def footer
    print "end module gms_assign\n"
  end
end

type1=[6]
type2=[6]

type1[0] = type2[0] = "x"
type1[1] = type2[1] = "y"
type1[2] = type2[2] = "z"
type1[3] = type2[3] = "xy"
type1[4] = type2[4] = "xz"
type1[5] = type2[5] = "yz"
type1[6] = type2[6] = "xyz"

func = Func.new

func.init("data_data_equal", "=")
func.header1

for i in 0..6 do
  for j in 0..6 do

    func.header2(type1[i], type2[j])
  end
end
func.header3

for i in 0..6 do
  for j in 0..6 do
    func.output(type1[i], type2[j])
  end
end
func.footer
