Module: environment-protocols Synopsis: Environment protocols Author: Andy Armstrong Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND /// Thread objects define class () slot thread-runtime-state :: , init-value: #"running"; slot thread-suspended? :: , init-value: #f; end class ; define open generic thread-stack-trace (server :: , thread :: ) => (top-frame :: ); define open generic thread-complete-stack-trace (server :: , thread :: ) => (all-frames :: ); define open generic thread-index (server :: , thread :: ) => (index :: ); define open generic thread-state (server :: , thread :: ) => (state :: ); define open generic create-application-thread (server :: , title :: ) => (thread :: ); define open generic suspend-application-thread (server :: , thread :: ) => (); define open generic resume-application-thread (server :: , thread :: ) => (); define open generic thread-current-interactor-level (server :: , thread :: ) => (level :: ); define open generic add-application-object-to-thread-history (server :: , thread :: , application-object :: ) => (varname :: false-or()); define open generic application-default-interactor-thread (server :: ) => (thread :: false-or()); /// Stepping (Added by phoward, 29 May 1997, at request of jason) define open generic step-application-out (server :: , thread :: , #key stack-frame) => (); define open generic step-application-over (server :: , thread :: , #key stack-frame) => (); define open generic step-application-into (server :: , thread :: ) => (); define open generic application-just-hit-dylan-error? (server :: , thread :: ) => (hit? :: ); define open generic application-just-hit-error? (server :: , thread :: ) => (hit? :: ); define open generic application-just-hit-breakpoint? (server :: , thread :: ) => (hit? :: ); define open generic application-just-interacted? (server :: , thread :: ) => (interacted? :: ); define open generic application-just-stepped? (server :: , thread :: ) => (stepped? :: ); /// CURRENT-STOP-BREAKPOINTS define open generic current-stop-breakpoints (server :: , thread :: ) => (breakpoints :: ); define method current-stop-breakpoints (project :: , thread :: ) => (breakpoints :: ) let server = choose-server(project, thread); if (server) current-stop-breakpoints(server, thread); else //---*** andrewa: this used to return #f which was a type error, //---*** is it better to return the empty sequence or to change //---*** the return type? #() end if; end method; /// Implementation // Override the default caching method, because the name can change // depending on when it is accessed (it can appear as a foreign thread). define method environment-object-primitive-name (server :: , object :: ) => (name :: ) get-environment-object-primitive-name(server, object) end method environment-object-primitive-name; define method environment-object-type-name (object :: ) => (label :: ) "Application thread" end method environment-object-type-name; define method thread-stack-trace (project :: , thread :: ) => (top-frame :: ) let server = choose-server(project, thread, error?: #t); thread-stack-trace(server, thread) end method thread-stack-trace; define method thread-complete-stack-trace (project :: , thread :: ) => (stack :: ) let server = choose-server(project, thread); if (server) // Dispatch to the server to get the sequence of frames. let stack = thread-complete-stack-trace(server, thread); // Stack frame environment objects have cache slots that enable them to // reference each other. These are filled in lazily, except when this // method is called to get a complete stack trace all at once. // So, in this case, we have to fill all the cache slots in now. // Find out how many frames there are, and hence the indices in the // sequence of the first (top) frame, and the last (bottom) frame. let count = size(stack); let last = count - 1; stack[0].stack-frame-top? := #t; stack[last].stack-frame-bottom? := #t; // The stack must have at least one frame, but may conceivably // (though this will probably never happen in real life) contain // _only_ one frame, in which case 'last' is equal to zero. That's // the reason for having these two 'unless' clauses. The bodies of // these should almost always get executed, but it should also be // impossible for an array-boundary error to occur. unless (stack[0].stack-frame-bottom?) stack[0].previous-frame-cache-slot := stack[1] end unless; unless (stack[last].stack-frame-top?) stack[last].next-frame-cache-slot := stack[last - 1] end unless; // Now go through whatever frames might exist between the "top" and // "bottom" frames, linking them together via their cache slots. for (i from 1 below last) stack[i].previous-frame-cache-slot := stack[i + 1]; stack[i].next-frame-cache-slot := stack[i - 1]; end for; // And return the sequence stack else #() end if end method; define method thread-index (project :: , thread :: ) => (index :: ) let server = choose-server(project, thread, error?: #t); thread-index(server, thread) end method; define method thread-state (project :: , thread :: ) => (state :: ) let server = choose-server(project, thread); if (server) thread-state(server, thread) else #"obsolete" end if end method; define method create-application-thread (project :: , title :: ) => (thread :: ) let application = project.project-application; if (application) create-application-thread(application, title) else error(make(, format-string: "Attempting to create thread from closed application")) end end method; define method suspend-application-thread (project :: , thread :: ) => () let server = choose-server(project, thread, error?: #t); suspend-application-thread(server, thread) end method; define method resume-application-thread (project :: , thread :: ) => () let server = choose-server(project, thread, error?: #t); resume-application-thread(server, thread) end method; define method step-application-out (project :: , thread :: , #key stack-frame = #f) => () let server = choose-server(project, thread); if (server) step-application-out(server, thread, stack-frame: stack-frame) end if end method; define method step-application-over (project :: , thread :: , #key stack-frame = #f) => () let server = choose-server(project, thread); if (server) step-application-over(server, thread, stack-frame: stack-frame) end if end method; define method step-application-into (project :: , thread :: ) => () let server = choose-server(project, thread); if (server) step-application-into(server, thread) end if end method; define method application-just-hit-dylan-error? (project :: , thread :: ) => (dylan-error? :: ) let server = choose-server(project, thread); server & application-just-hit-dylan-error?(server, thread); end method; define method application-just-hit-error? (project :: , thread :: ) => (error? :: ) let server = choose-server(project, thread); server & application-just-hit-error?(server, thread); end method; define method application-just-hit-breakpoint? (project :: , thread :: ) => (breakpoint? :: ) let server = choose-server(project, thread); server & application-just-hit-breakpoint?(server, thread); end method; define method application-just-interacted? (project :: , thread :: ) => (interacted? :: ) let server = choose-server(project, thread); server & application-just-interacted?(server, thread); end method; define method application-just-stepped? (project :: , thread :: ) => (stepped? :: ) let server = choose-server(project, thread); server & application-just-stepped?(server, thread); end method; define method thread-current-interactor-level (project :: , thread :: ) => (level :: ) let server = choose-server(project, thread); if (server) thread-current-interactor-level(server, thread) else 0 end if end method; define method add-application-object-to-thread-history (project :: , thread :: , application-object :: ) => (varname :: false-or()) let server = choose-server(project, thread); server & add-application-object-to-thread-history (server, thread, application-object) end method; define method application-default-interactor-thread (project :: ) => (thread :: false-or()) let application = project.project-application; application & application.application-default-interactor-thread end method;