module: dfmc-modeling 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 //// //// CALLABLE-OBJECT //// define abstract class <&callable-object> () end class <&callable-object>; define generic ^iep (function); define generic ^iep-setter (value, function); //// //// FUNCTION //// define inline-only function ^function-specializers (f :: <&function>) => (types) let sig = ^function-signature(f); let reqs = ^signature-required(sig); if (size(reqs) ~= ^signature-number-required(sig)) copy-sequence(reqs, end: ^signature-number-required(sig)) else reqs end if end; // Warning - run-time.h knows about this object's format! define abstract primary compiler-model-class (, ) () &runtime-only-computed-slot xep, init-keyword: xep:; end compiler-model-class ; define generic ^xep (f :: <&function>) => (res); define generic ^xep-setter (value, f :: <&function>); define method xep (f :: <&function>) ^xep(f) end; define method xep-setter (x, f :: <&function>) ^xep(f) := x end; //// //// GENERIC-FUNCTION //// // This object is just a place to store more datastructure in a g.f. (it goes in the cache slot). // USERS is an enumeration of all of the 's which use this // implementation of the g.f. define primary &class () &slot gf-cache-info-users :: , init-value: #[], init-keyword: users:; end &class; define primary &class () &slot simple-typechecked-gf-cache-info-entries :: , init-value: #[], init-keyword: entries:; &slot simple-typechecked-gf-cache-info-argmask :: , init-value: 0, init-keyword: argmask:; end &class; define primary &class () &slot partial-dispatch-gf-cache-info-caches :: , init-value: #(), init-keyword: caches:; end &class; define compiler-open generic ^generic-function-methods (gf :: <&generic-function>); define compiler-open generic ^generic-function-methods-setter (value, gf :: <&generic-function>); // Warning - run-time.h knows about this object's format! define abstract primary &class () lazy &slot function-signature :: false-at-compile-time-or(), init-value: #f, init-keyword: signature:; &slot %gf-cache, init-value: #f; lazy &slot debug-name :: , init-value: #f, init-keyword: debug-name:; lazy &computed-slot generic-function-methods :: , init-value: #(); // If we start using this it should probably be made lazy, as it would // only be used for creating the runtime object, not compilation. &slot discriminator, init-value: #f; // Compile-time slots. slot ^generic-function-properties :: , init-value: 0; lazy slot signature-spec :: , required-init-keyword: signature-spec:; lazy slot %generic-function-domains :: = #(); slot parameters-dynamic-extent, init-value: #f, init-keyword: dynamic-extent:; slot ^generic-function-cache-info = #f; metaclass ; end &class ; // define constant $max-incomplete-methods-log-size = 16; // COMPILE TIME ONLY define leaf packed-slots ^generic-function-properties (<&generic-function>, ) boolean slot %generic-function-methods-initialized? = #f; boolean slot %generic-function-domains-initialized? = #f; boolean slot ^generic-function-sealed? = #t, init-keyword: sealed?:; boolean slot ^generic-function-compiler-open? = #f; end packed-slots; ignore(^generic-function-compiler-open?); define runtime-slot-offset generic-function-methods (); // TODO: FORWARD DECLARED define compiler-open generic ^generic-function-domains (gf :: <&generic-function>); define method ^initialize (gf :: <&generic-function>, #rest all-keys, #key) next-method(); let plugh = dylan-value(#"$absent-engine-node"); apply(initialize-packed-slots, gf, all-keys); ^generic-function-compiler-open?(gf) := form-compiler-open?(model-definition(gf)); gf.^discriminator := plugh; end method; // This is the smaller runtime represetnation for a generic function. It is // used when we don't need to keep track of domain and library information. // By special dispensation, a compiler-open generic function gets made into // one of these. Don't check the type, use ^generic-function-sealed? in the // compiler. define primary &class () end &class; // The larger representation of a generic function, where we keep track of // method libraries and domain info. define primary &class () &slot incremental-gf-module :: , init-keyword: module:; lazy &slot incremental-gf-domain-info /* :: false-or() */, init-value: #f; lazy &slot incremental-gf-method-libraries :: , init-keyword: method-libraries:, init-value: #[]; &slot incremental-gf-properties, init-value: 0; metaclass ; end &class ; define leaf packed-slots ^incremental-gf-properties (<&incremental-generic-function>, ) boolean slot ^incremental-gf-sealed? = #t, init-keyword: sealed?:; boolean slot ^incremental-gf-method-complete? = #t; boolean slot ^incremental-gf-signatured? = #t, init-keyword: signatured?:; end packed-slots; ignore(^incremental-gf-signatured?); ignore(^incremental-gf-method-complete?); ignore(^incremental-gf-sealed?); define method ^initialize (g :: <&incremental-generic-function>, #key) next-method(); ^incremental-gf-module(g) := model-module-model(g); end method; //// //// METHOD //// // HACK: SHOULDN'T NEED THE FOLLOWING BUT &CLASS DOESN'T SUPPORT THESE MIXINS define abstract class <&referenced-object> () end; // Warning - run-time.h knows about this object's format! define primary compiler-model-class (, ) () end compiler-model-class; define method lambda-top-level? (f :: <&method>) => (well? :: ) #t end method; define method lambda-top-level?-setter (x, f :: <&method>) => (well? :: ) #t end method; /* define method ^debug-name (x :: <&method>) debug-name(x) | model-variable-name(x) end method; */ define compiler-open generic parameters (function); define compiler-open generic parameters-setter (value, function); define compiler-open generic body (function); define compiler-open generic body-setter (value, function); define compiler-open generic environment (function); define compiler-open generic environment-setter (value, function); define method environment (f :: <&method>) => (res) #[] end method; define compiler-open generic function (function); define compiler-open generic function-setter (value, function); define compiler-open generic ^next? (function); define compiler-open generic ^next?-setter (value, function); define generic ^function-next? (function); // Extended in dfmc-conversion. define compiler-open generic ^function-next?-setter (value, function); define method ^function-next? (x :: <&method>) => (z :: ) #f end method; define method ^function-next?-setter (y :: , x :: <&method>) => (z :: ) #f end method; define generic ^mep (function); define generic ^mep-setter (value, function); define generic ^keyword-specifiers (function); define generic ^keyword-specifiers-setter (value, function); define method ^keyword-specifiers (f :: <&method>) => (res) #[] end method; //define &class () // &slot %incr-method-library :: ; //end &class; //define method ^initialize (m :: <&incremental-method-mixin>, #key definition) // next-method(); // if (definition) // ^%incr-method-library(m) := namespace-model(language-definition(form-library(definition))) // end if //end method; //// //// LAMBDA //// define dood-class () // TODO: WHAT TYPE IS THIS? weak slot lambda-body-spec = #f, reinit-expression: #f, init-keyword: body-spec:; slot lambda-dfm-environment = #f, init-keyword: environment:; // TODO: TIE TO REAL PARAMETERS slot lambda-dfm-parameters :: false-or() = #f, init-keyword: parameters:; slot lambda-dfm-body = #f, init-keyword: body:; // TODO: TIE TO REAL QUEUE weak slot lambda-dfm-optimization-queue :: false-or() = #f, reinit-expression: #f; end dood-class; // Warning - run-time.h knows about this object's format! define primary &class () lazy &slot function-signature :: false-at-compile-time-or(), init-value: #f, init-keyword: signature:; &computed-slot mep, init-keyword: mep:; // &slot function-next? :: , // init-value: #f, // init-keyword: next?:; lazy slot debug-name, init-value: #f, init-keyword: compiler-debug-name:; // Compile-time slots. // slot call-site-summaries = make(); slot function-properties :: = 0; // definition slots lazy slot signature-spec :: , required-init-keyword: signature-spec:; // model slots slot parameters-dynamic-extent, init-value: #f, init-keyword: dynamic-extent:; lazy slot lambda-heap = #f; // dfm slots lazy slot lambda-body :: false-or() = make(); metaclass ; end &class; define runtime-slot-offset mep (); define macro lambda-body-transfer-definer { define lambda-body-transfer ?slotname:name , ?otherslotname:name ( ?type:* ) ; } => { define inline method ?slotname (f :: <&lambda>) => (v :: ?type) let body = lambda-body(f); body & ?otherslotname(body); end method; define inline method ?slotname ## "-setter" (v :: ?type , f :: <&lambda>) => (v :: ?type) ?otherslotname ## "-setter"(v, lambda-body(f)) end method } end macro; // TODO: DO THIS ALL IN ONE define lambda-body-transfer body-spec, lambda-body-spec (); define lambda-body-transfer environment, lambda-dfm-environment (); define lambda-body-transfer parameters, lambda-dfm-parameters (false-or()); define lambda-body-transfer body, lambda-dfm-body (); define lambda-body-transfer optimization-queue, lambda-dfm-optimization-queue (false-or()); define leaf packed-slots function-properties (<&lambda>, ) boolean slot lambda-optimized? = #f; boolean slot lambda-top-level? = #f; tristate slot lambda-next? = #"unknown"; tristate slot lambda-rest? = #"unknown"; tristate slot lambda-inlineable? = #"unknown"; boolean slot lambda-initializer? = #f; boolean slot lambda-has-free-references? = #f; field slot lambda-log-number-temporaries = 0, field-size: 6; boolean slot lambda-copied-down? = #f; // explicitly mark which functions are actually runtime boolean slot lambda-runtime-function? = #f; end packed-slots; define method ^make (class == <&method>, #rest all-keys, #key definition, signature-spec, #all-keys) => (res :: <&method>) // let dyn? = definition & form-dynamic?(definition); // let name? = definition & form-variable-name(definition); // let bdef = name? & binding-definition(lookup-binding(name?)); // let gdef = instance?(bdef, ) & bdef; // let sealed? = gdef & form-sealed?(gdef); // let incr? = gdef & ~sealed?; // if (definition) // format-out("\ndynamic=%= name=%= gdef=%= sealed=%= incr=%=", dyn?, name?, gdef, sealed?, incr?) // end if; apply(^make, if (~signature-spec | spec-argument-key?(signature-spec)) if (definition & ~form-dynamic?(definition)) // top-level? // if (incr?) <&incremental-keyword-method> else <&keyword-method> end <&keyword-method> else // if (incr?) <&incremental-keyword-closure-method> else <&keyword-closure-method> end <&keyword-closure-method> end if else if (definition & ~form-dynamic?(definition)) // top-level? // if (incr?) <&incremental-simple-method> else <&simple-method> end <&simple-method> else // if (incr?) <&incremental-simple-closure-method> else <&simple-closure-method> end <&simple-closure-method> end if end if, all-keys); end method; // define variable *dummy-call-site-summaries* = #f; // // define method call-site-summaries (x :: <&lambda>) => (res :: ) // *dummy-call-site-summaries* // | (*dummy-call-site-summaries* := make()) // end method; define method ^function-next? (x :: <&lambda>) => (z) lambda-next?(x) end method; /// /// TRAMPOLINE DFM RELATED SLOTS FOR EASIER MANAGEMENT /// define method ^iep (f :: <&lambda>) ^mep(f) end; define method ^iep-setter (v, f :: <&lambda>) ^mep-setter(v, f) end; define method iep (f :: <&lambda>) mep(f) end; define method make-mep (f :: <&lambda>) => (res :: <&code>) make(<&iep>, function: f) end method; define method initialize (function :: <&lambda>, #rest all-keys, #key body-spec) next-method(); apply(initialize-packed-slots, function, all-keys); body-spec(function) := body-spec; %mep(function) := make-mep(function); function end method; define method ^mep (lambda :: <&method>) %mep(lambda) end; define method ^mep-setter (v, lambda :: <&method>) %mep(lambda) := v end; define method mep (f :: <&method>) %mep(f) end; //// //// SIMPLE-METHOD //// define primary &class () metaclass ; end &class ; //define primary &class (, ) // metaclass ; //end &class ; define generic ^environment-size (object); define generic ^environment-element (object, index); define &class () // &slot environment, // init-value: #f; compiler-constant repeated &slot environment-element, size-getter: environment-size, size-init-keyword: size:, size-init-value: 0; // slot data, // init-value: vector(), // init-keyword: data:; end &class; // HACK: SHOULDN'T GENERATE THESE IN THE FIRST PLACE ignore(^environment-element-values); // HACK: DONT REALLY NEED THESE UNTIL CLOSURES ARE BUILT AT COMPILE-TIME // TODO: The size-getter: option isn't spotted as an accessor name by the // define &class macro, so have to hook up the compile-stage function // by hand. Fix! define &override-function ^environment-size end; define method ^environment-size (object :: <&closure-method-mixin>) 0 end method; define method ^environment-element (object :: <&closure-method-mixin>, index) #f end method; //// //// SIMPLE-CLOSURE-METHOD //// define primary &class (, ) metaclass ; end &class ; //define primary &class // (, ) // metaclass ; //end &class ; //// //// KEYWORD-METHOD //// define primary &class () &computed-slot iep, init-keyword: iep:, init-value: #f; runtime-constant lazy &computed-slot keyword-specifiers :: , init-value: #[], init-keyword: keyword-specifiers:; metaclass ; end &class ; define runtime-slot-offset iep (); //define primary &class (, ) // metaclass ; //end &class ; define method ^iep (f :: <&keyword-method>) %iep(f) end; define method ^iep-setter (v, f :: <&keyword-method>) %iep(f) := v end; define method iep (f :: <&keyword-method>) %iep(f) end; define method make-mep (f :: <&keyword-method>) => (res :: <&mep>) make(<&mep>, function: f) end method; define method initialize (function :: <&keyword-method>, #key) next-method(); function.%iep := make(<&iep>, function: function); function end method; define method keyword-specifiers (f :: <&keyword-method>) %keyword-specifiers(f) end method; define method keyword-specifiers-setter (v, f :: <&keyword-method>) %keyword-specifiers(f) := mapped-model(v) end method; define method ^keyword-specifiers (f :: <&keyword-method>) %keyword-specifiers(f) end method; define method ^keyword-specifiers-setter (v, f :: <&keyword-method>) %keyword-specifiers(f) := mapped-model(v) end method; //// //// KEYWORD-CLOSURE-METHOD //// define primary &class (, ) metaclass ; end &class ; //define primary &class // (, ) // metaclass ; //end &class ; //// //// INITIALIZER-METHOD //// // Initializer methods are automatically generated by the compiler for // each (concrete) class. This is a compile-time only distinction. define class <&initializer-method> (<&keyword-method>) end; define method ^class-constructor (class :: <&implementation-class>) => (constructor :: <&method>) if (slot-initialized?(class, %class-constructor)) %class-constructor(class) else let class-name = form-variable-name(model-creator(class)); let creator-name = splice-name-hygienically(class-name, "", " constructor"); // This forces installation. if (~lookup-model-object (creator-name, default: #f, error-if-circular?: #f)) // If there's no constructor model, or if we can't use it yet, use // the default for now. %class-constructor(class) := dylan-value(#"default-class-constructor"); end; %class-constructor(class) end; end method; define method ^class-constructor-setter (constructor :: <&method>, class :: <&implementation-class>) => (constructor :: <&method>) %class-constructor(class) := constructor end method; //// //// SLOT-INITIALIZER-METHOD //// // Slot initializer methods are generated for init functions or expressions, // another compile-time only distinction. define class <&slot-initializer-method> (<&lambda>) end; //// //// ACCESSOR-METHOD //// // TODO: figure out how to rearrange things so these can be abstract define /* abstract */ primary &class () runtime-constant &slot method-slot-descriptor, init-value: #f, init-keyword: slot-descriptor:; slot ^function-signature :: false-or(<&signature>), init-value: #f, init-keyword: signature:; end &class ; /* define method initialize (function :: <&accessor-method>, #key) next-method(); function end method; */ define /* abstract */ &class () end &class ; define /* abstract */ &class () end &class ; define /* abstract */ &class () end &class ; define /* abstract */ &class () end &class ; define &class (, ) end &class ; //define &class (, ) //end &class ; define method parameters-dynamic-extent (m :: <&getter-method>) #[] end method; define &class (, ) end &class ; //define &class (, ) //end &class ; define method parameters-dynamic-extent (m :: <&setter-method>) #[1] end method; define &class (, ) end &class ; //define &class (, // ) //end &class ; define method parameters-dynamic-extent (m :: <&repeated-getter-method>) #[1] end method; define &class (, ) end &class ; //define &class (, // ) //end &class ; define method parameters-dynamic-extent (m :: <&repeated-setter-method>) #[1, 2] end method; /* define method ^slot-accessor-name (m :: <&getter-method>) #"dynamic-slot-accessor" end method; define method ^slot-accessor-name (m :: <&setter-method>) #"dynamic-slot-accessor-setter" end method; define method ^slot-accessor-name (m :: <&repeated-getter-method>) #"dynamic-repeated-slot-accessor" end method; define method ^slot-accessor-name (m :: <&repeated-setter-method>) #"dynamic-repeated-slot-accessor-setter" end method; */ define generic ^accessor-method-xep-string (m :: <&accessor-method>) => (v :: ); define method ^accessor-method-xep-string (m :: <&repeated-getter-method>) => (v :: ) "slotacc_repeated_instance_getter_xep" end method; define method ^accessor-method-xep-string (m :: <&repeated-setter-method>) => (v :: ) "slotacc_repeated_instance_setter_xep" end method; define method ^accessor-method-xep-string (m :: <&getter-method>) => (v :: ) if (instance?(^method-slot-descriptor(m), <&any-class-slot-descriptor>)) "slotacc_single_q_class_getter_xep" else "slotacc_single_q_instance_getter_xep" end if end method; define method ^accessor-method-xep-string (m :: <&setter-method>) => (v :: ) if (instance?(^method-slot-descriptor(m), <&any-class-slot-descriptor>)) "slotacc_single_q_class_setter_xep" else "slotacc_single_q_instance_setter_xep" end if end method; // markt, this represents a copy-down method skeleton. define &class () end &class; define &class (, ) end &class; define &class (, ) end &class; define method ^make (class == <©-down-method>, #rest all-keys, #key signature-spec, #all-keys) => (res :: <©-down-method>) apply(^make, if (spec-argument-key?(signature-spec)) <&keyword-copy-down-method> else <&simple-copy-down-method> end if, all-keys) end method; //// //// CODE //// define abstract class <&runtime-object> () end class; define method function (fn :: <&callable-object>) fn end; define abstract primary class <&code> (, , <&callable-object>) slot function = #f, init-keyword: function:; end class; /// FOR NOW CODE IS ALWAYS ASSOCIATED WITH ITS CONTAINING FUNCTION /// THIS MIGHT CHANGE WHEN WE CREATE ON THE FLY IEP'S FOR REP'S define property-delegation (<&code>, function) model-definition, model-creator end property-delegation; //// //// LAMBDA-OR-CODE //// define constant <&lambda-or-code> = type-union(<&lambda>, <&code>); //// //// ENTRY-POINTS //// define abstract primary compiler-class () end; define abstract primary compiler-class () end; /// TODO: THIS CODE SLOT IS ONLY USED BY C-BACK-END /// WOULD LIKE TO MOVE THIS TO A SIDE TABLE define primary compiler-class () slot code = #f; end compiler-class; define primary compiler-class () end; define method function (i :: <&deferred-iep>) let f = next-method(); if (instance?(f, <&function>)) f else dylan-value(f) end end method; define method model-creator (i :: <&deferred-iep>) model-creator(function(i)) end method; define abstract class <&shared-entry-point> (<&runtime-object>, ) keyword function:; constant slot ^entry-point-key? :: = #f, init-keyword: key?:; constant slot ^entry-point-rest? :: = #f, init-keyword: rest?:; constant slot ^entry-point-number-required :: = 0, init-keyword: number-required:; constant slot ^entry-point-number-keys :: = 0, init-keyword: number-keys:; end class; ignore(^entry-point-number-keys); // HACK: STAYING OR GOING? define method ^entry-point-name (ep :: <&shared-entry-point>) => (res :: ) "" end method; define method ^entry-point-optionals? (ep :: <&shared-entry-point>) => (res :: ) ^entry-point-key?(ep) | ^entry-point-rest?(ep) end method; define constant $max-shared-entry-point-top-cache-size = 4; define constant $max-number-required = 256; // define constant $max-number-keywords = 256; define constant = ; define function make-shared-entry-point-cache () => (res :: ) make(, size: $max-shared-entry-point-top-cache-size) end function; define inline function lookup-shared-entry-point (cache :: , type :: , sig-spec :: ) => (res :: <&shared-entry-point>) local method as-int (x :: ) => (res :: ) if (x) 1 else 0 end end method; let k = spec-argument-key?(sig-spec) ~== #f; let kn = spec-argument-number-keys(sig-spec); let r = spec-argument-rest?(sig-spec); let i = as-int(k) * 2 + as-int(r); let v = element(cache, i, default: #f) | (element(cache, i) := make(, size: $max-number-required)); let n = spec-argument-number-required(sig-spec); let kv = element(v, n, default: #f) | (element(v, n) := make()); let e = element(kv, kn, default: #f) | (element(kv, kn) := make(type, key?: k, rest?: r, number-required: n, number-keys: kn)); e end function; define abstract class <&xep> (<&shared-entry-point>) end class; define method ^make (class == <&xep>, #key function, #all-keys) => (res :: <&xep>) ^make-xep(function) end method; define method ^xep (f :: <&function>) => (res :: <&xep>) make(<&xep>, function: f); end method; define method ^xep-setter (value, f :: <&function>) end method; define class <&generic-function-xep> (<&xep>) end class; define constant $generic-function-xeps :: = make-shared-entry-point-cache(); define method ^make-xep (function :: <&generic-function>) => (res :: <&generic-function-xep>) lookup-shared-entry-point ($generic-function-xeps, <&generic-function-xep>, signature-spec(function)) end method; define abstract class <&method-xep> (<&xep>) end class; define class <&lambda-xep> (<&method-xep>) end class; define constant $lambda-xeps :: = make-shared-entry-point-cache(); define method ^make-xep (function :: <&lambda>) => (res :: <&lambda-xep>) lookup-shared-entry-point ($lambda-xeps, <&lambda-xep>, signature-spec(function)) end method; define abstract class <&slot-accessor-xep> (<&method-xep>) constant slot ^entry-point-name :: = ""; end class; define class <&slot-getter-xep> (<&slot-accessor-xep>) inherited slot ^entry-point-number-required = 1; inherited slot ^entry-point-name = "slotacc_single_q_instance_getter_xep"; end class; define class <&class-slot-getter-xep> (<&slot-getter-xep>) inherited slot ^entry-point-name = "slotacc_single_q_class_getter_xep"; end class; define constant $slot-getter-xep = make(<&slot-getter-xep>); define constant $class-slot-getter-xep = make(<&class-slot-getter-xep>); define method ^make-xep (function :: <&getter-method>) => (res :: <&slot-getter-xep>) if (instance?(^method-slot-descriptor(function), <&any-class-slot-descriptor>)) $class-slot-getter-xep else $slot-getter-xep end if end method; define class <&slot-setter-xep> (<&slot-accessor-xep>) inherited slot ^entry-point-number-required = 2; inherited slot ^entry-point-name = "slotacc_single_q_instance_setter_xep"; end class; define class <&class-slot-setter-xep> (<&slot-setter-xep>) inherited slot ^entry-point-name = "slotacc_single_q_class_setter_xep"; end class; define constant $slot-setter-xep = make(<&slot-setter-xep>); define constant $class-slot-setter-xep = make(<&class-slot-setter-xep>); define method ^make-xep (function :: <&setter-method>) => (res :: <&slot-setter-xep>) if (instance?(^method-slot-descriptor(function), <&any-class-slot-descriptor>)) $class-slot-setter-xep else $slot-setter-xep end if end method; define class <&repeated-slot-getter-xep> (<&slot-getter-xep>) inherited slot ^entry-point-number-required = 2; inherited slot ^entry-point-name = "slotacc_repeated_instance_getter_xep"; end class; define constant $repeated-slot-getter-xep = make(<&repeated-slot-getter-xep>); define method ^make-xep (function :: <&repeated-getter-method>) => (res :: <&repeated-slot-getter-xep>) $repeated-slot-getter-xep end method; define class <&repeated-slot-setter-xep> (<&slot-setter-xep>) inherited slot ^entry-point-number-required = 3; inherited slot ^entry-point-name = "slotacc_repeated_instance_setter_xep"; end class; define constant $repeated-slot-setter-xep = make(<&repeated-slot-setter-xep>); define method ^make-xep (function :: <&repeated-setter-method>) => (res :: <&repeated-slot-setter-xep>) $repeated-slot-setter-xep end method; define abstract class <&mep> (<&shared-entry-point>) end class; define method ^make (class == <&mep>, #key function, #all-keys) => (res :: <&mep>) ^make-mep(function) end method; define abstract class <&method-mep> (<&mep>) end class; define class <&keyword-method-mep> (<&method-mep>) end class; define constant $keyword-method-meps :: = make-shared-entry-point-cache(); define method ^make-mep (function :: <&keyword-method>) => (res :: <&keyword-method-mep>) lookup-shared-entry-point ($keyword-method-meps, <&keyword-method-mep>, signature-spec(function)) end method; define constant <&kernel-ep> = type-union(<&any-kernel-ep>, <&xep>); // define constant <&code-based-ep> = type-union(<&any-code-based-ep>, <&mep>); define method lambda-top-level? (c :: <&code>) => (top-level? :: ) lambda-top-level?(function(c)) end; define method lookup-compile-stage-function (accessor :: <&code>) => (function :: false-or()) lookup-compile-stage-function(function(accessor)) end method; define property-delegation (<&iep>, function) parameters, environment, body, data, xep, keyword-specifiers, maximum-label, name, binding end property-delegation; define property-delegation-getters (<&iep>, function) named? :: end property-delegation-getters; define compiler-open generic frame-size (x) => (y); define method frame-size (lambda :: <&lambda>) => (result :: ) lambda.environment.frame-size end method; //// //// DOMAIN //// define abstract primary &class () runtime-constant lazy &slot domain-library :: , init-keyword: library:; lazy &slot domain-next /* :: false-or() */, init-value: #f, init-keyword: next:; constant slot ^domain-types, required-init-keyword: domain-types:; end &class; define method ^initialize (d :: <&domain>, #key) next-method(); ^domain-library(d) := ^home-library(model-module-model(d)) end method; define generic ^domain-type (object :: <&domain>, index :: ) => (t :: <&type>); define generic ^domain-type-setter (value :: <&type>, object :: <&domain>, index :: ); define generic ^domain-number-required (object :: <&domain>) => (n :: ); define method ^domain-number-required (d :: <&domain>) => (n :: ) size(^domain-types(d)) end method; define method ^domain-type (d :: <&domain>, i :: ) => (t :: <&type>) element(^domain-types(d), i) end method; define primary &class () lazy constant &slot domain-method :: , required-init-keyword: method:; end &class; define primary &class () repeated &slot domain-type :: , init-value: , size-getter: domain-number-required, size-init-keyword: size:, size-init-value: 0; end &class; define method ^initialize (d :: <&standalone-domain>, #key domain-types :: ) next-method(); let siz :: = size(domain-types); ^domain-type-values(d) := make(, size: siz); for (i :: from 0, t :: <&type> in domain-types) ^domain-type(d, i) := mapped-model(t) end for; end method; define method ^domain-number-required (object :: <&standalone-domain>) => (n :: ) size(^domain-type-values(object)) end method; // TODO: The size-getter: option isn't spotted as an accessor name by the // define &class macro, so have to hook up the compile-stage function // by hand. Fix! define &override-function ^domain-number-required end; define method ^domain-type (object :: <&standalone-domain>, index :: ) => (t :: <&type>) element(^domain-type-values(object), index) end method; define method ^domain-type-setter (value :: <&type>, object :: <&standalone-domain>, index :: ) element(^domain-type-values(object), index) := value end method; //// //// ENGINE-NODES //// // **** All the following constants are copied out of D-lib-dylan:dispatch-prologue.dylan. // **** They are also exported from dfmc-modeling. define constant engine-node$k-absent = 0; define constant engine-node$k-inapplicable = 1; define constant engine-node$k-unkeyed-single-method = 2; define constant engine-node$k-implicit-keyed-single-method = 3; define constant engine-node$k-explicit-keyed-single-method = 4; define constant engine-node$k-unrestricted-keyed-single-method = 5; /* define constant engine-node$k-reserved-terminal-n-a = 6; define constant engine-node$k-reserved-terminal-n-b = 7; define constant engine-node$k-reserved-terminal-n-c = 8; define constant engine-node$k-reserved-terminal-n-d = 9; define constant engine-node$k-reserved-terminal-n-e = 10; define constant engine-node$k-reserved-terminal-n-f = 11; define constant engine-node$k-reserved-terminal-n-g = 12; // define constant engine-node$k-reserved-terminal-n-h = 13; define constant engine-node$k-profiling-cache-header = 13; */ define constant engine-node$k-cache-header = 14; define constant engine-node$k-ambiguous-methods = 15; /* define constant engine-node$k-first-slot-engine-node = 16; define constant engine-node$k-boxed-instance-slot-getter = 16; define constant engine-node$k-boxed-instance-slot-setter = 17; define constant engine-node$k-boxed-repeated-instance-slot-getter = 18; define constant engine-node$k-boxed-repeated-instance-slot-setter = 19; define constant engine-node$k-boxed-class-slot-getter = 20; define constant engine-node$k-boxed-class-slot-setter = 21; define constant engine-node$k-raw-byte-repeated-instance-slot-getter = 22; define constant engine-node$k-raw-byte-repeated-instance-slot-setter = 23; define constant engine-node$k-reserved-slot-a-getter = 24; define constant engine-node$k-reserved-slot-a-setter = 25; define constant engine-node$k-reserved-slot-b-getter = 26; define constant engine-node$k-reserved-slot-b-setter = 27; */ define constant engine-node$k-reserved-repeated-slot-a-getter = 28; // define constant engine-node$k-reserved-repeated-slot-a-setter = 29; // define constant engine-node$k-reserved-repeated-slot-b-getter = 30; define constant engine-node$k-reserved-repeated-slot-b-setter = 31; // define constant engine-node$k-slot-engine-node-count = 16; define constant engine-node$k-typecheck = 32; define constant engine-node$k-if-type = 33; define constant engine-node$k-linear-by-class = 34; define constant engine-node$k-hashed-by-class = 35; define constant engine-node$k-linear-by-singleton-class = 36; define constant engine-node$k-hashed-by-singleton-class = 37; define constant engine-node$k-immediate-linear-singleton = 38; //define constant engine-node$k-immediate-hashed-noreloc-singleton = 39; //define constant engine-node$k-immediate-hashed-singleton = 40; define constant engine-node$k-value-object-linear-singleton = 41; define constant engine-node$k-monomorphic-by-class = 42; /* define constant engine-node$k-reserved-discriminator-a = 43; define constant engine-node$k-reserved-discriminator-b = 44; define constant engine-node$k-reserved-discriminator-c = 45; define constant engine-node$k-reserved-discriminator-d = 46; define constant engine-node$k-reserved-discriminator-e = 47; define constant engine-node$k-reserved-discriminator-f = 48; define constant engine-node$k-reserved-discriminator-g = 49; define constant engine-node$k-reserved-discriminator-h = 50; define constant engine-node$k-reserved-discriminator-i = 51; define constant engine-node$k-reserved-discriminator-j = 52; define constant engine-node$k-reserved-discriminator-k = 53; define constant engine-node$k-reserved-discriminator-l = 54; define constant engine-node$k-reserved-discriminator-m = 55; define constant engine-node$k-reserved-discriminator-n = 56; define constant engine-node$k-reserved-discriminator-o = 57; define constant engine-node$k-reserved-discriminator-p = 58; define constant engine-node$k-reserved-discriminator-q = 59; define constant engine-node$k-reserved-discriminator-r = 60; define constant engine-node$k-reserved-discriminator-s = 61; define constant engine-node$k-reserved-discriminator-t = 62; define constant engine-node$k-reserved-discriminator-u = 63; */ define constant properties$m-entry-type = 63; // define constant properties$s-entry-type = 6; define constant properties$v-entry-type = 0; // define constant properties$v-data = properties$s-entry-type; define constant engine-node$v-data-start = 14; // Single method engine node properties. define constant smen$v-nrequired = 6; define constant smen$s-nrequired = 8; define constant smen$m-nrequired = ash(ash(1, smen$s-nrequired) - 1, smen$v-nrequired); define constant smen$v-restp = 14; define constant smen$m-restp = ash(1, smen$v-restp); // define constant smen$v-data-start = 15; define constant $simple-typechecked-cache-arguments-limit = 8; define constant stchen$v-checkedmask = engine-node$v-data-start; define constant stchen$s-checkedmask = $simple-typechecked-cache-arguments-limit; define constant stchen$m-checkedmask = ash(ash(1, stchen$s-checkedmask) - 1, stchen$v-checkedmask); define constant $partial-dispatch-arguments-limit = 8; define constant pdisp$v-typemask = engine-node$v-data-start; define constant pdisp$s-typemask = $partial-dispatch-arguments-limit; define constant pdisp$m-typemask = ash(ash(1, pdisp$s-typemask) - 1, pdisp$v-typemask); define constant discriminator$v-argnum = 6; define constant discriminator$s-argnum = 8; define constant discriminator$m-argnum = ash(ash(1, discriminator$s-argnum) - 1, discriminator$v-argnum); define constant discriminator$v-nrequired = 14; define constant discriminator$s-nrequired = 8; define constant discriminator$m-nrequired = ash(ash(1, discriminator$s-nrequired) - 1, discriminator$v-nrequired); define constant discriminator$v-restp = 22; // define constant discriminator$m-restp = ash(1, discriminator$v-restp); // define constant discriminator$v-data-start = 23; define constant $engine-node-callback-names :: = #[#"%gf-dispatch-absent", // 0, absent, general-engine-node-n #"%gf-dispatch-inapplicable", // 1, inapplicable, general-engine-node-spread #f, // 2, unkeyed-single-method, single-method #f, // 3, implicit-keyed-single-method, implicit-keyed-single-method #f, // 4, explicit-keyed-single-method, explicit-keyed-single-method #f, // 5, unrestricted-keyed-single-method, unrestricted-keyed-single-method #f, // 6, reserved-terminal-n-a, general-engine-node-n-engine #f, // 7, reserved-terminal-n-b, general-engine-node-n-engine #f, // 8, reserved-terminal-n-c, general-engine-node-n-engine #f, // 9, reserved-terminal-n-d, general-engine-node-n-engine #f, // 10, reserved-terminal-n-e, general-engine-node-n-engine #f, // 11, reserved-terminal-n-f, general-engine-node-n-engine #f, // 12, reserved-terminal-n-g, general-engine-node-n-engine #f, // 13, profiling-cache-header, general-engine-node-n #f, // 14, cache-header, general-engine-node-n #"%gf-dispatch-ambiguous-methods", // 15, ambiguous-methods, general-engine-node-spread #f, // 16, boxed-instance-slot-getter, boxed-instance-slot-getter #f, // 17, boxed-instance-slot-setter, boxed-instance-slot-setter #f, // 18, boxed-repeated-instance-slot-getter, boxed-repeated-instance-slot-getter #f, // 19, boxed-repeated-instance-slot-setter, boxed-repeated-instance-slot-setter #"%gf-dispatch-boxed-class-slot-getter",// 20, boxed-class-slot-getter, general-engine-node-1 #"%gf-dispatch-boxed-class-slot-setter",// 21, boxed-class-slot-setter, general-engine-node-2 #f, // 22, raw-byte-repeated-instance-slot-getter, raw-byte-repeated-instance-slot-getter #f, // 23, raw-byte-repeated-instance-slot-setter, raw-byte-repeated-instance-slot-setter #f, // 24, reserved-slot-a-getter, general-engine-node-1 #f, // 25, reserved-slot-a-setter, general-engine-node-2 #f, // 26, reserved-slot-b-getter, general-engine-node-1 #f, // 27, reserved-slot-b-setter, general-engine-node-2 #f, // 28, reserved-repeated-slot-a-getter, general-engine-node-2 #f, // 29, reserved-repeated-slot-a-setter, general-engine-node-3 #f, // 30, reserved-repeated-slot-b-getter, general-engine-node-2 #f, // 31, reserved-repeated-slot-b-setter, general-engine-node-3 #"%gf-dispatch-typecheck", // 32, typecheck, discriminate-on-argument #"%gf-dispatch-if-type", // 33, if-type, discriminate-on-argument #"%gf-dispatch-linear-by-class", // 34, linear-by-class, discriminate-on-argument #"%gf-dispatch-hashed-by-class", // 35, hashed-by-class, discriminate-on-argument #"%gf-dispatch-linear-by-singleton-class",// 36, linear-by-singleton-class, discriminate-on-argument #"%gf-dispatch-hashed-by-singleton-class",// 37, hashed-by-singleton-class, discriminate-on-argument #"%gf-dispatch-immediate-linear-singleton",// 38, immediate-linear-singleton, discriminate-on-argument #"%gf-dispatch-immediate-hashed-noreloc-singleton",// 39, immediate-hashed-noreloc-singleton, discriminate-on-argument #"%gf-dispatch-immediate-hashed-singleton",// 40, immediate-hashed-singleton, discriminate-on-argument #"%gf-dispatch-slow-linear-singleton", // 41, value-object-linear-singleton, discriminate-on-argument #f, // 42, monomorphic-by-class, discriminate-on-argument #f, // 43, reserved-discriminator-a, discriminate-on-argument #f, // 44, reserved-discriminator-b, discriminate-on-argument #f, // 45, reserved-discriminator-c, discriminate-on-argument #f, // 46, reserved-discriminator-d, discriminate-on-argument #f, // 47, reserved-discriminator-e, discriminate-on-argument #f, // 48, reserved-discriminator-f, discriminate-on-argument #f, // 49, reserved-discriminator-g, discriminate-on-argument #f, // 50, reserved-discriminator-h, discriminate-on-argument #f, // 51, reserved-discriminator-i, discriminate-on-argument #f, // 52, reserved-discriminator-j, discriminate-on-argument #f, // 53, reserved-discriminator-k, discriminate-on-argument #f, // 54, reserved-discriminator-l, discriminate-on-argument #f, // 55, reserved-discriminator-m, discriminate-on-argument #f, // 56, reserved-discriminator-n, discriminate-on-argument #f, // 57, reserved-discriminator-o, discriminate-on-argument #f, // 58, reserved-discriminator-p, discriminate-on-argument #f, // 59, reserved-discriminator-q, discriminate-on-argument #f, // 60, reserved-discriminator-r, discriminate-on-argument #f, // 61, reserved-discriminator-s, discriminate-on-argument #f, // 62, reserved-discriminator-t, discriminate-on-argument #f // 63, reserved-discriminator-u, discriminate-on-argument ]; define constant $engine-node-entry-point-names :: = #[#"general-engine-node-n", // 0, absent #"general-engine-node-spread", // 1, inapplicable #"single-method", // 2, unkeyed-single-method #"implicit-keyed-single-method", // 3, implicit-keyed-single-method #"explicit-keyed-single-method", // 4, explicit-keyed-single-method #"unrestricted-keyed-single-method",// 5, unrestricted-keyed-single-method #"general-engine-node-n", // 6, reserved-terminal-n-a #"general-engine-node-n", // 7, reserved-terminal-n-b #"general-engine-node-n", // 8, reserved-terminal-n-c #"general-engine-node-n", // 9, reserved-terminal-n-d #"general-engine-node-n", // 10, reserved-terminal-n-e #"general-engine-node-n", // 11, reserved-terminal-n-f #"general-engine-node-n", // 12, reserved-terminal-n-g #"profiling-cache-header", // 13, profiling-cache-header #"cache-header", // 14, cache-header #"ambiguous-methods", // 15, ambiguous-methods #"boxed-instance-slot-getter", // 16, boxed-instance-slot-getter #"boxed-instance-slot-setter", // 17, boxed-instance-slot-setter #"boxed-repeated-instance-slot-getter",// 18, boxed-repeated-instance-slot-getter #"boxed-repeated-instance-slot-setter",// 19, boxed-repeated-instance-slot-setter #"general-engine-node-1", // 20, boxed-class-slot-getter #"general-engine-node-2", // 21, boxed-class-slot-setter #"raw-byte-repeated-instance-slot-getter",// 22, raw-byte-repeated-instance-slot-getter #"raw-byte-repeated-instance-slot-setter",// 23, raw-byte-repeated-instance-slot-setter #"general-engine-node-1", // 24, reserved-slot-a-getter #"general-engine-node-2", // 25, reserved-slot-a-setter #"general-engine-node-1", // 26, reserved-slot-b-getter #"general-engine-node-2", // 27, reserved-slot-b-setter #"general-engine-node-2", // 28, reserved-repeated-slot-a-getter #"general-engine-node-3", // 29, reserved-repeated-slot-a-setter #"general-engine-node-2", // 30, reserved-repeated-slot-b-getter #"general-engine-node-3", // 31, reserved-repeated-slot-b-setter #"typecheck-discriminator", // 32, typecheck #"if-type-discriminator", // 33, if-type #"discriminate-on-argument", // 34, linear-by-class #"discriminate-on-argument", // 35, hashed-by-class #"discriminate-on-argument", // 36, linear-by-singleton-class #"discriminate-on-argument", // 37, hashed-by-singleton-class #"discriminate-on-argument", // 38, immediate-linear-singleton #"discriminate-on-argument", // 39, immediate-hashed-noreloc-singleton #"discriminate-on-argument", // 40, immediate-hashed-singleton #"discriminate-on-argument", // 41, value-object-linear-singleton #"monomorphic-by-class-discriminator", // 42, immediate-hashed-singleton #"discriminate-on-argument", // 43, reserved-discriminator-a #"discriminate-on-argument", // 44, reserved-discriminator-b #"discriminate-on-argument", // 45, reserved-discriminator-c #"discriminate-on-argument", // 46, reserved-discriminator-d #"discriminate-on-argument", // 47, reserved-discriminator-e #"discriminate-on-argument", // 48, reserved-discriminator-f #"discriminate-on-argument", // 49, reserved-discriminator-g #"discriminate-on-argument", // 50, reserved-discriminator-h #"discriminate-on-argument", // 51, reserved-discriminator-i #"discriminate-on-argument", // 52, reserved-discriminator-j #"discriminate-on-argument", // 53, reserved-discriminator-k #"discriminate-on-argument", // 54, reserved-discriminator-l #"discriminate-on-argument", // 55, reserved-discriminator-m #"discriminate-on-argument", // 56, reserved-discriminator-n #"discriminate-on-argument", // 57, reserved-discriminator-o #"discriminate-on-argument", // 58, reserved-discriminator-p #"discriminate-on-argument", // 59, reserved-discriminator-q #"discriminate-on-argument", // 60, reserved-discriminator-r #"discriminate-on-argument", // 61, reserved-discriminator-s #"discriminate-on-argument", // 62, reserved-discriminator-t #"discriminate-on-argument" // 63, reserved-discriminator-u ]; define abstract primary compiler-class () slot ^engine-node-ep-properties :: , init-value: 0; constant slot ^engine-node, required-init-keyword: engine-node:; end compiler-class; define method ^initialize (ep :: <&engine-node-ep>, #rest all-keys, #key properties, #all-keys) next-method(); if (~properties) apply(initialize-packed-slots, ep, all-keys) end; end method; // An entry point of a object. We not only associate with a function, // but also know which argument number will be discriminated on. define primary compiler-class () end compiler-class; // An entry point of an engine node which is associated with a particular // function (hence we can know what the calling sequence will be like in advance). define primary compiler-class () // But it inherits the function slot from or somesuch. end compiler-class; // An entry point of an engine node which may not be associated with // any particular function. define primary compiler-class () constant slot ^entry-point-name, required-init-keyword: entry-point-name:; end compiler-class; define leaf packed-slots ^engine-node-ep-properties (<&function-linked-engine-node-ep>, ) field slot ^engine-node-ep-number-required = 0, field-size: 8, init-keyword: number-required:; boolean slot ^engine-node-ep-optionals? = #f, init-keyword: optionals?:; end packed-slots; ignore(^engine-node-ep-optionals?); define abstract &class () end &class; define abstract primary &class () &slot properties :: , init-value: 0; end &class; define abstract primary &class (, ) weak &slot engine-node-callback, reinit-expression: ^compute-engine-node-callback(self); weak &slot engine-node-entry-point, reinit-expression: ^compute-engine-node-entry-point(self); end &class; define inline method ^entry-type-number (e :: <&engine-node>) => (n :: ); ash(logand(e.^properties, properties$m-entry-type), - properties$v-entry-type) end method; define method ^entry-type-number-setter (n :: , e :: <&engine-node>) => () e.^properties := logior(logand(e.^properties, lognot(properties$m-entry-type)), ash(n, properties$v-entry-type)); end method; define method ^entry-point-name (e :: <&engine-node>) => (name :: false-or()) $engine-node-entry-point-names[^entry-type-number(e)] end method; define method ^entry-point-name (ep :: <&engine-node-ep>) => (name :: false-or()) $engine-node-entry-point-names[^entry-type-number(^engine-node(ep))] end method; define method function (e :: <&engine-node>) => (v) #f end method; define macro concrete-engine-node-initialization-definer { define ?mods:* concrete-engine-node-initialization "<" ## ?:name ## ">" (?self:name, ?params:*) ?:body end } => { define ?mods method initialize (?self :: "<&" ## ?name ## ">", ?params) ^entry-type-number(?self) := engine-node-constant(?name); ?=next-method(); ?body end method } end macro; define macro engine-node-constant // If you've seen one cache header, you've seen them all. Unless it's a profiling cache header // engine node. { engine-node-constant(?:name ## "-profiling-cache-header-engine-node") } => { engine-node$k-profiling-cache-header } { engine-node-constant(?:name ## "-cache-header-engine-node") } => { engine-node$k-cache-header } { engine-node-constant(?:name ## "-engine-node") } => { "engine-node$k-" ## ?name } { engine-node-constant(?:name ## "-gf-cache") } => { "engine-node$k-" ## ?name } { engine-node-constant(?:name ## "-discriminator") } => { "engine-node$k-" ## ?name } // { engine-node-constant(?:name) } // => { "engine-node$k-" ## ?name } end macro; define generic ^compute-engine-node-entry-point (e :: <&engine-node>) => (ep :: <&engine-node-ep>); define generic ^compute-engine-node-callback (e :: <&engine-node>) => (cb); define method ^compute-engine-node-callback (e :: <&engine-node>) => (cb) with-dependent-context ($compilation of model-creator(e)) let entry-type :: = ^entry-type-number(e); let cb = $engine-node-callback-names[entry-type]; if (cb == #"%gf-dispatch-absent" & ~instance?(e, <&singular-terminal-engine-node>)) ^engine-node-callback(dylan-value(#"$absent-engine-node")) else cb & ^make(<&deferred-iep>, function: cb) end if end with-dependent-context; end method; define method ^compute-engine-node-entry-point (e :: <&engine-node>) => (ep :: <&engine-node-ep>) with-dependent-context ($compilation of model-creator(e)) ^make(<&rogue-engine-node-ep>, engine-node: e, entry-point-name: ^entry-point-name(e)) end with-dependent-context; end method; define method initialize (e :: <&engine-node>, #key) next-method(); e.^engine-node-entry-point := ^compute-engine-node-entry-point(e); e.^engine-node-callback := ^compute-engine-node-callback(e); end method; // Have to do this proxy business because engine nodes (specifically // <&deferred-iep>'s) mess around with their slots in a way that seems // to confuse the database... So I decided to finesse this whole thing // by recreating any nodes that get dumped. //define class () // slot dood-engine-node-class :: subclass(<&engine-node>), // required-init-keyword: class:; // slot dood-engine-node-entry-type, // required-init-keyword: entry-type:; // slot dood-engine-node-creator, // required-init-keyword: creator:; //end class; //define method dood-restore-proxy // (dood :: , proxy :: ) => (object) // with-dood-context (dood-root(dood)) // with-dependent ($top-level-processing of dood-engine-node-creator(proxy)) // make(dood-engine-node-class(proxy), // entry-type: dood-engine-node-entry-type(proxy)) // end with-dependent // end with-dood-context //end method; //define method dood-make-engine-node-proxy // (dood :: , e :: <&engine-node>) => (proxy) // make(, // class: object-class(e), // entry-type: ^entry-type-number(e), // creator: model-creator(e)) //end method; //define method dood-disk-object (dood :: , i :: <&engine-node>) => (res) // if (dylan-library-library-description?(dood-root(dood))) // dood-as-proxy(dood, i, dood-make-engine-node-proxy) // else // just a regular cross-library ref... // next-method() // end; //end method; define abstract primary &class () end &class; define abstract primary &class () end &class; define abstract primary &class () end &class; define abstract primary &class () end &class; define abstract primary &class () &slot cache-header-engine-node-next, init-keyword: next:, init-value: #f; &slot cache-header-engine-node-parent, init-keyword: parent:, init-value: #f; slot function, required-init-keyword: function:; end &class; define method ^initialize (e :: <&cache-header-engine-node>, #key parent, function) next-method(); if (~^cache-header-engine-node-parent(e)) ^cache-header-engine-node-parent(e) := function end; if (~^cache-header-engine-node-next(e)) ^cache-header-engine-node-next(e) := dylan-value(#"$absent-engine-node"); end; end method; define method ^compute-engine-node-entry-point (e :: <&cache-header-engine-node>) => (ep :: <&engine-node-ep>) with-dependent-context ($compilation of model-creator(e)) let g :: <&generic-function> = function(e); // if (instance?(^%gf-cache(g), <&engine-node>)) let sig = ^function-signature(g); ^make(<&function-linked-engine-node-ep>, number-required: ^signature-number-required(sig), optionals?: ^signature-optionals?(sig), function: g, engine-node: e) // else // ^make(<&rogue-engine-node-ep>, // entry-point-name: #"general-engine-node-n", // engine-node: e) // end if end with-dependent-context; end method; define primary &class () end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; define primary &class () end &class; define concrete-engine-node-initialization (e, #key checkedmask :: = 0) ^properties(e) := logior(ash(checkedmask, stchen$v-checkedmask), ^properties(e)); end concrete-engine-node-initialization; define inline-only function ^stchen-checkedmask (e :: <&simple-typechecked-cache-header-engine-node>) => (checkedmask :: ) ash(logand(^properties(e), stchen$m-checkedmask), - stchen$v-checkedmask) end function; define generic ^partial-dispatch-type (object, index :: ) => (t :: <&type>); define generic ^partial-dispatch-type-setter (value :: <&type>, object, index :: ); define generic ^number-types (object) => (n :: ); define primary &class () repeated &slot partial-dispatch-type :: , init-value: , size-getter: number-types, size-init-keyword: size:, size-init-value: 0; end &class; define inline function ^pdisp-type-mask (e :: <&partial-dispatch-cache-header-engine-node>) => (checkedmask :: ) ash(logand(^properties(e), pdisp$m-typemask), - pdisp$v-typemask) end function; define concrete-engine-node-initialization (e, #key types :: false-or(), type-mask :: = 0) // HACK: CALLED WHEN FINALIZING COPYING, // ENTRY-POINT INITIALIZATION SHOULD BE SPLIT OUT when (types) let siz :: = size(types); let vals = make(, size: siz); ^partial-dispatch-type-values(e) := vals; ^properties(e) := logior(ash(type-mask, pdisp$v-typemask), ^properties(e)); for (i :: from 0, t :: <&type> in types) vals[i] := mapped-model(t) end for; end when; end concrete-engine-node-initialization; define method ^number-types (object :: <&partial-dispatch-cache-header-engine-node>) => (res :: ) size(^partial-dispatch-type-values(object)) end method; // TODO: The size-getter: option isn't spotted as an accessor name by the // define &class macro, so have to hook up the compile-stage function // by hand. Fix! define &override-function ^number-types end; define method ^partial-dispatch-type (object :: <&partial-dispatch-cache-header-engine-node>, index :: ) => (t :: <&type>) element(^partial-dispatch-type-values(object), index) end method; define method ^partial-dispatch-type-setter (value :: <&type>, object :: <&partial-dispatch-cache-header-engine-node>, index :: ) element(^partial-dispatch-type-values(object), index) := value end method; define primary &class () end &class; define concrete-engine-node-initialization (e, #key ) end concrete-engine-node-initialization; define primary &class () &slot profiling-call-site-cache-header-engine-node-count-1; &slot profiling-call-site-cache-header-engine-node-count-2; &slot profiling-call-site-cache-header-engine-node-id; &slot profiling-call-site-cache-header-engine-node-library; slot profiling-call-site-cache-header-engine-node-call; end &class; define concrete-engine-node-initialization (e, #key ) let zero = make(<&raw-machine-word>, value: 0); ^profiling-call-site-cache-header-engine-node-count-1(e) := zero; ^profiling-call-site-cache-header-engine-node-count-2(e) := zero; let ld = current-library-description(); ^profiling-call-site-cache-header-engine-node-id(e) := library-generate-call-site-id(ld); ^profiling-call-site-cache-header-engine-node-library(e) := namespace-model(language-definition(ld)); end concrete-engine-node-initialization; define abstract primary &class () slot function, required-init-keyword: function:; end &class; define method ^discriminator-argnum (d :: <&discriminator>) => (argnum :: ); ash(logand(d.^properties, discriminator$m-argnum), - discriminator$v-argnum) end method; define method ^discriminator-nrequired (d :: <&discriminator>) => (argnum :: ); ash(logand(d.^properties, discriminator$m-nrequired), - discriminator$v-nrequired) end method; define method ^discriminator-optionals? (d :: <&discriminator>) => (optionals? :: ); logbit?(discriminator$v-restp, d.^properties) end method; define method initialize (d :: <&discriminator>, #key entry-type :: , argnum :: , function :: <&generic-function>) next-method(); let sig-spec = signature-spec(function); let req-size = spec-argument-number-required(sig-spec); let p :: = ^properties(d); let p :: = logior(ash(spec-argument-number-required(sig-spec), discriminator$v-nrequired), p); let p :: = logior(ash(if (spec-argument-optionals?(sig-spec)) 1 else 0 end, discriminator$v-restp), p); let p :: = logior(ash(argnum, discriminator$v-argnum), p); ^properties(d) := p; end method; define method ^compute-engine-node-entry-point (d :: <&discriminator>) => (ep :: <&engine-node-ep>); ^make(<&discriminator-ep>, engine-node: d, number-required: ^discriminator-nrequired(d), optionals?: ^discriminator-optionals?(d), function: function(d)) end method; // The absent engine node. There is only one, so they are all ==. define primary &class () end &class; define concrete-engine-node-initialization (self, #key) end concrete-engine-node-initialization; // define &override-function ^get-absent-engine-node () // ^make(<&absent-engine-node>, entry-type: 0) // end; define function source-constructor-for-$absent-engine-node () let a = ^make(<&absent-engine-node>, entry-type: engine-node$k-absent); #{ define constant $absent-engine-node = ?a /* get-absent-engine-node() */; } end function; /* define ^mapping => <&absent-engine-node> // &instance $absent-engine-node => source-constructor-for-$absent-engine-node(); end ^mapping; */ do-define-core-unadorned-definition(#"$absent-engine-node", source-constructor-for-$absent-engine-node); // The inapplicable engine node. There is only one, so they are all ==. define primary &class () end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; // define &override-function ^get-inapplicable-engine-node () // ^make(<&inapplicable-engine-node>, entry-type: 0) // end; define function source-constructor-for-$inapplicable-engine-node () let a = ^make(<&inapplicable-engine-node>, entry-type: engine-node$k-inapplicable); #{ define constant $inapplicable-engine-node = ?a /* get-inapplicable-engine-node() */; } end function; /* define ^mapping => <&inapplicable-engine-node> // &instance $inapplicable-engine-node => source-constructor-for-$inapplicable-engine-node(); end ^mapping; */ do-define-core-unadorned-definition(#"$inapplicable-engine-node", source-constructor-for-$inapplicable-engine-node); define primary &class () &slot ambiguous-methods-engine-node-ordered :: , required-init-keyword: ordered:; &slot ambiguous-methods-engine-node-ambig :: , required-init-keyword: ambig:; end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; // This is for when we have a method and must give it next-method // data. We hope and expect that many more effective methods will not // require this than will, and that assumption is based on our ability // to tell at runtime whether a method needs its extra-argument. // Overlay: method, data, keys define abstract primary &class () &slot single-method-engine-node-method :: , required-init-keyword: method:; &slot single-method-engine-node-data, required-init-keyword: data:; slot function, required-init-keyword: function:; end &class; define inline-only function ^smen-nrequired (e :: <&single-method-engine-node>) => (nreq :: ) ash(logand(^properties(e), smen$m-nrequired), - smen$v-nrequired) end function; define inline-only function ^smen-optionals? (e :: <&single-method-engine-node>) => (optionals? :: ) logbit?(smen$v-restp, ^properties(e)) end function; define method initialize (e :: <&single-method-engine-node>, #key method: meth) let sig-spec = signature-spec(meth); ^properties(e) := logior(^properties(e), ash(spec-argument-number-required(sig-spec), smen$v-nrequired), if (spec-argument-optionals?(sig-spec)) smen$m-restp else 0 end); next-method() end method; define method ^compute-engine-node-entry-point (e :: <&single-method-engine-node>) => (ep :: <&function-linked-engine-node-ep>) make(<&function-linked-engine-node-ep>, engine-node: e, function: ^single-method-engine-node-method(e), number-required: ^smen-nrequired(e), optionals?: ^smen-optionals?(e)) end method; define primary &class () end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; define abstract primary &class () end &class; define primary &class () &slot single-method-engine-node-keys :: , required-init-keyword: keys:; end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; define primary &class () end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; define primary &class () end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; define abstract primary &class () end &class; define abstract primary &class () &slot lckd-index :: , init-value: 0; &slot lckd-hits :: , init-value: 0; // ONLY FOR PROFILING end &class; define abstract primary &class () &slot %hckd-count :: , init-value: 0; &slot %hckd-limit :: , init-value: 0; end &class; define abstract &class () end &class; define abstract &class () &slot class-keyed-discriminator-default; end &class; define generic ^class-keyed-discriminator-table-element (object, index :: ) => (value); define generic ^class-keyed-discriminator-table-element-setter (value, object, index :: ); define generic ^class-keyed-discriminator-table-size (object) => (n :: ); ignore(^class-keyed-discriminator-table-size); define primary &class (, ) repeated &slot class-keyed-discriminator-table-element, init-value: #f, size-getter: class-keyed-discriminator-table-size, size-init-keyword: size:, size-init-value: 0; end &class; // HACK: SHOULDN'T GENERATE THESE IN THE FIRST PLACE ignore(^class-keyed-discriminator-table-element-values); ignore(^class-keyed-discriminator-table-element-values-setter); define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; define primary &class (, ) repeated &slot class-keyed-discriminator-table-element, init-value: #f, size-getter: class-keyed-discriminator-table-size, size-init-keyword: size:, size-init-value: 0; end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; define primary &class (, ) repeated &slot class-keyed-discriminator-table-element, init-value: #f, size-getter: class-keyed-discriminator-table-size, size-init-keyword: size:, size-init-value: 0; end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; define primary &class (, ) repeated &slot class-keyed-discriminator-table-element, init-value: #f, size-getter: class-keyed-discriminator-table-size, size-init-keyword: size:, size-init-value: 0; end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; // data slots overlay: typecheck-discriminator-type, typecheck-discriminator-next. define primary &class () &slot typecheck-discriminator-type, required-init-keyword: type:; &slot typecheck-discriminator-next, required-init-keyword: next:; end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; define primary &class (, ) &slot monomorphic-by-class-discriminator-key, required-init-keyword: key:; &slot monomorphic-by-class-discriminator-next, required-init-keyword: next:; end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; // Do one thing or another depending on whether a type test is satisfied. We // could make a typecase-like version of this if we found there were lots of // chains of them. define primary &class () &slot if-type-discriminator-type, required-init-keyword: type:; &slot if-type-discriminator-then, init-value: #f; &slot if-type-discriminator-else, init-value: #f; end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; // Data slots overlay: singleton-discriminator-table, singleton-discriminator-default. define abstract primary &class () &slot singleton-discriminator-table :: , required-init-keyword: table:; &slot singleton-discriminator-default, init-value: #f; end &class; define abstract primary &class () &slot lsd-index :: , init-value: 0; &slot lsd-hits :: , init-value: 0; // HACK: ONLY FOR PROFILING end &class; define primary &class (, ) end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; define primary &class (, ) end &class; define concrete-engine-node-initialization (e, #key) end concrete-engine-node-initialization; //// //// DOOD PROXIES //// /// ABSENT-ENGINE-NODE define class () end class; define method dood-make-binding-value-proxy (dood :: , object :: <&absent-engine-node>) => (proxy) make(, binding: dylan-canonical-binding(#"$absent-engine-node")); end method; /// INAPPLICABLE-ENGINE-NODE define class () end class; define method dood-make-binding-value-proxy (dood :: , object :: <&inapplicable-engine-node>) => (proxy) make(, binding: dylan-canonical-binding(#"$inapplicable-engine-node")); end method; //// SLOT ACCESS ENGINE NODES define abstract primary &class () end &class; define abstract &class () end &class; define abstract &class () end &class; define abstract &class () end &class; define abstract primary &class () &slot slot-engine-node-size-offset :: , init-value: 0; end &class; define abstract &class () end &class; define abstract &class () end &class; define abstract &class () end &class; define abstract &class () end &class; define primary &class (, , ) end &class; define primary &class (, , ) end &class; define primary &class (, , ) end &class; define primary &class (, , ) end &class; define primary &class (, , ) end &class; define primary &class (, , ) end &class; define primary &class (, , ) end &class; define primary &class (, , ) end &class; define abstract primary &class () end &class; define primary &class (, , ) end &class; define primary &class (, , ) end &class; /* define function ^slot-method-requiring-class-discrimination? (m :: <&method>) if (instance?(m, <&accessor-method>)) let m :: <&accessor-method> = m; let sd :: <&slot-descriptor> = ^method-slot-descriptor(m); let c :: <&class> = ^slot-owner(sd); ~^class-primary?(c) else #f end if end function; define constant slotdiscrim$v-offset = engine-node$v-data-start; define function ^slot-engine-node-offset-setter (offset :: , e :: <&slot-access-engine-node>) => (offset :: ); let mask :: = ash(1, slotdiscrim$v-offset) - 1; let props :: = ^properties(e); ^properties(e) := logior(ash(offset, slotdiscrim$v-offset), logand(props, mask)); let callbacks :: = $engine-node-callback-names; if (~(element(callbacks, logand(ash(props, - properties$v-entry-type), ash(1, properties$s-entry-type) - 1)))) // ^engine-node-raw-integer(e) := offset ^engine-node-callback(e) := offset end if; offset end function; define function ^callback-slot-engine-node-offset (e :: <&slot-access-engine-node>) => (offset :: ); ash(^properties(e), - slotdiscrim$v-offset) end function; */ //// METHOD define method method-binding-and-library (model :: <&method>) => (binding, library) values(model-variable-binding(model), model-library(model)) end method; define method method-number (defn :: ) => (number :: ) // the position of this defn among the method definitions for this gf // defined in this library. local-definition-number(defn, ) end method; define function domain-number (defn :: ) => (number :: ) local-definition-number(defn, ) end function; define function local-definition-number (defn :: , kind :: ) => (number :: ) with-dependent-context ($compilation of defn) let local-defs = untracked-lookup-local-modifying-definitions(form-variable-binding(defn)); let i :: = 0; block (return) for (def in local-defs) when (instance?(def, kind)) when (def == defn) return(i) end when; i := i + 1; end when; end for; error("UNABLE TO FIND METHOD %= IN LOCAL DEFINITIONS %=", defn, local-defs); end block end; end function; define method method-number (defn :: ) => (res :: singleton(#f)) #f end method; define method lookup-method-by-number (binding :: , index :: ) => (res :: <&method>) let local-models = untracked-lookup-certain-local-modifying-models (binding-variable-name(binding), method-definition?); let i :: = 0; let model = block (return) for (model in local-models) when (instance?(model, <&method>)) when (index = i) return(model) end when; i := i + 1; end when; end for end block; model end method; define class () constant slot dood-proxy-method-index :: false-or(), required-init-keyword: index:; constant slot dood-proxy-method-library :: false-or(), required-init-keyword: library:; end class; define method dood-make-cross-method-proxy (dood :: , class :: subclass(), object :: <&method>) => (proxy :: ) let (binding, library) = method-binding-and-library(object); make(class, binding: binding, library: language-definition(library), index: method-number(model-definition(object))) end method; define method dood-make-binding-value-proxy (dood :: , object :: <&method>) => (proxy) dood-make-cross-method-proxy(dood, , object) end method; define method dood-restore-proxy (dood :: , proxy :: ) => (object) let index = dood-proxy-method-index(proxy); if (index) with-dood-context (namespace-original-library(dood-proxy-method-library(proxy))) lookup-method-by-number(dood-proxy-binding(proxy), index) end with-dood-context; else next-method(); end; end method; /// IEP define class () end class; define method dood-make-binding-value-proxy (dood :: , object :: <&iep>) => (proxy) dood-make-cross-method-proxy (dood, , function(object)) end method; define method dood-restore-proxy (dood :: , proxy :: ) => (object) ^iep(next-method()) end method; // eof