|
# SPDX-License-Identifier: GPL-2.0-or-later
# HomalgToCAS: A window to the outer world
#
# Implementations
#
## Implementation stuff to launch and terminate external CASystems.
####################################
#
# install global functions:
#
####################################
##
InstallGlobalFunction( TerminateCAS,
function( arg )
local nargs, container, weak_pointers, l, pids, i, R, streams, s;
nargs := Length( arg );
if nargs = 0 and IsBound( HOMALG_MATRICES.ContainerForWeakPointersOnHomalgExternalRings ) then
container := HOMALG_MATRICES.ContainerForWeakPointersOnHomalgExternalRings;
weak_pointers := container!.weak_pointers;
l := container!.counter;
pids := [ ];
for i in [ 1 .. l ] do
R := ElmWPObj( weak_pointers, i );
if R <> fail then
Add( pids, homalgExternalCASystemPID( R ) );
fi;
od;
pids := DuplicateFreeList( pids );
streams := container!.streams;
l := Length( streams );
for i in [ 1 .. l ] do
if not streams[i].pid in pids then
TerminateCAS( streams[i] );
Unbind( streams[i] );
fi;
od;
## don't replace the following by DuplicateFreeList since
## it runs into a "no method found"-error when comparing subobjects:
pids := [ ];
l := [ ];
for s in streams do
if not s.pid in pids then
Add( l, s );
Add( pids, s.pid );
fi;
od;
container!.streams := l;
elif nargs > 0 then
if IsRecord( arg[1] ) and IsBound( arg[1].lines ) then
s := arg[1];
if IsBound( s.TerminateCAS ) and IsFunction( s.TerminateCAS ) then
s.TerminateCAS( s );
if IsBound( arg[1].pid ) then
Print( "terminated the external CAS ", s.name, " with pid ", s.pid, "\n" );
else
Print( "terminated the external CAS ", s.name, "\n" );
fi;
else
Print( "the stream does not contain a TerminateCAS process\n" );
fi;
else
TerminateCAS( homalgStream( arg[1] ) );
fi;
fi;
end );
##
InstallGlobalFunction( LaunchCAS,
function( arg )
local nargs, HOMALG_IO_CAS, executables, e, s;
nargs := Length( arg );
HOMALG_IO_CAS := arg[1];
if IsString( HOMALG_IO_CAS ) then
HOMALG_IO_CAS := ValueGlobal( HOMALG_IO_CAS );
else
Error( "for security reasons LaunchCAS only accepts a string (as a first argument) which points to a HOMALG_IO_CAS record\n" );
fi;
if IsBound( HOMALG_IO_CAS.LaunchCAS ) and IsFunction( HOMALG_IO_CAS.LaunchCAS ) then
s := CallFuncList( HOMALG_IO_CAS.LaunchCAS, arg );
if s = fail then
Error( "the alternative launcher returned fail\n" );
fi;
else
if LoadPackage( "IO_ForHomalg" ) <> true then
Error( "the package IO_ForHomalg failed to load\n" );
fi;
s := CallFuncList( LaunchCAS_IO_ForHomalg, Concatenation( [ HOMALG_IO_CAS ], arg{[ 2 .. nargs ]} ) );
fi;
for e in NamesOfComponents( HOMALG_IO_CAS ) do
if not IsBound( s.( e ) ) then
s.( e ) := HOMALG_IO_CAS.( e );
fi;
od;
if not IsBound( s.variable_name ) then
s.variable_name := HOMALG_IO.variable_name;
fi;
if IsBound( HOMALG_IO.color_display ) and HOMALG_IO.color_display = true
and IsBound( s.display_color ) then
s.color_display := s.display_color;
fi;
if IsBound( HOMALG_IO.DeletePeriod ) and
( IsPosInt( HOMALG_IO.DeletePeriod ) or IsBool( HOMALG_IO.DeletePeriod ) ) then
s.DeletePeriod := HOMALG_IO.DeletePeriod;
fi;
s.StatisticsObject :=
NewStatisticsObject(
rec(
summary := rec(
HomalgExternalCallCounter := 0,
HomalgExternalVariableCounter := 0,
HomalgExternalCommandCounter := 0,
HomalgExternalOutputCounter := 0,
HomalgBackStreamMaximumLength := 0,
HomalgExternalWarningsCounter := 0
)
),
TheTypeStatisticsObjectForStreams
);
s.homalgExternalObjectsPointingToVariables :=
ContainerForWeakPointers( TheTypeContainerForWeakPointersOnHomalgExternalObjects );
s.homalgExternalObjectsPointingToVariables!.assignments_pending := [ ];
s.homalgExternalObjectsPointingToVariables!.assignments_failed := [ ];
s.homalgExternalObjectsPointingToVariables!.processes := [ ];
if IsBound( s.InitialSendBlockingToCAS ) then
s.InitialSendBlockingToCAS( s, "\n" );
else
s.SendBlockingToCAS( s, "\n" );
fi;
if ( not ( IsBound( HOMALG_IO.show_banners ) and HOMALG_IO.show_banners = false )
and not ( IsBound( s.show_banner ) and s.show_banner = false ) )
and ( ( IsBound( s.banner ) and ( IsString( s.banner ) or IsFunction( s.banner ) ) )
or Length( s.lines ) > 0 ) then
Print( "================================================================\n" );
if IsBound( s.color_display ) then
Print( s.color_display );
fi;
if IsBound( s.banner ) and IsString( s.banner ) then
Print( s.banner );
elif IsBound( s.banner ) and IsFunction( s.banner ) then
s.banner( s );
else
Print( s.lines );
fi;
Print( "\033[0m\n================================================================\n" );
fi;
return s;
end );
##
InstallGlobalFunction( InitializeMacros,
function( macros, stream )
local names, component, macros_names;
if not IsRecord( macros ) then
Error( "the second argument must be a record\n" );
fi;
names := SortedList( NamesOfComponents( macros ) );
if IsBound( macros._order ) and
IsList( macros._order ) and
ForAll( macros._order, IsString ) then
names := Concatenation( macros._order, Difference( names, macros._order ) );
fi;
macros_names := [ ];
for component in names do
if component[1] = '!' then
if IsFunction( macros.(component) ) then
macros.(component)( stream );
else
homalgSendBlocking( macros.(component), "need_command", stream, "initialize" );
fi;
fi;
od;
for component in names do
if not component[1] in [ '_', '!' ] then
if component[1] = '$' then
homalgSendBlocking( macros.(component), "need_command", stream, "initialize" );
else
homalgSendBlocking( macros.(component), "need_command", stream, "define" );
Add( macros_names, component );
fi;
fi;
od;
return macros_names;
end );
##
InstallGlobalFunction( UpdateMacrosOfCAS,
function( macros, CASmacros )
local component;
if IsBound( macros._Identifier ) then
if IsBound( CASmacros._included_packages ) then
if IsBound( CASmacros._included_packages.(macros._Identifier) ) and
CASmacros._included_packages.(macros._Identifier) = true then
## get out
return;
fi;
else
CASmacros._included_packages := rec( );
fi;
fi;
CASmacros._included_packages.(macros._Identifier) := true;
for component in NamesOfComponents( macros ) do
if component[1] <> '_' then
CASmacros.(component) := macros.(component);
fi;
od;
end );
##
InstallGlobalFunction( UpdateMacrosOfLaunchedCAS,
function( macros, stream )
local send, send_orig;
if IsBound( macros._Identifier ) then
if IsBound( stream.activated_packages ) then
if IsBound( stream.activated_packages.(macros._Identifier) ) and
stream.activated_packages.(macros._Identifier) = true then
## get out
return;
fi;
else
stream.activated_packages := rec( );
fi;
fi;
stream.activated_packages.(macros._Identifier) := true;
## save the original stream communicator
send := stream!.SendBlockingToCAS;
if IsBound( stream!.SendBlockingToCAS_original ) then
send_orig := stream!.SendBlockingToCAS_original;
else
send_orig := send;
fi;
## this is a way to avoid branching in the time critical homalgSendBlocking
stream!.SendBlockingToCAS :=
function( arg )
local container, assignments_pending;
## set back the original stream communicator
stream!.SendBlockingToCAS := send; ## GAP is wonderful
## save the current pending assignments
container := stream.homalgExternalObjectsPointingToVariables;
assignments_pending := container!.assignments_pending;
container!.assignments_pending := [ ];
## level 3: print the pictogram only
Info( InfoHomalgToCAS, 3, "\033[1;31;40m", "blocked the previous command which will be executed later and\033[0m" );
Info( InfoHomalgToCAS, 3, "\033[1;31;40m", "locked the stream to START initializing the ", macros._Identifier, "-macros\033[0m\n" );
if IsBound( stream.InitializeMacros ) then
stream.InitializeMacros( macros, stream );
else
InitializeMacros( macros, stream );
fi;
Info( InfoHomalgToCAS, 3, "\033[1;32;40mCOMPLETED initializing the ", macros._Identifier, "-macros, unlocked the stream,\033[0m" );
Info( InfoHomalgToCAS, 3, "\033[1;32;40m", "and about to execute the previous command which has been blocked\033[0m\n" );
## the command in arg might depend on the above initialization
## so do not move this line higher
container!.assignments_pending := assignments_pending;
CallFuncList( send_orig, arg );
end;
end );
##
InstallGlobalFunction( UpdateMacrosOfLaunchedCASs,
function( macros )
local name, streams, stream;
if not IsBound( macros._CAS_name ) then
return;
fi;
name := macros._CAS_name;
if not IsBound( HOMALG_MATRICES.ContainerForWeakPointersOnHomalgExternalRings ) then
return;
fi;
streams := HOMALG_MATRICES.ContainerForWeakPointersOnHomalgExternalRings!.streams;
for stream in streams do
if IsBound( stream.name ) and stream.name = name then
UpdateMacrosOfLaunchedCAS( macros, stream );
fi;
od;
end );
[ Dauer der Verarbeitung: 0.43 Sekunden
(vorverarbeitet)
]
|