From: Thomas Womack
Subject: Writing machine code from LISP
Date: 
Message-ID: <Uyn*o6ter@news.chiark.greenend.org.uk>
Is there any way, in any of the free LISPs, of simply telling the
computer to set some machine registers to point at a pre-existing
array of fixnums, and then to jump to the start of an array of bytes
which I've previously set up to contain position-independent machine
language?

Writing code to manipulate code is rather friendlier in LISP than in
C, but how do I go about actually calling the code once I've compiled
it into machine instructions?  I appreciate I'm losing eighty-nine
kinds of safety here.

Tom

From: William D Clinger
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <1145396607.364422.82500@t31g2000cwb.googlegroups.com>
> Is there any way, in any of the free LISPs, of simply telling the
> computer to set some machine registers to point at a pre-existing
> array of fixnums, and then to jump to the start of an array of bytes
> which I've previously set up to contain position-independent machine
> language?

Yes.

Without identifying the following implementation of
Scheme...

> (define f (lambda (x y) (* x y)))
> f
#<PROCEDURE f>
> (procedure-length f)
3
> (procedure-ref f 0)
#<BYTEVECTOR>
> (procedure-ref f 1)
#(#(f #f 2 #f #f (x y)))
> (procedure-ref f 2)
#<PROCEDURE>
> (define g (make-procedure 3))
> (procedure-set! g 0 (procedure-ref f 0))
> (procedure-set! g 1 #f)
> (procedure-set! g 2 #f)
> (g 10 25)
250

> I appreciate I'm losing eighty-nine
> kinds of safety here.

No kidding!  For this to work, you have to know
the system invariants that all compiled code must
preserve.  Even if you know those invariants,
you probably have a less-than-even chance of
preserving them through even a short sequence of
hand-written machine code.  That's why compilers
were invented.

Will
From: Thomas Womack
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <N5v*Kjver@news.chiark.greenend.org.uk>
Many thanks for that!  I expected that it would be possible, but I had
no idea which rocks to look behind to figure out how to do it: I'm
really very impressed that cffi is a specified part of the language
rather than something invented afresh with different syntax by each
consecutive implementation.

Tom
From: bradb
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <1145392333.349494.141450@z34g2000cwc.googlegroups.com>
Well, CFFI is not part of the language :)
Each implementation has its own Foreign Function Interface (FFI).
Usually this means a way to interface to C code.
CFFI is a layer that presents a unified API for doing FFI.  Basically,
CFFI handles all the nasty implementation specific stuff for you.

Brad
From: Thomas Womack
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <eRz*NQver@news.chiark.greenend.org.uk>
In article <························@z34g2000cwc.googlegroups.com>,
bradb <··············@gmail.com> wrote:
>Well, CFFI is not part of the language :)
>Each implementation has its own Foreign Function Interface (FFI).
>Usually this means a way to interface to C code.
>CFFI is a layer that presents a unified API for doing FFI.  Basically,
>CFFI handles all the nasty implementation specific stuff for you.

Ah.

I've just discovered this, or at least I've just discovered

$ cmucl -load bizarro.lisp
; Loading #p"/u3/twomack/bizarro.lisp".

Reader error at 921 on #<Stream for file "/u3/twomack/bizarro.lisp">:
package "CFFI" not found
[many lines elided]
$ clisp -repl bizarro.lisp

*** - READ from #<INPUT BUFFERED FILE-STREAM CHARACTER
#P"bizarro.lisp" @19>: there is no package with name "CFFI"
[many more lines elided]
$

This is under Debian, and clisp and cmucl were installed from the
Debian packages; do I just need to collect and install cl-cffi.deb?

Tom
From: bradb
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <1145400641.762380.200680@g10g2000cwb.googlegroups.com>
CFFI's home page is here http://common-lisp.net/project/cffi/
It is a moving project, so I don't know how well Debian tracks it.  I
would suggest using ASDF-INSTALL, or getting it from the homepage.

Cheers
Brad
From: Pascal Bourguignon
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <87y7y2ik4y.fsf@thalassa.informatimago.com>
"bradb" <··············@gmail.com> writes:
> Well, CFFI is not part of the language :)
> Each implementation has its own Foreign Function Interface (FFI).
> Usually this means a way to interface to C code.
> CFFI is a layer that presents a unified API for doing FFI.  Basically,
> CFFI handles all the nasty implementation specific stuff for you.

Which "proves" that we don't need a standardization body, just code.

Let's hope the next implementation will just implement the CFFI
interface instead of inventing its own ;-)

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"A TRUE Klingon warrior does not comment his code!"
From: bradb
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <1145400343.684559.224930@v46g2000cwv.googlegroups.com>
Correct, although see Thomas' problem below :(

Brad
From: Pascal Bourguignon
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <87bquyii5w.fsf@thalassa.informatimago.com>
"bradb" <··············@gmail.com> writes:
> Correct, although see Thomas' problem below :(

Once the useful libraries are labelled with CLRFI numbers,
the implementations can package them and announce proudly:

         "Conforming to CLRFI-1 to CLRFI-10."

Right now, they only can announce: "I've got a FFI and SOCKET package", 
or "I've got an ALIEN and SB-BSD-SOCKET" package.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush
From: Joerg Hoehle
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <uacafgjit.fsf@users.sourceforge.net>
Pascal Bourguignon <···@informatimago.com> writes:
[CFFI works great]
> Which "proves" that we don't need a standardization body, just code.

No. I actually agree with the guy (was it Erann/Ron?) who said that we
need specifications, not single implementations (like CFFI, CL-PPCRE).
Then implementations can purport to match specifications.

I believe only specifications give you freedom of choice and some form
of stability and competition at the same time.

What's CL about? the MOP?
If all you need is code, Python, Perl, Ruby etc. maybe better
alternatives, don't you think (fallacious question ;)?

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Pascal Bourguignon
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <87mzef2d4k.fsf@thalassa.informatimago.com>
Joerg Hoehle <······@users.sourceforge.net> writes:

> Pascal Bourguignon <···@informatimago.com> writes:
> [CFFI works great]
>> Which "proves" that we don't need a standardization body, just code.
>
> No. I actually agree with the guy (was it Erann/Ron?) who said that we
> need specifications, not single implementations (like CFFI, CL-PPCRE).
> Then implementations can purport to match specifications.
>
> I believe only specifications give you freedom of choice and some form
> of stability and competition at the same time.

Oh, I agree too, the important thing is the specification.  But I was
thinking of the principle used by RFCs and other successful standards,
that a specification must have at least one implementation to be valided.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Cats meow out of angst
"Thumbs! If only we had thumbs!
We could break so much!"
From: marc spitzer
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <slrne4i6ve.1tt.ms4720@sdf.lonestar.org>
On 2006-04-21, Pascal Bourguignon <···@informatimago.com> wrote:
> Joerg Hoehle <······@users.sourceforge.net> writes:
>>
>> I believe only specifications give you freedom of choice and some form
>> of stability and competition at the same time.
>
> Oh, I agree too, the important thing is the specification.  But I was
> thinking of the principle used by RFCs and other successful standards,
> that a specification must have at least one implementation to be valided.
>

If I remember correctly, for rfc's, you needed at least 2 independant 
projects that could interoperate according to the standard. 

marc

-- 
······@sdf.lonestar.org
SDF Public Access UNIX System - http://sdf.lonestar.org
From: Pascal Bourguignon
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <87odyu241u.fsf@thalassa.informatimago.com>
marc spitzer <······@sdf.lonestar.org> writes:

> On 2006-04-21, Pascal Bourguignon <···@informatimago.com> wrote:
>> Joerg Hoehle <······@users.sourceforge.net> writes:
>>>
>>> I believe only specifications give you freedom of choice and some form
>>> of stability and competition at the same time.
>>
>> Oh, I agree too, the important thing is the specification.  But I was
>> thinking of the principle used by RFCs and other successful standards,
>> that a specification must have at least one implementation to be valided.
>>
>
> If I remember correctly, for rfc's, you needed at least 2 independant 
> projects that could interoperate according to the standard. 

Right.  That would mean, one implementation of the API, and one
program using it.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: marc spitzer
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <slrne4m6tj.j5c.ms4720@sdf.lonestar.org>
On 2006-04-21, Pascal Bourguignon <···@informatimago.com> wrote:
> marc spitzer <······@sdf.lonestar.org> writes:
>
>> If I remember correctly, for rfc's, you needed at least 2 independant 
>> projects that could interoperate according to the standard. 
>
> Right.  That would mean, one implementation of the API, and one
> program using it.
>

not if I remember correctly, and they may have changed it since I looked,
but the standard I remember is that at least 2 seperate and independant 
implamentations, having both a client and server, needed to interoperate
with each other.  This was how the RFC was debugged, client A needed to 
work with server A and B and the same with client B.  Teams A and B were
seperate.  

marc

-- 
······@sdf.lonestar.org
SDF Public Access UNIX System - http://sdf.lonestar.org
From: Pascal Bourguignon
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <878xpwxsjv.fsf@thalassa.informatimago.com>
marc spitzer <······@sdf.lonestar.org> writes:

> On 2006-04-21, Pascal Bourguignon <···@informatimago.com> wrote:
>> marc spitzer <······@sdf.lonestar.org> writes:
>>
>>> If I remember correctly, for rfc's, you needed at least 2 independant 
>>> projects that could interoperate according to the standard. 
>>
>> Right.  That would mean, one implementation of the API, and one
>> program using it.
>>
>
> not if I remember correctly, and they may have changed it since I looked,
> but the standard I remember is that at least 2 seperate and independant 
> implamentations, having both a client and server, needed to interoperate
> with each other.  This was how the RFC was debugged, client A needed to 
> work with server A and B and the same with client B.  Teams A and B were
> seperate.  

I was refering not to a RFC, but to a library API.


To prove that an API works, you just need one library and one client
program (checking that the client program only use the library thru
the API, without any out-of-band communication).



How would you make interact two different implementations of a
library?  What would that prove?


If I define an API to get the factorial of an integer (note that there
is ext:! in clisp, perhaps something else in another implementation,
hence everybody is constantly rewritting their own half backed
factorial or fact function).

So I would define:

(FACTORIAL n)
N must be a positive integer. (factorial 0) === 1
If (minusp n) or n is not an integer, then a ARGUMENT-ERROR error is raised.
If the factorial is too big to be computed, then a OUT-OF-MEMORY error is raised.
Otherwise the factorial of n is returned. 

Now, I give you: com.informatimago.common-lisp.factorial:factorial
            and: net.common-lisp.factorial:factorial

How would that help?

But if I give you: com.informatimago.common-lisp.factorial:factorial
              and: com.informatimago.common-lisp.combinatorics:combinations

where combination uses the factorial API without messing with the
internals, and returns the right number of combinations for its
arguments, then you'll know that the API works.



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: marc spitzer
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <slrne4np89.clt.ms4720@sdf.lonestar.org>
On 2006-04-23, Pascal Bourguignon <···@informatimago.com> wrote:
>
> I was refering not to a RFC, but to a library API.
>

ok

>
> To prove that an API works, you just need one library and one client
> program (checking that the client program only use the library thru
> the API, without any out-of-band communication).
>

true

>
>
> How would you make interact two different implementations of a
> library?  What would that prove?
>

RFC's do not discus implamentations but how implamentations talk to
each other using a defined protocol, ntp,smtp,nntp ...
Perhaps we are talking about different things.  And it wont be the 
first thing I got wrong here.

>
> If I define an API to get the factorial of an integer (note that there
> is ext:! in clisp, perhaps something else in another implementation,
> hence everybody is constantly rewritting their own half backed
> factorial or fact function).
>
> So I would define:
>

[ valid argument that I needed to snip to get my nntp server
  to accept my post]

> where combination uses the factorial API without messing with the
> internals, and returns the right number of combinations for its
> arguments, then you'll know that the API works.
>

The reason for two complete and seperate implamentations is to debug the RFC.
For example lets say you and I both build a http 1.0 client and server as part
of the acceptance testing of the http protocol, back in the day, your client
works with your server and my client works with my server and we both believe
we have accuratly implamented the rfc.  Now when I try my client against your
server it does not work and the same for your client against my server.  Now
either one or both of us read the rfc wrong or the rfc itself is too vauge,
allowing for different _valid_ interptations of the text, and it needs to be 
fixed.  That is what I ment by needing two seperate systems to check how well
the rfc promotes interoperbillity among different client and servers.

marc 

-- 
······@sdf.lonestar.org
SDF Public Access UNIX System - http://sdf.lonestar.org
From: Pascal Costanza
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <4asq73Fuc7i5U1@individual.net>
Joerg Hoehle wrote:
> Pascal Bourguignon <···@informatimago.com> writes:
> [CFFI works great]
>> Which "proves" that we don't need a standardization body, just code.
> 
> No. I actually agree with the guy (was it Erann/Ron?) who said that we
> need specifications, not single implementations (like CFFI, CL-PPCRE).
> Then implementations can purport to match specifications.
> 
> I believe only specifications give you freedom of choice and some form
> of stability and competition at the same time.

Specifications should be based on experience with actual 
implementations, though. (I am not saying that you don't know that, I 
just think it's worthwhile to mention this.)

> What's CL about? the MOP?
> If all you need is code, Python, Perl, Ruby etc. maybe better
> alternatives, don't you think (fallacious question ;)?

They still don't have macros, right? ;)


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: justinhj
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <1145628494.247710.53630@t31g2000cwb.googlegroups.com>
Frank Buss wrote:
> justinhj wrote:
>
> > Can I infer from that there is a common internal format for cons cells
> > in both those (and other) lisp implementations?
>
> No, you can't infer this, because I've used cffi:with-foreign-object and
> copied the list to it.

Ah right

I just skimmed the asm and saw this comment

; get start of list

and assumed you were accessing the list in the asm.

One thing I like about Corman lisp is that the manual includes the
internal representation of all the types, so you can do significant
stuff in assembler. GC shouldn't be a problem during as assembler block
should it?

I'd expect there to be a way to turn of GC in a thread during an asm or
FFI call, but I may be off.

Justin
From: sharpnine
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <1146680871.069092.177050@j73g2000cwa.googlegroups.com>
Corman Lisp tries to make it pretty easy to do anything you want in
assembler. In Corman Lisp I am not sure why you would need to assemble
an arbitrary array of bytes (rather than use the inline assembler) but
this function would take a byte vector and convert to an executable
function:

(defun convert-bytes-to-function (name bytes)
    (let ((asm-statements '()))
        (do ((i (- (length bytes) 1) (- i 1)))
            ((< i 0))
            (push `(x86::db ,(aref bytes i)) asm-statements))
        (eval `(defasm ,name () (x86::encode-assembler-statements
,asm-statements)))))

Example:
(setf bytes #( #x55 #x8b #xec #x8b #x45 #x08 #x5d #xc3 ))
(convert-bytes-to-function 'foo bytes)  -> FOO

Of course this simply leverages the assembler.

There is not a way for a function (or assembly code) to "turn off"
other threads or the garbage collector. This is by design. However the
assembler code can use special byte codes to mark an atomic block which
will cause the garbage collector to allow that block to finish before
doing the collection. This only affects GC, not other threads.

Assembler code must be written very carefully and defensively, with the
understanding that the world might get moved underneath it between any
pair of instructions not defined as atomic. It may seem tricky, but
Corman Lisp includes many thousands of lines of assembly code that you
can read to understand how it works (as well as the manual).

Roger Corman
-------------------
justinhj wrote:
> Frank Buss wrote:
> > justinhj wrote:
> >
> > > Can I infer from that there is a common internal format for cons cells
> > > in both those (and other) lisp implementations?
> >
> > No, you can't infer this, because I've used cffi:with-foreign-object and
> > copied the list to it.
>
> Ah right
>
> I just skimmed the asm and saw this comment
>
> ; get start of list
>
> and assumed you were accessing the list in the asm.
>
> One thing I like about Corman lisp is that the manual includes the
> internal representation of all the types, so you can do significant
> stuff in assembler. GC shouldn't be a problem during as assembler block
> should it?
>
> I'd expect there to be a way to turn of GC in a thread during an asm or
> FFI call, but I may be off.
> 
> Justin
From: Joerg Hoehle
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <u1wva4190.fsf@users.sourceforge.net>
"justinhj" <········@gmail.com> writes:
> I'd expect there to be a way to turn of GC in a thread during an asm or
> FFI call, but I may be off.

Don't do that!
What you propose/expect in a hope for performance is in fact a killer.

o On most systems I know, GC is global, not thread local. Turning off
  GC or checking it thus requires global communication among all
  threads.  That ain't be fast.

o With threads, you'd be blocking all other threads that need memory
  just because your one library wants to do a not-so clever hack in
  one thread.  Obviously a no-no, isn't it?

o For how long would GC be blocked? What about callbacks while
  therein?  They'd get no memory and could die or block.  You and
  other programmers would be hunting for the bugs.

To me, the sole idea of turning off GC and/or threads should be
frowned upon, as in "EVAL is EVIL".  It's a poor idea of somebody not
yet used to parallelism and/or OS development, living in an
intellectual world of MS-DOS or ancient MacOS (cooperative
"multitasking").  There may be uses, but not at the level of
application or library writers.  I sincerely hope the examples above
make this clear.  Please learn to live with concurrency.  Learn the
patterns for synchronisation and communication in a parallel world
instead of retrograding to past thinking.


Roger corman writes about CormanLisp:
> There is not a way for a function (or assembly code) to "turn off"
> other threads or the garbage collector. This is by design.

Applause! Clap clap!  A reasonable voice in the darkness, really.
It seems (also from you slides I read long ago) Corman Lisp has a very
sound base for multithreading.

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Pascal Bourguignon
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <87slnq15j8.fsf@thalassa.informatimago.com>
Joerg Hoehle <······@users.sourceforge.net> writes:

> "justinhj" <········@gmail.com> writes:
>> I'd expect there to be a way to turn of GC in a thread during an asm or
>> FFI call, but I may be off.
> [...]
> To me, the sole idea of turning off GC and/or threads should be
> frowned upon, as in "EVAL is EVIL".  It's a poor idea of somebody not
> yet used to parallelism and/or OS development, living in an
> intellectual world of MS-DOS or ancient MacOS (cooperative
> "multitasking").  There may be uses, but not at the level of
> application or library writers.  I sincerely hope the examples above
> make this clear.  Please learn to live with concurrency.  Learn the
> patterns for synchronisation and communication in a parallel world
> instead of retrograding to past thinking.

MacOS experience tells us that it's quite possible to write safe code
with moving memory blocks, if you have a function to lock the one
memory block you're working with.  In MacOS, you'd get in general
"handles", that is pointers to pointer to the data.  The pointer to
the data can be modified when the data is moved by the Memory Manager.
If you want to work with a memory block, you can lock the handle,
derefer it, work with the block, then unlock the handle.  We can
easily have something similar with a garbage collector.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

READ THIS BEFORE OPENING PACKAGE: According to certain suggested
versions of the Grand Unified Theory, the primary particles
constituting this product may decay to nothingness within the next
four hundred million years.
From: Raffael Cavallaro
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <2006050407524516807-raffaelcavallaro@pasdespamsilvousplaitmaccom>
On 2006-05-04 05:51:55 -0400, Pascal Bourguignon <···@informatimago.com> said:

> We can
> easily have something similar with a garbage collector.

Agreed. It's nice to have a static memory region acessible from lisp as 
a middle ground between an OS that expects explicit manual memory 
management and a relocating lisp gc.
From: justinhj
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <1146790177.605639.290930@y43g2000cwc.googlegroups.com>
"To me, the sole idea of turning off GC and/or threads should be
frowned upon, as in "EVAL is EVIL".  It's a poor idea of somebody not
yet used to parallelism and/or OS development, living in an
intellectual world of MS-DOS or ancient MacOS (cooperative
"multitasking").  There may be uses, but not at the level of
application or library writers.  I sincerely hope the examples above
make this clear.  Please learn to live with concurrency.  Learn the
patterns for synchronisation and communication in a parallel world
instead of retrograding to past thinking. "

Wow thanks for the lecture ;-) I work with concurrent machines and have
done for several years so I am aware of the issues. I just wondered
whether you could safely access lisp structures from asm when GC is
running in another thread, and it seems from Roger's post that you can
if you're careful. 


Justin
From: Burton Samograd
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <87zmhx2q7g.fsf@gmail.com>
"justinhj" <········@gmail.com> writes:

> "To me, the sole idea of turning off GC and/or threads should be
> frowned upon, as in "EVAL is EVIL".  

I keep hearing that "EVAL is EVIL".  Not to start a flame war or
anything, but why is that?  I find eval very useful in many languages,
even so far as to wish that I had it in C for some complex tasks that
can be solved using it.  I realize that using eval can make code
difficult to understand for other people that need to maintain it; is
that why eval is evil, or are there other problems with it as well?

-- 
burton samograd					kruhft .at. gmail
kruhft.blogspot.com	www.myspace.com/kruhft	metashell.blogspot.com
From: Bill Atkins
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <87y7xhb57d.fsf@rpi.edu>
Burton Samograd <············@gmail.com> writes:

> "justinhj" <········@gmail.com> writes:
>
>> "To me, the sole idea of turning off GC and/or threads should be
>> frowned upon, as in "EVAL is EVIL".  
>
> I keep hearing that "EVAL is EVIL".  Not to start a flame war or
> anything, but why is that?  I find eval very useful in many languages,
> even so far as to wish that I had it in C for some complex tasks that
> can be solved using it.  I realize that using eval can make code
> difficult to understand for other people that need to maintain it; is
> that why eval is evil, or are there other problems with it as well?
>
> -- 
> burton samograd					kruhft .at. gmail
> kruhft.blogspot.com	www.myspace.com/kruhft	metashell.blogspot.com

Here are a couple of reasons:

  - Efficiency - EVAL's can often be eliminated by using macros or
    closures, which can be compiled in advance

  - Error-checking and type inference - a compiler can neither check
    for errors nor do type inference until the code is actually
    evaluated, at runtime

  - Maintainability (as you mention) - figuring out what code is being
    passed to an EVAL can be much more complicated than using a macro
    and MACROEXPAND'ing it

If it's really the only choice you've got (and sometimes that is the
case), then there's nothing wrong with using an EVAL.  I think the
normal admonition against EVAL is about preventing people from
immediately coming up with an EVAL solution when better constructs
(e.g. macros, closures) are available.

-- 
This is a song that took me ten years to live and two years to write.
- Bob Dylan
From: Pascal Bourguignon
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <87u085z062.fsf@thalassa.informatimago.com>
Burton Samograd <············@gmail.com> writes:

> "justinhj" <········@gmail.com> writes:
>
>> "To me, the sole idea of turning off GC and/or threads should be
>> frowned upon, as in "EVAL is EVIL".  
>
> I keep hearing that "EVAL is EVIL".  Not to start a flame war or
> anything, but why is that?  I find eval very useful in many languages,
> even so far as to wish that I had it in C for some complex tasks that
> can be solved using it.  I realize that using eval can make code
> difficult to understand for other people that need to maintain it; is
> that why eval is evil, or are there other problems with it as well?

There's nothing really evil with eval, but the pun.

The problem of eval is that it evaluates the expression in the null
lexical environment.  Therefore you cannot access the local variables:

(let ((x 1))
  (eval '(+ 1 x))) --> error x undefined.

So its usefulness is limited.

Newbies should rather use macros and closures.

(let ((x 1))
  (funcall (lambda () (+ 1 x)))) --> 2


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"A TRUE Klingon warrior does not comment his code!"
From: Duane Rettig
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <o01wv9ue8u.fsf@franz.com>
Pascal Bourguignon <···@informatimago.com> writes:

> Burton Samograd <············@gmail.com> writes:
>
>> "justinhj" <········@gmail.com> writes:
>>
>>> "To me, the sole idea of turning off GC and/or threads should be
>>> frowned upon, as in "EVAL is EVIL".  
>>
>> I keep hearing that "EVAL is EVIL".  Not to start a flame war or
>> anything, but why is that?  I find eval very useful in many languages,
>> even so far as to wish that I had it in C for some complex tasks that
>> can be solved using it.  I realize that using eval can make code
>> difficult to understand for other people that need to maintain it; is
>> that why eval is evil, or are there other problems with it as well?
>
> There's nothing really evil with eval, but the pun.

You're on the right track.  Programmers (and, it seems, especially Lispers)
tend to get all bent out of shape when a coding practice bites them in
the behind.  Or, they find rules of programming that state that something
is desirable, so of course it _must_ be used whenever possible.  Even
before I got into Lisp in the mid-80s, there was a colleague of mine who
worshipped Yourdon and "Structured Programming", and I got a good fill of
a lecture when I built a state-machine as the best solution to a particular
problem (which of course went completely against structured-programming
practices).  Ironically, just before I left and joined my present employer,
my colleague had found out that Yourdon had himself made some statements
that structured-programming didn't apply to all programming problems...

Back to the negatives: there is of course the ubiquitous Evil GoTo, which has
been around forever (but of course is the only universal way to get around
in assembler).  And when I came to Lisp, I was greeted by a familiar situation:
the hygenic macro, which of course proves how backward and raw Common Lisp is ...
(I hadn't heard of macro hygiene before, but I recognized it as another
manifestation of The One True Way to program)...

Good grief.

> The problem of eval is that it evaluates the expression in the null
> lexical environment.  Therefore you cannot access the local variables:
>
> (let ((x 1))
>   (eval '(+ 1 x))) --> error x undefined.
>
> So its usefulness is limited.

Well, yes, eval's usefulness is limited for this reason, but here's where you've
gotten off the track:  You just call this "the problem" with eval.  It is not.
The problem with your argument is that eval has been a lot of things in a lot
of different lisps, and the limitation that CL places on eval to operate in
the null lexical environment is an _effect_ of eval's problem, not its cause.

In fact, every implementation that provides an eval which interprets must include
some internal functionality that _does_ operate in a non-null environment.  In
Allegro CL, which takes full advantage of Environments Access (even within its
interpreter) the above code could have been successfully executed within a function
that explicitly looks for an environment argument:

CL-USER(1): (let ((x 1))
              (excl::**eval '(+ 1 x) sys:*interpreter-environment*))
2
CL-USER(2): 

> Newbies should rather use macros and closures.
>
> (let ((x 1))
>   (funcall (lambda () (+ 1 x)))) --> 2

Yes, you seem to have followed your own advice and used a macro (i.e. the
lambda form) but you missed one which is even more efficient: just plain
old funcall.  There is no reason why you couldn't have simplified the above
to just

(let ((x 1))
  (funcall '+ 1 x))  --> 2

or

(let ((x 1))
  (funcall #'+ 1 x))  --> 2

and though the semantics are not quite the same (why?) the simplification
does show the incredible power of the lowly funcall...

Note the Common Lisp spec passes very little judgement over eval.  An
exception: it recommends using the equivalent symbol-value over eval when
a symbol is the argument.  This hardly seems like an indictment of eval
as evil.

So what is it about eval that makes it less desirable to use in normal
Lisp coding?  I think I've provided some clues here.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Joerg Hoehle
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <uirp3gkkp.fsf@users.sourceforge.net>
Frank Buss <··@frank-buss.de> writes:
> But I've heard in #lisp that when creating a vector
> with type (unsigned-byte 8) it looks like a normal char array with unboxed
> elements in some implementations.
Yes, but GC will move such verctors around at unpredictable times.

> But there is work in progress for  a
> with-shared-vector-data macro in CFFI to make sure that all the nasty
> things can't happen, like relocating the array when GC is executed etc.,
> which would be bad for the receiving C program, if it holds a pointer to
> it.

The SHARED-VECTOR API is dead by design.  Either Lisp implementations
move (unsigned-byte 8) around, or they don't.  No implementation will
change its low-level strategy just because CFFI came up with this.

Similarly, some Lisp implementations store strings with an ending \0
(like C strings), others don't.  No existing implementation will
change its low-level strategy just because you could invent a
CFFI:WITH-POINTER-TO-0-TERMINATED-STRING.

Both have cost 0 on some implementations, and a high / infinite cost
on others.  Such a design is to be rejected because its the opposite
of "universal" or "common".

If you want foreign data with 8bit vectors, just allocate such a
foreign vector.

Regarding people wanting to use SYS::WITHOUT-INTERRUPTS or WITHOUT-GC
in application code: boy, that was good enough >20 years ago.  Since
then, hackers matured.
Can you pronounce WITHOUT-INTERRUPTS and THREADS in a single sentence?

Regards,
	Jorg Hohle
From: Frank Buss
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <1n9ry1g939i0r.14qvrjz91ns6r$.dlg@40tude.net>
Joerg Hoehle wrote:

> The SHARED-VECTOR API is dead by design.  Either Lisp implementations
> move (unsigned-byte 8) around, or they don't.  No implementation will
> change its low-level strategy just because CFFI came up with this.

In LispWorks you can allocate objects in-static-area and I assume other
implementations provide something similiar.

> If you want foreign data with 8bit vectors, just allocate such a
> foreign vector.

But maybe you are right and it would be the best way to allocate a foreign
vector :-)

> Regarding people wanting to use SYS::WITHOUT-INTERRUPTS or WITHOUT-GC
> in application code: boy, that was good enough >20 years ago.  Since
> then, hackers matured.
> Can you pronounce WITHOUT-INTERRUPTS and THREADS in a single sentence?

Yes, interrupts and threads are different concepts, but at least in device
drivers interrupts are used often, so if Lisp is used for device driver
development, without-interrupts might be useful.

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Joerg Hoehle
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <uejzrgjry.fsf@users.sourceforge.net>
Frank Buss <··@frank-buss.de> writes:
> With CFFI this code works, at least with CLISP 2.38 and LispWorks 4.3.7
> (defun assembler-sum (list)
>   (let ((program 
>          '(
> #x55            ;      push ebp       ; save frame pointer
> #x8b #xec       ;      mov  ebp, esp  ; get stack pointer
[...]
>     (cffi:with-foreign-object (code :unsigned-char (length program))
>       (loop for byte in program
[...]
>        (cffi:foreign-funcall code :pointer data :int (length list)

I'm quite surprised, because I'd have expected an instruction & data
cache mismatch, or even a segfault for trying to execute bytes located
in a data section (the heap) -- no the stack in your case.

In order to work on many platforms, I believe you need to be able to
access/flush the cache and/or set execute permissions on the
appropriate memory region.


>With CFFI this code works, at least [...] on Windows:
Grr... I'd expected this to fail on Linux, but your code also works
there (just tested on Ubuntu Breezy i386 with clisp-2.35) :-( :-(

And it even works when using CFFI:FOREIGN-MALLOC (malloc space) :-(

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Pascal Bourguignon
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <87r73r2d7r.fsf@thalassa.informatimago.com>
Joerg Hoehle <······@users.sourceforge.net> writes:

> Frank Buss <··@frank-buss.de> writes:
>> With CFFI this code works, at least with CLISP 2.38 and LispWorks 4.3.7
>> (defun assembler-sum (list)
>>   (let ((program 
>>          '(
>> #x55            ;      push ebp       ; save frame pointer
>> #x8b #xec       ;      mov  ebp, esp  ; get stack pointer
> [...]
>>     (cffi:with-foreign-object (code :unsigned-char (length program))
>>       (loop for byte in program
> [...]
>>        (cffi:foreign-funcall code :pointer data :int (length list)
>
> I'm quite surprised, because I'd have expected an instruction & data
> cache mismatch, or even a segfault for trying to execute bytes located
> in a data section (the heap) -- no the stack in your case.
>
> In order to work on many platforms, I believe you need to be able to
> access/flush the cache and/or set execute permissions on the
> appropriate memory region.
>
>
>>With CFFI this code works, at least [...] on Windows:
> Grr... I'd expected this to fail on Linux, but your code also works
> there (just tested on Ubuntu Breezy i386 with clisp-2.35) :-( :-(
>
> And it even works when using CFFI:FOREIGN-MALLOC (malloc space) :-(

Well, if a cache flush is not done at a convenient place by the
implementation, it could not work in some cases.

To break it, you could start modifying between to foreign-funcalls a
code vector allocated once.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Cats meow out of angst
"Thumbs! If only we had thumbs!
We could break so much!"
From: Frank Buss
Subject: Re: Writing machine code from LISP
Date: 
Message-ID: <b2vs2pkoy1t7.qf0pfzicjcj1$.dlg@40tude.net>
Joerg Hoehle wrote:

> I'm quite surprised, because I'd have expected an instruction & data
> cache mismatch, or even a segfault for trying to execute bytes located
> in a data section (the heap) -- no the stack in your case.

That's how buffer overflows works :-)

> In order to work on many platforms, I believe you need to be able to
> access/flush the cache and/or set execute permissions on the
> appropriate memory region.

I think AMD processors have such a feature, I don't know if Intel has this,
too, but you are right, special functions may be needed to make it work on
other platforms. Maybe we should take a look at Common Lisp implementations
and how they do (compile 'function).

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de