#! ruby -Ks
#-- ap_src_maker.rb
#-- ap_src_maker.pi

require "phi"
require "Hash_add" # [ap-ext:0147] Hash_add.rb

####################
##
## 呼び出し側で次のグローバル変数を用意しておくこと。（ださい仕様）(^^;
##
## $dl_class
## $ap_class
## $public_method_data
##

######### static data ########

# TSearchDirection、TItemStates、TLVCompare

# この型であれば、uses xx で dl_XX、ap_XX で変換できる。というデータ。
# キーは、@dl_class.downcase
# 配列[0] が nil であれば "ap_#{@dl_class[1..-1]}(%s)"
# 配列[1] が nil であれば "dl_#{@dl_class[1..-1]}(%s)"

def int_alias(dl_class,dl_file)
  ["ap_Integer(ord(%s))","#{dl_class}(dl_Integer(%s))",dl_file]
end

def handle_alias(dl_class,dl_file)
  ["ap_Handle(ord(%s))","#{dl_class}(dl_Handle(%s))",dl_file]
end

def set_alias(dl_class,dl_file)
  ["ap_Set(%s)","#{dl_class}(dl_Set(%s))",dl_file]
end

# ここに登録すると、引数が一つの ap_XX(%s) がデフォルトになる。
def type_converter1
  @type_converter1 ||= {
    "Char".downcase              => ["ap_Integer(ord(%s))","char(dl_Integer(%s))",nil],
    "Double".downcase            => ["ap_Float(%s)","dl_Double(%s)",nil],
    "Currency".downcase          => ["ap_Float(%s)","dl_Double(%s)",nil],
    "TSQLTimeStamp".downcase     => ["ap_DateTime(%s)","dl_DateTime(%s)","uDateTime"],
    "TDateTime".downcase         => ["ap_DateTime(%s)","dl_DateTime(%s)","uDateTime"],
    "Variant".downcase           => ["ap_Variant(%s)","dl_Variant(%s)",nil],
    "WideString".downcase        => ["ap_String(%s)","dl_String(%s)",nil],
    "String".downcase            => ["ap_String(%s)","dl_String(%s)",nil],
    "TImeName".downcase          => ["ap_String(%s)","dl_String(%s)",nil],
    "TBlobData".downcase         => ["ap_String(%s)","dl_String(%s)",nil],
##    "TBcd".downcase              => ["ap_Integer(%s)","dl_Integer(%s)",nil],
    "Integer".downcase           => ["ap_Integer(%s)","dl_Integer(%s)",nil],
    "LongInt".downcase           => ["ap_Integer(%s)","dl_Integer(%s)",nil],
    "Word".downcase              => ["ap_Integer(%s)","dl_Integer(%s)",nil],
    "LongWord".downcase          => ["ap_Integer(%s)","dl_Integer(%s)",nil],
    "Boolean".downcase           => ["ap_Bool(%s)","dl_Boolean(%s)",nil],
    "LongBool".downcase          => ["ap_Bool(%s)","dl_Boolean(%s)",nil],
    "TImeMode".downcase          => int_alias("TImeMode",nil),
    "TBevelKind".downcase        => int_alias("TBevelKind",nil), # set_alias
    "TBevelWidth".downcase       => int_alias("TBevelWidth",nil),
    "TBorderWidth".downcase      => int_alias("TBorderWidth",nil),
    "TConnectionState".downcase  => int_alias("TConnectionState",nil),
    "TLocaleCode".downcase       => int_alias("TLocaleCode",nil),
    "TBorderStyle".downcase      => int_alias("TBorderStyle",nil),
    "TScrollStyle".downcase      => int_alias("TScrollStyle",nil),
    "TGridOption".downcase       => int_alias("TGridOption",nil),
    "TColor".downcase            => int_alias("TColor",nil),
    "TSearchDirection".downcase  => int_alias("TSearchDirection",nil),
    "TItemState".downcase        => int_alias("TItemState",nil),
    "HMONITOR".downcase          => handle_alias("HMONITOR",nil),
    "HWND".downcase              => handle_alias("HWND",nil),
    "HDC".downcase               => handle_alias("HDC",nil),
    "TItemStates".downcase       => ["ap_ItemStates(%s)","dl_ItemStates(%s)"],
    "TObjectStates".downcase     => ["ap_ObjectStates(%s)","dl_ObjectStates(%s)"],
    "TSearchTypes".downcase      => ["ap_SearchTypes(%s)","dl_SearchTypes(%s)","uSearchTypes"],
    "TBlobType".downcase         => int_alias("TBlobType",nil),
    "TObjectState".downcase      => int_alias("TObjectState",nil),
    "TAffectRecords".downcase    => int_alias("TAffectRecords",nil),
    "TBlobStreamMode".downcase   => int_alias("TBlobStreamMode",nil),
    "TExecuteOptions".downcase   => ["ap_ExecuteOptions(%s)","dl_ExecuteOptions(%s)"],
    "TPersistFormat".downcase    => int_alias("TPersistFormat",nil),
    "TSeekOption".downcase       => int_alias("TSeekOption",nil),
    "TFilterGroup".downcase      => int_alias("TFilterGroup",nil),
    "TRecordStatusSet".downcase  => ["ap_RecordStatusSet(%s)","dl_RecordStatusSet(%s)"],
    "TFileEditStyle".downcase    => int_alias("TFileEditStyle",nil),
    "TCanvasOrientation".downcase  => int_alias("TCanvasOrientation",nil),
    "TSearchOptions".downcase    => ["ap_SearchOptions(%s)","dl_SearchOptions(%s)"],
    "TEditorStrInfo".downcase    => int_alias("TEditorStrInfo",nil),
    "TFormState".downcase        => int_alias("TFormState",nil),
    "TTileMode".downcase         => int_alias("TTileMode",nil),
    "TWindowState".downcase      => int_alias("TWindowState",nil),
    "TWinControl".downcase       => [],
##    "TControl".downcase          => [],
    "HPALETTE".downcase          => handle_alias("HPALETTE",nil),
    "THandle".downcase           => handle_alias("THandle",nil), # ??
    "HBitmap".downcase           => handle_alias("HBitmap",nil), # ??
    "TTransparentMode".downcase  => int_alias("TTransparentMode",nil), # ??
    "TBitmapHandleType".downcase => int_alias("TBitmapHandleType",nil), # ??
    "TPixelFormat".downcase      => int_alias("TPixelFormat",nil), # ??
    "TFieldType".downcase       => int_alias("TFieldType",nil), # ??

    "TGridState".downcase       => int_alias("TGridState",nil), # ??
    "TShiftState".downcase      => set_alias("TShiftState",nil), # ??
    "TMouseButton".downcase     => int_alias("TMouseButton",nil), # set ??
    "TGridScrollDirection".downcase     => int_alias("TGridScrollDirection",nil), # set ??
    "TAlignment".downcase     => int_alias("TAlignment",nil), # set ??
    "TEditStyle".downcase     => int_alias("TEditStyle",nil), # set ??
    "TGridDrawState".downcase     => int_alias("TGridDrawState",nil), # set ??
    "TComponentName".downcase       => ["ap_String(%s)","dl_String(%s)",nil],
##    "TComponent".downcase       => [],
    "TComponentState".downcase     => int_alias("TComponentState",nil),
    "TComponentStyle".downcase     => int_alias("TComponentStyle",nil),
    "TAnchors".downcase     => set_alias("TAnchors",nil),
    "TDockOrientation".downcase     => int_alias("TDockOrientation",nil),
  }
end

##[エラー] uDBGrid.pas(568): 未定義の識別子 : 'dl_Rect'

# ここに登録すると、引数が二つの ap_iXX(%s,%s) がデフォルトになる。
def type_converter2
  @type_converter2 ||= {
    "TRect".downcase            => ["ap_iRect(%s,%s)","dl_Rect(%s)","uRect"],
    "TFont".downcase            => [nil,nil,"uFont"],
    "TPoint".downcase           => [nil,"dl_Point(%s)","uPoint"],
    "TListItem".downcase        => [nil,nil,"uListItem"],
    "TListItems".downcase       => [nil,nil,"uListItem"],
    "TListColumn".downcase      => [nil,nil,"uListColumn"],
    "TField".downcase           => [nil,nil,"uField"],
    "TSizeConstraints".downcase => [nil,nil,"uSizeConstraints"],
    "TBasicAction".downcase     => [nil,nil,"uAction, ActnList"],
  }
end

def type_converter
  @type_converter ||= type_converter1 + type_converter2
end

def type_conv(dl_class)
  type_converter[dl_class.downcase]
end

def ap_conv(dl_class)
  conv = type_converter1[dl_class.downcase]
  return ( conv[0] || "ap_#{dl_class[1..-1]}(%s)" ) if conv
  conv = type_converter2[dl_class.downcase]
  return ( conv[0] || "ap_i#{dl_class[1..-1]}(%s,%s)" ) if conv
  return "ap_i#{dl_class[1..-1]}(%s,%s)"
end

def dl_conv(dl_class)
  default = "ap_data_get_struct(%s)"
  conv = type_converter[dl_class.downcase]
  ( conv && conv[1] ) || default
end

#-- 使うとまずいことになる変数名のリスト

def invalid_dlv_names
  @invalid_dlv_names ||= <<MMMM.split.collect{|n|n.downcase}
dl_Rect
dl_Point
MMMM
end

def adjust_dlv_name(name)
  invalid_dlv_names.include?(name.downcase) ? name+"0" : name
end

######## makers ############

#### args ####

# returns ["","",""] or ["arg1,arg2","dl_arg1:dl_class1;//dl_arg1:dl_class2;//..","dl_arg1 := #{conv1};//.."]
def make_args1(hash)
  args = hash[:args]
  return [] if args.nil? || args.empty?
  arr1=[]  # ["arg1" , "arg2" , ..]
  arr2=[]  # ["dl_arg1:dl_class1" , "dl_arg2:dl_class2" , ..]
  arr3=[]  # ["dl_arg1 := conv1;"  , " dl_arg2 := conv2;" , ..]
  arr4=[]  # ["dl_arg1","dl_arg2" , ..]
  args.each{|arg_name,dl_class|
    arr1.push(arg_name);
    dlv_name = adjust_dlv_name( "dlv_"+arg_name )
    arr2.push("  #{dlv_name} : #{dl_class};\n");
    conv = dl_conv(dl_class) % arg_name
    arr3.push("  #{dlv_name} := #{conv};\n")
    arr4.push(dlv_name)
  }
  return([arr1.join(", "), arr2.join, arr3.join, arr4.join(", ")])
end

def make_args2(hash)
  args = hash[:args]
  return [] if args.nil? || args.empty?
  arr1=[]  # ["dl_arg1:dl_class1; \n .."]
  arr2=[]  # ["dl_arg1 := dl_conv1(argv[0]); \n .." ]
  arr3=[]  # ["dl_arg1 , dl_arg2,.."]
  i = 0
  args.each{|arg_name,dl_class|
    dlv_name = adjust_dlv_name( "dlv_"+arg_name )
    arr1.push("  #{dlv_name} : #{dl_class};\n");
    conv = dl_conv(dl_class) % "argv[#{i}]"
    arr2.push("  #{dlv_name} := #{conv};\n")
    arr3.push(dlv_name)
    i += 1
  }
  return([arr1.join, arr2.join, arr3.join(", ")])
end

#### property ####

def make_prop_get(hash,tt=nil)
  tt ||= hash[:ret_type]
  conv = ap_conv(tt) % ["real.#{@dl_name}","This"]
  uu = (type_conv(tt) || [])[2]
  @str_method << <<MMMM

function #{@ap_class}_get_#{@ap_name}(This: Tvalue): Tvalue; cdecl;
var
  real: #{@dl_my_class};
begin
  real := ap_data_get_struct(This);
  result := #{conv};  #{uu ? "// uses "+uu : ""}
end;
MMMM
  @str_init << "  DefineAttrGet(c#{@ap_class}, '#{@ap_name}', #{@ap_class}_get_#{@ap_name});\n"
  if /Bool/ =~ hash[:ret_type]
    if @ap_name[0,3] == "as_"
      # skip
    else
      if @ap_name[0,3] == "is_"
        @str_init << "  rb_define_alias(c#{@ap_class} , '#{@ap_name[3..-1]}?', '#{@ap_name}');\n"
      else
        @str_init << "  rb_define_alias(c#{@ap_class} , '#{@ap_name}?', '#{@ap_name}');\n"
      end
    end
  end
end

def make_prop_set(hash,tt=nil)
  tt ||= hash[:ret_type]
  conv = dl_conv(tt) % "v"
  @str_method << <<MMMM

function #{@ap_class}_set_#{@ap_name}(This, v: Tvalue): Tvalue; cdecl;
var
  real: #{@dl_my_class};
begin
  real := ap_data_get_struct(This);
  real.#{@dl_name} := #{conv};
  result := v;
end;
MMMM
  @str_init << "  DefineAttrSet(c#{@ap_class}, '#{@ap_name}', #{@ap_class}_set_#{@ap_name});\n"
end

def make_property(hash)
  make_prop_get(hash) if hash[:r]
  make_prop_set(hash) if hash[:w]
end

#### indexer ####

def make_indexer_get(hash,tt=nil)
  tt ||= hash[:ret_type]
  args    = hash[:args]
  arg_cnt = args.size
  args1,args2,args3 = make_args2(hash)
  ret_type = hash[:ret_type]
  ret_conv = ap_conv(ret_type) % ["real.#{@dl_name}[#{args3}]","This"]
  @str_method << <<MMMM

function #{@ap_class}_get_#{@ap_name}(argc: integer; argv: Tvalue_array; This: Tvalue): Tvalue; cdecl;
var
  real: #{@dl_my_class};
#{args1}begin
  if argc < #{arg_cnt} then ap_raise(ap_eArgError, sToo_few_args);
  real := ap_data_get_struct(This);
#{args2}  result := #{ret_conv};
end;
MMMM
end

def make_indexer_set(hash,tt=nil)
  tt ||= hash[:ret_type]
  args    = hash[:args]
  arg_cnt = args.size
  args1,args2,args3,args4,args5 = make_args2(hash)
  val_type = hash[:ret_type]
  val_conv = dl_conv(val_type) % "argv[#{arg_cnt}]"
  @str_method << <<MMMM

function #{@ap_class}_set_#{@ap_name}(argc: integer; argv: Tvalue_array; This: Tvalue): Tvalue; cdecl;
var
  real: #{@dl_my_class};
#{args1}begin
  if argc < #{arg_cnt+1} then ap_raise(ap_eArgError, sToo_few_args);
  real := ap_data_get_struct(This);
#{args2}  real.#{@dl_name}[#{args3}] := #{val_conv};
  result := argv[#{arg_cnt}];
end;
MMMM
end

def indexer_init(hash)
  g = hash[:r] ? "@#{@ap_class}_get_#{@ap_name}" : "nil"
  s = hash[:w] ? "@#{@ap_class}_set_#{@ap_name}" : "nil"
  @str_init << "  DefineIndexer(c#{@ap_class}, '#{@ap_name}', #{g}, #{s});\n"
end

def make_indexer(hash)
  make_indexer_set(hash) if hash[:w]
  make_indexer_get(hash) if hash[:r]
  indexer_init(       hash)
end

#### procedure ####

def make_procedure_inheritable(hash)
  inherit_name = "inherited_"+@dl_name
  args1,args2,args3,args4 = make_args1(hash)
  args1 = ", "+args1     if args1
  args4 = "( #{args4} )" if args4
  id_name = "id_" + @ap_name
  dl_args = hash[:dl_args]

  @str_my_class << <<MMMM
  protected
    procedure #{@dl_name}#{dl_args};override;
  public
    procedure #{inherit_name};
MMMM
  @str_method << <<MMMM

var
  #{id_name}: Tid;
procedure #{@dl_my_class}.#{@dl_name}#{dl_args};
begin
  #{(dl_args != "") ? "引数の処理が未完成です" : "// no arg" }
  rb_funcall2(Self.tag, #{id_name}, 0, nil);
end;
procedure #{@dl_my_class}.#{inherit_name}#{dl_args};
begin
  inherited #{@dl_name};
end;
function #{@ap_class}_#{@ap_name}(This#{args1} : Tvalue): Tvalue; cdecl;
var
  real: #{@dl_my_class};
#{args2}begin
  real := ap_data_get_struct(This);
#{args3}  real.#{inherit_name}#{args4};
  result := This;
end;
MMMM
  arg_cnt = hash[:args].size
  @str_init << "  #{id_name} := rb_intern('#{@ap_name}');\n"
  @str_init << "  rb_define_method(c#{@ap_class}, '#{@ap_name}', @#{@ap_class}_#{@ap_name}, #{arg_cnt});\n"
end

def inheritable?(hash)
p  hash[:dynamic]
  hash[:dynamic]
end

def make_procedure(hash)
  return make_procedure_inheritable(hash) if inheritable?(hash)
  args1,args2,args3,args4 = make_args1(hash)
  args1 = ", "+args1     if args1
  args4 = "( #{args4} )" if args4
  @str_method << <<MMMM

function #{@ap_class}_#{@ap_name}(This#{args1} : Tvalue): Tvalue; cdecl;
var
  real: #{@dl_my_class};
#{args2}begin
  real := ap_data_get_struct(This);
#{args3}  real.#{@dl_name}#{args4};
  result := This;
end;
MMMM
  arg_cnt = hash[:args].size
  @str_init << "  rb_define_method(c#{@ap_class}, '#{@ap_name}', @#{@ap_class}_#{@ap_name}, #{arg_cnt});\n"
end

#### function ####

def make_args_ary(hash,ary_name)
  args = hash[:args]
  return [] if args.nil? || args.empty?
  arr1=[]  # ["ary := rb_ary_new" , "rb_ary_push(ary,apv_arg1)" , ..]
  arr2=[]  # ["apv_arg1 := ap_conv(dl_arg1)" , "apv_arg2 := ap_conv(dl_arg2)" , ..]
  args.each{|arg_name,dl_class|
  
    ret_conv = ap_conv(ret_type) % ["real.#{@dl_name}[#{args3}]","This"]
    arr1.push(arg_name);
    dlv_name = adjust_dlv_name( "dlv_"+arg_name )
    arr2.push("  #{dlv_name} : #{dl_class};\n");
    conv = dl_conv(dl_class) % arg_name
    arr3.push("  #{dlv_name} := #{conv};\n")
    arr4.push(dlv_name)
  }
  return([arr1.join(", "), arr2.join, arr3.join, arr4.join(", ")])
end

def make_function_inheritable(hash)
  inherit_name = "inherited_"+@dl_name
  args1,args2,args3,args4 = make_args1(hash)
  args1 = ", "+args1     if args1
  args4 = "( #{args4} )" if args4
  ret_type = hash[:ret_type]
  dl_args  = hash[:dl_args]
  conv = ap_conv(ret_type) % ["dlv_ret","This"]
  id_name = "id_" + @ap_name

  @str_my_class << <<MMMM
  protected
    procedure #{@dl_name}#{dl_args};override;
  public
    procedure #{inherit_name};
MMMM
  @str_method << <<MMMM

var
  #{id_name}: Tid;
function #{@dl_my_class}.#{@dl_name}#{dl_args}: #{ret_type};
var
  apv_ret : Tvalue;
begin
  #{(dl_args != "") ? "引数の処理が未完成です" : "// no arg" 
  
  
  }
  apv_ret := rb_funcall2(Self.tag, #{id_name}, 0, nil);
  result := #{dl_conv(ret_type) % "apv_ret"};
end;
function #{@dl_my_class}.#{inherit_name}#{dl_args};
begin
  result := inherited #{@dl_name};
end;
function #{@ap_class}_#{@ap_name}(This#{args1} : Tvalue): Tvalue; cdecl;
var
  real: #{@dl_my_class};
  dlv_ret: #{ret_type};
#{args2}begin
  real := ap_data_get_struct(This);
#{args3}  dlv_ret := real.#{inherit_name}#{args4};
  result := #{ap_conv(ret_type) % ["dlv_ret","This"]};
end;
MMMM
  arg_cnt = hash[:args].size
  @str_init << "  #{id_name} := rb_intern('#{@ap_name}');\n"
  @str_init << "  rb_define_method(c#{@ap_class}, '#{@ap_name}', @#{@ap_class}_#{@ap_name}, #{arg_cnt});\n"
end

def make_function(hash)
  return make_function_inheritable(hash) if inheritable?(hash)
  args1,args2,args3,args4 = make_args1(hash)
  args1 = ", "+args1     if args1
  args4 = "( #{args4} )" if args4
  conv = ap_conv(hash[:ret_type]) % ["real.#{@dl_name}#{args4}","This"]
  @str_method << <<MMMM

function #{@ap_class}_#{@ap_name}(This#{args1} : Tvalue): Tvalue; cdecl;
var
  real: #{@dl_my_class};
#{args2}begin
  real := ap_data_get_struct(This);
#{args3}  result := #{conv};
end;
MMMM
  arg_cnt = hash[:args].size
  @str_init << "  rb_define_method(c#{@ap_class}, '#{@ap_name}', @#{@ap_class}_#{@ap_name}, #{arg_cnt});\n"
  if /Bool/ =~ hash[:ret_type]
    ##if @ap_name[0,3] == "as_"
    ##  # skip
    ##else
      if @ap_name[0,3] == "is_"
        @str_init << "  rb_define_alias(c#{@ap_class} , '#{@ap_name[3..-1]}?', '#{@ap_name}');\n"
    ##  else
    ##    @str_init << "  rb_define_alias(c#{@ap_class} , '#{@ap_name}?', '#{@ap_name}');\n"
      end
    ##end
  end
end

def make_init(hash)
  @dl_name = hash[:name]
  @ap_name = Phi.downcase(@dl_name)

end

######### decoders ########

# return [[name1,arg_type],[na,e2,arg_type],..]
# function MonitorFromPoint(const Point: TPoint;      MonitorDefault: TMonitorDefaultTo = mdNearest): TMonitor;

def decode_arg_names(arg_names,arg_type)
  if /^(.*)\,(.*)$/ =~ arg_names
    s1,s2=[$1,$2]
    return decode_arg_names(s1,arg_type)+decode_arg_names(s2,arg_type)
  end
  if /^(.*)\s+(.*)$/ =~ arg_names  # "const xx" "var xx"
    arg_names = $2
  end
  arg_default = ""
  if /^(.*)\s*\=\s*(.*)$/ =~ arg_type  # "const xx" "var xx"
    arg_type = $1
    arg_default = $2
  end
  [[arg_names.strip,arg_type.strip,arg_default.strip]]
end

  # return [[name1,type1],[na,e2,type2],..]
def decode_args(args)
  case args
  when /^(.*)\;(.*)$/ ; s1,s2=[$1,$2] ; return decode_args(s1)+decode_args(s2)
  when /^(.*)\:(.*)$/ ; s1,s2=[$1,$2] ; return decode_arg_names(s1,s2)
  end
  p [args]
  raise "no type of arg??"
end

def decode_lines(lines)
  list = []
  lines.each{|line|
    line = line.strip
    next if line.empty?
    hash = {}
    begin
      if /(\(.*\))/ =~ line
        hash[:dl_args] = $1
      else
        hash[:dl_args] = ""
      end

      case line
      when /^\#/
        next # comment not remark
      when /^property\s+(.*)$/i
        rest = $1
        if /^(.*)\s+write\s+(\w+)/ =~ rest then rest = $1.strip ; hash[:w] = true ; end
        if /^(.*)\s+read\s+(\w+)/  =~ rest then rest = $1.strip ; hash[:r] = true ; end
        case rest
        when /(\w+)\s*\[(.+)\]\s*\:\s*(\w+)/
          hash += {:method_type=>:indexer, :name=>$1, :args=>decode_args($2), :ret_type=>$3}
        when /(\w+)\s*:\s*(\w+)/
          hash += {:method_type=>:property, :name=>$1, :ret_type=>$2}
        else
          p [:undecodable_property_line, line]
          next
        end
      when /^procedure\s+(.*)$/i
        rest = $1
        case rest
        when /(\w+)\((.+)\)/
          hash += {:method_type=>:procedure, :name=>$1, :args=>decode_args($2)}
        when /(\w+)/
          hash += {:method_type=>:procedure, :name=>$1, :args=>[]}
        else
          p [:undecodable_procedure_line, line]
          next
        end
      when /^function\s+(.*)$/i
        rest = $1
        case rest
        when /(\w+)\((.+)\)\s*:\s*(\w+)/
          hash += {:method_type=>:function, :name=>$1, :args=>decode_args($2), :ret_type=>$3}
        when /(\w+)\s*:\s*(\w+)/
          hash += {:method_type=>:function, :name=>$1, :args=>[], :ret_type=>$2}
        else
          p [:undecodable_function, line]
          next
        end
      else
        p [:public_method_data, :unknown, line]
        next
      end

      hash[:dynamic]  = true if /\;\s*dynamic\s*\;/i  =~ line
      hash[:override] = true if /\;\s*override\s*\;/i =~ line
      hash[:overload] = true if /\;\s*overload\s*\;/i =~ line
      hash[:virtual]  = true if /\;\s*virtual\s*\;/i  =~ line

      dl_name = hash[:name]
      next unless dl_name
      ap_name = Phi.downcase(dl_name)
      if @ap_methods.include? ap_name
        p [:method_alreay_exist, ap_name, hash]
        next
      else
        case ap_name
        when /^get_(.*)$/
          if @ap_methods.include? $1
            p [:method_alreay_exist, ap_name, hash]
            next
          end
        when /^set_(.*)$/
          if @ap_methods.include? $1+"="
            p [:method_alreay_exist, ap_name, hash]
            next
          end
        end
      end
##p hash
##raise
      list.push hash
    rescue
      p [:error_in_decode_lines, ap_name, hash]
      next
    end
  }
  return list
end

######### main ########

@dl_class = $dl_class
@dl_my_class = @dl_class.to_s.dup
@dl_my_class[1,0] = "Phi_"
@public_method_data = $public_method_data
@ap_methods = eval("#{$ap_class}.instance_methods(true)") rescue []

@ap_class  = @dl_class[1..-1]

@str_interface = ""  # interface
@str_method = ""  # method_definition
@str_init = ""  # init
@str_my_class = ""  # type MyXX = class(XX) .. end;

p "----"

@str_my_class << "type\n#{@dl_my_class} = class(#{@dl_class})\n"  # init

list = decode_lines( @public_method_data )
list.each{ |hash|
  make_init(hash)
  case hash[:method_type]
  when :property  ; make_property( hash)
  when :indexer   ; make_indexer(  hash)
  when :procedure ; make_procedure(hash)
  when :function  ; make_function( hash)
  else
    p [:unknown_method_type, hash]
  end
}

@str_my_class << "end;"

p "----"
puts "(**** str_interface made by ap_src_maker ****)"
puts @str_interface
puts "(**** made by ap_src_maker ****)"
puts "(**** str_my_class made by ap_src_maker ****)"
puts @str_my_class
puts "(**** made by ap_src_maker ****)"
puts "(**** str_method made by ap_src_maker ****)"
puts @str_method
puts "(**** made by ap_src_maker ****)"
puts "(**** str_init made by ap_src_maker ****)"
puts @str_init
puts "(**** made by ap_src_maker ****)"

