Module: internal Author: Jonathan Bachrach 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 ignore(); ignore(); ignore(environment-element); ignore(%machine-word-data); ignore(%single-float-data); ignore(%double-float-data); ignore(%%double-integer-low); ignore(%%double-integer-high); //// //// TAG CHECK //// //// | data or address | 2 tag bits | //// define constant $direct-object-classes :: = primitive-untraced-allocate (primitive-machine-word-multiply-low (primitive-word-size(), integer-as-raw(4))); define constant $direct-object-mm-wrappers :: = primitive-untraced-allocate (primitive-machine-word-multiply-low (primitive-word-size(), integer-as-raw(4))); define macro tag-bits { tag-bits(?x:expression) } => { primitive-machine-word-logand(primitive-cast-pointer-as-raw(?x), integer-as-raw(3)) } end macro; define macro indirect-object-tag-bits? { indirect-object-tag-bits? (?bits:expression) } => { primitive-machine-word-equal?(?bits, integer-as-raw(0)) } end macro; /* define inline function indirect-object? (x) => (value :: ) indirect-object-tag-bits?(tag-bits(x)) end function; */ define macro indirect-object? { indirect-object? (?x:expression) } => { indirect-object-tag-bits?(tag-bits(?x)) } end macro; //// //// LOW-LEVEL COMPARISONS //// define macro pointer-id? { pointer-id?(?x:expression, ?y:expression) } => { primitive-id?(?x, ?y) } end macro; define macro value-object? { value-object?(?x:expression) } => /* { indirect-object?(?x) & pointer-id?(indirect-object-class(indirect-object-class(?x)), ) } */ { indirect-object?(?x) & logbit?(0 /* subtype bit number */, mm-wrapper-subtype-mask(indirect-object-mm-wrapper(?x))) } end macro; //// //// DIRECT OBJECTS //// define function install-direct-object-class (tag :: , class :: ) => () primitive-element($direct-object-classes, integer-as-raw(tag), integer-as-raw(0)) := class; primitive-element($direct-object-mm-wrappers, integer-as-raw(tag), integer-as-raw(0)) := class-mm-wrapper(class); end function; install-direct-object-class(0, ); //// //// | data | 01 | //// install-direct-object-class(1, ); define constant -instance? = method (x, c == ) => (well? :: ); primitive-machine-word-equal?(tag-bits(x), integer-as-raw(1)) end method; ignore(-instance?); //// //// | ascii code | 10 | //// install-direct-object-class(2, ); define constant -instance? = method (x, c == ) => (well? :: ); primitive-machine-word-equal?(tag-bits(x), integer-as-raw(2)) end method; ignore(-instance?); //// //// | ascii code | 11 | //// install-direct-object-class(3, ); define constant -instance? = method (x, c == ) => (well? :: ); primitive-machine-word-equal?(tag-bits(x), integer-as-raw(3)) end method; ignore(-instance?); // BOOTED: define ... class ... end; ignore(mm-wrapper-fixed-part); ignore(mm-wrapper-variable-part); ignore(mm-wrapper-pattern-element); define function make-mm-wrapper (implementation-class :: , fixed-part-header :: , variable-part-header :: ) let wrapper :: = system-allocate-wrapper(); wrapper.mm-wrapper-implementation-class := implementation-class; wrapper.mm-wrapper-fixed-part := integer-as-raw(fixed-part-header); wrapper.mm-wrapper-variable-part // store version 2 in high byte := primitive-machine-word-bit-field-deposit (integer-as-raw(2), integer-as-raw($machine-word-size - 8), integer-as-raw(8), integer-as-raw(variable-part-header)); // wrapper.mm-wrapper-number-patterns := 0; wrapper end function; define macro %mm-wrapper-implementation-class { %mm-wrapper-implementation-class (?instance:expression) } => { primitive-element(?instance, integer-as-raw(0), primitive-header-size()) } end macro; define macro %mm-wrapper-implementation-class-setter { %mm-wrapper-implementation-class-setter (?value:expression, ?instance:expression) } => { primitive-element(?instance, integer-as-raw(0), primitive-header-size()) := ?value } end macro; define constant $number-header-words = 1; /* define inline-only function instance-header (instance) => (value :: ) primitive-element(instance, integer-as-raw(0), integer-as-raw(0)) end function; */ define macro instance-header { instance-header (?instance:expression) } => { primitive-element(?instance, integer-as-raw(0), integer-as-raw(0)) } end macro; define inline-only function instance-header-setter (new-value :: , instance) => (value :: ) primitive-element(instance, integer-as-raw(0), integer-as-raw(0)) := new-value end function; //define macro indirect-object-mm-wrapper // { indirect-object-mm-wrapper (?instance:expression) } // => { instance-header(?instance) } //end macro; define inline-only function indirect-object-mm-wrapper (instance) => (mm-wrapper ::) let mm-wrapper :: = instance-header(instance); mm-wrapper end function; //// //// INSTANCE //// /* define inline-only function indirect-object-class (instance) => (value :: ) instance.instance-header.%mm-wrapper-implementation-class.%implementation-class-class end function; */ /// TODO: NEED SETTER //define macro indirect-object-implementation-class // { indirect-object-implementation-class (?instance:expression) } // => { %mm-wrapper-implementation-class // (indirect-object-mm-wrapper(?instance)) } //end macro; //define macro indirect-object-class // { indirect-object-class (?instance:expression) } // => { %implementation-class-class // (%mm-wrapper-implementation-class // (indirect-object-mm-wrapper(?instance))) } //end macro; define inline-only function indirect-object-implementation-class (x) => (ic :: ) let mm-wrapper :: = indirect-object-mm-wrapper(x); mm-wrapper-implementation-class(mm-wrapper) end function; define inline-only function indirect-object-class (x) => (c :: ) iclass-class(mm-wrapper-implementation-class(indirect-object-mm-wrapper(x))) end function; define macro direct-object-class-with-tag-bits { direct-object-class-with-tag-bits(?tag-bits:expression) } => { primitive-element($direct-object-classes, ?tag-bits, integer-as-raw(0)) } end macro; define inline-only function direct-object-class (instance) => (value :: ) direct-object-class-with-tag-bits(tag-bits(instance)) end function; /* define macro direct-object-class { direct-object-class(?instance:expression) } => { direct-object-class-with-tag-bits(tag-bits(?instance)) } end macro; */ define function object-class (instance) => (value :: ) let bits :: = tag-bits(instance); if (indirect-object-tag-bits?(bits)) indirect-object-class(instance) else direct-object-class-with-tag-bits(bits) end if end function; //// OBJECT-MM-WRAPPER define inline-only function direct-object-mm-wrapper-with-tag-bits (bits :: ) => (res :: ) let mm-wrapper :: = primitive-element($direct-object-mm-wrappers, primitive-unwrap-machine-word(bits), integer-as-raw(0)); mm-wrapper end function; define inline-only function direct-object-mm-wrapper (instance) => (res :: ) direct-object-mm-wrapper-with-tag-bits(primitive-wrap-machine-word(tag-bits(instance))) end function; /* define macro direct-object-mm-wrapper { direct-object-mm-wrapper (?instance:expression) } => { direct-object-mm-wrapper-with-tag-bits(tag-bits(?instance)) } end macro; define macro direct-object-mm-wrapper-with-tag-bits { direct-object-mm-wrapper-with-tag-bits(?tag-bits:expression) } => { primitive-element($direct-object-mm-wrappers, ?tag-bits, integer-as-raw(0)) } end macro; */ define inline function object-mm-wrapper (instance) => (value :: ) let bits :: = tag-bits(instance); if (indirect-object-tag-bits?(bits)) indirect-object-mm-wrapper(instance) else direct-object-mm-wrapper-with-tag-bits(primitive-wrap-machine-word(bits)) end if end function; define inline function object-implementation-class (instance) => (value :: ) let bits :: = tag-bits(instance); if (indirect-object-tag-bits?(bits)) indirect-object-implementation-class(instance) else let wrapper :: = direct-object-mm-wrapper-with-tag-bits(primitive-wrap-machine-word(bits)); mm-wrapper-implementation-class(wrapper) end if end function; //// SLOT ACCESS define inline-only function initialized-slot-element (instance, offset :: ) primitive-initialized-slot-value(instance, integer-as-raw(offset)) end function; define inline-only function slot-element (instance, offset :: ) primitive-slot-value(instance, integer-as-raw(offset)) end function; define inline-only function slot-element-setter (new-value, instance, offset :: ) primitive-slot-value(instance, integer-as-raw(offset)) := new-value end function; define inline-only function repeated-slot-element (instance, offset :: , index :: ) primitive-repeated-slot-value (instance, integer-as-raw(offset), integer-as-raw(index)) end function; define inline-only function repeated-slot-element-setter (new-value, instance, offset :: , index :: ) primitive-repeated-slot-value (instance, integer-as-raw(offset), integer-as-raw(index)) := new-value end function; define inline-only function byte-slot-element (instance, base-offset :: , byte-offset :: ) => (value :: ) primitive-raw-as-byte-character (primitive-byte-element (instance, integer-as-raw(base-offset), integer-as-raw(byte-offset))) end function; define inline-only function byte-slot-element-setter (new-value :: , instance, base-offset :: , byte-offset :: ) => (value :: ) primitive-byte-element (instance, integer-as-raw(base-offset), integer-as-raw(byte-offset)) := primitive-byte-character-as-raw(new-value); new-value end function; //// //// ALLOCATION //// /// !@#$ THESE SHOULD BE UNIFIED /* New Interface to primitive-allocate: size of memory to be allocated MM class wrapper number of slots to fill fill value repeated-size(tagged) repeated-size slot offset */ // TODO: Put back inline-only when all calls can be inlined. /* inline-only */ define inline function system-allocate-simple-instance-i (iclass :: , #key fill = %unbound) let storage-size = iclass.instance-storage-size; primitive-object-allocate-filled (integer-as-raw($number-header-words + storage-size), iclass.iclass-instance-header, integer-as-raw(storage-size), fill, integer-as-raw(0), integer-as-raw(0), fill); end function; /* inline-only ? */ define inline function system-allocate-simple-instance (class :: , #key fill = %unbound) system-allocate-simple-instance-i (class-implementation-class(class), fill: fill) end function; define generic system-allocate-repeated-instance (class :: , type :: , fill, repeated-size :: , repeated-fill) => (instance); /// REPEATED OBJECT INSTANCE ALLOCATION -- DEFAULT define inline method system-allocate-repeated-instance (class :: , type :: , fill, repeated-size :: , repeated-fill) => (instance) system-allocate-repeated-object-instance(class, fill, repeated-size, repeated-fill) end method; define macro repeated-instance-allocator-definer { define ?adj:* repeated-instance-allocator (?:name, ?alloc:name, ?type:name, ?unboxer:name) } => { define ?adj repeated-instance-allocator-aux (?name, ?alloc, ?type, ?unboxer); define inline-only function "system-allocate-repeated-" ## ?name ## "-instance" (class :: , fill, repeated-size :: , repeated-fill :: ?type) "system-allocate-repeated-" ## ?name ## "-instance-i" (class-implementation-class(class), fill, repeated-size, repeated-fill) end function; define inline method system-allocate-repeated-instance (class :: , type == ?type, fill, repeated-size :: , repeated-fill :: ?type) => (instance) "system-allocate-repeated-" ## ?name ## "-instance" (class, fill, repeated-size, repeated-fill) end method; } end macro; /* /// TODO: USE THIS OF ICLASS PROPERTY FOR LEAF OBJECTS define function mm-wrapper-raw-fixed-part? (mm-wrapper :: ) => (well? :: ) let fixed-part = raw-as-integer(mm-wrapper.mm-wrapper-fixed-part); logbit?(1, fixed-part) & block (return) for (i :: from 0 below mm-wrapper-number-patterns(mm-wrapper)) let pattern = mm-wrapper-pattern-element(mm-wrapper, i); unless (primitive-machine-word-equal?(pattern, integer-as-raw(0))) return(#f) end unless; end for; #t end block; end function; */ define macro repeated-instance-allocator-aux-definer { define repeated-instance-allocator-aux (?:name, ?alloc:name, ?type:name, ?unboxer:name) } => { define inline-only function "system-allocate-repeated-" ## ?name ## "-instance-i" (iclass :: , fill, repeated-size :: , repeated-fill :: ?type) let size-offset = iclass.instance-storage-size; let raw-size-offset = iclass.instance-storage-size; let raw-number-words = integer-as-raw($number-header-words + size-offset); let mm-wrapper = iclass.iclass-instance-header; let raw-number-slots = integer-as-raw(size-offset - 1); let raw-repeated-size = integer-as-raw(repeated-size); let raw-size-offset = integer-as-raw(size-offset); let raw-repeated-fill = ?unboxer(repeated-fill); "primitive-" ## ?alloc ## "-allocate-filled" (raw-number-words, mm-wrapper, raw-number-slots, fill, raw-repeated-size, raw-size-offset, raw-repeated-fill); end function; } { define leaf repeated-instance-allocator-aux (?:name, ?alloc:name, ?type:name, ?unboxer:name) } => { define inline-only function "system-allocate-repeated-" ## ?name ## "-instance-i" (iclass :: , fill, repeated-size :: , repeated-fill :: ?type) let size-offset = iclass.instance-storage-size; let raw-size-offset = iclass.instance-storage-size; let raw-number-words = integer-as-raw($number-header-words + size-offset); let mm-wrapper = iclass.iclass-instance-header; let raw-number-slots = integer-as-raw(size-offset - 1); let raw-repeated-size = integer-as-raw(repeated-size); let raw-size-offset = integer-as-raw(size-offset); let raw-repeated-fill = ?unboxer(repeated-fill); // if (mm-wrapper-raw-fixed-part?(mm-wrapper)) // HACK: FOR NOW UNTIL WE CAN IDENTIFY THESE CLASSES // EITHER BY MM-WRAPPER OR ICLASS PROPERTY BIT if (~subclass?(iclass-class(iclass), )) "primitive-" ## ?alloc ## "-allocate-leaf-filled" (raw-number-words, mm-wrapper, raw-number-slots, fill, raw-repeated-size, raw-size-offset, raw-repeated-fill); else "primitive-" ## ?alloc ## "-allocate-filled" (raw-number-words, mm-wrapper, raw-number-slots, fill, raw-repeated-size, raw-size-offset, raw-repeated-fill); end if end function; } end macro; define repeated-instance-allocator (object, object, , identity); define leaf repeated-instance-allocator (byte-character, byte, , primitive-byte-character-as-raw); define repeated-instance-allocator (unicode-character, word, , primitive-unicode-character-as-raw); define leaf repeated-instance-allocator (byte, byte, , integer-as-raw); define repeated-instance-allocator (double-byte, double-byte, , integer-as-raw); define repeated-instance-allocator (word, word, , primitive-unwrap-machine-word); // define repeated-instance-allocator // (double-word, double-word, , primitive-unwrap-double-integer); define repeated-instance-allocator (single-float, single-float, , primitive-single-float-as-raw); define repeated-instance-allocator (double-float, double-float, , primitive-double-float-as-raw); /// TERMINATED REPEATED BYTE ALLOCATION define inline-only function system-allocate-repeated-byte-instance-terminated-i (iclass :: , repeated-size :: , fill) let size-offset = iclass.instance-storage-size; let nul-adjust = 1; // extra byte for nul terminator primitive-byte-allocate-leaf-filled-terminated (integer-as-raw($number-header-words + size-offset), integer-as-raw(repeated-size + nul-adjust), iclass.iclass-instance-header, integer-as-raw(size-offset - 1), fill, integer-as-raw(repeated-size), integer-as-raw(size-offset)); end function; define inline-only function system-allocate-repeated-byte-instance-terminated (class :: , repeated-size :: , fill) system-allocate-repeated-byte-instance-terminated-i(class-implementation-class(class), repeated-size, fill) end function; /// WEAK REPEATED INSTANCES define inline-only function system-allocate-weak-repeated-instance (class :: , repeated-size :: , fill, assoc-link) system-allocate-weak-repeated-instance-i(class-implementation-class(class), repeated-size, fill, assoc-link) end function; define inline-only function system-allocate-weak-repeated-instance-i (iclass :: , repeated-size :: , fill, assoc-link) let size-offset = iclass.instance-storage-size; primitive-allocate-weak-in-awl-pool (integer-as-raw($number-header-words + size-offset + repeated-size), iclass.iclass-instance-header, integer-as-raw(size-offset + repeated-size), fill, integer-as-raw(repeated-size), integer-as-raw(size-offset), assoc-link); end function; define inline-only function system-allocate-strong-repeated-instance (class :: , repeated-size :: , fill) system-allocate-strong-repeated-instance-i (class-implementation-class(class), repeated-size, fill) end function; define inline-only function system-allocate-strong-repeated-instance-i (iclass :: , repeated-size :: , fill) let size-offset = iclass.instance-storage-size; primitive-allocate-in-awl-pool (integer-as-raw($number-header-words + size-offset + repeated-size), iclass.iclass-instance-header, integer-as-raw(size-offset + repeated-size), fill, integer-as-raw(repeated-size), integer-as-raw(size-offset), #f); end function; define inline-only function system-allocate-wrapper () let class = ; let repeated-size = 0; let size-offset = class.instance-storage-size; primitive-allocate-wrapper (integer-as-raw($number-header-words + size-offset + repeated-size), class.class-instance-header, integer-as-raw(size-offset + repeated-size), %unbound, integer-as-raw(repeated-size), integer-as-raw(size-offset)); end function; //// //// DYNAMIC SPECIALIZERS SUPPORT //// define not-upgrade not-inline function make- (next? :: , required :: , values :: , rest-value /* false-or() */, signature-properties :: ) => (signature :: ) make(, key?: #f, required: required, values: values, rest-value: rest-value, next?: next?, properties: signature-properties) end; define not-upgrade not-inline function make- (next? :: , required :: , values :: , rest-value /* false-or() */, signature-properties :: , keys :: , key-types :: ) => (signature :: ) make(, key?: #t, required: required, keys: keys, key-types: key-types, values: values, rest-value: rest-value, next?: next?, properties: signature-properties) end; define function function-required-type (function :: , index :: ) => (type :: ) signature-required(function-signature(function))[index] end; define function function-key-type (function :: , index :: ) => (type :: ) signature-key-types(function-signature(function))[index] end; define function function-value-type (function :: , index :: ) => (type :: ) signature-values(function-signature(function))[index] end; define function function-rest-value-type (function :: ) => (type :: false-or()) signature-rest-value(function-signature(function)) end; /* //// //// CLOSURE SUPPORT !@#$ NOT IMPLEMENTED YET //// define function %copy-method (function :: ) => (copy :: ) function.copy-simple-instance end function; define function %copy-method-using-environment (function :: , new-environment) let new-function :: = function.%copy-method; new-function.environment := new-environment; new-function end function; define function %copy-method-using-signature (function :: , new-signature :: ) let new-function :: = function.%copy-method; new-function.function-signature := new-signature; new-function end function; */ //// //// //// define primary class () constant slot value-cell-object :: ; end class; ignore(); ignore(value-cell-object); //// //// //// define primary class () constant slot value-cell-raw-object :: ; end class; ignore(); ignore(value-cell-raw-object); define primary class () constant slot value-cell-raw-object-1 :: ; constant slot value-cell-raw-object-2 :: ; end class; ignore(); ignore(value-cell-raw-object-1); ignore(value-cell-raw-object-2); //// //// //// // BOOTED: define class ... end; // BOOTED: define constant %unbound ...; // !@#$ BOOT ME define inline function unbound () %unbound end function; define inline function unbound? (object) object == unbound() end function; //// //// //// // BOOTED: define constant %empty-list = ...; //// //// SPECIAL STUFF //// define constant %bs-empty = ""; %bs-empty; define constant %sv-empty = #(); // Hack!!! #[] %sv-empty; // UNUSED AT PRESENT // (define %supplied?? (system-allocate-simple-instance )) // define constant %unsupplied? = %unsupplied?; // !@#$ BOOT ME // UNUSED AT PRESENT // (define %special-rest-marker (system-allocate-simple-instance )) // NEED THIS TO INTRODUCE KEYWORD // define constant %allow-other-keys = #(#"allow-other-keys"); //// //// MULTIPLE-VALUES SUPPORT //// define function values (#rest arguments) %dynamic-extent(arguments); primitive-values(arguments); end function; //// //// SUPPORT //// // BOOTED: define class ... end; // BOOTED: define constant %true = ...; // BOOTED: define constant %false = ...; define method uninstantiable-error (class) error("Cannot instantiate %=, it is not an instantiable type.", class) end method; define sealed method make (class == , #rest all-keys, #key) => (res) uninstantiable-error(class); end method; ///// ///// LOW-LEVEL ERROR SUPPORT ///// /// !@#$ THIS SHOULD GO ELSEWHERE /// !@#$ IT SHOULD BE BOUND AS IN INTERPRETER /// !@#$ NEED A VALUE FOR RUNNING STANDALONE // define variable *last-top-level* = #f; define class () end; define class () end; define class () end; define class () end; define class () end; define not-inline function odd-keyword-arguments-error (function :: ) => (will-never-return :: ) error(make(, format-string: "Attempted to call %= with an odd number of keywords", format-arguments: list(function))) end function; define class () end; define not-inline function unknown-keyword-argument-error (function :: , keyword :: ) => (will-never-return :: ) error(make(, format-string: "Attempted to call %= with an unknown keyword %=", format-arguments: list(function, keyword))) end function; define class () end; define not-inline function argument-count-error (function :: , argument-count :: ) => (will-never-return :: ) error(make(, format-string: "Attempted to call %= with %d arguments", format-arguments: list(function, argument-count))) end function; define class () end; define not-inline function argument-count-overflow-error (function :: , argument-count :: , argument-count-max :: ) => (will-never-return :: ) error(make(, format-string: "Function %= called with %d > %d arguments", format-arguments: list(function, argument-count, argument-count-max))) end function; define not-inline function bad-function-error (function) => (will-never-return :: ) error(make(, value: function, type: )); end function; bad-function-error; define not-inline function type-check-error (value, type) => (will-never-return :: ) error(make(, value: value, type: type)); end function; define class () end; define not-inline function stack-overflow-error () => (will-never-return :: ) let name = thread-name(current-thread()); let condition = if (name) make(, format-string: "Stack overflow on current thread, %=.", format-arguments: list(name)) else make(, format-string: "Stack overflow on current (unnamed) thread.", format-arguments: #()); end; error(condition); end function; //// //// ERROR FUNCTIONS FOR NEW DISPATCH //// define class () end; define open generic ambiguous-method-error (gf :: , args :: , ordered :: , ambig :: ); define method ambiguous-method-error (gf :: , args :: , ordered :: , ambig :: ) error(make(, format-string: "Method selection is ambiguous applying %= to %= - got %= ordered methods, %= unorderable", format-arguments: list(gf, args, ordered, ambig))) end method; define not-inline function no-applicable-method-error (gf :: , args :: ) block () error(make(, format-string: "No applicable method, applying %= to %=.", format-arguments: list(gf, args))) exception (, init-arguments: vector(format-string: "Try calling %= again with arguments: %=.", format-arguments: vector(gf, args))) apply(gf, args); end; end function; define constant repeated-slot-getter-index-out-of-range-trap = method (inst, idx :: ) let sd :: = repeated-slot-descriptor(object-class(inst)); error(make(, format-string: "Out of range attempting to fetch %= of %= at index %=.", format-arguments: list(slot-getter(sd) | sd, inst, idx))) end method; define constant repeated-slot-setter-index-out-of-range-trap = method (value, inst, idx :: ) let sd :: = repeated-slot-descriptor(object-class(inst)); error(make(, format-string: "Out of range attempting to store %= into %= of %= at index %=.", format-arguments: list(value, slot-getter(sd) | sd, inst, idx))) end method; // Re-spread arguments from mepargs format. // We always return a heap-consed vector for the sake of storing the args in conditions. define constant reconstruct-args-from-mepargs = method (gf :: , mepargs :: ) let signature :: = function-signature(gf); let n :: = size(mepargs); let (nreq :: , nopt :: , optvec :: ) = if (signature-optionals?(signature)) let optvec :: = vector-element(mepargs, n - 1); values(n - 1, size(optvec), optvec) else values(n, 0, #[]) end if; let args :: = make(, size: nopt + nreq); for (i :: from 0 below nreq) vector-element(args, i) := vector-element(mepargs, i) end for; for (i :: from nreq, j :: from 0 below nopt) vector-element(args, i) := vector-element(optvec, j) end for; args end method; define constant reconstruct-keywords = method (keyvec :: , method-keyword-table-format?) if (method-keyword-table-format?) let ndata :: = size(keyvec); let nkeys :: = ash(ndata, -1); let nkeyvec :: = make(, size: nkeys); for (i :: from 0 below nkeys, j :: from 0 by 2) vector-element(nkeyvec, i) := vector-element(keyvec, j) end for; nkeyvec else // generic functions use just a vector of the keywords currently. keyvec end if end method; define constant odd-number-of-keyword-args-trap = method (mepargs :: , disphdr :: , engine-node) engine-node; // Maybe someday. let gf :: = parent-gf(disphdr); error(make(, format-string: "The function %= was called with an odd number of keyworded arguments in args %=", format-arguments: list(gf, reconstruct-args-from-mepargs(gf, mepargs)))) end method; define variable *gf-invalid-keyword-error-is-warning* = #t; define constant invalid-keyword-trap = method ( mepargs :: , disphdr :: , engine-node :: , key, keyvec :: , implicit? :: ) engine-node; // Maybe someday. let gf :: = parent-gf(disphdr); let args = reconstruct-args-from-mepargs(gf, mepargs); if (~instance?(key, )) error(make(, format-string: "The function %= was given %= where a keyword was expected in the call with arguments %=", format-arguments: list(gf, key, args))) elseif (*gf-invalid-keyword-error-is-warning*) signal("The function %= was given the unrecognized keyword %= in the call with arguments %=.\n" "The keywords recognized for this call are %=.", gf, key, args, reconstruct-keywords(keyvec, implicit?)); %method-apply-with-optionals(single-method-engine-node-method(engine-node), single-method-engine-node-data(engine-node), mepargs) else error(make(, format-string: "The function %= was given the unrecognized keyword %= in the call with arguments %=.\n" "The keywords recognized for this call are %=.", format-arguments: list(gf, key, args, reconstruct-keywords(keyvec, implicit?)))) end if end method; //// //// EXTRAS IN LOW RUN-TIME //// define function apply (function :: , #rest arguments) %dynamic-extent(arguments); let size :: = arguments.size; vector-element(arguments, size - 1) := as(, vector-element(arguments, size - 1)); primitive-apply(function, arguments); end function; define inline function %method-apply-with-optionals (function, next-methods, arguments) primitive-mep-apply-with-optionals(function, next-methods, arguments) end function; /// MEMORY MANAGEMENT FUNCTIONS define inline function address-of (object :: ) => (address :: ) primitive-wrap-machine-word(primitive-cast-pointer-as-raw(object)) end function address-of; /// @@@@ SHOULD GO ELSEWHERE define method invoke-debugger (condition :: ) primitive-invoke-debugger ("Condition of class %= occurred", vector(object-class(condition))); #f end method invoke-debugger; define method invoke-debugger (condition :: ) primitive-invoke-debugger (condition-format-string(condition), as(, condition-format-arguments(condition))); #f end method invoke-debugger; define method inside-debugger? () => (debugging? :: ) primitive-inside-debugger?() end method inside-debugger?; /// $NOT-FOUND GLOBAL CONSTANT // define constant $not-found = system-allocate-simple-instance(); define constant $not-found :: = #("NOT FOUND"); // define constant $dummy-implementation-class = ; /// LIBRARY VERSION CHECKING define class () end; define generic library-version-error (library :: , used-library :: ); define method library-version-error (lib :: , used-lib :: ) let used-lib-lib = used-library(used-lib); error(make(, format-string: "Version mismatch: Library %= expected version %=.%= of library %=, " "but got version %=.%= instead", format-arguments: list(namespace-name(lib), library-major-version(used-lib), library-minor-version(used-lib), namespace-name(used-lib-lib), library-major-version(used-lib-lib), library-minor-version(used-lib-lib)))) end method; // define class () end; define generic library-incompatibility-error (library :: , used-library :: ); define method library-incompatibility-error (lib :: , used-lib :: ) let used-lib-lib = used-library(used-lib); error(make(, format-string: "Library incompatibility: library %= was compiled in production mode " "against an older version of used library %=, and is not compatible " "with the newer version. Library %= must be recompiled to use this " "version of library %=", format-arguments: list(namespace-name(lib), namespace-name(used-lib-lib), namespace-name(lib), namespace-name(used-lib-lib)))) end method; define constant $library-build-count-wildcard = -1; define constant $library-build-count-only-wildcard = -2; define inline function system-developer-library? (lib :: ) => (well? :: ) library-build-count(lib) == $library-build-count-wildcard end function; define inline function major-minor-only-library? (lib :: ) => (well? :: ) library-build-count(lib) == $library-build-count-only-wildcard end function; define variable *version-checks?* = #t; define function version-checks?-setter (well?) *version-checks?* := well?; end function; define inline function version-checks? () => (well? :: ) *version-checks?* end function; define function %used-library-version-check (lib :: , used-lib :: ) let used-lib-lib = used-library(used-lib); unless (~version-checks?() | system-developer-library?(used-lib-lib) | system-developer-library?(lib)) if (library-major-version(used-lib-lib) ~== library-major-version(used-lib) | library-minor-version(used-lib-lib) < library-minor-version(used-lib)) library-version-error(lib, used-lib) elseif (used-library-binding(used-lib) == #"tight" & ~major-minor-only-library?(lib) & ~major-minor-only-library?(used-lib-lib) & library-build-count(used-lib-lib) ~== library-build-count(used-lib)) library-incompatibility-error(lib, used-lib) end if end unless end function; define function %library-version-check (lib :: , module) for (ul in used-libraries(lib)) %used-library-version-check(lib, ul); end for; // register the runtime module dylan-runtime-module-handle(lib.namespace-name) := module; end function; // A simple runtime mapping from internal dylan-library names (as symbols) // to their runtime DLL module handles (what addresses the DLLs are actually // loaded into memory) define variable *dylan-runtime-modules* = #f; define variable *dylan-runtime-module* = #f; define function dylan-runtime-module-handle(library :: ) => (module) if (*dylan-library-initialized?*) if (library == #"dylan") *dylan-runtime-module* else unless (*dylan-runtime-modules*) *dylan-runtime-modules* := make(); end unless; element(*dylan-runtime-modules*, library, default: #f); end if; else *dylan-runtime-module* end if; end function; define function dylan-runtime-module-handle-setter(module, library :: ) => (module) if (*dylan-library-initialized?*) if (library = "dylan") *dylan-runtime-module* := module else unless (*dylan-runtime-modules*) *dylan-runtime-modules* := make(
); end unless; *dylan-runtime-modules*[as(, library)] := module end if; else *dylan-runtime-module* := module end if; end function; define function lookup-runtime-module(library :: ) => (module) dylan-runtime-module-handle(library) end function; /// SHARED SYMBOLS define shared-symbols %shared-dylan-symbols #"above", #"abstract?", #"all-keys?", #"allocation", #"allow-other-keys", #"arguments", #"below", #"by", #"capacity", #"class", #"code", #"collections", #"constant", #"count", #"debug-name", #"default", #"dimensions", #"domain-types", #"each-subclass", #"element-type", #"end", #"failure", #"fill", #"fixed-part", #"format-argument", #"format-arguments", #"format-string", #"from", #"function", #"generic-function", #"getter", #"grow-size-function", #"hash-function", #"high", #"implementation-class", #"inherited-slots", #"init-arguments", #"init-data", #"init-evaluated?", #"init-function", #"init-keyword", #"init-keyword-required?", #"init-supplied?", #"init-value", #"init-value?", #"initial-count", #"instance-storage-size", #"key", #"key-test", #"key-types", #"key?", #"keys", #"keyword-specifiers", #"keywords", #"lock", #"low", #"max", #"maximum-count", #"min", #"mode", #"name", #"next", #"next?", #"number-patterns", #"number-required", #"number-values", #"object", #"operation", #"ordered", #"owner", #"password", #"primary?", #"priority", #"processing", #"properties", #"read", #"rehash-limit", #"repeated", #"required", #"required-init-keyword", #"rest-value", #"rest-value?", #"rest?", #"sealed?", #"sequences", #"setter", #"signature", #"size", #"skip", #"slot-descriptor", #"slots", #"stable", #"start", #"storage-size", #"superclasses", #"synchronization", #"test", #"test-function", #"thread", #"timeout", #"to", #"token", #"type", #"type1", #"type2", #"unknown", #"users", #"value", #"values", #"values?", #"vector", #"virtual", #"weak", #"write" end shared-symbols; define shared-symbols %shared-streams-symbols #"element-type", #"direction", #"locator", #"encoding", #"outer-stream", #"if-exists", #"if-does-not-exist", #"abort?", #"wait?", #"input", #"output", #"input-output", #"new-version", #"overwrite", #"replace", #"truncate", #"signal", #"append" end shared-symbols; /// CPL ABSTRACTION define method all-superclasses (iclass :: ) => (supers :: ) let supers :: = #(); for (super :: in class-rcpl-vector(iclass), i :: from class-rcpl-position(iclass) to 0 by -1) supers := pair(super, supers); end; supers end method; define method all-superclasses-setter (supers :: , iclass :: ) => (supers :: ) supers end method; define macro for-each-superclass { for-each-superclass (?:name :: ?:expression of ?class:expression, ?more:*) ?loopbody:* end } => { let super-vector :: = class-rcpl-vector(?class); for (super-i :: from class-rcpl-position(?class) to 0 by -1, ?more) let ?name :: = super-vector[super-i]; ?loopbody end } end macro; /// HACK BEGIN: NEEDED FOR GROUNDING OUT PARTIAL DISPATCH define constant $empty-subjunctive-class-universe :: = make-empty-subjunctive-class-universe(); /// HACK END: // eof