Module: dfmc-definitions 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 //// The boot framework. // The boot-record records the set of things that must be inserted into // a Dylan world at the very start. Some of things are core definitions // such as converters and macros, and these are booted at the definition // level. The rest are expressed as source to be fed to the compiler. define class () constant slot booted-set-keys :: = make(
); constant slot booted-set-order :: = make(); end class; define method register-thunk-in (set :: , thunk) => () // If it exists already, place where it was before. Otherwise append let key-table = booted-set-keys(set); let order = booted-set-order(set); let key = thunk-name(thunk); let posn = element(key-table, key, default: #f); if (posn) // signal("Redefining thunk for %=.", key); order[posn] := thunk; else element(key-table, key) := size(order); add!(order, thunk); thunk end; end method; define class () constant slot booted-namespace-thunks :: = make(); constant slot booted-expander-thunks :: = make(); constant slot booted-definition-thunks :: = make(); constant slot booted-source-thunks :: = make(); slot booted-constant-names :: = make(); end class; define abstract class () constant slot thunk-name, required-init-keyword: name:; end class; define class () constant slot thunk-definition-constructor, required-init-keyword: definition-constructor:; end class; define method thunk-definition (thunk :: ) thunk-definition-constructor(thunk)() end method; define class () constant slot thunk-source-constructor, required-init-keyword: source-constructor:; end class; define constant *boot-record* = make(); define method register-definition-thunk (booted-thunks, thunk) => () let record = *boot-record*; register-thunk-in(record.booted-thunks, thunk); end method; define method register-source-thunk (thunk) => () let record = *boot-record*; register-thunk-in(record.booted-source-thunks, thunk); end method; define function find-definition-thunk (booted-thunks, name) => (thunk) let record = *boot-record*; let pos = element(record.booted-thunks.booted-set-keys, name, default: #f); pos & element(record.booted-thunks.booted-set-order, pos) end function; define method register-constant-variable-name (name) => () let record = *boot-record*; booted-constant-names(record) := add-new!(booted-constant-names(record), name); end method; define method booted-constant-definitions () => (definitions) map(dylan-definition, booted-constant-names(*boot-record*)); end method; define method booted-source-sequence () => (sources) let record = *boot-record*; map-as(, method (thunk) thunk-source-constructor(thunk)() end, record.booted-source-thunks.booted-set-order) end method; define method booted-definition-sequence () => (definitions) let record = *boot-record*; local method definitions-of (thunks) map-as(, thunk-definition, thunks.booted-set-order) end; local method installed-definitions-of (thunks) map-as(, method (thunk) let form = thunk-definition(thunk); install-top-level-form(form); form end, thunks.booted-set-order) end; concatenate!(definitions-of(record.booted-namespace-thunks), installed-definitions-of(record.booted-expander-thunks), definitions-of(record.booted-definition-thunks)) end method; //// Booted definitions //// Database support // The class of forms which are always defined in the compiler image rather // than being stored in a database. // Not every form which is booted via the boot record is a // , only ones which contain stuff that can't be stored // in a database. For example namespaces and booted constant definitions // are stored in the database in the ordinary way. define class () constant slot booted-form-boot-id :: , required-init-keyword: boot-id:; end class; define class () constant slot dood-proxy-booted-form-boot-id :: , required-init-keyword: boot-id:; constant slot dood-proxy-booted-form-parent :: , required-init-keyword: parent:; constant slot dood-proxy-booted-form-sequence-number :: , required-init-keyword: sequence-number:; end class; define method dood-make-booted-form-proxy (dood :: , form :: ) => (proxy) make(, boot-id: form.booted-form-boot-id, parent: form.form-parent-form, sequence-number: form.form-sequence-number); end method; define method dood-disk-object (dood :: , form :: ) => (proxy :: ) assert(dylan-library-library-description?(dood.dood-root)); dood-as-proxy(dood, form, dood-make-booted-form-proxy) end method; define method dood-restore-proxy (dood :: , proxy :: ) => (object) dood-restore-compiler-booted-proxy(dood, proxy, booted-definition-thunks) end method; define function dood-restore-compiler-booted-proxy (dood :: , proxy :: , booted-thunks) let thunk = find-definition-thunk(booted-thunks, proxy.dood-proxy-booted-form-boot-id); assert(thunk, "Dylan database/compiler version mismatch"); let sequence-number = proxy.dood-proxy-booted-form-sequence-number; let parent = proxy.dood-proxy-booted-form-parent; with-dood-context (dood-root(dood)) with-boot-form-creation (sequence-number of parent) let form = thunk-definition(thunk); form.form-parent-form := parent; // TODO: Really should preserve who-calls info in the DB. // For now, at least ensure dependency tracking knows the dep info is gone form.form-stripped? := #t; // form.form-dependencies := proxy.... // form.form-referenced-variables := proxy.... form end with-boot-form-creation; end with-dood-context; end function; // Boot definitions define method do-define-core-instance (boot-name, class-name, value) local method boot-instance () define-booted-constant (make-variable-name-fragment(boot-name), make-variable-name-fragment(class-name), value); end; register-constant-variable-name(boot-name); register-definition-thunk (booted-definition-thunks, make(, name: boot-name, definition-constructor: boot-instance)); end method; define method do-define-core-library (boot-name, name, clauses) local method boot-library () apply(define-parsed-library, name, clauses); end; register-definition-thunk (booted-namespace-thunks, make(, name: boot-name, definition-constructor: boot-library)); local method boot-library-model () let library = dylan-library(); let definition = namespace-definition(library); generate-initializer-source-with-namespace(definition, library) end; register-source-thunk (make(, name: boot-name, source-constructor: boot-library-model)); end method; define method do-define-core-module (boot-name, name, clauses) local method boot-module () apply(define-parsed-module, name, clauses) end; register-definition-thunk (booted-namespace-thunks, make(, name: boot-name, definition-constructor: boot-module)); local method boot-module-model () let module = lookup-module-in(dylan-library(), name); let definition = namespace-definition(module); generate-initializer-source-with-namespace(definition, module) end; register-source-thunk (make(, name: boot-name, source-constructor: boot-module-model)); end method; define dood-class () /* abstract */ weak slot form-macro-object, required-init-keyword: macro-object:; weak slot form-expander, required-init-keyword: expander:; // set by initalize method. lazy slot form-macro-word; lazy slot form-macro-word-class; end; define method form-compile-stage-only? (form :: ) => (compile-stage-only?) #t end method; define method initialize (definition :: , #key) next-method(); let compiled-macro = form-macro-object(definition); let (word, word-class) = macro-word-in-variable-name (compiled-macro, form-variable-name(definition).fragment-identifier); definition.form-macro-word := word; definition.form-macro-word-class := word-class; end method; define /* abstract */ class <&definition> (, ) end; define class () end; define method dood-make-booted-form-proxy (dood :: , form :: <&definition>) => (proxy) make(, boot-id: form.booted-form-boot-id, parent: form.form-parent-form, sequence-number: form.form-sequence-number); end method; define method dood-restore-proxy (dood :: , proxy :: ) => (object) dood-restore-compiler-booted-proxy(dood, proxy, booted-expander-thunks) end method; define method do-define-core-entity (name, klass, word, word-class, macro-object, expander) => () local method definition-constructor () make(klass, boot-id: name, source-location: #f, adjectives: #(), variable-name: make-variable-name-fragment(name), macro-object: macro-object, expander: expander) end; register-definition-thunk (booted-expander-thunks, make(, name: name, definition-constructor: definition-constructor)); end method; define class <¯o-definition> (<&definition>) end; define method initialize (definition :: <¯o-definition>, #key) next-method(); // TODO: If it may use procedural templates, ensure that the result // is a parsed body in the correct hygiene context. This is a hygiene // workaround. form-expander(definition) := compose(as-body, form-expander(definition)); end method; define method do-define-core-macro (name, word, word-class, macro-object, expander) => () do-define-core-entity (name, <¯o-definition>, word, word-class, macro-object, expander); end method; define class <&converter-definition> (<&definition>) end; define method do-define-core-converter (name, word, word-class, macro-object, expander) => () do-define-core-entity (name, <&converter-definition>, word, word-class, macro-object, expander); end method; define class <&definition-definition> (<&definition>) end; define method do-define-core-definition (name, word, word-class, macro-object, expander) => () do-define-core-entity (name, <&definition-definition>, word, word-class, macro-object, expander); end method; define constant *evaluator-overrides* = make(
); define method do-define-evaluator-override (name, function) => () *evaluator-overrides*[name] := function; end; // Open so can map iep -> function in modeling. define compiler-open generic lookup-compile-stage-function (model-object) => (function :: false-or()); define method lookup-compile-stage-function (accessor) => (function :: false-or()) lookup-override-function(*evaluator-overrides*, accessor) end method; define method booted-module? (module :: ) #f end; define method booted-module? (module :: ) let cr = form-compilation-record(namespace-definition(module)); let ld = compilation-record-library(cr); dylan-library-library-description?(ld) & cr == ld.compilation-context-records[0] end; define method lookup-override-function (table :: , binding :: ) => (fn :: false-or()) booted-module?(binding.binding-home) & element(table, binding.binding-identifier, default: #f) end; define method lookup-override-function (table :: , model :: ) => (fn :: false-or()) when (model) let binding = model-variable-binding(model); binding & lookup-override-function(table, binding); end; end; //// Booted primitives define method maybe-blat-model-value (defn :: ) let binding = form-variable-binding(defn); binding & untracked-retract-binding-model-object(binding) end method; define method do-define-core-primitive (name, adjectives, value, signature) let initargs = parse-primitive-adjectives(name, adjectives); let variable = make-variable-name-fragment(name); local method primitive-constructor () let definition = apply(make, , boot-id: name, source-location: #f, variable-name: variable, adjectives: adjectives, signature: signature, value: value, initargs); maybe-blat-model-value(definition); definition end; register-definition-thunk (booted-definition-thunks, make(, name: name, definition-constructor: primitive-constructor)); end method; //// The top type define /* abstract */ class () end class; define method form-compile-stage-only? (form :: ) => (compile-stage-only?) #t end method; define class () end class; define function do-define-top-type (name) local method definition-constructor () make(, source-location: #f, variable-name: make-variable-name-fragment(name), adjectives: #()); end; register-definition-thunk (booted-definition-thunks, make(, name: name, definition-constructor: definition-constructor)); end; //// The bottom type define class () end class; define function do-define-bottom-type (name) local method definition-constructor () make(, source-location: #f, variable-name: make-variable-name-fragment(name), adjectives: #()); end; register-definition-thunk (booted-definition-thunks, make(, name: name, definition-constructor: definition-constructor)); end; //// Booted raw-types define class (, ) constant slot form-supertype-name, required-init-keyword: supertype-name:; constant slot form-raw-type-descriptor-function :: , required-init-keyword: descriptor-function:; end class; define function do-define-raw-type (name, supertype-name, descriptor-function) local method definition-constructor () let definition = make(, boot-id: name, source-location: #f, variable-name: make-variable-name-fragment(name), supertype-name: supertype-name & make-variable-name-fragment(supertype-name), descriptor-function: descriptor-function, adjectives: #()); maybe-blat-model-value(definition); definition end; register-definition-thunk (booted-definition-thunks, make(, name: name, definition-constructor: definition-constructor)); end; //// Booted classes. define method do-define-core-unadorned-definition (name, constructor :: ) => () register-source-thunk (make(, name: name, source-constructor: constructor)); end method; //// for raw structs // it's not really booted, but it's closer to anything her than anything else define /* abstract */ class () constant slot form-members, required-init-keyword: members:; constant slot form-options, required-init-keyword: options:; end; define class () end class; define &definition raw-struct-type-definer { define raw-struct-type ?:name ?root-name:name (?options:*) ?members:* end} => do-define-raw-aggregate (, name, root-name, members, options); members: { } => #(); { ?member:*; ...} => pair(member, ...); member: { member ?:name } => list(#"member", name); { bitfield-member ?:name ?width:expression } => list(#"bitfield-member", name, width); { array-member ?:name ?length:expression } => list(#"array-member", name, length); options: { } => #(); { ?option:expression, ... } => pair(option, ...); end; define function do-define-raw-aggregate (class, name, root-name, member-fragments, options) list(make(class, source-location: fragment-source-location(root-name), variable-name: name, adjectives: #(), members: member-fragments, options: options)); end; define class () end class; define &definition raw-union-type-definer { define raw-union-type ?:name ?root-name:name (?options:*) ?members:* end} => do-define-raw-aggregate (, name, root-name, members, options); members: { } => #(); { ?member:*; ...} => pair(member, ...); member: { member ?:name } => list(#"member", name); { array-member ?:name ?length:expression } => list(#"array-member", name, length); options: { } => #(); { ?option:expression, ... } => pair(option, ...); end; // eof