Module: dfmc-mangling 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 define constant $module-separator = "Y"; define constant $library-separator = "V"; define constant $local-suffix = "_"; define constant $hygiene-marker = "F"; define constant $escape-separator = "Z"; define constant $constant-prefix = "K"; define constant $symbol-prefix = "J"; define constant $indirection-prefix = "I"; define constant $wrapper-suffix = "W"; define constant $iep-suffix = "I"; define constant $method-mangled-marker-string = "M"; define constant $slot-mangled-marker-string = "H"; define constant $dylan-module-separator = "K"; define constant $domain-mangled-marker-string = "RD_"; // Note that the following must be characters rather than strings, since // the initialization of mangles tables assumes that. define constant $method-marker = '#'; define constant $method-mangled-marker = $method-mangled-marker-string[0]; define constant $slot-marker = ','; define constant $slot-mangled-marker = $slot-mangled-marker-string[0]; define constant $constant-marker = $constant-prefix[0]; define constant $iep-marker = $iep-suffix[0]; define constant $indirection-marker = $indirection-prefix[0]; define constant $wrapper-marker = $wrapper-suffix[0]; define constant $module-marker = $module-separator[0]; define constant $library-marker = $library-separator[0]; define constant $escape-marker = $escape-separator[0]; define constant $symbol-marker = $symbol-prefix[0]; define constant $local-marker = $local-suffix[0]; define constant $hygiene-char = $hygiene-marker[0]; define constant $dylan-module-marker = $dylan-module-separator[0]; define constant $all-prefix-markers = vector($constant-marker, $indirection-marker, $symbol-marker); define constant $all-suffix-markers = vector($local-marker, $wrapper-marker, $iep-marker); define constant $all-decoration-markers = concatenate($all-prefix-markers, $all-suffix-markers); define table $mangle-dylan-module = { #"dylan" => 'd', #"internal" => 'i', #"dylan-primitives" => 'p', #"dylan-extensions" => 'e', #"dylan-c-ffi" => 'c', #"dylan-incremental" => 'n', #"dylan-threads" => 't', #"dispatch-engine" => 'g', #"machine-word-lowlevel" => 'm' }; define constant $demangle-dylan-module = begin let tbl = make(); for (abbrev keyed-by mod in $mangle-dylan-module) element(tbl, abbrev) := mod; end for; tbl end; define constant $min-character-code = 0; define constant $max-character-code = 255; // We allow 8 bit ascii. /// MANGLING define constant $mangles-data = vector(#('-', '_'), #('!', 'X'), #('$', 'D'), #('%', 'P'), #('*', 'T'), #('/', 'S'), #('<', 'L'), #('>', 'G'), #('?', 'Q'), #('+', 'A'), #('&', 'B'), #('^', 'C'), #('_', 'U'), #('@', 'O'), #('=', 'E'), #('~', 'N'), list($method-marker, $method-mangled-marker), list($slot-marker, $slot-mangled-marker)); define abstract class () constant slot mangler-buffer = make(); constant slot mangler-table = make(, size: $max-character-code + 1); end class; define abstract class () end class; define class () end class; // Guarantee instantiability of the class. define sealed method make (c == , #rest keys, #key, #all-keys) => (mangler :: ) apply(make, , keys) end method; define class () // Options a assumed to be in the form of prefixes and/or // suffixes to the basic mangle. This are stored as // strings, which is convenient because they can be zero // or more characters in each case. slot mangler-prefix-options :: = ""; slot mangler-suffix-options :: = ""; end class; define method mangler-position (mangler :: ) => (res :: ) size(mangler-buffer(mangler)) end method; define method initialize (mangler :: , #key, #all-keys) => () next-method(); initialize-mangler-table(mangler); end method; // TODO: // At the moment, this method only deals with the options that are // needed by the debugger, and the processing of those keywords is // quite simple-minded. The interface and its implementation may need // to be generalized somewhat. define sealed method initialize (mangler :: , #key constant-object-extension = #f, wrapper-object-extension = #f, iep-extension = #f, #all-keys) => () next-method(); let prefix = ""; let suffix = ""; if (constant-object-extension) prefix := $constant-prefix; elseif (wrapper-object-extension) prefix := $constant-prefix; suffix := $wrapper-suffix; elseif (iep-extension) prefix := $constant-prefix; suffix := $iep-suffix; end if; mangler.mangler-prefix-options := prefix; mangler.mangler-suffix-options := suffix; end method; define method initialize-mangler-table (mangler :: ) => () let table = mangler-table(mangler); // fill with default manglings for (i from $min-character-code to $max-character-code) table[i] := concatenate ($escape-separator, mangle-integer(i), $escape-separator); end for; // fill in special cases for (mangle in $mangles-data) table[as(, mangle[0])] := mangle[1]; end for; // fill C allowable versions for (i from as(, 'a') to as(, 'z')) table[i] := as(, i); end for; for (i from as(, '0') to as(, '9')) table[i] := as(, i); end for; end method; define method mangler-as-string (mangler :: , #key start :: = 0) => (res :: ) // if (start = 0) // as(, mangler-buffer(mangler)) // else // as(, copy-sequence(mangler-buffer(mangler), start: start)) // end if let buffer :: = mangler-buffer(mangler); let buffer-size :: = size(buffer); let string :: = make(, size: buffer-size - start); // without-bounds-checks for (i :: from start below buffer-size, j :: from 0) string[j] := buffer[i]; end for; // end without-bounds-checks; string end method; // The method for is responsible for // installing the prefixes and suffixes in the final string. // (Is this the most efficient way? It certainly seems to be // the cleanest). define method mangler-as-string (mangler :: , #key start :: = 0) => (res :: ) concatenate (mangler.mangler-prefix-options, next-method(), mangler.mangler-suffix-options) end method; define method mangler-reset (mangler :: ) => (res :: ) size(mangler-buffer(mangler)) := 0; mangler end method; define inline method mangle-raw-into (mangler :: , name :: ) add!(mangler-buffer(mangler), name); end method; define inline method mangle-raw-into (mangler :: , name :: ) concatenate!(mangler-buffer(mangler), name); end method; define inline method mangle-raw-into (mangler :: , name :: ) concatenate! (mangler-buffer(mangler), as-lowercase(as(, name))); end method; define method mangle-name-into (mangler :: , name :: ) for (c in name) mangle-raw-into(mangler, mangler-table(mangler)[as(, c)]); end for; end method; define method mangle-name-into (mangler :: , name) mangle-name-into(mangler, as-lowercase(as(, name))) end method; define method mangle-name-raw (mangler :: , name) => (res :: ) mangler-reset(mangler); mangle-name-into(mangler, name); mangler-as-string(mangler) end method; define method mangle-name-locally (mangler :: , name) => (res :: ) mangler-reset(mangler); mangle-name-into(mangler, name); mangle-raw-into(mangler, $local-suffix); mangler-as-string(mangler) end method; define method mangle-name-hygienically (mangler :: , name, marker :: ) => (res :: ) mangler-reset(mangler); mangle-name-into(mangler, name); concatenate (mangler-as-string(mangler), $hygiene-marker, mangle-integer(marker)) end method; define method mangle-binding-spread (mangler :: , variable-name, module-name, library-name) => (res :: ) mangler-reset(mangler); mangle-name-into(mangler, variable-name); mangle-namespace-spread-into(mangler, module-name, library-name); mangler-as-string(mangler) end method; define method mangle-namespace-spread-into (mangler :: , module-name, library-name) local method non-dylan-mangle () unless (module-name = library-name) mangle-raw-into(mangler, $module-separator); mangle-name-into(mangler, module-name); end unless; mangle-raw-into(mangler, $library-separator); mangle-name-into(mangler, library-name); end method; if (as(, library-name) = #"dylan") let abbreviation = element($mangle-dylan-module, as(, module-name), default: #f); if (abbreviation) mangle-raw-into(mangler, $library-separator); mangle-raw-into(mangler, $dylan-module-separator); mangle-raw-into(mangler, abbreviation); else non-dylan-mangle() end if else non-dylan-mangle() end if; end method; define constant $number-characters :: = "0123456789"; define method mangle-integer (number :: ) => (mangled-number :: ) iterate process-integer (number :: = number, index :: = 1) let (quotient :: , remainder :: ) = truncate/(number, 10); let digit :: = $number-characters[remainder]; if (quotient = 0) let result :: = make(, size: index); result[0] := digit; result else let result :: = process-integer(quotient, index + 1); result[result.size - index] := digit; result end if; end iterate; end method; // Higher Level DFMC Mangling functions define inline method mangle-constant(name :: ) => (name :: ) concatenate($constant-prefix, name) end method; define inline method mangle-symbol(name :: ) => (name :: ) concatenate($constant-prefix, $symbol-prefix, name) end method; define inline method mangle-generic-method (mangler :: , name :: , number :: , method-library-name, generic-library-name) => (name :: ) let library-name = if (generic-library-name == method-library-name) "" else mangle-name-raw(mangler, method-library-name) end if; concatenate($constant-prefix, name, $method-mangled-marker-string, library-name, $method-mangled-marker-string, mangle-integer(number)) end method; define inline method mangle-local-method (name :: , number :: ) => (name :: ) concatenate($constant-prefix, name, $hygiene-marker, mangle-integer(number)) end method; define inline method mangle-domain (name :: , number :: , library-name :: ) => (name :: ) concatenate($constant-prefix, name, $domain-mangled-marker-string, library-name, $domain-mangled-marker-string, mangle-integer(number)) end method; define inline method mangle-slot-descriptor (mangler :: , slot-name :: , slot-library, owner-name :: , owner-module, owner-library) => (name :: ) if (slot-library == owner-library) concatenate($constant-prefix, slot-name, $slot-mangled-marker-string, owner-name) else let namespace-part :: = begin mangler-reset(mangler); mangle-namespace-spread-into(mangler, owner-module, owner-library); mangler-as-string(mangler) end; concatenate($constant-prefix, slot-name, $slot-mangled-marker-string, owner-name, namespace-part) end if end method; define inline method mangle-wrapper(name :: ) => (name :: ) concatenate($constant-prefix, name, $wrapper-suffix) end method; // eof