Module: commands-internals Synopsis: Commands protocols and basic classes Author: Scott McKay, Hugh Greene 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 /// String-based commands define open abstract class () end class ; define open generic command-pattern-string (command :: ) => (pattern :: ); define open generic command-argument-names (command :: ) => (argument-names :: ); define open generic string-for-command (command :: ) => (string :: ); define open generic string-for-argument (server, command :: , name :: , value) => (string :: ); define open abstract primary class (, ) sealed constant slot command-pattern-string :: , required-init-keyword: pattern-string:; end class ; define macro string-command-definer { define ?modifiers:* string-command ?class:name (?superclasses:*) ?slots:* end } => { define constant "$" ## ?class ## "-names" :: = make(); define ?modifiers string-command-class ?class (?superclasses) sealed class slot command-argument-names :: = "$" ## ?class ## "-names", setter: #f; ?slots end; define string-command-slots ?class ?slots end; } end macro string-command-definer; define macro string-command-class-definer { define ?modifiers:* string-command-class ?class:name (?superclasses:*) ?slots:* end } => { define ?modifiers class ?class (?superclasses) ?slots end } slots: { } => { } { ?slot:*; ... } => { ?slot ... } slot: { ?modifiers:* named-argument ?arg-name:name is ?slot-name:name ?stuff:* } => { ?modifiers slot ?slot-name ?stuff; } { ?other:* } => { ?other; } end macro string-command-class-definer; define macro string-command-slots-definer { define string-command-slots ?class:name end } => { } { define string-command-slots ?class:name ?modifiers:* named-argument ?arg-name:name is ?slot-name:name ?stuff:*; ?more-slots:* end } => { "$" ## ?class ## "-names"[?#"arg-name"] := ?slot-name; define string-command-slots ?class ?more-slots end; } { define string-command-slots ?class:name ?other-slot:*; ?more-slots:* end } => { define string-command-slots ?class ?more-slots end; } end macro string-command-slots-definer; /// Argument substitution define method string-for-command (command :: ) => (string :: ) let server = command-server(command); let pattern = command-pattern-string(command); let length :: = size(pattern); let result :: = make(); let i :: = 0; while (i < length) let char :: = pattern[i]; case char = '$' & i < length - 2 & pattern[i + 1] = '(' => let open = i + 1; let close = find-char(pattern, ')', start: open, end: length); let name = close & copy-sequence(pattern, start: open + 1, end: close); let name = name & as(, name); let getter = element(command-argument-names(command), name, default: #f); let object = getter & getter(command); let string = string-for-argument(server, command, name, object); if (getter) for (j :: from 0 below size(string)) add!(result, string[j]) end; i := close + 1 else for (j :: from i to (close | length - 1)) add!(result, pattern[j]) end; i := (close | length - 1) + 1 end; char = '$' & i < length - 2 & pattern[i + 1] = '$' => add!(result, pattern[i]); i := i + 2; otherwise => add!(result, pattern[i]); i := i + 1; end end; as(, result) end method string-for-command; // We get the server and the name into the action so that the value can be // printed in special ways, e.g., some server might want booleans to be printed // as "yes" and "no" for some arguments define method string-for-argument (server, command :: , name :: , value) => (string :: ) object-to-string(value) end method string-for-argument; define sealed method find-char (string :: , char, #key start: _start = 0, end: _end = size(string)) => (index :: false-or()) block (return) for (index :: from _start below _end) when (string[index] = char) return(index) end end end end method find-char; /// Value printing define open generic object-to-string (object) => (string :: ); // Default just uses 'format-to-string' define method object-to-string (object :: ) => (string :: ) format-to-string("%=", object) end method object-to-string; define sealed method object-to-string (string :: ) => (string :: ) string end method object-to-string; define sealed method object-to-string (char :: ) => (string :: ) make(, size: 1, fill: char) end method object-to-string; define sealed method object-to-string (symbol :: ) => (string :: ) as(, symbol) end method object-to-string; define sealed method object-to-string (integer :: ) => (string :: ) integer-to-string(integer) end method object-to-string; define sealed method object-to-string (float :: ) => (string :: ) float-to-string(float) end method object-to-string; define method object-to-string (sequence :: ) => (string :: ) select (size(sequence)) 0 => ""; 1 => object-to-string(sequence[0]); otherwise => reduce1(method (s1, s2) concatenate(s1, ", ", s2) end method, map(object-to-string, sequence)) end end method object-to-string; /// Sample usage /* define open abstract primary string-command () named-argument pathname is %pathname :: , required-init-keyword: pathname:; named-argument start-line is %start-line :: = 0, init-keyword: start-line:; named-argument start-col is %start-col :: = 0, init-keyword: start-col:; named-argument end-line is %end-line :: = 0, init-keyword: end-line:; named-argument end-col is %end-col :: = 0, init-keyword: end-col:; end string-command ; define sealed class () keyword pattern-string: = "(new-file \"$(pathname)\");"; end class ; define sealed class () keyword pattern-string: = "(open-file \"$(pathname)\")" "(go-to \"$(pathname)\" $(start-line) $(start-col))" end class ; define sealed class () keyword pattern-string: = "(close-file \"$(pathname)\");"; end class ; define sealed class () keyword pattern-string: = "FileNew($(pathname));"; end class ; define sealed class () keyword pattern-string: = "FileOpen($(pathname));" "GoTo($(pathname), $(start-line), $(start-col));" end class ; define sealed class () keyword pattern-string: = "FileClose($(pathname));"; end class ; */