powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Макросы
20 сообщений из 20, страница 1 из 1
Макросы
    #38955847
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть 3 вопроса по макросам

1. Можно как-то генерировать многострочные макросы?
2. Использую#define TestMacro ##SafeExpression($$aa^B())для генерирации COS кода. Как достичь аналогичного результата с использованием методов классов?
Например (не компилируется):#define TestMacro2 ##SafeExpression(##class(App.Gen).GenCOS()))Есть вариант с#define TestMacro3 ##function($ClassMethod("App.Test","GenCOS"))Но хотелось бы просто писать ##class(App.Gen).GenCOS()
3. Возможно передать в макрос произвольное количество аргументов? Как args... только для макросов.
...
Рейтинг: 0 / 0
Макросы
    #38955947
Фотография DAiMor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
eduard931. Можно как-то генерировать многострочные макросы? ##continue


2. ##expression и ##safeexpression с использованием кода из класса в mac коде работает, из другого класса кстати тоже без проблем. Может все таки ошибку компиляции приложишь, а так только гадание на кофейной гуще получается.

eduard933. Возможно передать в макрос произвольное количество аргументов? Как args... только для макросов.
# def1arg
...
Рейтинг: 0 / 0
Макросы
    #38955969
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DAiMor,

1. Ошибся, имеется в виду в коде, вызываемом макросом. Хочу, чтобы он возвращал несколько строк кода, а не одну как в методе GetString.
2. Код:Class App.Test Extends %RegisteredObject
{

ClassMethod Test()
{
  #define Hello(%in) ##safeexpression(##class(App.Test).GetString(%in))
  w $$$Hello("abc")
}

ClassMethod GetString(str)
{
  q "Hello "_str
}

}Выдает ошибку:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
---------------------------
Studio
---------------------------
ОШИБКА #5475: Ошибка при компиляции программы: App.Test.1.  Ошибок:  App.Test.1.INT(8) ERROR #1026: Invalid command : '}' : Offset:14 [zTest+1^App.Test.1]

  > ОШИБКА #5030: Возникла ошибка при компиляции класса App.Test
---------------------------
ОК   
---------------------------
Посмотрел на int код и нашел ошибку - генерируется строка без кавычек:
Код: sql
1.
w Hello abc


Как это исправить? Попробовал добавить ##Quote над ##safeexpression, но тогда генерируется w "##safeexpression(##class(App.Test).GetString(""abc""))"
Думал, что решилС помощью модификации метода GetString:

ClassMethod GetString(str)
{
  q """Hello "_str_""
}

Но при компиляции вылезают ошибки. Сравнить с компиляцией после

ClassMethod GetString(str)
{
  q """Hello "_str_""""
}
Возможно решить это с помощью макросов?

3. Спасибо, то что надо.
...
Рейтинг: 0 / 0
Макросы
    #38955974
Фотография DAiMor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ClassMethod GetString(str)
{
    quit """Hello: "_str_""""
}#define hello(%str) ##expression(##class(User.Test).GetString(%str))
    w $$$hello("John")
...
Рейтинг: 0 / 0
Макросы
    #38955981
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DAiMor,

Заработало, но разве ##safeexpression и ##expression не должны иметь одинаковое поведение при одном классе?

Docs - http://docs.intersystems.com/cache20151/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_macros#GCOS_C5959 When a method contains an ##Expression this is detected when the class is compiled. Because the compiler does not parse the content of the ##Expression, this ##Expression could generate different code in a subclass. To avoid this, Cache causes the compiler to regenerate the method code for each subclass. For example, ##Expression(%classname) inserts the current classname; when you compile a subclass, the code expects it will insert the subclass classname. Cache forces this method to be regenerated in the subclass to ensure that this occurs.
If you know that the code will never be different in a subclass, you can avoid regenerating the method for each subclass. To do this, substitute the ##SafeExpression preprocessor directive for ##Expression. These two preprocessor directives are otherwise identical.

Добавление ещё одной кавычки в GetString вижу.
...
Рейтинг: 0 / 0
Макросы
    #38956029
Фотография DAiMor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
eduard931. Ошибся, имеется в виду в коде, вызываемом макросом. Хочу, чтобы он возвращал несколько строк кода, а не одну как в методе GetString.похоже, что так сделать не получится почему то компилятор при получении многострочного результата ругается на то что ожидается конец строки.
...
Рейтинг: 0 / 0
Макросы
    #38956031
Фотография DAiMor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
eduard93Заработало, но разве ##safeexpression и ##expression не должны иметь одинаковое поведение при одном классе?а разве это не так ?
...
Рейтинг: 0 / 0
Макросы
    #38956070
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
eduard931. Ошибся, имеется в виду в коде, вызываемом макросом. Хочу, чтобы он возвращал несколько строк кода, а не одну как в методе GetString.Используйте CodeMode = objectgenerator
eduard932.Class App.Test Extends %RegisteredObject
{

ClassMethod Test()
{
  #define Hello1(%in) ##safeexpression(##class(App.Test).GetString1(%in))
  #define Hello2(%in) ##safeexpression(##class(App.Test).GetString2(%in))
  
  w $$$Hello1("abc")
  w $$$Hello2("abc")
}

ClassMethod GetString1(str) As %String [ CodeMode = expression ]
{
$$$quote("Hello ")_"_"_$$$quote(str)
}

ClassMethod GetString2(str) As %String [ CodeMode = expression ]
{
$$$quote("Hello "_str)
}

}РезультатzTest() public {
  w "Hello "_"abc"
  w "Hello abc" }
...
Рейтинг: 0 / 0
Макросы
    #38958034
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servitИспользуйте CodeMode = objectgeneratorКак его использовать для генерации кода в макросе?

Вот например нужен макрос - написать строку n раз:Class App.Test Extends %RegisteredObject
{

ClassMethod Test()
{
  #define WriteNTimes(%str,%cnt) ##safeexpression(##class(App.Test).GenStrings(%str,%cnt))
  $$$WriteNTimes("Hello World!",2)
}

ClassMethod GenStrings(string As %String = "", count As %Integer = 1) [ CodeMode = objectgenerator ]
{
  For i = 1:1:$g(count,0) {
     Do %code.WriteLine(" Write """ _ $g(string) _ """,!")
  }  
    Quit $$$OK
}
}При компиляции ошибка:Studio
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
---------------------------
Studio
---------------------------
ОШИБКА #5475: Ошибка при компиляции программы: App.Test:Test.  Ошибок:  

ERROR:  App.Test.1(4) : MPP5646 : завершение  ##expression  с ошибкой: $ze=##class(App.Test).GenStrings("Hello World!",2)

 TEXT: 	##safeexpression(##class(App.Test).GenStrings("Hello World!",2)) }
---------------------------
ОК   
---------------------------

Ещё такой вопрос: возможны ли необязательные аргументы в макросах:ClassMethod UnrequiredArgs()
{
  #define Log(%lvl,%msg) w "Level: ",%lvl,!,"Message: ",$g(%msg),!
  $$$Log(0,"It's a message!")
  $$$Log(0)
}Ошибка.Studio
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
---------------------------
Studio
---------------------------
ОШИБКА #5475: Ошибка при компиляции программы: App.Test:UnrequiredArgs.  Ошибок:  

ERROR:  App.Test.1(5) : MPP5614 : Недостаточно аргументов в макросе: 'Log'

 TEXT: 	$$$Log(0) }
---------------------------
ОК   
---------------------------
Код прилагается, вызов: do ##class(App.Test).Test()
 do ##class(App.Test).UnrequiredArgs()
...
Рейтинг: 0 / 0
Макросы
    #38958623
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
eduard93Как его использовать для генерации кода в макросе?В макросе - никак. Генерация нескольких строк - это уже целая программа, что противоречит концепции простой одностроковой подстановки: Conventions for Macro Values .
К тому же в этом случае возникают доп. вопросы, например с метками.eduard93Вот например нужен макрос - написать строку n раз:У Вас вперемешку run-time и compile-time.
Например, так:Class App.Test [ Abstract ]
{

Parameter count = 2;

Parameter string = "Hello World!";

ClassMethod Test()
{
  d ..WriteNTimes1(),..WriteNTimes2(),..WriteNTimes3(),..UnrequiredArgs()
}

/// управление через параметры класса
ClassMethod WriteNTimes1() [ CodeMode = objectgenerator ]
{
  For i = 1:1:$G(%parameter("count"),0) {
    Do %code.WriteLine($$$FormatText(" Write %1,!",$$$quote($G(%parameter("string")))))
  }
}

/// управление непосредственно
ClassMethod WriteNTimes2() [ CodeMode = objectgenerator ]
{
  For i = 1:1:4 {
    Do %code.WriteLine($$$FormatText(" Write %1,!",$$$quote(i_" : "_i)))
  }
}

/// управление через глобалы
ClassMethod WriteNTimes3() [ CodeMode = objectgenerator ]
{
  #Execute s ^count=5,^string="test"
  /*
  до компиляции ^count и ^string должны уже содержать нужные значения
  */
  For i = 1:1:$G(^count,0) {
    Do %code.WriteLine($$$FormatText(" Write %1,!",$$$quote($G(^string))))
  }
}

ClassMethod UnrequiredArgs() [ PlaceAfter = WriteNTimes3 ]
{
  #def1arg Log(%args) ##safeexpression("w "_##Quote("Level: ")_","_$li(%literalargs,1)_",!,"_##Quote("Message: ")_","_$s($ll(%literalargs)>1:$li(%literalargs,2),1:##Quote(""))_",!")
  #def1arg Log1(%args) ##safeexpression(##class(App.Test).Log(%literalargs))
  
  $$$Log(0,"It's a message!")
  $$$Log(0)
  $$$Log1(,,,"asd")
  $$$Log1("","",,,,,"asd")
}

ClassMethod Log(list As %List) As %String [ PlaceAfter = UnrequiredArgs ]
{
  s lvl=$li(list,1)
  s msg=$s($ll(list)>1:$li(list,2),1:"")
  s:lvl="" lvl=$$$quote(lvl)
  s:msg="" msg=$$$quote(msg)

  q "w "_##Quote("Level: ")_","_lvl_",!,"_##Quote("Message: ")_","_msg_",!"
}

}Результат компиляции:zTest() public {
  d ..WriteNTimes1(),..WriteNTimes2(),..WriteNTimes3(),..UnrequiredArgs() }
zWriteNTimes1() public {
 Write "Hello World!",!
 Write "Hello World!",! }
zWriteNTimes2() public {
 Write "1 : 1",!
 Write "2 : 2",!
 Write "3 : 3",!
 Write "4 : 4",! }
zWriteNTimes3() public {
 Write "test",!
 Write "test",!
 Write "test",!
 Write "test",!
 Write "test",! }
zUnrequiredArgs() public {
  w "Level: ",0,!,"Message: ","It's a message!",!
  w "Level: ",0,!,"Message: ","",!
  w "Level: ","",!,"Message: ","",!
  w "Level: ","",!,"Message: ","",! }
eduard93Ещё такой вопрос: возможны ли необязательные аргументы в макросах:Да, см. пример выше. Ещё здесь: 6396428 .
...
Рейтинг: 0 / 0
Макросы
    #38958900
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit, Спасибо.
...
Рейтинг: 0 / 0
Макросы
    #38971714
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit Макросы в InterSystems Caché eduard93Компилятор классов использует определение класса для генерации MAC кодаДокументация
  • Caché generates INT code for each routine and each class you compile.
  • источник
  • <...> Generated routines are routines which are derived or created by compiling other routines or classes. There are two types of generated routines: 1. .INT code which is created when Caché compiles a .MAC file, or a class. 2. .MAC code which is created when Caché compiles certain types of classes. источник
...
Рейтинг: 0 / 0
Макросы
    #38971736
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Макросы
    #38971921
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey MaslovСтоило бы упомянуть и о том, что команда $$$Многострочного_Макроса должна быть единственной в строке.
<...>
Попробуйте, например, вернуть значение из многострочного макроса (как его может вернуть однострочный макрос-выражение).
<...>
Понятно, что через переменную вернуть можно (нарушая все правила приличия ))). Не увидел в вашем примере конструкций вида: set result=$$$SomeMacro(...)
Например:test.MAC  n a,b,c
  
#Define MyAdd(%a,%b) $$%mmmuMyAdd(%a,%b) ##continue
#IfNDef 0 ##continue
#Define 0 ##continue
  g ##Unique(new) ##continue
%mmmuMyAdd(a,b) {##continue
  q a+b ##continue
} ##continue
##Unique(old) ##continue
#EndIf ##continue
##Lit()

  s a=$$$MyAdd(1,2) w a,!
  s b=$$$MyAdd(2,3) w b,!
  s c=$$$MyAdd(3,4) w c,!
test.INT  n a,b,c
  s a=$$%mmmuMyAdd(1,2) 
  g %mmmu1 
%mmmuMyAdd(a,b) {
  q a+b 

%mmmu1 
 w a,!
  s b=$$%mmmuMyAdd(2,3) 
 w b,!
  s c=$$%mmmuMyAdd(3,4) 
 w c,!Результат
Код: plaintext
1.
2.
3.
USER>d ^test
3
5
7
Alexey MaslovmorrisonAlexey MaslovНа самом деле, компилятор классов генерирует INT-код.Тоже думал так, но похоже что сначала mac?А вы проверьте на практике…В WRC тоже считают, что INT. Обещали поправить документацию.
...
Рейтинг: 0 / 0
Макросы
    #38971976
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MAC генерируется в очень редких случаях: например, если в классе есть методы-генераторы и наличествует флаг компиляции "k" ( Keep Generated Source Code ).
ПримерClass my.a Extends %RegisteredObject
{

/// w ##class(my.a).MyAdd1(1,2)
ClassMethod MyAdd1(
  a,
  b) As %Integer [ CodeMode = generator, PlaceAfter = MyAdd2 ]
{
  $$$GENERATE(" #Define c1 11")
  $$$GENERATE(" Quit a+b+$$$c1+$$$c2")
}

/// w ##class(my.a).MyAdd2(1,2)
ClassMethod MyAdd2(
  a,
  b) As %Integer [ CodeMode = objectgenerator ]
{
  Do %code.WriteLine(" #Define c2 22")
  Do %code.WriteLine(" Quit a+b+$$$c2")
}

}
Кстати, кто попробует пример выше, сможет увидеть некоторые недокументированные директивы MPP в сгенерированном MAC-коде.
...
Рейтинг: 0 / 0
Макросы
    #38972004
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit#Define MyAdd(%a,%b) $$%mmmuMyAdd(%a,%b) ##continue
...
Всё ждал, когда подобный пример предложит Эдуард, но так и не дождался... Как говорится, "типа круто", но итог проделанных ухищрений: в макроопределение упрятана функция. В чём полезность сего деяния? Чем это лучше (гибче, etc), чем просто написать такую же точно функцию и явно её вызывать?
...
Рейтинг: 0 / 0
Макросы
    #38972072
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey MaslovКак говорится, " типа круто ", но итог проделанных ухищрений <...>

В чём полезность сего деяния? Чем это лучше (гибче, etc) <...>?
- Папа, сделай мне iPhone.
По прошествии времени ...
- На, сынок.
- В чём полезность сего деяния? Чем это лучше стандартного iPhone?
- ?!

Вывод: папе раньше нужно было спрашивать: "А тебе это зачем, сынок?"
Я сам удивился вопросу (зачем это?), но раз Вы задали, значит это Вам действительно нужно было.
Собственно сам вопрос не с этой ли целью задавался, не ради ли "возможно/невозможно/как"?

Инструмент предоставляет возможности. Как ими распорядиться или не распорядиться - решать разработчику.
...
Рейтинг: 0 / 0
Макросы
    #38972106
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы, похоже, лучше меня знаете, что и зачем я спрашиваю.
Даже когда спрашиваю в другом месте и другого человека )))
...
Рейтинг: 0 / 0
Макросы
    #38973968
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servitAlexey Maslovпропущено...
А вы проверьте на практике…В WRC тоже считают, что INT. Обещали поправить документацию.Официальный ответ WRC (от разработчиков):"When you compile a class we generate MAC code in a temporary array, but this is never saved
as a MAC routine and in fact it is not even valid as a MAC routine as it is just a series of method
fragments which we stitch together. Then we ask the macro processor to turn these fragments into
INT code and this INT code may be saved if the 'k' flag is present when we combine these
fragments into a routine. So cls->int->obj is probably the correct order, with the mac piece
being hidden from users so it should not be documented as such."

So the mac part is more of an internal process and the documentation will be changed accordingly.
eduard93 ,

Исправлять ли статью решать Вам.
...
Рейтинг: 0 / 0
Макросы
    #38976982
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Документация<...> Generated routines are routines which are derived or created by compiling other routines or classes. There are two types of generated routines:

1. .INT code which is created when Caché compiles a .MAC file, or a class.
2. .MAC code which is created when Caché compiles certain types of classes.
источник servit How These Code Elements Work Together Во вчерашнем билде 2015.2.FT документацию в обоих случаях уже исправили и картинку заменили.
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Макросы
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]