Module: environment-protocols Synopsis: Environment protocols Author: Andy Armstrong, Jason Trenouth, Roman Budzianowski 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 /// Project objects define constant = one-of(#"compiler", #"application", #"both"); define constant $first-numeric-id = 10000; define open abstract primary class (, ) slot project-proxy = #f, init-keyword: proxy:; sealed slot project-application :: false-or() = #f, init-keyword: application:; sealed slot project-compiler-database :: false-or() = #f, init-keyword: compiler-database:; sealed slot project-next-numeric-id :: = $first-numeric-id; constant sealed slot project-object-table :: = make-object-cache(); constant sealed slot project-query-database ::
= make-object-cache(); sealed slot project-server-path :: = #"compiler", init-keyword: server-path:; constant sealed slot environment-object-breakpoints :: = make(
); constant sealed slot source-location-breakpoints :: = make(); sealed slot project-properties :: = #(); constant sealed slot project-profile-state :: = make(); end class ; define open generic server-project (server :: ) => (project :: ); define open generic project-proxy (project :: ) => (proxy); define open generic project-application (project :: ) => (application :: false-or()); define open generic project-compiler-database (project :: ) => (compiler-database :: false-or()); define open generic project-database-changed?(project :: ) => (yes? :: ); define open generic project-sources-changed?(project :: ) => (yes? :: ); // open-project should attempt to open an existing project define open generic open-project (locator :: ) => (project :: false-or()); // find-project should either find the project in the work space, or open // a project if not found. define open generic find-project (name :: ) => (project :: false-or()); // new-project should create new user project, let's change the name to reflect this define open generic create-new-user-project (name :: , location :: ) => (project :: false-or()); // accordingly, new-project-from-file doesn't make sense, // let's change the name define open generic open-project-from-file (locator :: ) => (project :: false-or()); define open generic create-exe-project-from-file (locator :: ) => (project :: false-or()); define open generic import-project-from-file (locator :: , #key filename) => (project :: false-or()); define open generic close-project (project :: ) => (); define open generic open-projects () => (projects :: ); define open generic project-opened-by-user? (project :: ) => (by-user? :: ); define open generic project-opened-by-user?-setter (by-user? :: , project :: ) => (by-user? :: ); define open generic project-read-only? (project :: ) => (read-only? :: ); define open generic project-can-be-built? (project :: ) => (can-be-built? :: ); define open generic project-can-be-debugged? (project :: ) => (can-be-debugged? :: ); define open generic project-compiled? (project :: ) => (compiled? :: ); define open generic project-sources (project :: , #key) => (sources :: ); define open generic project-start-function-name (project :: ) => (name :: false-or()); define open generic project-start-function-name-setter (name :: false-or(), project :: ) => (name :: false-or()); define open generic project-canonical-sources (project :: ) => (sources :: ); define open generic project-other-sources (project :: , #key) => (sources :: ); define open generic project-directory (project :: ) => (directory :: ); define open generic project-filename (project :: ) => (filename :: false-or()); define open generic project-build-filename (project :: ) => (filename :: false-or()); define open generic project-build-filename-setter (filename :: , project :: ) => (filename :: ); define open generic project-debug-filename (project :: ) => (filename :: false-or()); define open generic project-debug-filename-setter (filename :: false-or(), project :: ) => (filename :: false-or()); define open generic project-debug-arguments (project :: ) => (arguments :: ); define open generic project-debug-arguments-setter (arguments :: , project :: ) => (arguments :: ); define open generic project-debug-machine-address (project :: ) => (name :: false-or()); define open generic project-debug-machine-address-setter (name :: false-or(), project :: ) => (name :: false-or()); define open generic project-debug-machine (project :: ) => (machine :: false-or()); define open generic project-debug-machine-setter (machine :: false-or(), project :: ) => (machine :: false-or()); define open generic project-debug-directory (project :: ) => (directory :: false-or()); define open generic project-debug-directory-setter (directory :: false-or(), project :: ) => (directory :: false-or()); define open generic project-build-directory (project :: ) => (directory :: false-or()); define open generic project-bin-directory (project :: ) => (directory :: ); define open generic project-release-directory (project :: ) => (directory :: ); define open generic project-add-source-record (project :: , record :: ) => (); define open generic project-remove-source-record (project :: , record :: ) => (); define open generic project-reorder-source-records (project :: , compare-function :: ) => (); define open generic save-project (project :: , #key save-database? :: = #f, filename :: false-or() = #f) => (); define open generic save-project-database (project :: ) => (); define open generic do-project-used-libraries (function :: , server :: , project :: ) => (); define open generic do-project-file-libraries (function :: , server :: , file :: ) => (); define open generic do-used-projects (function :: , project :: , #key indirect?, read-only?) => (); define open generic project-bind-variable (server :: , variable-name :: , object :: , #key module) => (success? :: ); /// Project property protocols define constant = one-of(#"loose", #"tight"); define constant = one-of(#"harp", #"c"); define constant = one-of(#"executable", #"dll"); define constant = one-of(#"console", #"gui"); define open generic session-property (key :: ) => (value); define open generic session-property-setter (value, key :: ) => (value); define open generic project-compilation-mode (project :: ) => (mode :: ); define open generic project-compilation-mode-setter (mode :: , project :: ) => (mode :: ); define open generic project-compiler-back-end (project :: ) => (back-end :: ); define open generic project-compiler-back-end-setter (back-end :: , project :: ) => (back-end :: ); define open generic project-target-type (project :: ) => (target-type :: ); define open generic project-target-type-setter (target-type :: , project :: ) => (target-type :: ); define open generic project-interface-type (project :: ) => (interface-type :: ); define open generic project-interface-type-setter (interface-type :: , project :: ) => (interface-type :: ); define open generic project-base-address (project :: ) => (address :: false-or()); define open generic project-base-address-setter (address :: false-or(), project :: ) => (address :: false-or()); define open generic project-major-version (project :: ) => (version :: ); define open generic project-major-version-setter (version :: , project :: ) => (version :: ); define open generic project-minor-version (project :: ) => (version :: ); define open generic project-minor-version-setter (version :: , project :: ) => (version :: ); /// File extensions define function environment-locator-type (locator :: ) => (type :: false-or()) let extension = locator.locator-extension; if (extension) //---*** Shouldn't use \= on the extension... select (as-lowercase(extension) by \=) project-file-extension() => #"hdp"; lid-file-extension() => #"lid"; dylan-file-extension(), "dyl" => #"dylan"; executable-file-extension() => #"exe"; "htm", "html" => #"html"; otherwise => as(, extension); end end end function environment-locator-type; define open generic project-file-extension () => (extension :: ); define open generic lid-file-extension () => (extension :: ); define open generic dylan-file-extension () => (extension :: ); define open generic executable-file-extension () => (extension :: ); /// Current project handling define variable *current-project* :: false-or() = #f; define function current-project () => (project :: false-or()) *current-project* end function current-project; define function current-project-setter (project :: false-or()) => (project :: false-or()) *current-project* := project end function current-project-setter; /// project building define open generic open-project-compiler-database (project :: , #key warning-callback, error-handler) => (database :: false-or()); define open generic parse-project-source (project :: , #key warning-callback, progress-callback, error-handler, process-subprojects?) => (well? :: ); define open generic build-project (project :: , #key clean?, link?, release?, output, warning-callback, progress-callback, error-handler, save-databases?, copy-sources?, process-subprojects?, messages) => (built? :: ); define open generic remove-project-build-products (project :: , #key error-handler, process-subprojects?) => (); define open generic link-project (project :: , #key progress-callback, error-handler, process-subprojects?, build-script, target, force?, unify?, release?, messages) => (); define open generic default-build-script () => (build-script :: ); define open generic default-build-script-setter (build-script :: ) => (build-script :: ); /// Source records //---*** Maybe subsumed by do-project-file-libraries define open generic find-project-source-record (project :: , filename :: ) => (record :: false-or()); define open generic find-source-record-library (project :: , record :: ) => (library :: false-or()); define open generic source-record-projects (source-record :: ) => (projects :: ); // The return type is unspecified because it may change if the info moves // to compiler databases, or be different for non-file source records. define open generic source-record-colorization-info (project :: , source-record :: ) => (info /* :: false-or() */); /// Source editing // this gf has to take a server, because // is an abstract type and we may have to do some processing define open generic edit-source-location (server :: , source-location :: ) => (); define open generic edit-source-record (server :: , source-record :: , #key start-line, start-column, end-line, end-column) => (); define open generic edit-definition (server :: , object :: ) => (found-definition? :: ); /// Top level forms define open generic source-record-top-level-forms (server :: , sr :: , #key project) => (source-forms :: ); /// Some project implementation define function project-name (project :: ) => (name :: ) environment-object-primitive-name(project, project) end function project-name; define function project-full-build-filename (project :: ) => (pathname :: ) let bin-directory = project.project-bin-directory; let filename = project.project-build-filename; merge-locators(filename, bin-directory) end function project-full-build-filename; define function project-used-projects (project :: , #key indirect?, read-only?) => (projects :: ) let projects = make(); do-used-projects (method (project :: ) add!(projects, project) end, project, indirect?: indirect?, read-only?: read-only?); projects end function project-used-projects; define method open-project (locator :: ) => (project :: false-or()) select (locator.environment-locator-type) #"exe" => create-exe-project-from-file(locator); #"hdp", #"lid", #"ddb" => open-project-from-file(locator); otherwise => error("Internal error: open-project called on '%s' with non-project extension %=", locator, locator.locator-extension); end end method open-project; define method server-project (project :: ) => (project :: ) project end method server-project; define method environment-object-type-name (object :: ) => (label :: ) "Project" end method environment-object-type-name; /// Project query database handling define method record-client-query (project :: , client, object :: , type :: ) => () ignore(type); let database = project-query-database(project); let clients = element(database, object, default: #f) | (element(database, object) := make()); add-new!(clients, client) end method record-client-query; define method note-object-properties-changed (project :: , object :: , type :: ) => () let clients = element(project-query-database(project), object, default: #()); for (client in clients) note-object-properties-changed(client, object, type) end end method note-object-properties-changed; /// Id caching // // Note that only unique ids are cached define method lookup-environment-object-by-id (project :: , id :: ) => (object :: false-or()) #f end method lookup-environment-object-by-id; define method cache-environment-object-with-id (project :: , id :: , object :: ) => (object :: ) object end method cache-environment-object-with-id; define method lookup-environment-object-by-id (project :: , id :: ) => (object :: false-or()) let table = project-object-table(project); element(table, id, default: #f) end method lookup-environment-object-by-id; define method cache-environment-object-with-id (project :: , id :: , object :: ) => (object :: ) let table = project-object-table(project); element(table, id) := object end method cache-environment-object-with-id; define method lookup-environment-object-by-id (project :: , id :: ) => (object :: false-or()) let table = project-object-table(project); element(table, id, default: #f) end method lookup-environment-object-by-id; define method cache-environment-object-with-id (project :: , id :: , object :: ) => (object :: ) let table = project-object-table(project); element(table, id) := object end method cache-environment-object-with-id; /// Lookup environment object define sealed generic lookup-environment-object (class :: subclass(), #key project :: , id :: false-or(), application-object-proxy, compiler-object-proxy) => (object :: false-or(), id :: false-or()); define method lookup-environment-object (class :: subclass(), #key project :: , id :: false-or(), application-object-proxy: proxy, compiler-object-proxy) => (object :: false-or(), id :: false-or()) ignore(compiler-object-proxy); let application = project-application(project); let object-for-proxy = proxy & lookup-environment-object-by-proxy(application, proxy); case object-for-proxy => let id = id | environment-object-id(project, object-for-proxy); values(object-for-proxy, id); subtype?(class, ) => let id = id | application-proxy-id(application, proxy); if (id) values(lookup-environment-object-by-id(project, id), id) else values(#f, generate-unique-id(project)) end; otherwise => values(#f, #f); end end method lookup-environment-object; define method lookup-environment-object (class :: subclass(), #key project :: , id :: false-or(), application-object-proxy, compiler-object-proxy: proxy) => (object :: false-or(), id :: false-or()) ignore(application-object-proxy); let database = project-compiler-database(project); let object-for-proxy = proxy & lookup-environment-object-by-proxy(database, proxy); case object-for-proxy => let id = id | environment-object-id(project, object-for-proxy); values(object-for-proxy, id); subtype?(class, ) => let id = id | compiler-database-proxy-id(database, proxy); if (id) values(lookup-environment-object-by-id(project, id), id) else values(#f, generate-unique-id(project)) end; otherwise => values(#f, #f); end end method lookup-environment-object; define method lookup-environment-object (class :: subclass(), #key project :: , id :: false-or(), application-object-proxy, compiler-object-proxy) => (object :: false-or(), id :: false-or()) let application = project-application(project); let database = project-compiler-database(project); block (return) local method maybe-return (object) => () object & return(object, id | environment-object-id(project, object)) end method maybe-return; maybe-return (application & application-object-proxy & lookup-environment-object-by-proxy(application, application-object-proxy)); maybe-return (database & compiler-object-proxy & lookup-environment-object-by-proxy(database, compiler-object-proxy)); if (subtype?(class, )) let id = case id => id; application-object-proxy => application-proxy-id(application, application-object-proxy); compiler-object-proxy => compiler-database-proxy-id(database, compiler-object-proxy); otherwise => error("lookup-environment-object called with no id or proxies"); end; if (id) values(lookup-environment-object-by-id(project, id), id) else values(#f, generate-unique-id(project)) end else values(#f, #f) end end end method lookup-environment-object; /// Numeric id handling define sealed method generate-unique-id (project :: ) => (id :: ) //---*** This needs to be thread safe... let number = project.project-next-numeric-id; project.project-next-numeric-id := number + 1; number end method generate-unique-id; /// Project object interning define sealed generic make-environment-object (class :: subclass(), #key project :: , library :: false-or(), id :: false-or(), application-object-proxy, compiler-object-proxy) => (object :: ); define method make-environment-object (class :: subclass(), #rest args, #key project :: , library :: false-or(), id :: false-or(), application-object-proxy: proxy, compiler-object-proxy) => (object :: ) ignore(compiler-object-proxy); let application = project-application(project); debug-assert(application, "Project %= has no application", project); debug-assert(id | proxy, "make-environment-object called with no id or proxy"); let (object, id) = lookup-environment-object (class, project: project, id: id, application-object-proxy: proxy); let object = if (instance?(object, class)) let old-proxy = application-object-proxy(object); debug-assert(~old-proxy | old-proxy == proxy, "Environment object %= found for two proxies: %=, %=", object, old-proxy, proxy); application-object-proxy(object) := proxy; object else make(class, application-object-proxy: proxy, id: id, library: library) end; id & cache-environment-object-with-id(project, id, object); cache-environment-object(application, proxy, object) end method make-environment-object; define method make-environment-object (class :: subclass(), #rest args, #key project :: , library :: false-or(), id :: false-or(), application-object-proxy, compiler-object-proxy: proxy) => (object :: ) ignore(application-object-proxy); let database = project-compiler-database(project); debug-assert(database, "Project %= has no compiler database %=", project); debug-assert(id | proxy, "make-environment-object called with no id or proxy"); let (object, id) = lookup-environment-object (class, project: project, id: id, compiler-object-proxy: proxy); let object = if (instance?(object, class)) let old-proxy = compiler-object-proxy(object); /*---*** Need to work out why this fails sometimes... debug-assert(~old-proxy | old-proxy == proxy, "Environment object %= found for two proxies: %=, %=", object, old-proxy, proxy); */ unless (~old-proxy | old-proxy == proxy) debug-message("Environment object %= found for two proxies: %=, %=", object, old-proxy, proxy) end; compiler-object-proxy(object) := proxy; object else make(class, compiler-object-proxy: proxy, id: id, library: library) end; id & cache-environment-object-with-id(project, id, object); cache-environment-object(database, proxy, object) end method make-environment-object; define method make-environment-object (class :: subclass(), #rest args, #key project :: , library :: false-or(), id :: false-or(), application-object-proxy, compiler-object-proxy) => (object :: ) let application = project-application(project); let database = project-compiler-database(project); let (object, id) = lookup-environment-object (class, project: project, id: id, application-object-proxy: application-object-proxy, compiler-object-proxy: compiler-object-proxy); let object = if (instance?(object, class)) object else make(class, application-object-proxy: application-object-proxy, compiler-object-proxy: compiler-object-proxy, id: id, library: library) end; id & cache-environment-object-with-id(project, id, object); if (application & application-object-proxy) cache-environment-object(application, application-object-proxy, object) end; if (database & compiler-object-proxy) cache-environment-object(database, compiler-object-proxy, object) end; if (application-object-proxy) application-object-proxy(object) := application-object-proxy end; if (compiler-object-proxy) compiler-object-proxy(object) := compiler-object-proxy end; object end method make-environment-object; /// Server handling define sealed generic choose-server (project :: , object :: , #key error?, default-server) => (server :: false-or()); define method ensure-application-server (project :: , object :: , #key error?) => (application :: false-or()) let application = project-application(project); case ~application => error? & closed-server-error(object); ensure-application-proxy(application, object) => application; invalid-object?(project, object) => invalid-object-error(project, object); otherwise => #f; end end method ensure-application-server; define method ensure-database-server (project :: , object :: , #key error?) => (database :: false-or()) let database = project-compiler-database(project); case ~database => error? & closed-server-error(object); ensure-database-proxy(database, object) => database; invalid-object?(project, object) => invalid-object-error(project, object); otherwise => #f; end end method ensure-database-server; define method choose-server (project :: , object :: , #key error?, default-server) => (server :: false-or()) ignore(default-server); ensure-application-server(project, object, error?: error?) end method choose-server; define method choose-server (project :: , object :: , #key error?, default-server) => (server :: false-or()) ignore(default-server); ensure-database-server(project, object, error?: error?) end method choose-server; define method choose-server (project :: , object :: , #key error?, default-server) => (server :: false-or()) let database = project-compiler-database(project); let application = project-application(project); local method maybe-application () => (application :: false-or()) ensure-application-proxy(application, object) & application end method maybe-application; local method maybe-compiler-database () => (database :: false-or()) ensure-database-proxy(database, object) & database end method maybe-compiler-database; let server = case database & application => let server-path = default-server | project-server-path(project); select (server-path) #"compiler" => maybe-compiler-database() | maybe-application(); #"application" => maybe-application() | maybe-compiler-database(); // #"both" => ???; otherwise => unknown-server-path-error(server-path); end; database => maybe-compiler-database(); application => maybe-application(); otherwise => #f; end; case ~database & ~application => error? & closed-server-error(object); server => server; invalid-object?(project, object) => invalid-object-error(project, object); otherwise => #f; end end method choose-server; define method environment-object-home-server? (project :: , object :: ) => (home? :: ) let application = project-application(project); application & environment-object-home-server?(application, object) end method environment-object-home-server?; define method environment-object-home-server? (project :: , object :: ) => (home? :: ) let database = project-compiler-database(project); database & environment-object-home-server?(database, object) end method environment-object-home-server?; define method environment-object-home-server? (project :: , object :: ) => (home? :: ) let database = project-compiler-database(project); let application = project-application(project); (database & environment-object-home-server?(database, object)) | (application & environment-object-home-server?(application, object)) end method environment-object-home-server?; /// Environment object existence define method environment-object-exists? (project :: , object :: ) => (exists? :: ) #t end method environment-object-exists?; define method environment-object-exists? (project :: , object :: ) => (exists? :: ) application-object-exists?(project, object) end method environment-object-exists?; define method environment-object-exists? (project :: , object :: ) => (exists? :: ) compiler-object-exists?(project, object) end method environment-object-exists?; define method environment-object-exists? (project :: , object :: ) => (exists? :: ) compiler-object-exists?(project, object) | application-object-exists?(project, object) end method environment-object-exists?; define method application-object-exists? (project :: , object :: ) => (exists? :: ) let application = project-application(project); application & ensure-application-proxy(application, object) & #t end method application-object-exists?; define method compiler-object-exists? (project :: , object :: ) => (exists? :: ) let database = project-compiler-database(project); database & ensure-database-proxy(database, object) & #t end method compiler-object-exists?; define method invalid-object? (project :: , object :: ) => (invalid? :: ) ~application-object-proxy(object) end method invalid-object?; define method invalid-object? (project :: , object :: ) => (invalid? :: ) ~compiler-object-proxy(object) end method invalid-object?; define method invalid-object? (project :: , object :: ) => (invalid? :: ) ~application-object-proxy(object) & ~compiler-object-proxy(object) end method invalid-object?; /// Closed server errors define function unknown-server-path-error (server-path :: ) error("Server path %= not known!", server-path) end function unknown-server-path-error; define method closed-server-error (object :: ) error(make(, format-string: "Attempting to query %= from closed application", format-arguments: vector(object))) end method closed-server-error; define method closed-server-error (object :: ) error(make(, format-string: "Attempting to query %= from closed project", format-arguments: vector(object))) end method closed-server-error; define method closed-server-error (object :: ) error(make(, format-string: "Attempting to query %= from closed application or project", format-arguments: vector(object))) end method closed-server-error; define function invalid-object-error (project :: , object :: ) error(make(, format-string: "Querying obsolete object %=", format-arguments: vector(object), project: project, object: object)) end function invalid-object-error; /// Environment objects define method get-environment-object-primitive-name (project :: , object :: ) => (name :: false-or()) let server = choose-server(project, object); server & get-environment-object-primitive-name(server, object) end method get-environment-object-primitive-name; define method environment-object-source (project :: , object :: ) => (source :: false-or()) let server = choose-server(project, object); server & environment-object-source(server, object) end method environment-object-source; /// Application objects define method invalidate-application-proxy (project :: , object :: ) => () //--- Note that we don't bother removing this object from the //--- cache because it is a weak table so the GC will do it //--- for us more efficiently. application-object-proxy(object) := #f end method invalidate-application-proxy; /// Compiler objects define method invalidate-compiler-proxy (project :: , object :: ) => () //--- Note that we don't bother removing this object from the //--- cache because it is a weak table so the GC will do it //--- for us more efficiently. compiler-object-proxy(object) := #f end method invalidate-compiler-proxy; /// Source record stuff define method source-record-top-level-forms (project :: , sr :: , #key project: subproject) => (source-forms :: ) let database = project-compiler-database(project); if (database) source-record-top-level-forms(database, sr, project: subproject) else #[] end end method source-record-top-level-forms; define method source-record-projects (record :: ) => (projects :: ) let projects = make(); let filename = source-record-location(record); for (project in open-projects()) let records = project-sources(project); if (member?(filename, records, test: method (filename :: , record :: ) => (true?) filename = source-record-location(record) end)) add!(projects, project) end end; projects; end method source-record-projects; define method source-record-projects (record :: ) => (projects :: ) vector(source-record-project(record)) end method; //---*** This version doesn't deal with links, we probably shouldn't have this at all. //---*** The emulator has its own version of this... define method find-project-source-record (project :: , filename :: ) => (record :: false-or()) block (return) for (record in project-sources(project)) when (record.source-record-location = filename) return(record) end end end end method find-project-source-record; define method project-canonical-source-record (project :: , record :: ) => (canonical-record :: false-or()) let canonical-sources = project-canonical-sources(project); block (return) for (source in canonical-sources) if (source == record) return(source) end end; for (source in canonical-sources) if (source-record-name(source) = source-record-name(record)) return(source) end end end end method project-canonical-source-record; define method project-canonical-filename (project :: , file :: ) => (canonical-filename :: false-or()) if (~project-read-only?(project)) make(, directory: project.project-build-directory, base: file.locator-base, extension: file.locator-extension) end end method project-canonical-filename; /// Library handling define method do-project-used-libraries (function :: , server :: , project :: ) => () assert(server = project, "Querying used libraries for %= using different server %=", project, server); let database = project-compiler-database(project); database & do-project-used-libraries(function, database, project) end method do-project-used-libraries; define function project-used-libraries (server :: , project :: ) => (libraries :: ) collect-environment-objects(do-project-used-libraries, server, project) end function project-used-libraries; define method do-project-file-libraries (function :: , project :: , file :: ) => () let database = project-compiler-database(project); database & do-project-file-libraries(function, database, file) end method do-project-file-libraries; /// Active project define variable *active-project* :: false-or() = #f; define function active-project () => (project :: false-or()) *active-project* end function active-project; define function active-project-setter (project :: false-or()) => (project :: false-or()) *active-project* := project; let message = if (project) make(, project: project); else make() end; broadcast($project-channel, message); project end function active-project-setter; define method note-user-project-opened (project-object :: ) => () let message = make(, project: project-object); broadcast($project-channel, message); end method note-user-project-opened; /// Finding environment objects by name define method find-environment-object (project :: , id :: , #rest keys, #key, #all-keys) => (object :: false-or()) lookup-environment-object-by-id(project, id) | begin let server-path = project-server-path(project); let database = project-compiler-database(project); //---*** andrewa: don't query the application server for now let application = #f; // project-application(project); let server :: false-or() = select (server-path) #"compiler" => database | application; #"application" => application | database; // #"both" => ???; otherwise => unknown-server-path-error(server-path); end; server & apply(find-environment-object, server, id, keys) end end method find-environment-object; /// Project start function define function project-start-function (project :: ) => (function :: false-or()) let library = project-library(project); let name = project-start-function-name(project); if (library & name) let module = library-default-module(project, library); if (module) let object = find-environment-object(project, name, module: module); if (instance?(object, )) object end end end end function project-start-function; /// Debugging define method find-machine (address :: ) => (machine :: false-or()) block (return) do-machine-connections (method (machine :: ) if (address = machine-network-address(machine)) return(machine) end end, include-local?: #f); #f end end method find-machine; define method project-debug-machine (project :: ) => (machine :: false-or()) let address = project-debug-machine-address(project); if (address) find-machine(address) | block () make(, network-address: address) exception () #f end end end method project-debug-machine; define method project-debug-machine-setter (machine :: false-or(), project :: ) => (machine :: false-or()) let name = if (machine & machine ~== environment-host-machine()) machine-network-address(machine) end; project-debug-machine-address(project) := name; machine end method project-debug-machine-setter; /// Playground project /// /// This shouldn't be necessary, but the project manager lets us down ///---*** andrewa: aim to remove this one day... define constant $minimal-playground-project-name = "minimal-dylan-playground"; define constant $playground-project-name = "dylan-playground"; define constant $gui-playground-project-name = "gui-dylan-playground"; define function playground-project-name () => (name :: ) if (release-contains-library-pack?(#"GUI")) $gui-playground-project-name elseif (release-contains-library-pack?(#"Core")) $playground-project-name else $minimal-playground-project-name; end end function playground-project-name; define function find-playground-project () => (project :: false-or()) find-project(playground-project-name()) end function find-playground-project; // The "just-name?:" keyword should be passed as #t when you want to check // the playground-project-ness but the project may not have been opened // properly yet. define function playground-project? (project :: , #key just-name? :: = #f) => (playground? :: ) let project-name = environment-object-primitive-name(project, project); (just-name? | project.project-read-only?) & project-name = playground-project-name() end function playground-project?; define function playground-application-filename (project :: ) => (filename :: false-or()) let lid-filename = project.project-filename; if (lid-filename) let filename = make(, directory: lid-filename.locator-directory, name: project.project-build-filename.locator-name); debug-message("Playground filename: %s", as(, filename)); file-exists?(filename) & filename end end function playground-application-filename;