Artifact 118390306b21158a148f98da5d07a145270b566bbe357608be7a39327d9d6317:
- File
psl-1983/3-1/lpt/10-functions.lpt
— part of check-in
[eb17ceb7f6]
at
2020-04-21 19:40:01
on branch master
— Add Reduce 3.0 to the historical section of the archive, and some more
files relating to version sof PSL from the early 1980s. Thanks are due to
Paul McJones and Nelson Beebe for these, as well as to all the original
authors.git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/historical@5328 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 38238) [annotate] [blame] [check-ins using] [more...]
- File
psl-1983/lpt/10-functions.lpt
— part of check-in
[eb17ceb7f6]
at
2020-04-21 19:40:01
on branch master
— Add Reduce 3.0 to the historical section of the archive, and some more
files relating to version sof PSL from the early 1980s. Thanks are due to
Paul McJones and Nelson Beebe for these, as well as to all the original
authors.git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/historical@5328 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 38238) [annotate] [blame] [check-ins using]
PSL Manual 7 February 1983 Function Definition section 10.0 page 10.1 CHAPTER 10 CHAPTER 10 CHAPTER 10 FUNCTION DEFINITION AND BINDING FUNCTION DEFINITION AND BINDING FUNCTION DEFINITION AND BINDING 10.1. Function Definition in PSL . . . . . . . . . . 10.1 10.1.1. Notes on Code Pointers . . . . . . . . . 10.1 10.1.2. Functions Useful in Function Definition. . . . 10.2 10.1.3. Function Definition in LISP Syntax . . . . . 10.4 10.1.4. Function Definition in RLISP Syntax . . . . . 10.6 10.1.5. Low Level Function Definition Primitives . . . 10.6 10.1.6. Function Type Predicates. . . . . . . . . 10.7 10.2. Variables and Bindings. . . . . . . . . . . . 10.8 10.2.1. Binding Type Declaration. . . . . . . . . 10.8 10.2.2. Binding Type Predicates . . . . . . . . . 10.9 10.3. User Binding Functions. . . . . . . . . . . . 10.10 10.3.1. Funargs, Closures and Environments . . . . . 10.10 10.1. Function Definition in PSL 10.1. Function Definition in PSL 10.1. Function Definition in PSL Functions in PSL are GLOBAL entities. To avoid function-variable naming clashes, the Standard LISP Report required that no variable have the same name as a function. There is no conflict in PSL, as separate function cells and value cells are used. A warning message is given for compatibility. The first major section in this chapter describes how to define new functions; the second describes the binding of variables in PSL. The final section presents binding functions useful in building new interpreter functions. 10.1.1. Notes on Code Pointers 10.1.1. Notes on Code Pointers 10.1.1. Notes on Code Pointers Print ____ _______ Print A code-pointer may be displayed by the Print functions or expanded by Explode Explode Explode. The value appears in the convention of the implementation (#<Code:a nnnn>, where a is the number of arguments of the function, and ____ _______ nnnn is the function's entry point, on the DEC-20 and VAX). A code-pointer Compress Compress may not be created by Compress. (See Chapter 12 for descriptions of Explode Compress Explode Compress ____ _______ Explode and Compress.) The code-pointer associated with a compiled GetD GetD function may be retrieved by GetD and is valid as long as PSL is in execution (on the DEC-20 and VAX, compiled code is not relocated, so PutD ____ _______ ____ _______ PutD code-pointers do not change). A code-pointer may be stored using PutD, Put SetQ Put SetQ Put, SetQ and the like or by being bound to a variable. It may be checked Eq Eq ____ _______ for equivalence by Eq. The value may be checked for being a code-pointer CodeP CodeP by the CodeP function. Function Definition 7 February 1983 PSL Manual page 10.2 section 10.1 10.1.2. Functions Useful in Function Definition 10.1.2. Functions Useful in Function Definition 10.1.2. Functions Useful in Function Definition __ In PSL, ids have a function cell that usually contains an executable instruction which either JUMPs directly to the entry point of a compiled function or executes a CALL to an auxiliary routine that handles interpreted functions, undefined functions, or other special services (such ________ as auto-loading functions, etc). The user can pass anonymous function ____ _______ objects around either as a code-pointer, which is a tagged object referring ______ to a compiled code block, or a lambda expression, representing an interpreted function. PutD PutD _____ __ ____ _____ ____ ______ ____ _______ __ ____ (PutD FNAME:id TYPE:ftype BODY:{lambda,code-pointer}): id expr _____ ____ ____ Creates a function with name FNAME and type TYPE, with BODY as PutD PutD the function definition. If successful, PutD returns the name of the defined function. ____ _______ If the body is a code-pointer or is compiled (i.e. !*COMP=T as the function was defined), a special instruction to jump to the start of the code is placed in the function cell. If it is a ______ lambda, the lambda expression is saved on the property list under the indicator !*LAMBDALINK and a call to an interpreter function LambdaLink LambdaLink (LambdaLink) is placed in the function cell. ____ ____ _____ The TYPE is recorded on the property list of FNAME if it is not ____ ____ ____ expr expr an expr. [??? We need to add code to check that the the arglist has no [??? We need to add code to check that the the arglist has no [??? We need to add code to check that the the arglist has no more than 15 arguments for exprs, 1 argument for fexprs and more than 15 arguments for exprs, 1 argument for fexprs and more than 15 arguments for exprs, 1 argument for fexprs and macros, and ??? for nexprs. Declaration mechanisms to avoid macros, and ??? for nexprs. Declaration mechanisms to avoid macros, and ??? for nexprs. Declaration mechanisms to avoid overhead also need to be available. (In fact are available overhead also need to be available. (In fact are available overhead also need to be available. (In fact are available for the compiler, although still poorly documented.) When for the compiler, although still poorly documented.) When for the compiler, although still poorly documented.) When should we expand macros? ???] should we expand macros? ???] should we expand macros? ???] PutD GetD PutD _____ GetD ____ _____ After using PutD on FNAME, GetD returns a pair of the the FNAME's ____ ____ (TYPE . BODY). GlobalP GlobalP The GlobalP predicate returns T if queried with the defined _____ function's name. If the function FNAME has already been declared as a GLOBAL or FLUID variable the warning: *** FNAME is a non-local variable _____ occurs, but the function is defined. If function FNAME is already defined, a warning message appears: *** Function FNAME has been redefined ____ Note: All function types may be compiled. The following switches are useful when defining functions. PSL Manual 7 February 1983 Function Definition section 10.1 page 10.3 __________ ______ !*REDEFMSG [Initially: T] switch If !*REDEFMSG is not NIL, the message *** Function `FOO' has been redefined is printed whenever a function is redefined. __________ ______ !*USERMODE [Initially: T] switch Controls action on redefinition of a function. All functions defined if !*USERMODE is T are flagged USER. Functions which are flagged USER can be redefined freely. If an attempt is made to redefine a function which is not flagged USER, the query Do you really want to redefine the system function `FOO'? is made, requiring a Y, N, YES, NO, or B response. B starts the break loop, so that one can change the setting of !*USERMODE. After exiting the break loop, one must answer Y, Yes, N, or No. YesP YesP See YesP in Chapter 13. If !*UserMode is NIL, all functions can be redefined freely, and all functions defined have the USER flag removed. This provides some protection from redefining system functions. __________ ______ !*COMP [Initially: NIL] switch PutD PutD The value of !*COMP controls whether or not PutD compiles the function defined in its arguments before defining it. If !*COMP is NIL the function is defined as a lambda expression. If !*COMP is non-NIL, the function is first compiled. Compilation produces certain changes in the semantics of functions, particularly FLUID type access. GetD GetD _ ___ ___ ____ ____ (GetD U:any): {NIL, pair} expr _ If U is not the name of a defined function, NIL is returned. If _ ____ U is a defined function then the pair ____ _____ _____ _____ ____ _____ _____ _____ ____ _____ _____ _____ expr, fexpr, macro, nexpr expr, fexpr, macro, nexpr ____ _______ ______ ({expr, fexpr, macro, nexpr} . {code-pointer, lambda}) is returned. CopyD CopyD ___ __ ___ __ ___ __ ____ (CopyD NEW:id OLD:id): NEW:id expr ___ ___ The function body and type for NEW become the same as OLD. If no ___ definition exists for OLD an error: ***** OLD has no definition in COPYD Function Definition 7 February 1983 PSL Manual page 10.4 section 10.1 ___ is given. NEW is returned. RemD RemD _ __ ___ ____ ____ (RemD U:id): {NIL, pair} expr _ Removes the function named U from the set of defined functions. GetD ____ GetD Returns the (ftype . function) pair or NIL, as does GetD. The ________ _ function type attribute of U is removed from the property list of _ U. 10.1.3. Function Definition in LISP Syntax 10.1.3. Function Definition in LISP Syntax 10.1.3. Function Definition in LISP Syntax De Df Dn Dm Ds De Df Dn Dm Ds The functions De, Df, Dn, Dm, and Ds are most commonly used in the LISP syntax form of PSL. They are difficult to use from RLISP as there is not a convenient way to represent the argument list. The functions are compiled if the compiler is loaded and the GLOBAL !*COMP is T. De De _____ __ ______ __ ____ __ ____ __ _____ (De FNAME:id PARAMS:id-list [FN:form]): id macro ____ ____ ____ expr _____ expr ____ __ Defines the function named FNAME, of type expr. The forms FN are made into a lambda expression with the formal parameter list 1 ______ PARAMS, and this is used as the body of the function. Previous definitions of the function are lost. The name of the _____ defined function, FNAME, is returned. Df Df _____ __ _____ __ ____ __ ___ __ _____ (Df FNAME:id PARAM:id-list FN:any): id macro _____ _____ _____ fexpr _____ fexpr ____ __ Defines the function named FNAME, of type fexpr. The forms FN are made into a lambda expression with the formal parameter list ______ PARAMS, and this is used as the body of the function. Previous definitions of the function are lost. The name of the _____ defined function, FNAME, is returned. Dn Dn _____ __ _____ __ ____ __ ___ __ _____ (Dn FNAME:id PARAM:id-list FN:any): id macro _____ _____ _____ nexpr _____ nexpr ____ __ Defines the function named FNAME, of type nexpr. The forms FN are made into a lambda expression with the formal parameter list ______ PARAMS, and this is used as the body of the function. _______________ 1 Or the compiled code pointer for the lambda expression if the compiler is on. PSL Manual 7 February 1983 Function Definition section 10.1 page 10.5 Previous definitions of the function are lost. The name of the _____ defined function, FNAME, is returned. Dm Dm _____ __ _____ __ ____ __ ___ __ _____ (Dm MNAME:id PARAM:id-list FN:any): id macro _____ _____ _____ macro _____ macro ____ __ Defines the function named FNAME, of type macro. The forms FN are made into a lambda expression with the formal parameter list ______ PARAMS, and this is used as the body of the function. Previous definitions of the function are lost. The name of the _____ defined function, FNAME, is returned. Ds Ds _____ __ _____ __ ____ __ ___ __ _____ (Ds SNAME:id PARAM:id-list FN:any): id macro ______ _______ ______ _______ ______ _______ smacro Smacros smacro _____ Smacros Defines the smacro SNAME. Smacros are actually a syntactic _____ _____ _____ macro macro notation for a special class of macros, those that essentially treat the macro's argument as a list of arguments to be substituted into the body of the expression and then expanded in _____ _____ _____ macro macro line, rather than using the computational power of the macro to defmacro defmacro customize code. Thus they are a special case of defmacro. See also the BackQuote facility. For example: Lisp syntax: To make a substitution macro for FIRST ->CAR we could say (DM FIRST(X) (LIST 'CAR (CADR X))) Instead the following is clearer (DS FIRST(X) (CAR X)) 10.1.4. Function Definition in RLISP Syntax 10.1.4. Function Definition in RLISP Syntax 10.1.4. Function Definition in RLISP Syntax [??? THIS IS NOT SUFFICIENT DOCUMENTATION! Either move it all to [??? THIS IS NOT SUFFICIENT DOCUMENTATION! Either move it all to [??? THIS IS NOT SUFFICIENT DOCUMENTATION! Either move it all to chapter 3 or do a better job here. ???] chapter 3 or do a better job here. ???] chapter 3 or do a better job here. ???] In RLISP syntax, procedures are defined by using the Procedure construct, as discussed in Chapter 3. mode type PROCEDURE name(args); body; where mode is SYSLISP or LISP or SYMBOLIC and defaults to LISP, and type defaults to EXPR. Function Definition 7 February 1983 PSL Manual page 10.6 section 10.1 10.1.5. Low Level Function Definition Primitives 10.1.5. Low Level Function Definition Primitives 10.1.5. Low Level Function Definition Primitives PutD GetD PutD GetD The following functions are used especially by PutD and GetD, defined Eval Apply Eval Apply above in Section 10.1.2, and by Eval and Apply, defined in Chapter 11. FUnBoundP FUnBoundP _ __ _______ ____ (FUnBoundP U:id): boolean expr ________ _ Tests whether there is a definition in the function cell of U; returns NIL if so, T if not. Note: Undefined functions actually call a special function, UndefinedFunction Error FUnBoundP UndefinedFunction Error FUnBoundP UndefinedFunction, that invokes Error. FUnBoundP defines UndefinedFunction UndefinedFunction "unbound" to mean "calls UndefinedFunction". FLambdaLinkP FLambdaLinkP _ __ _______ ____ (FLambdaLinkP U:id): boolean expr _ Tests whether U is an interpreted function; return T if so, NIL if not. This is done by checking for the special code-address of lambdaLink lambdaLink the lambdaLink function, which calls the interpreter. FCodeP FCodeP _ __ _______ ____ (FCodeP U:id): boolean expr _ Tests whether U is a compiled function; returns T if so, NIL if not. MakeFUnBound MakeFUnBound _ __ ___ ____ (MakeFUnBound U:id): NIL expr _ Makes U an undefined function by planting a special call to an UndefinedFunction UndefinedFunction ________ _ error function, UndefinedFunction, in the function cell of U. MakeFLambdaLink MakeFLambdaLink _ __ ___ ____ (MakeFLambdaLink U:id): NIL expr _ Makes U an interpreted function by planting a special call to an lambdaLink lambdaLink interpreter support function (lambdaLink) function in the ________ _ function cell of U.} MakeFCode MakeFCode _ __ _ ____ _______ ___ ____ (MakeFCode U:id C:code-pointer): NIL expr _ Makes U a compiled function by planting a special JUMP to the _ code-address associated with C. GetFCodePointer GetFCodePointer _ __ ____ _______ ____ (GetFCodePointer U:id): code-pointer expr ____ _______ _ Gets the code-pointer for U. PSL Manual 7 February 1983 Function Definition section 10.1 page 10.7 Code!-Number!-Of!-Arguments Code!-Number!-Of!-Arguments _ ____ _______ ___ _______ ____ (Code!-Number!-Of!-Arguments C:code-pointer): {NIL,integer} expr Some compiled functions have the argument number they expect _ stored in association with the codepointer C. This integer, or NIL is returned. _____ ____ _____ ____ _____ ____ [??? Should be extended for nexprs and declared exprs. ???] [??? Should be extended for nexprs and declared exprs. ???] [??? Should be extended for nexprs and declared exprs. ???] 10.1.6. Function Type Predicates 10.1.6. Function Type Predicates 10.1.6. Function Type Predicates See Section 2.7 for a discussion of the function types available in PSL. ExprP ExprP _ ___ _______ ____ (ExprP U:any): boolean expr ____ ____ ____ expr _ ____ _______ ______ __ expr Test if U is a code-pointer, lambda form, or an id with expr definition. FExprP FExprP _ ___ _______ ____ (FExprP U:any): boolean expr _____ _____ _____ fexpr _ __ fexpr Test if U is an id with fexpr definition. NExprP NExprP _ ___ _______ ____ (NExprP U:any): boolean expr _____ _____ _____ nexpr _ __ nexpr Test if U is an id with nexpr definition. MacroP MacroP _ ___ _______ ____ (MacroP U:any): boolean expr _____ _____ _____ macro _ __ macro Test if U is an id with macro definition. 10.2. Variables and Bindings 10.2. Variables and Bindings 10.2. Variables and Bindings __ Variables in PSL are ids, and associated values are usually stored in and __ retrieved from the value cell of this id. If variables appear as Prog Prog parameters in lambda expressions or in Prog's, the contents of the value cell are saved on a binding stack. A new value or NIL is stored in the Prog Prog value cell and the computation proceeds. On exit from the lambda or Prog the old value is restored. This is called the "shallow binding" model of LISP. It is chosen to permit compiled code to do binding efficiently. For even more efficiency, compiled code may eliminate the variable names and simply keep values in registers or a stack. The scope of a variable is the range over which the variable has a defined value. There are three different binding mechanisms in PSL. LOCAL BINDING Only compiled functions bind variables locally. Local Function Definition 7 February 1983 PSL Manual page 10.8 section 10.2 variables occur as formal parameters in lambda expressions Prog Prog and as LOCAL variables in Prog's. The binding occurs as a Prog Prog lambda expression is evaluated or as a Prog form is executed. The scope of a local variable is the body of the function in which it is defined. FLUID BINDING FLUID variables are GLOBAL in scope but may occur as formal Prog Prog parameters or Prog form variables. In interpreted functions, all formal parameters and LOCAL variables are considered to have FLUID binding until changed to LOCAL binding by compilation. A variable can be treated as a FLUID only by declaration. If FLUID variables are used as parameters or LOCALs they are rebound in such a way that the previous binding may be restored. All references to FLUID variables are to the currently active binding. Access to the values is by name, going to the value cell. GLOBAL BINDING GLOBAL variables may never be rebound. Access is to the value bound to the variable. The scope of a GLOBAL variable is universal. Variables declared GLOBAL may not appear as Prog Prog parameters in lambda expressions or as Prog form variables. A variable must be declared GLOBAL prior to its use as a GLOBAL variable since the default type for undeclared variables is FLUID. Note that the interpreter does not stop one from rebinding a global variable. The compiler will issue a warning in this situation. 10.2.1. Binding Type Declaration 10.2.1. Binding Type Declaration 10.2.1. Binding Type Declaration Fluid Fluid ______ __ ____ ___ ____ (Fluid IDLIST:id-list): NIL expr __ ______ __ The ids in IDLIST are declared as FLUID type variables (ids not ______ previously declared are initialized to NIL). Variables in IDLIST already declared FLUID are ignored. Changing a variable's type from GLOBAL to FLUID is not permissible and results in the error: ***** ID cannot be changed to FLUID Global Global ______ __ ____ ___ ____ (Global IDLIST:id-list): NIL expr __ ______ __ The ids of IDLIST are declared GLOBAL type variables. If an id has not been previously declared, it is initialized to NIL. Variables already declared GLOBAL are ignored. Changing a variable's type from FLUID to GLOBAL is not permissible and results in the error: ***** ID cannot be changed to GLOBAL PSL Manual 7 February 1983 Function Definition section 10.2 page 10.9 UnFluid UnFluid ______ __ ____ ___ ____ (UnFluid IDLIST:id-list): NIL expr ______ The variables in IDLIST which have been declared as FLUID variables are no longer considered as FLUID variables. Others are ignored. This affects only compiled functions, as free variables in interpreted functions are automatically considered FLUID (see [Griss 81]). 10.2.2. Binding Type Predicates 10.2.2. Binding Type Predicates 10.2.2. Binding Type Predicates FluidP FluidP _ ___ _______ ____ (FluidP U:any): boolean expr _ If U is FLUID (by declaration only), T is returned; otherwise, NIL is returned. GlobalP GlobalP _ ___ _______ ____ (GlobalP U:any): boolean expr _ If U has been declared GLOBAL or is the name of a defined function, T is returned; else NIL is returned. UnBoundP UnBoundP _ __ _______ ____ (UnBoundP U:id): boolean expr _ Tests whether U has no value. 10.3. User Binding Functions 10.3. User Binding Functions 10.3. User Binding Functions The following functions are available to build one's own interpreter functions that use the built-in FLUID binding mechanism, and interact well with the automatic unbinding that takes place during Throw and Error calls. [??? Are these correct when Environments are managed correctly ???] [??? Are these correct when Environments are managed correctly ???] [??? Are these correct when Environments are managed correctly ???] UnBindN UnBindN _ _______ _________ ____ (UnBindN N:integer): Undefined expr Prog Prog Used in user-defined interpreter functions (like Prog) to restore _ previous bindings to the last N values bound. LBind1 LBind1 ______ __ ___________ ___ _________ ____ (LBind1 IDNAME:id VALUETOBIND:any): Undefined expr ______ Support for LAMBDA-like binding. The current value of IDNAME is ___________ saved on the binding stack; the value of VALUETOBIND is then ______ bound to IDNAME. Function Definition 7 February 1983 PSL Manual page 10.10 section 10.3 PBind1 PBind1 ______ __ _________ ____ (PBind1 IDNAME:id): Undefined expr Prog Prog ______ Support for Prog. Binds NIL to IDNAME after saving value on the LBind1 LBind1 ______ binding stack. Essentially LBind1(IDNAME, NIL) 10.3.1. Funargs, Closures and Environments 10.3.1. Funargs, Closures and Environments 10.3.1. Funargs, Closures and Environments [??? Not yet connected to V3 ???] [??? Not yet connected to V3 ???] [??? Not yet connected to V3 ???] We have an experimental implementation of Baker's re-rooting funarg scheme [Baker 78], in which we always re-root upon binding; this permits efficient use of a GLOBAL value cell in the compiler. We are also considering implementing a restricted FUNARG or CLOSURE mechanism. The implementation we have does not work with the current version of PSL. This currently uses a module (ALTBIND) to redefine the fluid binding _ ____ mechanism of PSL to be functionally equivalent to an a-list binding scheme. However, it retains the principal advantage of the usual shallow binding scheme: variable lookup is extremely cheap -- just look in a value cell. Typical LISP programs currently run about 8% slower if using ALTBIND than with the initial shallow binding mechanism. It is expected that this 8% difference will go away presently. This mechanism will also probably become a standard part of PSL, rather than an add on module. To use ALTBIND simply do "load altbind;" ["(load altbind)" in LISP]. Existing code, both interpreted and compiled, should then commence using the new binding mechanism. The following functions are of most interest to the user: Closure Closure _ ____ ____ _____ (Closure U:form): form macro Function Function This is similar to Function, but returns a function closure Function Function including environment information, similar to Function in LISP Function* Eval Apply Function* Eval Apply 1.5 and Function* in LISP 1.6 and MACLISP. Eval and Apply are redefined to handle closures correctly. Currently only closures ____ ____ ____ expr expr of exprs are supported. EvalInEnvironment EvalInEnvironment _ ____ ___ ___ _______ ___ ____ (EvalInEnvironment F:form ENV:env-pointer): any expr ApplyInEnvironment ApplyInEnvironment __ ________ ____ ____ ____ ___ ___ _______ ___ ____ (ApplyInEnvironment FN:function ARGS:form-list ENV:env-pointer): any expr Eval Apply Eval Apply These are like Eval and Apply, but take an extra, last argument, and environment pointer. They perform their work in this environment instead of the current one. The following functions should be used with care: PSL Manual 7 February 1983 Function Definition section 10.3 page 10.11 CaptureEnvironment CaptureEnvironment ___ _______ ____ (CaptureEnvironment ): env-pointer expr Save the current bindings to be restored at some later point. CaptureEnvironment CaptureEnvironment This is best used inside a closure. CaptureEnvironment returns ____ an environment pointer. This object is normally a circular list structure, and so should not be printed. The same warning applies to closures, which contain environment pointers. It is hoped that environment pointers will be made a new LISP data type soon, and will be made to print safely, relaxing this restriction. [??? add true envpointer ???] [??? add true envpointer ???] [??? add true envpointer ???] RestoreEnvironment RestoreEnvironment ___ ___ _______ _________ ____ (RestoreEnvironment PTR:env-pointer): Undefined expr Restore old bindings to what they were in the captured ___ environment, PTR. ClearBindings ClearBindings _________ ____ (ClearBindings ): Undefined expr Restore bindings to top level, i.e strip the entire stack. For a demonstration of closures, do (in RLISP) `in "PU:altbind-tests.red";'. [??? Give a practical example ???] [??? Give a practical example ???] [??? Give a practical example ???]