OSDN Git Service

Rename .eval -> .exec. Add new .eval.
authordevans <devans>
Mon, 17 Aug 2009 15:27:55 +0000 (15:27 +0000)
committerdevans <devans>
Mon, 17 Aug 2009 15:27:55 +0000 (15:27 +0000)
* pmacros.scm (-pmacro-built-exec): Renamed from -pmacro-builtin-eval.
(-pmacro-builtin-eval): New function.
(pmacros-init!): Add .exec.
* doc/pmacros.texi: Update, .exec -> .eval.  Document new .eval.
* testsuite/location-1.test: Update.
* testsuite/pmacros-1.test: Add test for .eval.

cgen/ChangeLog
cgen/doc/pmacros.texi
cgen/pmacros.scm
cgen/testsuite/location-1.test
cgen/testsuite/pmacros-1.test

index 9728afd..3db6b2b 100644 (file)
@@ -1,3 +1,13 @@
+2009-08-17  Doug Evans  <dje@sebabeach.org>
+
+       Rename .eval -> .exec.  Add new .eval.
+       * pmacros.scm (-pmacro-built-exec): Renamed from -pmacro-builtin-eval.
+       (-pmacro-builtin-eval): New function.
+       (pmacros-init!): Add .exec.
+       * doc/pmacros.texi: Update, .exec -> .eval.  Document new .eval.
+       * testsuite/location-1.test: Update.
+       * testsuite/pmacros-1.test: Add test for .eval.
+
 2009-08-16  Doug Evans  <dje@sebabeach.org>
 
        * doc/porting.texi: Remove support for Guile 1.4.
index d8769db..1728b8a 100644 (file)
@@ -147,9 +147,10 @@ they have no special meaning.}
 
 Variable macros are expanded simply by replacing their name with their value.
 
-After a pmacro has been expanded, if the result of the pmacro is another
-pmacro invocation, it is in turn processed.  This happens just once,
-not repeatedly.
+After a pmacro has been expanded, if the result is a symbol that names
+another pmacro, it is in turn processed.  This happens just once,
+not repeatedly.@footnote{This behaviour will go away eventually, do not
+rely on it.}
 
 Here is a simple example that uses pmacros to simplify the
 definition of several instructions.
@@ -200,15 +201,15 @@ Note how the first @code{begin} is nested within a list, and does not
 appear in the ``top level'' list.
 
 Another way to accomplish the same thing that doesn't require
-@code{.splice}, @code{.unsplice} is to use @code{.for-each}, @code{.eval}.
+@code{.splice}, @code{.unsplice} is to use @code{.for-each}, @code{.exec}.
 @code{.for-each} is only used for its side-effects, it does not
 return a result.  Therefore, in order to actually cause the
 @file{.cpu} file reader to see any definitions we need to use
-@code{.eval} to pass the dnis to the reader.
+@code{.exec} to pass the dnis to the reader.
 
 @smallexample
 (define-pmacro (define-arith-insn ispec)
-  (.eval (dni (.ref ispec 0)
+  (.exec (dni (.ref ispec 0)
            (.str (.ref ispec 0) " reg/reg")
            ()
            (.str (.ref ispec 0) " $dr,$sr")
@@ -216,7 +217,7 @@ return a result.  Therefore, in order to actually cause the
            (set dr ((.ref ispec 0) dr sr))
            ()
            ))
-  (.eval (dni (.ref ispec 0)
+  (.exec (dni (.ref ispec 0)
            (.str (.ref ispec 0) " reg/imm")
            ()
            (.str (.ref ispec 0) " $dr,$imm")
@@ -769,7 +770,7 @@ The syntax is @samp{(.for-each macro list1 [list2 ...])}.
 There is no result, or rather the result is always the empty list ().
 Note that this macro is therefore useless for macro expansion.
 It's purpose is to process @code{macro} for its side-effects.
-The @code{.eval} builtin pmacro is useful here.
+The @code{.exec} builtin pmacro is useful here.
 
 @node Conditional macros
 @section Conditional macros
@@ -825,33 +826,58 @@ then the empty list @code{()} is returned.
 @node Pmacro utilities
 @section Pmacro utilities
 
-Macros for working with pmacros.
+Pmacros for working with pmacros.
 
 @menu
-* Immediate evaluation of a macro:: The @code{.eval} builtin
-* Applying a macro to a list::      The @code{.apply} builtin
-* Defining a pmacro inline::        The @code{.pmacro} builtin
-* Passing macros as arguments::     Passing a macro to another macro
-* Defining a block of locals::      The @code{.let}, @code{.let*} builtins
-* A block of statements::           The @code{.begin} builtin
+* Re-evaluating an expression::      The @code{.eval} builtin
+* Immediate execution of a command:: The @code{.exec} builtin
+* Applying a pmacro to a list::      The @code{.apply} builtin
+* Defining a pmacro inline::         The @code{.pmacro} builtin
+* Passing pmacros as arguments::     Passing a pmacro to another pmacro
+* Defining a block of locals::       The @code{.let}, @code{.let*} builtins
+* A block of statements::            The @code{.begin} builtin
 @end menu
 
-@node Immediate evaluation of a macro
-@subsection Immediate evaluation of a macro
+@node Re-evaluating an expression
+@subsection Re-evaluating an expression
 @cindex .eval
 
 Syntax: @samp{(.eval expr)}
 
+Sometimes one wishes to build up an expression in non-trivial ways
+and then have the expression evaluated.
+Use the @code{.eval} builtin pmacro for this purpose,
+it re-evaluates @samp{expr}, invoking any pmacros contained therein.
+
+A perhaps contrived example is when one wants to construct the pmacro's
+name from a set of parameters.
+
+Example:
+
+@smallexample
+(define-pmacro (do-foo a b) (foo a b))
+(define-pmacro (do-bar a b) (bar a b))
+(define-pmacro (doer what a b) (.eval (.list (.sym do- what) a b)))
+(doer foo 1 2) ;; --> (foo 1 2)
+(doer bar 3 4) ;; --> (bar 3 4)
+@end smallexample
+
+@node Immediate execution of a command
+@subsection Immediate execution of a command
+@cindex .exec
+
+Syntax: @samp{(.exec expr)}
+
 Sometimes one wishes to pass an expression to the @file{.cpu} file reader
 immediately, rather than waiting for it to process the expression
 that is the result of a pmacro.  This typically happens with the
 @code{.for-each} builtin pmacro.
-Use the @code{.eval} builtin pmacro for this purpose.
+Use the @code{.exec} builtin pmacro for this purpose.
 It immediately passes @samp{expr} to the @file{.cpu} file reader
-and returns @code{()} as a result.
+for processing and returns @code{()} as a result.
 
-@node Applying a macro to a list
-@subsection Applying a macro to a list
+@node Applying a pmacro to a list
+@subsection Applying a pmacro to a list
 @cindex .apply
 
 Invoke a macro with each argument coming from an element of a list,
@@ -920,8 +946,8 @@ to the arg2 argument of the outer pmacro.
 The contents of a @code{.pmacro} are not evaluated until the pmacro
 is invoked.
 
-@node Passing macros as arguments
-@subsection Passing macros as arguments
+@node Passing pmacros as arguments
+@subsection Passing pmacros as arguments
 
 Macros may be passed to other macros.
 
index cb37fb5..5567e8f 100644 (file)
@@ -51,7 +51,7 @@
 
 ; pmacro-debug - expand all pmacros in an expression,
 ;                printing various debugging messages.
-;                This does not process .eval.
+;                This does not process .exec.
 ;
 ;      (pmacro-debug expression)
 
 ; (.upcase string)
 ; (.downcase string)
 ; (.substring string start end)       - get part of a string
-; (.splice a b (.unsplice c) d e ...) - quasi-quote/unquote-splicing
+; (.splice a b (.unsplice c) d e ...) - splice list into another list
 ; (.iota count [start [increment]])   - number generator
 ; (.map pmacro arg1 . arg-rest)
 ; (.for-each pmacro arg1 . arg-rest)
-; (.eval expr)                        - process expr immediately
+; (.eval expr)                        - expand (or evaluate it) expr
+; (.exec expr)                        - execute expr immediately
 ; (.apply pmacro-name arg)
 ; (.pmacro (arg-list) expansion)      - akin go lambda in Scheme
 ; (.let (var-list) expr1 . expr-rest) - akin to let in Scheme
 )
 
 ; Expand any pmacros in EXPR, printing various debugging messages.
-; This does not process .eval.
+; This does not process .exec.
 
 (define (pmacro-debug expr)
   ; FIXME: Need unwind protection.
 ; (pmacro-expand '(splice-test (1 (2) 3))) --> (1 2 3)
 ;
 ; Similar to `(1 ,@'(2) 3) in Scheme, though the terminology is slightly
-; different (??? may need to revisit).  In Scheme we have quasi-quote,
-; unquote, unquote-splicing.  Here we have splice, unsplice.
+; different (??? may need to revisit).  In Scheme there's quasi-quote,
+; unquote, unquote-splicing.  Here we have splice, unsplice; with the proviso
+; that pmacros don't have the concept of "quoting", thus all subexpressions
+; are macro-expanded first, before performing any unsplicing.
+; [??? Some may want a quoting facility, but I'd like to defer adding it as
+; long as possible (and ideally never add it).]
+;
+; NOTE: The implementation relies on .unsplice being undefined so that
+; (.unsplice (42)) is expanded unchanged.
 
 (define -pmacro-builtin-splice
   (lambda arg-list
-    ; ??? Not the most efficient implementation, but will the difference
-    ; ever be measureable?
+    ; ??? Not the most efficient implementation.
     (let loop ((arg-list arg-list) (result '()))
       (cond ((null? arg-list) result)
            ((and (pair? (car arg-list)) (eq? '.unsplice (caar arg-list)))
 )
 
 ; (.eval expr)
+; NOTE: This is implemented as a syntactic form in order to get ENV and LOC.
+; That's an implementation detail, and this is not really a syntactic form.
+;
+; ??? I debated whether to call this .expand, .eval has been a source of
+; confusion/headaches.
+
+(define (-pmacro-builtin-eval loc env expr)
+  ;; -pmacro-expand is invoked twice because we're implemented as a syntactic
+  ;; form:  We *want* to be passed an evaluated expression, and then we
+  ;; re-evaluate it.  But syntactic forms pass parameters unevaluated, so we
+  ;; have to do the first one ourselves.
+  (-pmacro-expand (-pmacro-expand expr env loc) env loc)
+)
+
+; (.exec expr)
 
-(define (-pmacro-builtin-eval expr)
-  ;; If we're expanding pmacros for debugging purposes, don't eval,
+(define (-pmacro-builtin-exec expr)
+  ;; If we're expanding pmacros for debugging purposes, don't execute,
   ;; just return unchanged.
   (if -pmacro-debug?
-      (list '.eval expr)
+      (list '.exec expr)
       (begin
        (reader-process-expanded! expr)
        nil)) ;; need to return something the reader will accept
          (list '.iota '(count . start-incr) #f -pmacro-builtin-iota "iota number generator")
          (list '.map '(pmacro list1 . rest) #f -pmacro-builtin-map "map a pmacro over a list of arguments")
          (list '.for-each '(pmacro list1 . rest) #f -pmacro-builtin-for-each "execute a pmacro over a list of arguments")
-         (list '.eval '(expr) #f -pmacro-builtin-eval "process expr immediately")
+         (list '.eval '(expr) #t -pmacro-builtin-eval "expand(evaluate) expr")
+         (list '.exec '(expr) #f -pmacro-builtin-exec "execute expr immediately")
          (list '.apply '(pmacro arg-list) #f -pmacro-builtin-apply "apply a pmacro to a list of arguments")
          (list '.pmacro '(params expansion) #t -pmacro-builtin-pmacro "create a pmacro on-the-fly")
          (list '.let '(locals expr1 . rest) #t -pmacro-builtin-let "create a binding context, let-style")
index b172b61..e8d53d8 100644 (file)
@@ -18,7 +18,7 @@ cat > ${cpu_file} <<EOF
 )
 
 (.for-each (.pmacro (name)
-             (.eval (define-test-insn name)))
+             (.exec (define-test-insn name)))
            test-insns)
 EOF
 
index b31eaa5..76ba0ba 100644 (file)
@@ -100,6 +100,11 @@ cat > ${cpu_file} <<EOF
 (print-match "ABC")
 (print-expr (.apply .upcase (abc)))
 
+(test-name ".eval")
+(print-match "(explicitly-undefined 42)")
+(define-pmacro (eval-test1 a) (explicitly-undefined a))
+(print-expr (.eval (.splice eval-test1 (.unsplice (42)))))
+
 (test-name ".let")
 (print-match "xyzzy")
 (print-expr (.let ((x xyzzy)) x))