А можно ли узнать тип ANY-параметра

AN> вроде этот вопрос уже поднимался, но я не могу найти: можно ли при передаче
AN> в процедуру ANY-параметра определить в процедуре его тип, т.е. чё было было
AN> передано STRING, LONG али ещё чего:

AN> Пример:

AN> SomeProc PROCEDURE(? Param)
AN> code
AN> !вот здесь хочется узнать тип переданного Param и в зависимости от этого
AN> учинить определённые действия

Легально можно узнать только, что переменная, скрытая под ANY, является строкой или нет. Для получения более детальной информации необходимо уже работать непосредственно с самим UFO-обьектом, который скрыт под ANY-оберткой. Проще всего воспользоваться INTERFACE-механизмом и с его помощью использовать методы UFO-обьекта. Уже на протяжении трех версий C50/C55/C60 структура VMT для UFO-обьекта остается неизменной, что позволяет использовать единый INTERFACE для этих версий. Измениться-ли он в будущих версиях — х/з, но хочется надеятся, что нет.

Итак:

TUFO_CallInterface INTERFACE,TYPE
Dummy1               PROCEDURE
Dummy2               PROCEDURE
Dummy3               PROCEDURE
Dummy4               PROCEDURE
Dummy5               PROCEDURE
_Type                PROCEDURE(LONG _UFOaddr),LONG
Dummy6               PROCEDURE
Dummy7               PROCEDURE
Dummy8               PROCEDURE
Dummy9               PROCEDURE
Dummy10              PROCEDURE
Dummy11              PROCEDURE
Dummy12              PROCEDURE
Dummy13              PROCEDURE
Dummy14              PROCEDURE
Dummy15              PROCEDURE
Dummy16              PROCEDURE
_Address             PROCEDURE(LONG _UFOaddr),LONG
Dummy17              PROCEDURE
Dummy18              PROCEDURE
Dummy19              PROCEDURE
Dummy20              PROCEDURE
_Max                 PROCEDURE(LONG _UFOaddr),LONG
_Size                PROCEDURE(LONG _UFOaddr),LONG
                   END

Набор методов немного неполный.
Как легко заметить из описания, вызов методов несколько необычен. Т.е. реально вызов метода, например _Type, выглядит как _Type(LONG _UFOaddr,LONG _UFOaddr).
Причем предполагается, что оба параметра одинаковы. Зачем так сделано? Это связано с несколько нестандартным вариантом вызова методов UFO-обькта. О чем, кстати, я уже как-то писал в данной рассылке. В этих методах предполагается, что адрес самого обьекта передается не в EAX, а в EBX! А в EAX, кстати, некоторые методы предполагают получать один их параметров вызова! Именно поэтому остальные методы в данном описании не используются, т.к. через INTERFACE-механизм невозможно использовать EAX иначе чем для передачи адреса обьекта. Такой-же нестандартный вариант вызовов используется в Кларионе еще в нескольких обьектах. Но, как я уже писал, опять-же, в данной рассылке, в C60 работа с новыми обьектами построена уже по стандартному варианту. И с ними уже проще работать. Очевидно разработчики SV понемногу «разворачиваются» к обычным
программистам и дают возможность нам «забраться» в RTL.
Что не может не радовать!

Однако, что-то я отвлекся!

_Type    - возвращает тип переменной, скрытой под ANY-оберткой.
           Расшифровку типов можно посмотреть в LIBSRCEQUATES.CLW
_Address - возвращает адрес переменной, на которую ссылается
           данный UFO-обьект.
_Max     - возвращает кол-во элементов в текущей размерности массива.
           Для обычных переменных возвращает 0.
_Size    - возвращает размер переменной, на которую ссылается
           данный UFO-обьект.
           Для массивов возвращает ПОЛНЫЙ размер массива.

Как с этим работать?

  MAP
    MyProc(*? _Var)
  END

UFO &TUFO_CallInterface
Var DECIMAL(11,2)
Any ANY

  ...
  Any &= Var
  UfoAddr# = Address(Any)
    OMIT('***',_C55_)
  Peek(UfoAddr#,UfoAddr#)     ! Только для C50
    ***
  UFO &= (UfoAddr#)
  Type# = UFO._Type(UfoAddr#)
  Dim# = UFO._Max(UfoAddr#)   ! Массив?
  if Dim#
     Message('Массив из '& Dim# &' элементов типа '& Type#)
  else
     Message('Переменная типа '& Type#)
  .
  MyProc(Var)
  ...

MyProc Procedure(*? _Var)

  Code
  UfoAddr# = Address(_Var)
    OMIT('***',_C55_)
  Peek(UfoAddr#,UfoAddr#)     ! Только для C50
    ***
  UFO &= (UfoAddr#)
  Type# = UFO._Type(UfoAddr#)
  Dim# = UFO._Max(UfoAddr#)   ! Массив?
  if Dim#
     Message('Массив из '& Dim# &' элементов типа '& Type#)
  else
     Message('Переменная типа '& Type#)
  .
  Return

Я показал два примера использования UFO-обьекта.
Прямо в коде программы и в процедуре.
Все абсолютно работоспособно в C50/C55/C60.