Смекни!
smekni.com

Программирование и разработка приложений в Maple (стр. 64 из 135)

В качестве простого средства отладки Maple-процедур можно использовать и модифицированный метод контрольных точек. Этот метод состоит в следующем. Для генерации процедур, обеспечивающих возвращение значений заданных выражений в установленных контрольных точках, служит процедура ChkPnt [103], кодируемая в самом начале тела тестируемой процедуры Proc в виде вызова ChkPnt(args). Затем в требуемых местах процедуры Proc кодируются вызовы следующего формата:

chkpntN(_x1, _x2, _x3, …, _xn, x1, x2, x3, …, xn)(); (1) chkpntN(_x1, _x2, _x3, …, _xn, x1, x2, x3, …, xn)(x1, x2, x3, …, xn); (2) где N – номер контрольной точки и xj (j=1 .. n) – имена выражений, значения которых требуется получить в данной точке процедуры.

Вызов тестируемой процедуры Proc(args) на кортеже ее основных фактических аргументов не включает механизма контрольных точек, тогда как вызов процедуры Proc(args, chkpnt=N) для N из диапазона [1 .. 61] обеспечивает вывод значений требуемых выражений в контрольной точке с номером N (формат 1) либо вывод значений с их возвратом (формат 2), как это наглядно иллюстрирует достаточно прозрачный фрагмент.

ChkPnt := proc() local a k, ; unassign seq(( cat '( chkpnt k', ), k = 1 .. 61));

assign(a = {seq(`if`(type(args[ ]k , 'equation'), args[ ]k , NULL), k = 1 .. nargs)})

; seq(`if`(lhs(a[k]) = 'chkpnt' and type(rhs(a[k]), 'posint'), RETURN(assign( cat '( chkpnt', rhs(a k[ ])) = (( ) → [WARNING(

" in %1 variables %2 have the following values %3 ", procname,

[seq(args[ ]k , k = 1 .. 1/2 nargs× )], [seq(eval args[ ]( k ), k = 1/2 nargs× + 1 .. nargs)]), RETURN(RETURN )])), eval(cat('chkpnt', eval(rhs(a[k]))))), NULL), k = 1 .. nops(a))

end proc

> Proc:=proc(x::numeric, y::numeric, z::numeric) local a,b,c; ChkPnt(args); a:=evalf(sqrt(x^2 + y^2 + z^2), 4): chkpnt1(_x, _y, _z, _a, x, y, z, a)(); b:= evalf(sqrt(x^3 + y^3 + z^3), 4):

chkpnt2(_a, _b, a, b)(a, b); c:= evalf(sin(a) + cos(b), 4): chkpnt3(_a, _b, _c, a, b, c)();

WARNING("Results: a=%1, b=%2, c=%3", a, b, c) end proc; Proc := proc(x::numeric, y::numeric, z::numeric) local a b c, , ; ChkPnt args ;( ) a := evalf(sqrt(x^2 + y^2 + z^2), 4); chkpnt1(_x _y _z _a x y z a, , , , , , , )( ); b := evalf(sqrt(x^3 + y^3 + z^3), 4); chkpnt2(_a _b a b, , , )(a b, ); c := evalf(sin(a) + cos(b), 4); chkpnt3(_a _b _c a b c, , , , , )( ); WARNING "Results: a=%1, b=%2, c=%3", ( a b c, , ) end proc

> Proc(64.42, 59.47, 39.67);

Warning, Results: a=96.23, b=734.8, c=1.862

> Proc(64.42, 59.47, 39.67, chkpnt = 2); ⇒ 96.23, 734.8

Warning, in chkpnt2 variables [_a, _b] have the following values [96.23, 734.8]

> Proc(64.42, 59.47, 39.67, chkpnt = 1);

Warning, in chkpnt1 variables [_x, _y, _z, _a] have the following values

[64.42, 59.47, 39.67, 96.23]

> Proc(64.42, 59.47, 39.67, chkpnt = 3);

Warning, in chkpnt3 variables [_a, _b, _c] have the following values [96.23, 734.8, 1.862]

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

Наконец, по вызову процедуры maplemint(P) производится вывод протокола результатов семантического анализа P-процедуры, включая ее никогда не выполняемые предложения. Следующий простой фрагмент иллюстрирует результат применения процедуры maplemint на примере анализа простой процедуры:

> AGN:= proc(_x) local a,b; a:= 64(x): b:= ln(x + a): a:= `if`(x >= 10, 3(b^2), `G`) end proc: > maplemint(AGN);

This expression may be missing an operator like '*': 64(x)

This expression may be missing an operator like '*': 3(b^2)

These names were used as global names, but were not declared: x, G

These parameters were never used explicitly: _x

В качестве полезного упражнения читателю рекомендуется проверить различные варианты отладки Maple-процедур на основе рассмотренных отладочных средств. Наш опыт работы с ПС различных уровня и назначения вполне позволяет констатировать, что при достаточно полном соответствии описания функционирования конструкций ПС их реализации, хороших знаниях сущности погружаемой в их среду задачи и возможностей данного средства существует целый ряд более эффективных средств отладки, чем методы трассировки и контрольных точек в их чистом виде. Наша практика создания различного рода ПС не использовала данной методологии в ее классическом виде, как не отвечающей основной задаче эффективной отладки. В целом же, даже достаточно сложные процедуры возможно отлаживать и без указанных выше средств, имея ввиду интерактивный характер Maple-языка, позволяющий вполне успешно вести пошаговую интуитивную отладку процедур параллельно с их написанием, т.е. использовать методику и приемы т.н. эвристического программирования (точнее, его элементы). Именно подобным образом создавалось большинство наших программных средств.

В заключение настоящей главы кратко остановимся еще на одном вопросе, связанном с оптимизацией процедур. В качестве определенного подспорья здесь может оказаться и процедура maplemint, чей вызов maplemint(Proc) генерирует отчет с семантической информацией по заданной процедуре Proc (активной в текущем сеансе либо находящейся в Maple-библиотеке, логически связанной с главной библиотекой пакета) и выводит коды, которые невыполнимы при вызове процедуры. Вызов maplemint(Proc) генерирует информацию по таким аспектам процедуры Proc как: константы, присваиваемые в качестве значений; декларированные глобальные переменные, начинающиеся с символа '_' (подчеркивания); неиспользуемые декларированные глобальные переменные; используемые, но не декларированные глобальные переменные; неспользуемые декларированные локальные переменные; переменные цикла, повторно используемые во вложенных циклах; недостижимый код; ключевые слова break и/или next, обнаруженные вне цикла; отсутствие знака умножения '*' и др. Несколько детальнее с данным средством можно ознакомиться по конструкции ?maplemint, тогда как с исходным текстом процедуры можно ознакомиться по следующему предложению:

> interface(verboseproc = 3); eval(`maplemint/recurse`);

Между тем, текущая реализация процедуры maplemint не поддерживает получения семантической информации по процедурам, содержищим модульные объекты и средства обработки особых и ошибочных ситуаций. Но и перечисленное может оказаться достаточно полезным при решении ряда вопросов оптимизации Maple-процедур. Следующий фрагмент иллюстрирует примеры применения процедуры maplemint.

> maplemint(sin);

Error, (in maplemint/expression) the module system is not yet supported > maplemint(MkDir);

Error, (in maplemint/statement) exception handling is not yet supported > maplemint(Find);

These names were used as global names, but were not declared: __filesize

> maplemint(Sts);

These names were used as global names, but were not declared: k These local variables were used before they were assigned a value: a > maplemint(Case);

These local variables were used before they were assigned a value: k > maplemint(Kvantil);

These names were used as global names, but were not declared: x, t > maplemint(save1);

This code is unreachable: while not Fend(p) do h := readline(p); writeline(a,`if`(h[-1] <> ";",h,cat(h[1 .. -2],":"))) end do

null(close(f, a), writebytes(f, readbytes(a, infinity)), close(f), fremove(a))

These local variables were never used: h, k

These local variables were used before they were assigned a value: a, p

These local variables were used before they were assigned a value: k

These parameters were never used explicitly: F

These names were used as global names, but were not declared: c

These local variables were never used: x

These local variables were used before they were assigned a value: a, b, zeta, s, nu These parameters were never used explicitly: E

> maplemint(save2);

These names were used as global names, but were not declared: omega, c, c, c These local variables were used before they were assigned a value: x, b, nu > maplemint(Proc);

Error, (in maplemint/statement) exception handling is not yet supported

> Proc(64, 59, 39, 10, 17, 44); Proc(); ⇒ 233/6

Error, (in Proc) procedure call has no arguments

Из приведенного фрагмента можно сделать ряд выводов, а именно: (1) сложные процедуры, как правило, используют средства обработки особых и ошибочных ситуаций, поэтому они не доступны для анализа процедурой maplemint (даже такая примитивная как процедураProc из последнего примера недоступна для maplemint), (2) далеко не всегда результаты семантического анализа соответствуют конкретному алгоритму тестируемой процедуры, например, для формальных аргументов подпроцедур, глобальных переменных, индексов суммирования и т.д., и (3) в ряде случаев выводимая информация не совсем корректна с точки зрения Maple-языка, как это иллюстрирует нижеследующий весьма простой фрагмент:

> P:= proc() assign('libname' = op([libname, "D:/RANS/IAN"])); `+`(args)/nargs end proc:

> maplemint(P);

These names were used as global names, but were not declared:

"C:&bsol;Program Files&bsol;Maple 8/lib",

"c:/program files/maple 8/lib/userlib"

В данном фрагменте в качестве имен глобальных переменных указывается не предопределенная libname-переменная, а ее значение, что совсем не одно и то же. Имеются и другие некорректности. Однако, для случая достаточно простых процедур вышеуказанное средство Maple может быть вполне полезным, прежде всего, для не столь искушенного пользователя.

Наконец, синтаксический контролер Mint анализирует программу Maple и генерирует сообщение о возможных ошибках в mpl-файле данных с исходным Maple-текстом. Если файл не задан, то для чтения исходного Maple-текста используется стандартный ввод. Анализ завершается по достижении конца текста. Более детально с данным средством синтаксической проверки Maple-программ можно ознакомиться по конструкции ?mint.

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

Действительно, Maple-язык позволяет в интерактивном режиме программировать алгоритм вашей задачи поэтапно, также поэтапно производя отладку полученных документов либо процедур. Он же позволяет относительно несложно производить их постепенную доводку до нужных требований; при этом, сам процесс такого программирования обеспечивает уточнение отдельных составляющих программируемого алгоритма. При этом, отладка всего комплекса сводится к отладке последовательно связанных его составляющих, которая производится одновременно с их программированием. А так как составляющие с учетом весьма крупных (в плане поддерживаемых операций) функциональных средств Maple-языка, как правило, хорошо обозримы, то и процесс их отладки существенно упрощается, а с ним и весь процесс отладки в целом. Именно данная методика и использовалась нами при создании средств нашей Библиотеки [41,103,109]. Опыт ее применения со всей очевидностью доказал ее жизнеспособность и во многих случаях большую эффективность, чем имеющиеся для этих целей стандартные средства отладки. Правда, описанный подход априори предполагает как хорошее знание сути программируемого приложения, так и саму программную среду пакета.