[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jinx@CHAMARTIN.AI.MIT.EDU: Extending the address space of MIT Cscheme (long reply)]



Date: Thu, 5 May 88 15:28:29 edt
From: jinx@CHAMARTIN.AI.MIT.EDU (Guillermo J. Rozas)
To: shebs%defun@cs.utah.edu
In-Reply-To: Stanley T. Shebs's message of Thu, 5 May 88 08:32:54 MDT <8805051432.AA02983@defun.utah.edu>
Subject: Extending the address space of MIT Cscheme (long reply)
Reply-To: jinx@zurich.ai.mit.edu


    I was suggesting user-defined types, a la DEFSTRUCT.  Some types are just
    not "important" enough to be made into primitives.  User-defined types are
    such an important abstraction it's surprising to see CScheme not use them;
    it would save a lot in the many switch statements on types.

CScheme has a defstruct-like macro (define-structure).  Most of the
types you saw in the C files are used by the implementation as GJS
implied.  An altogether different question is whether defstruct really
provides (relatively opaque) types or merely convenient syntax for
constructors, selectors and mutators for standard types.

    >1) Using a virtual machine is a common technique these days to
    >implement interpreters.  We have made no claim that our interpreter
    >will run code as fast as code produced by native code compilers.  Thus
    >there is no attempt to make the CScheme interpreter run as fast as
    >anybody else's compiled code.  As far as interpreters go, it's not
    >great, but it's not bad in terms of speed, but provides much more
    >convenience and ease of debugging than any other interpreter I know.
    >
    >2) Most of the hairy C and macrology arise not from using a virtual
    >machine, but from the fact that the PARTICULAR virtual machine we
    >chose cannot be conveniently written in C without paying an undue
    >penalty.

    These two statements seem contradictory - first you're saying that there
    is no attempt to make things as fast as compiled code, but that using
    functions instead of macros exacts an undue penalty.  I don't understand!

They are not contradictory.  The first version of the C Scheme
interpreter ran about 4 times slower than the assembly language
version on the same hardware.  We were not attempting to achieve
native code speed, merely regain the penalty imposed by naively coding
in C.

    I found the check for the *necessity* of GC, and it was in the same place
    that most other implementations put it.  What I didn't find was how the check
    actually got a GC going!  No doubt it will seem straightforward to me too,
    once it's pointed out...

The relevant macros are (in microcode/primitive.h and microcode/gc.h)

#define Primitive_GC(Amount)						\
{									\
  Request_GC (Amount);							\
  Primitive_Interrupt ();						\
}

#define Primitive_Interrupt signal_interrupt_from_primitive

#define Request_GC(Amount)						\
{									\
  REQUEST_INTERRUPT(INT_GC);						\
  GC_Space_Needed = Amount;						\
}

where signal_interrupt_from_primitive is a procedure in
microcode/utils.c.

I would hardly call this a maze.  A good cross-reference program could
easily help you sort this one out.  Even grep suffices most of the
time, and certainly in this case.

    >    References to the compiler and Edwin, thus violating every principle of
    >    abstraction known to exist.
    >
    >What?  Please explain, I don't understand what that means.

    I'm speaking of edwin.h and com*.c.  Why are they for?

I don't believe that the fact that you don't know what they are for
implies that some abstraction principles have been violated.

compiler.c and related files are various hooks for the compiler.  The
default version of the system assumes that there is no compiler, so
the hooks are just stubs.  When the compiler is ported to a new
machine/operating system, appropriate versions of these files are
written reflecting some of the machine-dependent decisions made, and
implementing the compiled code interface to the interpreter.  It is a
relatively simple and innocuous way of providing a system which can
coexist with the compiler but does not require its presence.

edwin.h is a spurious part of the release.  rgxprim.c and syntax.c
(which are the only files that need it) are files essentially taken
 from GNU Emacs, and could easily be spliced out of the load sequence
since the system does not use them.

A problem that must be faced when attempting to write a (relatively)
portable EXTENSIBLE C program is that there is no standardized dynamic
loader for C, so all of the C code that you may ever want to use must
be linked to your interpreter at interpreter generation time.

We could have attempted to write a dynamic linker for C, but the
resulting system would probably have been far less portable, and even
harder to read.