"Собрать" функцию из переменных.

Автор Tigrik, 7 июня 2020, 16:46

0 Пользователи и 1 гость просматривают эту тему.

Tigrik

Цитата: sokol92 от  9 июня 2020, 14:49
Я могу это интерпретировать (тексты не смотрел, нет свободных пары дней на поиски :)) только таким образом: тип параметра k "угадывается" по значению "пустышки", при этом исходный тип значения где-то теряется по дороге...
На самом деле, как мне думается, здесь, нет никаких особенностей.

Вы правы, но только не "угадывается", а определяется - это и есть исходный тип значения и он никуда не теряется.
Типы возвращаемых параметров задаются СТРОГО в 1-ом массиве invoke самим своим значением: если есть кавычки - это символьный параметр; если до 32767, то это Integer, если больше, то Long; аналогично с Single и Double.
В самой вызываемой процедуре можно проводить любые действия над параметрами, при условии, что бы не было переполнения ячейки параметров, если такое случается, то и получаем ошибку: "Недопустимое значение или тип данных.Переполнение."
Но если результат возвращаемого параметра не соответствует типу, "заявленному" в invoke, то ничего не возвращается (остается, что и было задано в массиве).

mikekaganski

Цитата: sokol92 от  9 июня 2020, 14:49
  ...

Это в принципе баг. Связан он с i#66055, где Noel Power сделал передаваемые по ссылке значения фиксированным типом (и таким образом сломал обработку значений типа Variant).

При этом проблема, которую решал Ноэль, похоже, не воспроизводится больше, если откатить его патч. Так что исправление должно быть простым.

Напишите баг, чтобы его можно было исправить. Не забудьте отписать его номер здесь. Спасибо.
С уважением,
Михаил Каганский

Tigrik

Цитата: mikekaganski от 10 июня 2020, 11:21
Цитата: sokol92 от  9 июня 2020, 14:49
  ...

Это в принципе баг. Связан он с i#66055, где Noel Power сделал передаваемые по ссылке значения фиксированным типом (и таким образом сломал обработку значений типа Variant).

При этом проблема, которую решал Ноэль, похоже, не воспроизводится больше, если откатить его патч. Так что исправление должно быть простым.

Напишите баг, чтобы его можно было исправить. Не забудьте отписать его номер здесь. Спасибо.
Спасибо Михаил за ответ.

Я, только-только, всего несколько месяцев, разбираюсь с Basic и очень многое ещё не понимаю в нем.
Я не знаю как составлять баг - может быть, кто-нибудь из опытных и профессионалов, при наличие свободного времени и желания, возьмется за это.

kompilainenn

Цитата: Tigrik от 10 июня 2020, 11:41Я не знаю как составлять баг - может быть, кто-нибудь из опытных и профессионалов, при наличие свободного времени и желания, возьмется за это.
bugs.documentfoundation.org - идете туда, создаете логин/пароль себе, логинитесь, и создаете баг репорт на английском
Поддержать разработчиков LibreOffice можно тут, а наш форум вот тут

sokol92

Михаил, спасибо за расследование! Я могу сообщить о баге немного позднее (у меня уже скопилась длинная очередь).
Владимир.

mikekaganski

С уважением,
Михаил Каганский

sokol92

#21
Здравствуйте, Михаил! Я прочитал Ваши сообщения по ссылке, спасибо!
Я думаю, разумным решением будет возвращать в aOutParam значения строго в соответствии с теми типами, которые указаны в сигнатуре вызываемой функции. "Не вижу препятствий" :). Фактические Dummy-параметры (для out параметров) вообще должны игнорироваться.
Владимир.

mikekaganski

Цитата: sokol92 от 11 июня 2020, 14:32Я думаю, разумным решением будет возвращать в aOutParam значения строго в соответствии с теми типами, которые указаны в сигнатуре вызываемой функции. "Не вижу препятствий"

Не вполне понял, что Вы имеете ввиду. Что изменить на что в каком случае? Потому что оно и так должно возвращать в соответствии.
С уважением,
Михаил Каганский

sokol92

#23
Вы приводите следующий пример вызываемой процедуры:

Sub Foo (Byref v As Long)
 v = 100000
End Sub


На входе (в данной конкретной функции не будет использовано) переданное в элементе массива aParams числовое значение (Integer, Double, ...) должно быть преобразовано в Long.
Возвращаться в массиве aOutParams должно значение типа Long.

В чем недостаток такого подхода?
Владимир.

mikekaganski

Вызов через UNO API должен делать то же самое, что делает и Basic.
Смотрите:


Sub Foo(ByRef n As Long)
  print n
  n = 100000
End Sub

Sub Bar
  Dim i As Integer
  i = 5
  Foo(i)
  print i
End Sub


Что должен сделать этот код? Запихнуть 100000 в 16-битную переменную? или вывалиться с ошибкой?

StarBasic в этом случае позволяет работать этому коду: он создаёт временную переменную типа Long, которую инициализирует значением переданной i, выполняет Foo, а затем отбрасывает времянку (т.е. на выходе i такая же, как и на входе - 5). То есть в случае, когда тип переданной переменной совпадает с типом аргумента, это работает как передача по неконстантной ссылке в C++, а если не совпадает - как по константной.

Вы предлагаете в случае вызова той же функции через UNO изменить происходящее: в выходные параметры будет записываться значение времянки, независимо от типа переданного значения. Тогда это приводит к разнице в зависимости от способа вызова, что совершенно некорректно.
С уважением,
Михаил Каганский

sokol92

#25
Об "обычном" вызове. Когда фактический аргумент любой функции заключен в скобки, то все происходит, как у Вас написано с созданием временной переменной (и в VBA так же). В случае вызова метода Invoke в массиве aOutParam должна возвращаться переменная типа Long, которая просто не будет использована в вызывающей программе.

Если мы при вызове функции указываем фактический аргумент без скобок, то в VBA в момент компиляции будет выдана ошибка "ByRef argument type mismatch". Star Basic (6.4.4.2) ведет себя в этом случае по-другому: обнаружив несоответствие типов он вместо того, чтобы сообщить об ошибке, создает временную переменную и т.д.  Даже если функция Foo возвращает 1, значение переменной i останется 5 (проверил c VBASupport 1 и без).

То есть сейчас при обычном вызове: если тип формального параметра с модификаторов Byref отличается от типа фактического параметра, то значение фактического параметра по завершению работы вызываемого макроса не изменяется, сообщение об ошибке не выдается. Не думаю, что это правильно.

В методе invoke вызывающая программа сама решает, как поступить со значениями, возвращаемыми через массив aOutParam. В любом случае она ожидает тот тип, который указан в описании вызываемой функции.
Владимир.

mikekaganski

#26
Цитата: sokol92 от 11 июня 2020, 15:49Об "обычном" вызове. Когда фактический аргумент любой функции заключен в скобки, то все происходит, как у Вас написано с созданием временной переменной (и в VBA так же)
Нет, только в VBA. В StarBasic не так.

Цитата: sokol92 от 11 июня 2020, 15:49В случае вызова метода Invoke в массиве aOutParam должна возвращаться переменная типа Long, которая просто не будет использована в вызывающей программе.
Нет. Вызывающая программа не знает, использовать ли её возвращённое значение. Это в данном случае я специально передал 100000; мог бы сделать n = n * n, и тогда по результату вообще неясно, использовать или нет. Вы пытаетесь переложить на вызывающий код обязанности Runtime Basic.

Цитата: sokol92 от 11 июня 2020, 15:49Не думаю, что это правильно
Неважно. Это так, и если попробовать сделать кардинальное изменение, тысячи макросов сломаются. Причём таких, которые некому исправлять. Пройдённый этап.

Цитата: sokol92 от 11 июня 2020, 15:49В любом случае она ожидает тот тип, который указан в описании вызываемой функции.
Неправда. Вы вызываете макрос, имя которого получили как строку. Вы даже не знаете, какие типы параметров она может принимать, без очень серьёзной обработки.
С уважением,
Михаил Каганский

mikekaganski

Цитата: mikekaganski от 11 июня 2020, 15:54
Цитата: sokol92 от 11 июня 2020, 15:49Об "обычном" вызове. Когда фактический аргумент любой функции заключен в скобки, то все происходит, как у Вас написано с созданием временной переменной (и в VBA так же)
Нет, только в VBA. В StarBasic не так.
Да и в VBA не так, если уж.
В VBA ByRef-параметры процедуры (Sub), заключённые в скобки, всегда передаются через временную переменную, даже если типы соответствуют. Если передавать в процедуру без скобок, используется ByRef-передача и строгий контроль типов.
У функций (Function) там сложнее. Если функция вызывается как процедура, то обработка параметров аналогична процедуре. А если её возвращаемое значение используется (например, присваивается), то ByRef-агрументы в скобках проверяются строго.

В StarBasic нет различий между синтаксисом с и без скобок, и между разными вариантами вызова функций. Это другой язык из того же семейства.
С уважением,
Михаил Каганский

sokol92

#28
В VBA нет разницы в случае использования аргументов, заключенных в скобки (то есть, выражений), между функциями и процедурами.  Пример с выражением (i):

(VBA)
Option Explicit
Function Foo(ByRef n As Long) As Long
 MsgBox n
 n = 1
End Function
Sub Bar()
 Dim i As Integer, result
 i = 5
 result = Foo((i))
 MsgBox i & " " & result
End Sub


Возвращаемся к Invoke. Согласно описанию параметра aParams в документации "out parameters are undefined in sequence, i.e., the value has to be ignored by the callee". Я предлагал выше это и сделать.
Владимир.

mikekaganski

#29
Цитата: sokol92 от 11 июня 2020, 17:05В VBA нет разницы в случае использования аргументов, заключенных в скобки, между функциями и процедурами.
Ну, то, что Вы описываете, это особенность синтаксиса VBA, в котором есть разница в синтаксисе передачи аргументов в функцию в зависимости от использования её аргумента.

VBA:

Sub s1(ByRef i As Integer)
 i = 5
End Sub

Sub s2(ByRef n As Long)
 n = 10
End Sub

Function f1(n As Long)
 n = 100000
 f1 = True
End Function

Sub test()
 Dim n As Long, i As Integer
 n = 0: i = 0
 s1 (n) ' <= OK
 s1 (i) ' <= OK
 MsgBox n & " " & i
 n = 0: i = 0
 s2 (n) ' <= OK
 s2 (i) ' <= OK
 MsgBox n & " " & i
 n = 2: i = 2
 b = f1(n) ' <= OK
 f1 (i) ' <= OK
 MsgBox n & " " & i

 s1 n ' <= error
 s2 i ' <= error
 b = f1(i) ' <= error
 If f1(i) Then End Sub ' <= Error
End Sub


Цитата: sokol92 от 11 июня 2020, 17:05Возвращаемся к Invoke. Согласно описанию параметра aParams в документации "out parameters are undefined in sequence, i.e., the value has to be ignored by the callee". Я предлагал выше это и сделать.
Разве? Во-первых, там написано про aParams, а не про обсуждаемый aOutParam; во-вторых, полностью фраза выглядит "pure, out parameters are undefined in sequence, i.e., the value has to be ignored by the callee", что означает "чисто Out-параметры (то есть те, которые не In и не InOut) не обозначены в последовательности, то есть значение, передаваемое в этой последовательности, должно игнорироваться вызываемой (а не вызывающей, что, кмк, Вы прочитали!) функцией". Речь не идёт вообще о возвращаемом значении, речь о том, как поступать с передаваемым в функцию значением, которое функция не использует.

Теперь ещё раз. Мы говорим о работе с абстрактным интерфейсом XScript. Этот интерфейс может использоваться любым кодом (C; C#; Python; Java; ...) для вызова любого макроса (на Basic/Python/Java/...). В него передаётся строка, которая определяет расположение макроса, и его параметры. Макрос, который она вызывает, может быть где угодно и изменяться как и когда угодно. Интерфейс может использоваться в рамках интроспекции. А всё, что Вы предлагаете - это заставить функцию, использующую этот интерфейс, знать все особенности синтаксиса любого языка (в т.ч., который ещё только будет добавлен в поддержку в следующем году). Это не работает.
С уважением,
Михаил Каганский