summaryrefslogtreecommitdiff
path: root/lisp/README
blob: f6e5fdb03d3905789e30ef48fae15bbc4141912a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
$XFree86: xc/programs/xedit/lisp/README,v 1.12 2002/11/23 08:26:47 paulo Exp $

LAST UPDATED:	$Date$


    SUMMARY

  This is a small lisp interpreter for xedit. It implements a subset of
Common Lisp and the xedit package implements several of the basic Emacs
lisp functions.

(shared modules not broken, but needs a redesign for better performance,
 but won't be made available in the default build probably for a long time,
 it would be really better to generate the interface dinamically, and/or just
 link agains't the required libraries and use a ffi interface)
+------------------------------------------------------------------------
|   It has a very simple method for loading shared modules, slightly based on
| the XFree86 loader code, that is currently disabled by default. To enable it,
| edit lisp.cf and change BuildSharedLispModules to YES.
|
|   Assuming you have built it with BuildSharedLispModules enabled, you can build
| a small test application can be built in this directory running "make lsp".
| Two lisp programs are available in the test directory. To test the programs
| run "./lsp test/hello.lsp" or "./lsp test/widgets.lsp".
+------------------------------------------------------------------------

  Currently, it should be used as an helper and/or a small calculator embedded
in xedit. For the future it should be possible to write entire interfaces
in the xedit text buffers.


    USAGE SUMMARY

  To evaluate lisp expressions, put the text cursor just after the
lisp expression and press:
C-x,C-e	- will evaluate it, and print the result to the message window
C-j	- will evaluate it, and print the result to the edit window, any
	  errors are printed to the message window.
C-g	- will send an SIGINT to the lisp process, and that process will
	  stop whatever it was processing and jump to the toplevel,
	  to wait for more input.

Note that C-j will only work in the *scratch* buffer.


     NOTES

  The improvements to xedit including the several possibilites to extend
the editor using Lisp are expected to allow making of xedit a versatile
text editor for programming, but there is code being (slowly) developed
that should also make it useable as a small word processor, for things
like WYSIWYG html, etc.
  The xedit development is being done very slowly, maybe it will get
somewhere someday, but it is a pet/hobby project, there is no intention
of making of it an end user editor (the idea is to make it an useful
development tool).
  In some aspects the development is trying to mimic several Emacs
features, but there is no intention of competition (if xedit ever get
something better than Emacs, I hope that it serves as a motivation to
make of Emacs an even better editor), actually it is expected to explore
different areas and use alternate solutions for the implementation.
  Most work in a computer is done in a text editor and the more the editor
can help the user the better.


(debugger is broken and very slow, no prevision for fixing it, but is
 expected to work correctly for interpreted only code)
+------------------------------------------------------------------------
|     DEBUGGER
|
|   There is a, currently, very simple debugger implement in the interpreter.
| The debugger is now optional, and off by default. To make it available,
| you need to recompile with -DDEBUGGER.
| To use the debugger, run the lsp sample program as "./lsp -d", and optionally
| pass a second parameter, for the file to be interpreted. Once the debugger
| prompt is visible, type "help" for a summary of options. To leave the debugger
| type "continue".
|   Note that the debugger is still very simple, it won't work from xedit, and
| won't drop to the debugger on "fatal errors". It allows adding breakpoints to
| functions and watchpoints to variables. Support for changing data and going to
| the debugger on fatal errors should be added at some time.
+------------------------------------------------------------------------


    COMPILER

  Now there is a very simple bytecode compiler. It is far from finished, but
for simple code can show significant better performance.
  There is not yet an interface to compile entire files and no interface to
store the generated bytecode in disk. There is an interface to bytecode
compile toplevel forms as a LAMBDA NIL, but it is not yet exported.
  If your code needs to call GO/RETURN/RETURN-FROM as the result of an EVAL,
it must jump to code in the interpreter, after compiling all calls to
GO/RETURN/RETURN-FROM are just stack adjusting and jumps in the bytecode.
CATCH/THROW and UNWIND-PROTECT are running as interpreted code for now, so it
is safe to use these, but code in such blocks is not compiled/optimized
(not even macro expansion is done, as it understands that while not compiled,
everything is candidate to redefinition at any time).
  To compile the code, just write a function, and compile it, example:

	(defun fact (n)
	    (if (< n 2)
		1
		(* n (fact (1- n)))
	    )
	)
	FACT

	(compile 'fact)
	FACT
	NIL
	NIL

	(disassemble 'fact)
	Function FACT:
	1 required argument: N
	0 optional arguments
	0 keyword parameters
	No rest argument

	Bytecode header:
	1 element used in the stack
	2 elements used in the builtin stack
	0 elements used in the protected stack
	Constant 0 = 1
	Constant 1 = (2)
	Symbol 0 = N
	Builtin 0 = *
	Builtin 1 = 1-
	Builtin 2 = <

	Initial stack:
	0 = N

	Bytecode stream:
	   0  LOAD&PUSH (0)
	   2  LOADCON&PUSH [1]	    ;  (2)
	   4  CALL 2 [2]	    ;  <
	   7  JUMPNIL 8
	  10  LOADCON [0]	    ;  1
	  12  NOOP
	  13  JUMP 19
	  16  LOAD&PUSH (0)
	  18  LOAD&PUSH (0)
	  20  CALL 1 [1]	    ;  1-
	  23  LET* [0]		    ;  N
	  25  LETREC 1
	  27  UNLET 1
	  29  BCONS1
	  30  CALL 1 [0]	    ;  *
	  33  RETURN
	FACT


  There are several optimizations that should be done at some time, I don't
think adding NOOP opcodes will help everywhere to make aligned memory reads
of shorts and ints.
  It should have explicitly visible registers, not the abstraction of "the
current value", so the code generator can choose register allocation for
loop control variables, commonly used variables, etc, for example. Jumps
should have 3 types: byte relative, 2 bytes relative and 4 bytes relative.
For now there is only 2 byte relative jumps, byte relative jumps
can show a significant performance increase, but they are disable until
it is decided how inlined functions will work, if it just updates the bytecode
header and cut&past the bytecode, jumps must be updated, and some jumps
may not fit anymore in a byte.


    OPTIMIZATION

  There are plenty of possibilities to make the interpreter run faster. Some
optimizations that can make it run quite faster in certain cases are:
  o Better object memory layout and gc. The current memory allocation code
    is very bad, it try to keep 3 times more free objects than the currently
    used number, this can consume a lot of memory. The reason is to reduce
    the gc time cost so that it will in average miss only one in every 4
    collect tries.
  o Implement real vectors, currently they are just a list, so it cannot
    just deference a given index, and gc time is very long also.
  o Most lists are never changed once created, it could somehow add an index
    field in the cons cell, so that NTH/NTHCDR/LENGTH like code could just
    deference the correct object, instead of traversing the CDR of every
    cons. This would probably require implementing lists as vectors, while
    making it easy to deference would make life harder when deleting/inserting
    sublists in a list. It should also better be done in a way that does
    not require a lot of objects allocated linearly.


    HELPING

  Send comments and code to me (paulo@XFree86.Org) or to the XFree86
mailing/patch lists.

--
Paulo