Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346############################################################################# ## ## homalgSendBlocking.gi HomalgToCAS package Mohamed Barakat ## ## Copyright 2007-2008 Lehrstuhl B für Mathematik, RWTH Aachen ## ## Implementation stuff to manage the communication. ## ############################################################################# #################################### # # methods for operations: # #################################### ## InstallGlobalFunction( homalgFlush, function( arg ) local nargs, verbose, stream, container, weak_pointers, l, pids, R, p, i, var, active_ring_creation_number, ring_creation_numbers, deleted, streams; ## the internal garbage collector: GASMAN( "collect" ); nargs := Length( arg ); verbose := true; if nargs > 0 and IsStringRep( arg[nargs] ) then nargs := nargs - 1; verbose := false; fi; ## nargs is the number of arguments _without_ an optional last "quiet" string; see above 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 p := homalgExternalCASystemPID( R ); ## do not rely on the (not p in pids) criterion ## for streams with an active ring if not p in pids or IsBound( homalgStream( R )!.active_ring ) then Add( pids, p ); ## it is now important to pass the ring R and not merely its stream ## to homalgFlush as R might not the currently active ring; ## this is important for computer algebra systems like Singular, ## which have the "feature" that a variable is stored in the ring ## which was active when the variable was assigned... if verbose then homalgFlush( R ); else homalgFlush( R, "quiet" ); fi; fi; fi; od; deleted := Filtered( [ 1 .. l ], i -> not IsBoundElmWPObj( weak_pointers, i ) ); container!.deleted := deleted; if IsBound( HOMALG_IO.InformAboutCASystemsWithoutActiveRings ) and HOMALG_IO.InformAboutCASystemsWithoutActiveRings = true then 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 ); deleted := [ ]; for i in [ 1 .. l ] do if not streams[i].pid in pids then Add( deleted, streams[i].pid ); fi; od; if deleted <> [ ] and verbose then Print( "the external CASs with pids ", deleted, " have no active rings: they can be terminated by launching TerminateCAS()\n" ); fi; fi; elif nargs > 0 then if IsHomalgExternalRingRep( arg[1] ) then R := arg[1]; stream := homalgStream( R ); elif IsRecord( arg[1] ) and IsBound( arg[1].lines ) and IsBound( arg[1].pid ) then stream := arg[1]; else Error( "the first argument is neither an external ring nor a stream\n" ); fi; container := stream.homalgExternalObjectsPointingToVariables; weak_pointers := container!.weak_pointers; l := container!.counter; ## exclude already deleted external objects: var := Difference( [ 1 .. l ], container!.deleted ); if IsBound( stream.active_ring ) then if not IsBound( R ) then R := stream.active_ring; fi; ## R is either already the active ring ## or the one we will make active below active_ring_creation_number := R!.creation_number; ring_creation_numbers := container!.ring_creation_numbers; ## this is important for computer algebra systems like Singular, ## which have the "feature" that a variable is stored in the ring ## which was active when the variable was assigned... ## mapping all existing variables to the active ring ## -- besides being a bad idea anyway -- would result in various disasters: ## non-zero entries of a matrix over a ring S (e.g. polynomial ring) ## often become zero when the matrix is mapped to another ring (e.g. exterior ring), ## and of course remain zero when the matrix is mapped back to the original ring S. var := Filtered( var, i -> not IsBoundElmWPObj( weak_pointers, i ) and IsBound( ring_creation_numbers[i] ) and ring_creation_numbers[i] = active_ring_creation_number ); ## set the argument to be the active ring if var <> [ ] and IsHomalgExternalRingRep( R ) and not IsIdenticalObj( R, stream.active_ring ) then homalgSendBlocking( "\"we've just reset the ring for garbage collection\"", "need_command", R, HOMALG_IO.Pictograms.initialize ); fi; ## free the entries corresponding to external objects about to be deleted Perform( var, function( i ) Unbind( ring_creation_numbers[i] ); end ); else var := Filtered( var, i -> not IsBoundElmWPObj( weak_pointers, i ) ); fi; l := Length( var ); deleted := Union2( container!.deleted, var ); if IsBound( stream.multiple_delete ) and ( l > 1 or ( not IsBound( stream.delete ) and l > 0 ) ) then stream.multiple_delete( List( var, v -> Concatenation( stream.variable_name, String( v ) ) ), stream ); container!.deleted := deleted; elif IsBound( stream.delete ) and l > 0 then Perform( var, function( p ) stream.delete( Concatenation( stream.variable_name, String( p ) ), stream ); end ); container!.deleted := deleted; fi; if IsBound( stream.garbage_collector ) then ## the external garbage collector: stream.garbage_collector( stream ); if verbose then Print( "completed garbage collection in the external CAS ", stream.name, " with pid ", stream.pid, "\n" ); fi; fi; fi; end ); ## InstallGlobalFunction( TerminateAllCAS, function( ) local stream; for stream in HOMALG_MATRICES.ContainerForWeakPointersOnHomalgExternalRings!.streams do stream!.TerminateCAS( stream ); od; end ); ## InstallGlobalFunction( _SetElmWPObj_ForHomalg, ## is not based on homalgFlush for performance reasons function( stream, ext_obj ) local container, weak_pointers, l, DeletePeriod, var, active_ring_creation_number, ring_creation_numbers, deleted; container := stream.homalgExternalObjectsPointingToVariables; weak_pointers := container!.weak_pointers; l := container!.counter; if IsBound( stream.DeletePeriod ) then if IsBool( stream.DeletePeriod ) then DeletePeriod := stream.DeletePeriod; else DeletePeriod := l mod stream.DeletePeriod = 0; fi; else DeletePeriod := true; fi; if DeletePeriod then ## exclude already deleted external objects: var := Difference( [ 1 .. l ], container!.deleted ); fi; if IsBound( stream.active_ring ) then active_ring_creation_number := stream.active_ring!.creation_number; ring_creation_numbers := container!.ring_creation_numbers; ## set the active ring for the new external object ring_creation_numbers[l + 1] := active_ring_creation_number; if DeletePeriod then ## this is important for computer algebra systems like Singular, ## which have the "feature" that a variable is stored in the ring ## which was active when the variable was assigned... ## mapping all existing variables to the active ring ## -- besides being a bad idea anyway -- would result in various disasters: ## non-zero entries of a matrix over a ring S (e.g. polynomial ring) ## often become zero when the matrix is mapped to another ring (e.g. exterior ring), ## and of course remain zero when the matrix is mapped back to the original ring S. var := Filtered( var, i -> not IsBoundElmWPObj( weak_pointers, i ) and IsBound( ring_creation_numbers[i] ) and ring_creation_numbers[i] = active_ring_creation_number ); ## free the entries corresponding to external objects about to be deleted Perform( var, function( i ) Unbind( ring_creation_numbers[i] ); end ); fi; else if DeletePeriod then var := Filtered( var, i -> not IsBoundElmWPObj( weak_pointers, i ) ); fi; fi; l := l + 1; container!.counter := l; ## sanity check if not Concatenation( stream.variable_name, String( l ) ) = homalgPointer( ext_obj ) then Error( "\033[01m\033[5;31;47mexpecting an external object with pointer = ", Concatenation( stream.variable_name, String( l ) ), " but recieved one with pointer = ", homalgPointer( ext_obj ), "\033[0m" ); fi; SetElmWPObj( weak_pointers, l, ext_obj ); if DeletePeriod then l := Length( var ); deleted := Union2( container!.deleted, var ); if IsBound( stream.multiple_delete ) and ( l > 1 or ( not IsBound( stream.delete ) and l > 0 ) ) then stream.multiple_delete( List( var, v -> Concatenation( stream.variable_name, String( v ) ) ), stream ); container!.deleted := deleted; elif IsBound( stream.delete ) and l > 0 then Perform( var, function( p ) stream.delete( Concatenation( stream.variable_name, String( p ) ), stream ); end ); container!.deleted := deleted; fi; ## never ever call the internal or the external garbage collector in this procedure fi; end ); ## InstallGlobalFunction( homalgCreateStringForExternalCASystem, function( arg ) local nargs, L, l, stream, break_lists, assignments_pending, used_pointers, void_matrices, s; nargs := Length( arg ); ## Do not waste time with syntax checks; ## this is not a procedure for end users. #if nargs = 0 or not IsList( arg[1] ) then # Error( "the first argument must be a list\n" ); #fi; L := arg[1]; l := Length( L ); break_lists := false; if nargs > 1 and IsRecord( arg[2] ) then stream := arg[2]; if IsBound( stream.break_lists ) and stream.break_lists = true then break_lists := true; fi; fi; if nargs > 2 and arg[3] = "break_lists" then break_lists := true; fi; assignments_pending := [ ]; used_pointers := [ ]; void_matrices := [ ]; s := List( [ 1 .. l ], function( a ) local o, CAS, stream, statistics_summary, counter, t, ext_obj; o := L[a]; if IsStringRep( o ) then return o; else if IsHomalgExternalMatrixRep( o ) then if not ( HasIsVoidMatrix( o ) and IsVoidMatrix( o ) ) or HasEval( o ) then t := homalgPointer( o ); ## now we enforce evaluation!!! Add( used_pointers, t ); elif IsBound( o!.void_pointer ) then t := o!.void_pointer; Add( used_pointers, t ); else CAS := homalgExternalCASystem( o ); stream := homalgStream( o ); statistics_summary := stream.StatisticsObject!.summary; IncreaseExistingCounterInObject( statistics_summary, "HomalgExternalVariableCounter" ); ## never interchange the previous line with the next one counter := statistics_summary!.HomalgExternalVariableCounter; t := Concatenation( stream.variable_name, String( counter ) ); MakeImmutable( t ); ## now that we have just increased the variable counter and ## created the new variable we need to *immediately* create ## the enveloping external object and insert it in ## the weak pointer list using _SetElmWPObj_ForHomalg, ## before we start executing commands in the external CAS, ## that might cause an error; the weak pointer list ## which expects the l-th external object (i.e., the one ## with pointer = homalg_variable_l) at the l-th position ## would otherwise run out of sync) ext_obj := homalgExternalObject( t, CAS, stream ); ## the following line relies on the feature, that homalgExternalObjects ## are now assigned homalg_variables strictly sequentially!!! _SetElmWPObj_ForHomalg( stream, ext_obj ); o!.void_pointer := t; ## do not Add counter directly to container!.assignments_pending ## as possibly remaining Eval's will invoke homalgSendBlocking ## which will move container!.assignments_pending to ## container!.assignments_failed; rather collect them in the variable ## assignments_pending and pass them back to homalgSendBlocking Add( assignments_pending, counter ); Add( void_matrices, [ o, ext_obj ] ); fi; elif IsHomalgExternalRingElementRep( o ) or IsHomalgExternalRingRep( o ) or IshomalgExternalObjectRep( o ) then t := homalgPointer( o ); Add( used_pointers, t ); elif IsList( o ) and not IsStringRep( o ) then if break_lists then if ForAll( o, IsStringRep ) then t := JoinStringsWithSeparator( o ); elif ForAll( o, e -> IsHomalgExternalMatrixRep( e ) or IsHomalgExternalRingElementRep( e ) ) then t := JoinStringsWithSeparator( List( o, homalgPointer ) ); else t := String( List( o, i -> i ) ); ## get rid of the range representation of lists t := t{ [ 2 .. Length( t ) - 1 ] }; fi; else t := String( List( o, i -> i ) ); ## get rid of the range representation of lists fi; else t := String( o ); fi; if a < l and not IsStringRep( L[a+1] ) then t := Concatenation( t, "," ); fi; return t; fi; end ); return [ Flat( s ), assignments_pending, used_pointers, void_matrices ]; end ); ## InstallGlobalFunction( homalgSendBlocking, function( arg ) local L, nargs, properties, need_command, need_display, need_output, ar, pictogram, option, break_lists, R, ext_obj, stream, type, prefix, suffix, e, RP, CAS, PID, container, counter, homalg_variable, used_pointers, void_matrices, l, eoc, enter, statistics, statistics_summary, fs, io_info_level, picto, void_matrix, o, max, display_color, esc; if IsBound( HOMALG_IO.homalgSendBlockingInput ) then Add( HOMALG_IO.homalgSendBlockingInput, arg ); fi; Info( InfoHomalgToCAS, 10, "homalgSendBlocking <-- ", arg ); if not IsList( arg[1] ) then Error( "the first argument must be a list\n" ); elif IsStringRep( arg[1] ) then L := [ arg[1] ]; else L := arg[1]; fi; nargs := Length( arg ); properties := [ ]; need_command := false; need_display := false; need_output := false; for ar in arg{[ 2 .. nargs ]} do ## the order of the following might be important for the performance!!! if IsList( ar ) and ar <> [ ] and ForAll( ar, IsFilter ) then ## this must come before prefix and suffix Append( properties, ar ); elif not IsBound( prefix ) and IsList( ar ) and not IsStringRep( ar ) then prefix := ar; elif not IsBound( suffix ) and IsList( ar ) and not IsStringRep( ar ) then suffix := ar; elif not IsBound( R ) and IsHomalgExternalRingRep( ar ) then R := ar; ext_obj := R; stream := homalgStream( ext_obj ); elif not IsBound( ext_obj ) and IshomalgExternalObjectRep( ar ) then ext_obj := ar; stream := homalgStream( ext_obj ); elif not IsBound( R ) and IsHomalgExternalMatrixRep( ar ) then R := HomalgRing( ar ); ext_obj := R; stream := homalgStream( ext_obj ); elif not IsBound( ext_obj ) and IsHomalgExternalRingElementRep( ar ) then R := HomalgRing( ar ); ext_obj := R; stream := homalgStream( ext_obj ); elif IsRecord( ar ) and IsBound( ar.lines ) and IsBound( ar.pid ) then if not IsBound( stream ) or not IsBound( ext_obj ) then stream := ar; if IsBound( stream.name ) then ext_obj := homalgExternalObject( "", stream.name, stream ); fi; fi; elif not IsBound( pictogram ) and IsStringRep( ar ) and Length( ar ) <= 5 then pictogram := ar; elif not IsBound( option ) and IsStringRep( ar ) and Length( ar ) > 5 and ar <> "break_lists" then ## the first occurrence of an option decides if PositionSublist( LowercaseString( ar ), "command" ) <> fail then need_command := true; elif PositionSublist( LowercaseString( ar ), "display" ) <> fail then need_display := true; elif PositionSublist( LowercaseString( ar ), "output" ) <> fail then need_output := true; else Error( "option must be one of { \"need_command\", \"need_display\", \"need_output\" }, but received: ", ar, "\n" ); fi; option := ar; elif not IsBound( type ) and IsType( ar ) then type := ar; elif IsFilter( ar ) then Add( properties, ar ); elif not IsBound( break_lists ) and ar = "break_lists" then break_lists := ar; else Error( "this argument should be in { IsList, IsStringRep, IsFilter, IsRecord, IshomalgExternalObjectRep, IsHomalgExternalRingElementRep, IsHomalgExternalRingRep, IsHomalgExternalMatrixRep } but recieved: ", ar,"\n" ); fi; od; if not IsBound( ext_obj ) then ## R is also not yet defined e := Filtered( L, a -> IsHomalgExternalMatrixRep( a ) or IsHomalgExternalRingElementRep( a ) or IsHomalgExternalRingRep( a ) or IshomalgExternalObjectRep( a ) ); if e <> [ ] then ext_obj := e[1]; for ar in e do if IsHomalgExternalMatrixRep( ar ) then R := HomalgRing( ar ); break; elif IsHomalgExternalRingRep( ar ) then R := ar; break; elif IsHomalgExternalRingElementRep( ar ) then R := HomalgRing( ar ); break; fi; od; else Error( "either the list provided by the first argument must contain at least one external matrix or an external ring or one of the remaining arguments must be an external ring or an external object\n" ); fi; stream := homalgStream( ext_obj ); fi; if IsBound( R ) then if IsBound( stream.active_ring ) and not IsIdenticalObj( R, stream.active_ring ) and IsBound( stream.setring ) and IsFunction( stream.setring ) then stream.setring( R ); if IsBound( stream.setinvol ) and IsFunction( stream.setinvol ) then stream.setinvol( R ); fi; fi; RP := homalgTable( R ); if IsBound(RP!.homalgSendBlocking) then return RP!.homalgSendBlocking( arg ); fi; fi; CAS := homalgExternalCASystem( ext_obj ); PID := homalgExternalCASystemPID( ext_obj ); if not IsBound( break_lists ) then break_lists := "do_not_break_lists"; fi; container := stream.homalgExternalObjectsPointingToVariables; ## if a homalgSendBlocking instance finds assignments still pending then ## for sure something went wrong with the previous homalgSendBlocking instance if container!.assignments_pending <> [ ] then ## for some odd reason assigning to a variable, e.g., ## assignments_pending := container!.assignments_pending ## and reassigning ## container!.assignments_pending := assignments_pending ## at the end does not work properly Append( container!.deleted, container!.assignments_pending ); Append( container!.assignments_failed, container!.assignments_pending ); container!.assignments_pending := [ ]; fi; if IsBound( prefix ) and prefix <> [ ] then prefix := Concatenation( homalgCreateStringForExternalCASystem( prefix, stream, break_lists )[1], " " ); fi; if IsBound( suffix ) then suffix := homalgCreateStringForExternalCASystem( suffix, stream, break_lists )[1]; fi; ## this line may trigger an evaluation which will trigger homalgSendblocking again L := homalgCreateStringForExternalCASystem( L, stream, break_lists ); ## never separate the previous line from the following one! Append( container!.assignments_pending, L[2] ); ## for some odd reason assigning to a variable, e.g., ## assignments_pending := container!.assignments_pending ## and reassigning ## container!.assignments_pending := assignments_pending ## at the end does not work properly used_pointers := L[3]; void_matrices := L[4]; L := L[1]; l := Length( L ); if l > 0 and L{[l..l]} = "\n" then enter := ""; eoc := ""; else enter := "\n"; if l > 0 and ( ( Length( stream.eoc_verbose ) > 0 and l-Length( stream.eoc_verbose )+1 > 0 and L{[l-Length( stream.eoc_verbose )+1..l]} = stream.eoc_verbose ) or ( l-Length( stream.eoc_quiet )+1 > 0 and L{[l-Length( stream.eoc_quiet )+1..l]} = stream.eoc_quiet ) ) then eoc := ""; elif not IsBound( option ) then eoc := stream.eoc_quiet; ## as little back-traffic over the stream as possible else if need_command then eoc := stream.eoc_quiet; ## as little back-traffic over the stream as possible else eoc := stream.eoc_verbose; fi; fi; fi; statistics := stream.StatisticsObject; statistics_summary := statistics!.summary; if not IsBound( option ) then IncreaseExistingCounterInObject( statistics_summary, "HomalgExternalVariableCounter" ); ## never interchange the previous line with the next one counter := statistics_summary.HomalgExternalVariableCounter; homalg_variable := Concatenation( stream.variable_name, String( counter ) ); MakeImmutable( homalg_variable ); ## now that we have just increased the variable counter and ## created the new variable we need to *immediately* create ## the enveloping external object and insert it in ## the weak pointer list using _SetElmWPObj_ForHomalg, ## before we start executing commands in the external CAS, ## that might cause an error; the weak pointer list ## which expects the l-th external object (i.e., the one ## with pointer = homalg_variable_l) at the l-th position ## would otherwise run out of sync) if not IsBound( type ) then ext_obj := homalgExternalObject( homalg_variable, CAS, stream ); else ext_obj := homalgExternalObject( homalg_variable, CAS, stream, type ); fi; ## the following line relies on the feature, that homalgExternalObjects ## are now assigned homalg_variables strictly sequentially!!! _SetElmWPObj_ForHomalg( stream, ext_obj ); ## never separate the previous line from the following one! Add( container!.assignments_pending, counter ); if properties <> [ ] and IshomalgExternalObjectRep( ext_obj ) then for ar in properties do Setter( ar )( ext_obj, true ); od; fi; if IsBound( prefix ) then if IsBound( suffix ) then L := Concatenation( prefix, homalg_variable, suffix, " ", stream.define, " ", L, eoc, enter ); else L := Concatenation( prefix, homalg_variable, " ", stream.define, " ", L, eoc, enter ); fi; else L := Concatenation( homalg_variable, " ", stream.define, " ", L, eoc, enter ); fi; else if IsBound( prefix ) then L := Concatenation( prefix, " ", L, eoc, enter ); else L := Concatenation( L, eoc, enter ); fi; if need_command then IncreaseExistingCounterInObject( statistics_summary, "HomalgExternalCommandCounter" ); else IncreaseExistingCounterInObject( statistics_summary, "HomalgExternalOutputCounter" ); fi; fi; ConvertToStringRep( L ); if ( IsBound( HOMALG_IO.save_CAS_commands_to_file ) and HOMALG_IO.save_CAS_commands_to_file = true ) or IsBound( stream.CAS_commands_file ) then if not IsBound( stream.CAS_commands_file ) then stream.CAS_commands_file := Concatenation( "commands_file_of_", CAS, "_with_PID_", String( PID ) ); fs := IO_File( stream.CAS_commands_file, "w" ); if fs = fail then Error( "unable to open the file ", stream.CAS_commands_file, " for writing\n" ); fi; if IO_Close( fs ) = fail then Error( "unable to close the file ", stream.CAS_commands_file, "\n" ); fi; fi; fs := IO_File( stream.CAS_commands_file, "a" ); if IO_WriteFlush( fs, L ) = fail then Error( "unable to write in the file ", stream.CAS_commands_file, "\n" ); fi; if IO_Close( fs ) = fail then Error( "unable to close the file ", stream.CAS_commands_file, "\n" ); fi; fi; ## <#GAPDoc Label="homalgSendBlocking:view_communication"> ## <Description> ## This is the part of the global function <C>homalgSendBlocking</C> ## that controls the visibility of the communication. ## <Listing Type="Code"><![CDATA[ io_info_level := InfoLevel( InfoHomalgToCAS ); if not IsBound( pictogram ) then pictogram := HOMALG_IO.Pictograms.unknown; picto := pictogram; elif io_info_level >= 3 then picto := pictogram; ## add colors to the pictograms if pictogram = HOMALG_IO.Pictograms.ReducedEchelonForm and IsBound( HOMALG_MATRICES.color_BOE ) then pictogram := Concatenation( HOMALG_MATRICES.color_BOE, pictogram, "\033[0m" ); elif pictogram = HOMALG_IO.Pictograms.BasisOfModule and IsBound( HOMALG_MATRICES.color_BOB ) then pictogram := Concatenation( HOMALG_MATRICES.color_BOB, pictogram, "\033[0m" ); elif pictogram = HOMALG_IO.Pictograms.DecideZero and IsBound( HOMALG_MATRICES.color_BOD ) then pictogram := Concatenation( HOMALG_MATRICES.color_BOD, pictogram, "\033[0m" ); elif pictogram = HOMALG_IO.Pictograms.SyzygiesGenerators and IsBound( HOMALG_MATRICES.color_BOH ) then pictogram := Concatenation( HOMALG_MATRICES.color_BOH, pictogram, "\033[0m" ); elif pictogram = HOMALG_IO.Pictograms.BasisCoeff and IsBound( HOMALG_MATRICES.color_BOC ) then pictogram := Concatenation( HOMALG_MATRICES.color_BOC, pictogram, "\033[0m" ); elif pictogram = HOMALG_IO.Pictograms.DecideZeroEffectively and IsBound( HOMALG_MATRICES.color_BOP ) then pictogram := Concatenation( HOMALG_MATRICES.color_BOP, pictogram, "\033[0m" ); elif need_output or need_display then pictogram := Concatenation( HOMALG_IO.Pictograms.color_need_output, pictogram, "\033[0m" ); else pictogram := Concatenation( HOMALG_IO.Pictograms.color_need_command, pictogram, "\033[0m" ); fi; else picto := pictogram; fi; if io_info_level >= 3 then if ( io_info_level >= 7 and not need_display ) or io_info_level >= 8 then ## print the pictogram, the prompt of the external system, ## and the sent command Info( InfoHomalgToCAS, 7, pictogram, " ", stream.prompt, L{[ 1 .. Length( L ) - 1 ]} ); elif io_info_level >= 4 then ## print the pictogram and the prompt of the external system Info( InfoHomalgToCAS, 4, pictogram, " ", stream.prompt, "..." ); else ## print the pictogram only Info( InfoHomalgToCAS, 3, pictogram ); fi; fi; ## ]]></Listing> ## </Description> ## <#/GAPDoc> IncreaseExistingCounterInObject( statistics_summary, "HomalgExternalCallCounter" ); IncreaseCounterInObject( statistics, picto ); ## always keep the above two lines together if IsBound( stream!.log_processes ) and stream!.log_processes = true then l := Length( stream.variable_name ); stream.description_of_last_process := [ container!.assignments_pending, List( used_pointers, a -> Int( a{[ l + 1 .. Length( a ) ]} ) ), need_output = false, pictogram ]; fi; stream.SendBlockingToCAS( stream, L ); if stream.errors <> "" then if IsBound( stream.only_warning ) and PositionSublist( stream.errors, stream.only_warning ) <> fail then stream.warnings := stream.errors; IncreaseExistingCounterInObject( statistics_summary, "HomalgExternalWarningsCounter" ); else Error( "the external CAS ", CAS, " (running with PID ", PID, ") returned the following error:\n", "\033[01m", stream.errors ,"\033[0m\n" ); fi; elif IsBound( stream.error_stdout ) and PositionSublist( stream.lines, stream.error_stdout ) <> fail then Error( "the external CAS ", CAS, " (running with PID ", PID, ") returned the following error:\n", "\033[01m", stream.lines ,"\033[0m\n" ); fi; for void_matrix in void_matrices do SetEval( void_matrix[1], void_matrix[2] ); ResetFilterObj( void_matrix[1], IsVoidMatrix ); Unbind( void_matrix[1]!.void_matrix ); od; ## we can now assume that every variable got assigned container!.assignments_pending := [ ]; max := Maximum( statistics_summary.HomalgBackStreamMaximumLength, Length( stream.lines ) ); if max > statistics_summary.HomalgBackStreamMaximumLength then statistics_summary.HomalgBackStreamMaximumLength := max; if HOMALG_IO.SaveHomalgMaximumBackStream = true then stream.HomalgMaximumBackStream := stream.lines; fi; fi; if IsBound( HOMALG_IO.break_point ) and HOMALG_IO.break_point = statistics_summary.HomalgExternalVariableCounter and not need_display then Error( "break_pointing as required at HOMALG_IO.break_point = ", statistics_summary.HomalgExternalVariableCounter, "\n" ); fi; if not IsBound( option ) then return ext_obj; elif need_display then if IsBound( stream.color_display ) then display_color := stream.color_display; esc := "\033[0m"; else display_color := ""; ## esc must be empty, otherwise GAPDoc's TestManualExamples will complain esc := ""; fi; if IsBound( stream.trim_display ) and IsFunction( stream.trim_display ) then L := stream.trim_display( stream.lines ); else L := stream.lines; fi; return Concatenation( display_color, L, esc, "\n" ); elif IsBound( stream.normalized_white_space ) and IsFunction( stream.normalized_white_space ) then ## unless meant for display, normalize the white spaces caused by Maple L := stream.normalized_white_space( stream.lines ); else L := stream.lines; fi; if need_output then if IsBound( stream.remove_enter ) and stream.remove_enter = true then RemoveCharacters( L, "\n" ); fi; RemoveCharacters( L, "\\ " ); Info( InfoHomalgToCAS, 5, "/------------------" ); Info( InfoHomalgToCAS, 5, stream.output_prompt, "\"", L, "\"" ); Info( InfoHomalgToCAS, 5, "\\==================" ); if IsBound( stream.check_output ) and stream.check_output = true and '\n' in L and not ',' in L then Error( "\033[01m", "the output received from the external CAS ", CAS, " (running with PID ", PID, ") contains an ENTER = '\\n' but no COMMA = ',' ... this is most probably a mistake!!!", "\033[0m\n" ); fi; fi; if not need_command then return L; fi; end ); ## InstallGlobalFunction( homalgDisplay, function( arg ) local L, ar; if IsList( arg[1] ) then L := arg[1]; else L := [ arg[1] ]; fi; ar := Concatenation( [ L ], arg{[ 2 .. Length( arg ) ]}, [ "need_display", HOMALG_IO.Pictograms.Display ] ); Print( CallFuncList( homalgSendBlocking, ar ) ); end ); ## InstallGlobalFunction( StringToInt, function( s ) if s = "" then Error( "received an empty string while expecting a string containing an integer\n" ); else return Int( s ); fi; end ); ## InstallGlobalFunction( StringToIntList, function( arg ) local l, lint; if arg[1] = "[]" then return [ ]; fi; l := SplitString( arg[1], ",", "[ ]\n" ); lint := List( l, Int ); if fail in lint then Error( "the first argument is not a string containg a list of integers: ", arg[1], "\n"); fi; return lint; end ); ## InstallGlobalFunction( StringToDoubleIntList, function( s ) local l, lint; if s = "[]" then return [ ]; fi; l := SplitString( s, "", ",[ ]\n" ); lint := List( l, Int ); if fail in lint then Error( "the first argument is not a string containg a list of list of two integers: ", s, "\n"); fi; l := Length( lint ); if IsOddInt( l ) then Error( "expected an even number of integers: ", s, "\n"); fi; return List( [ 1 .. l/2 ], a -> [ lint[2*a-1], lint[2*a] ] ) ; end ); #################################### # # View, Print, and Display methods: # #################################### InstallMethod( ViewObj, "for homalg external objects with an IO stream", [ IshomalgExternalObjectRep ], function( o ) Print( "<A homalg external object residing in the CAS " ); if IsBound( homalgStream( o ).color_display ) then Print( "\033[1m" ); fi; Print( homalgExternalCASystem( o ), "\033[0m running with pid ", homalgExternalCASystemPID( o ), ">" ); end );