Save2 := proc() local a b c j k G S, , , , , , , ν, ,f ω, ;h `if`(nargs < 2, RETURN(NULL), assign(ν = interface(warnlevel), ω = (x → null interface(( warnlevel = x))))) ; if type(args[-1], 'file') then f := args[-1]; ω(0) elif not type(eval args[-1]( ), {'symbol', 'string'}) then ERROR "<%1> can't specify a datafile",( args -1[ ]) else ω(0); f := MkDir(args -1[ ], 1) end if; assign(h = cat(currentdir( ), "/$Art16_Kr9$")); assign(G = [ ], S = ""), ω(2), assign( a = {op(SLD(convert '( procname args( )', 'string')[7 .. -1], ",")[1 .. -2])}); seq `if` type(( ( eval args[ ]( j ), {`module`, 'procedure'}), assign(' 'G = [op(G), args[ ]j ]), NULL), j = 1 .. nargs − 1), assign(b = a minus {op(map(convert, G, 'string'))}), `if`(b = { } and G = [ ], RETURN(ω ν( )), NULL); if b ≠ { } then assign(c = cat "_Vars_", " := proc() global ",( seq(cat(b j[ ], ","), j = 1 .. nops(b)), "; assign(" seq(, cat(convert(cat "'", [ ],( b j "'") = eval(convert(b j[ ], 'symbol')), 'symbol'), `,`), j = 1 .. nops(b)), ") end proc:")), seq(assign('S' = cat(S, `if`(member(k, {op Search2( ,( c {""" ",)" ",;", , }))}), NULL, c k[ ]))), k = 1 .. length( )c ), writebytes( ,h S), fclose(h), (proc() read h; fremove(h) end proc )( ) end if; Save1([[op(G), `if`(b = { }, NULL, _Vars_)]], [f]), ω(ν), f end proc |
> MM:=module () export x, m; m:= module() export y; y:= () -> `+`(args) end module end module: MM1:= module() local F,m; export a; option package; m:= module() export y; y:=() -> `+`(args) end module; F:=() -> m:- y(args); a:=F end module: SVEGAL:=module() export x; x:=() -> `+`(args)/nargs^6 end module: PP:=proc() `+`(args)/nargs^2 end proc: PP1:=proc() `+`(args)/nargs end proc: PP2:=proc() `+`(args)/nargs end proc: GS:=module() export x; x:=() -> `+`(args)/nargs^3 end module: avz:=61: agn:=56: Art:=14: Kr:=7: > Save2(op({MM, 'avz', SVEGAL, MM1, 'agn', GS, 'Art', PP, 'Kr', PP1, 'Svet'}), "C:/RANS/IAN/RAC/REA/Academy/Art_Kr.txt.m"); "c:\rans\ian\rac\rea\academy\art_kr.txt.m" Read1 := proc(F::{list({string, symbol}), set({string, symbol})}) local k j act_tab rf v t fg nm T U R, , , , , , , , , , ; `if`(F = [ ] or F = { }, ERROR("files for reading are absent"), NULL); assign(fg = (a string:: → `if`(search(a, "/"), a[2 .. -2], a)), U = {anames( )}); assign( act_tab = table(['procs' = { }, 'mods1' = { }, 'mods2' = { }, 'vars' = { }]), T = table [( 'procs' = { }, 'mods1' = { }, 'mods2' = { }, 'vars' = { }])); v := table([""" = 1, "#" = 2, "$" = 3, "%" = 4, "&" = 5, "'" = 6, "(" = 7, ")" = 8, "*" = 9, "+" = 10, "," = 11, "-" = 12, "." = 13, "/" = 14, "0" = 15, "1" = 16, "2" = 17, "3" = 18, "4" = 19, "5" = 20, "6" = 21, "7" = 22, "8" = 23, "9" = 24, ":" = 25, ";" = 26, "<" = 27, "=" = 28, ">" = 29, "?" = 30, "@" = 31, "A" = 32, "B" = 33, "C" = 34, "D" = 35, "E" = 36, "F" = 37, "G" = 38, "H" = 39, "I" = 40, "J" = 41, "K" = 42, "L" = 43, "M" = 44, "N" = 45, "O" = 46, "P" = 47, "Q" = 48, "R" = 49, "S" = 50, "T" = 51, "U" = 52, "V" = 53, "W" = 54, "X" = 55, "Y" = 56, "Z" = 57]); rf := proc(f) local _h _p _p1 k _z _g _r _q, , , , , , , ; close( )f , assign(_p = { }, _p1 = { }, _z = {seq(lhs(op 2,( eval( )v )[ ]k ), k = 1 .. nops([indices( )v ]))}); do _h := readline(f); if _h = 0 then break else if cat " ",( f)[-2 .. -1] = ".m" then if _h[1] = "I" and member(_h[2], _z) then _p := {cat(``, _h[3 .. 2 + eval( [v _h[2]])]), op(_p)} ; _p1 := _p end if else if _h[1 .. 11] = "unprotect('"then _g := Search(_h ` `, ); _p := {op(_p), cat(``, fg(_h[_g[1] + 1 .. _g[2] − 1]))} |
elif evalb(
assign('_q' = Search2(_h, {" := mod" " := proc", })),
_q ≠ [ ]) then
_p := {op(_p), cat(``, fg(_h[1 .. _q[1] − 1]))} elif search(_h ` := `, , '_r') then
_p1 := {op(_p1), cat(``, fg(_h[1 .. _r − 1]))} end if
end if
end if
end do; close(f), [_p, _p1]
end proc ;
for k to nops(F) do try if not type(F k[ ], 'file') then
WARNING("<%1> is not a file or does not exist", F[k]); next elif not TRm( [ ])F k then
WARNING("file <%1> is not readable by statement <read>" [ ], F k )
;
next
else if nargs = 1 then read [ ]F k ; next else nm := (proc(`_$$$_`) read `_$$$_`; rf `_$$$_`( ) end proc )( F k[ ]); for j to nops(nm[1]) do if type(eval(nm[1][ ]j ), 'procedure') and member(nm[1][ ]j , {anames '( procedure')}) then act_tab['procs'] :=
{nm[1][ ]j , op(act_tab['procs'])} elif type(eval(nm[1][j]), `module`) and member(nm[1][ ]j , {anames(`module`)}) then if type(nm[1][ ]j , 'mod1') then act_tab['mods1'] :=
{nm[1][ ]j , op(act_tab['mods1'])} else act_tab['mods2'] :=
{nm[1][j], op(act_tab['mods2'])} end if
end if
end do; act_tab['vars'] := { op(act_tab['vars']), op(nm[2] intersect{anames( )})} minus map(op,
{act_tab['procs'], act_tab['mods1'], act_tab['mods2']}) end if end if
catch "local and global": NULL "Processing of especial situations with program modules"( ) end try end do; `if`(member(_Vars_, act_tab['procs']), _Vars_( ), NULL), assign(R = act_tab['mods1'] union act_tab['mods2']), `if`(R ≠ { }, map(eval R, ), NULL); `if`(act_tab['procs'] ≠ { }, (proc() try map(act_tab['procs'], ``) catch "": NULL end try end proc )( ), NULL); null(`if`(1 < nargs, [assign(args[2] = eval(act_tab)), `if`(nargs = 3, [seq( assign(' [ ]'T k = U intersectact_tab k[ ]), k = ['procs', 'mods1', 'mods2', 'vars']) , assign(args 3[ ] = eval(T))], NULL)], NULL)) end proc > restart; Read1(["C:/RANS/IAN/RAC/REA/Academy/Art_Kr.txt.m"], 'h'), eval(h); table([procs = {_Vars_, SVEGAL, PP, PP1, MM, MM1, GS}, mods1 = {}, mods2 = {}, vars = {}]) > [avz, agn, Art, Kr], 36*PP(42, 47, 67, 62, 89, 96), SVEGAL:- x(42, 47, 67), GS:- x(42, 47, 67); [61 56 14 7, , , ], 403,, |
Процедура Save2 весьма существенно расширяет предложение save с полным наследованием синтаксиса последнего. но в отличие от него позволяет корректно сохранять в m-файлах переменные, процедуры и программные модули. Вызов процедуры возвращает полный путь к файлу с сохраненными Maple-объектами. В свою очередь, процедура Read1(F) используется как для загрузки в память файлов, сохраненных по Save2, так и для получения имен объектов, сохраненных в них, в разрезе их типов. В этом же контексте представляет интерес, например, реализованная однострочным экстракодом процедура savemu, обеспечивающая корректное сохранение модулей в m-файлах с возвратом NULL-значения. Последующее чтение таких файлов read-предложением делает доступными экспорты (exp) сохраненного в них модуля по конструкции M[exp](args), при этом, сами сохраненные модули не распознаются пакетом в качестве таковых.
savemu := (M::{`module`, set(`module`), list(`module`)}, F) → (proc() local a b c f, , , ; assign(a = (x → `if`(type(x `module`, ), [ ]x , x)), c = "", f = cat([libname][1][1 .. 2], "\_$Art16Kr9$_" );) map(mod21, a M( )), seq( assign('c' = cat(c, b, " := eval('parse'(convert(eval(", b, "), 'string'))):")), b = a M( )); (proc() writeline ,(f c), close( )f ; read f; fremove( )f end proc )( ), (proc() save args, F end proc )(op(a M( ))) end proc )( ) > module A () export B, G; B:= () -> `*`(args): G:= () -> sqrt(`+`(args)) end module: M:= module() export vs; vs:= () -> `+`(args)/nargs end module: savemu({A, M}, "C:/tmp/m.m"); restart; read("C:/tmp/m.m"); > map(type, [A,M],`module`),A[B](1,2,3),A[G](9,10,17), M[vs](2,3,4,5,6); ⇒ [false, false], 6,6,4 |
С другими нашими средствами Save-группы можно ознакомиться в [41-43,103,108,109].
Средства доступа к файлам включают ряд функций, при этом под «файлом» подразумевается не только организованная совокупность данных во внешней памяти ПК, но и канал, а также непосредственный интерфейс с пользователем. В этом отношении все составляющие понятие файл компоненты являются эквивалентными и за редким исключением любой файл обрабатывается одним и тем же набором функций доступа. Для обеспечения доступа к файлам данных Maple-язык располагает рядом достаточно эффективных для ПС данного типа средств. Как и в случае большинства известных систем программирования, для инициации операций обмена с файлом данных требуется предварительное его открытие, а после завершения работы с файлом – его закрытие; при этом, если открытие файла должно быть явным (кроме случая стандартных и специальных файлов), то закрытие его, в общем случае, не обязательно должно быть явным, ибо в конце работы с прикладной программой все используемые ею ресурсы, включая файлы различных типов, закрываются автоматически. Однако, для большинства ПС число одновременно открытых файлов ограничено и их максимальное количество колеблется в пределах (8-24). Для случая нашего пакета количество открытых пользовательских файлов не должно превышать 7. С целью устранения данного ограничения нами была создана процедура holdof, предлагающая следующий механизм расширения числа доступных каналов ввода/вывода (в/в), а именно.
Если число открытых каналов в/в меньше семи, вызов процедуры holdof(hold) возвращает список логических номеров открытых каналов в/в; в противном случае возвращается логический номер открытого канала в/в с сохранением состояния файла данных, ранее открытого по данному каналу. Успешный вызов процедуры позволяет использовать дополнительный канал для работы с файлами. После завершения работы с выделенным каналом вызовом процедуры holdof(restore) восстанавливается отложенное состояние файла данных, ранее открытого по этому каналу с возвратом NULL-значения. Таким образом, схема использования процедуры holdof имеет следующий принципиальный вид: holdof(hold) => обработка файла данных на выделенном канале в/в => holdof(restore)
holdof := proc(C::symbol) local a b k, , , ψ, ,j ω; global _avzagnartkrarn63 ; ψ := x → {k $ (k = 0 .. 6)} minus {seq(x j[ ][1], j = 4 .. nops( )x )}; `if` member(( C, {'hold', 'restore'}), assign(a = iostatus( )), ERROR("argument should be 'hold' or 'restore' but has received <%1>", C)); if C = 'hold' then `if`(nops(a) < 10, RETURN(ψ(a)), NULL); for k from 4 to nops(a) do if not member(a k[ ][2], {"terminal" "default", }) and member(a[k][3], {'STREAM', 'RAW'}) then _avzagnartkrarn63 := filepos(a k[ ][2]), a k[ ]; close(a k[ ][1]), RETURN(a k[ ][1]) end if end do; |
if type(_avzagnartkrarn63 , 'assignable1') then ERROR "too many files already open"( ) end if else try `if`( not typeseq(_avzagnartkrarn63, 'seqn'), RETURN( ), assign67(ω = _avzagnartkrarn63 )); unassign '( _avzagnartkrarn63'), close(ω[2][1]) catch "file descriptor not in use"null("processing of an open I/O channel"): end try ; b := [`if`(ω[2][3] = 'RAW', 'open', 'fopen'), ω[2][2], op(ω[2][5 .. `if`(ω[2][3] = 'RAW', 5 6, )])]; null(OpenLN(ω[2][1], op(b)), filepos(ω[2][1], ω[1])), `if`(1 < nargs, NULL, WARNING( "file <%1> had been restored on I/O channel <%2>" [, ω 2][2], ω[2][1 ))] end if end proc |
В ряде случаев, имеющих дело с доступом к файлам данных, требуется обеспечить открытие файла по конкретному каналу. Для этого может быть полезна процедура OpenLn.