John Leuner <[EMAIL PROTECTED]> writes:

> I've been working on an experimental port of jolt-burg. The main difference is
> that my implementation language is Common Lisp and that my compiler targets
> relocatable ELF object files.

Interesting!

I was inspired by you, and tried my hand at getting similar changes
into jolt2.  The attached patch should apply cleanly on top of SVN
-r407, followed by my jolt2-fixes.patch that I posted earlier.

Here is the function/examples2/slink/README file (also included in the
attached jolt2-slink.patch) for more information:

SLINK 0.2
*********

Slink is the beginning of a statically-linking compiler extension for
Jolt2 (think "Static LINK" or "System LINK").  It was partly inspired
by John Leuner's Common Lisp port of jolt-burg that creates
relocatable ELF objects.  I'm basically attempting to land the same
kinds of features in COLA proper without changing too much of the
existing compiler machinery.

It has many limitations, but is a proof-of-concept and will probably
evolve (the main direction for evolution is to make the changes less
and less dependent on patching Jolt2's Id sources directly, and
instead accomplish its features at runtime via slink.k and friends).

The centerpiece of this system is slink-compile, which currently can
only generate i386 assembly code.  The following new syntax is
introduced:

(define (slink SYMBOL))
  Import SYMBOL from the system linker.  If running with the dynamic
  compiler, this is equivalent to:

     (active SYMBOL (dlsym "SYMBOL"))

  If under the static compiler (slink-compile), this will cause future
  references to SYMBOL to be resolved at link time rather than
  runtime.

(define (slink SYMBOL) EXPRESSION)
  Create a region of memory containing the results of EXPRESSION.
  SYMBOL is exported to the system linker.  Only expressions resulting
  in integers, strings, floats, and lambdas currently work.

To get a feel for things, run "make test" which exercises slink both
at runtime and compile time.  You'll notice that the results of this
execution are a binary executable (slinktest) with no runtime
dependency on COLA.

IMPLEMENTATION
**************

I did a lot of work creating a bunch of slink-specific methods in the
existing COLA compiler.  Now I'm gradually undoing as much of that
work as possible to leave only the core features in Jolt2, so that the
rest can be just another unprivileged application.

Once you understand what the slink syntax does, it shouldn't be too
hard to follow what I needed to do to get things working.  A "grep -i
slink *.st" is very informative (and half the reason I needed to find
a catchy name that wouldn't be buried in the other identifiers).

Toplevel Jolt expressions are gathered up and attached to the system's
initialisation functions so that they are executed at program start
(for i386, using the same method as C++ constructors).

The syntax and actives systems will need to be revisited, probably to
do something like Scheme-48 where a "load-syntax" or "require-syntax"
will import only the syntax elements into the namespace (thereby
avoiding problems with importing undesired lambdas and toplevel code
evaluation by accident).

It would be really nice to implement a few more CodeGenerator backends
to bypass assembly language entirely and generate binaries.

Slink has a naive three-region model for assembler output.  First
comes a bss section with all the variables, then a data section with
all the strings, then finally a text section with all the compiled
functions.  To my knowledge, this is adequate for the platforms on
which COLA already runs, but of course it would be good to be able to
provide something akin to linker scripts in the future to allow much
more flexible layout.

Have fun,

-- 
Michael FIG <[EMAIL PROTECTED]> //\
   http://michael.fig.org/    \//

Generate assembler from Jolt code.

diff -r 531fb2c16da1 function/examples2/slink/README
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/function/examples2/slink/README	Wed Apr 23 23:40:24 2008 -0600
@@ -0,0 +1,76 @@
+SLINK 0.2
+*********
+
+Slink is the beginning of a statically-linking compiler extension for
+Jolt2 (think "Static LINK" or "System LINK").  It was partly inspired
+by John Leuner's Common Lisp port of jolt-burg that creates
+relocatable ELF objects.  I'm basically attempting to land the same
+kinds of features in COLA proper without changing too much of the
+existing compiler machinery.
+
+It has many limitations, but is a proof-of-concept and will probably
+evolve (the main direction for evolution is to make the changes less
+and less dependent on patching Jolt2's Id sources directly, and
+instead accomplish its features at runtime via slink.k and friends).
+
+The centerpiece of this system is slink-compile, which currently can
+only generate i386 assembly code.  The following new syntax is
+introduced:
+
+(define (slink SYMBOL))
+  Import SYMBOL from the system linker.  If running with the dynamic
+  compiler, this is equivalent to:
+
+     (active SYMBOL (dlsym "SYMBOL"))
+
+  If under the static compiler (slink-compile), this will cause future
+  references to SYMBOL to be resolved at link time rather than
+  runtime.
+
+(define (slink SYMBOL) EXPRESSION)
+  Create a region of memory containing the results of EXPRESSION.
+  SYMBOL is exported to the system linker.  Only expressions resulting
+  in integers, strings, floats, and lambdas currently work.
+
+To get a feel for things, run "make test" which exercises slink both
+at runtime and compile time.  You'll notice that the results of this
+execution are a binary executable (slinktest) with no runtime
+dependency on COLA.
+
+IMPLEMENTATION
+**************
+
+I did a lot of work creating a bunch of slink-specific methods in the
+existing COLA compiler.  Now I'm gradually undoing as much of that
+work as possible to leave only the core features in Jolt2, so that the
+rest can be just another unprivileged application.
+
+Once you understand what the slink syntax does, it shouldn't be too
+hard to follow what I needed to do to get things working.  A "grep -i
+slink *.st" is very informative (and half the reason I needed to find
+a catchy name that wouldn't be buried in the other identifiers).
+
+Toplevel Jolt expressions are gathered up and attached to the system's
+initialisation functions so that they are executed at program start
+(for i386, using the same method as C++ constructors).
+
+The syntax and actives systems will need to be revisited, probably to
+do something like Scheme-48 where a "load-syntax" or "require-syntax"
+will import only the syntax elements into the namespace (thereby
+avoiding problems with importing undesired lambdas and toplevel code
+evaluation by accident).
+
+It would be really nice to implement a few more CodeGenerator backends
+to bypass assembly language entirely and generate binaries.
+
+Slink has a naive three-region model for assembler output.  First
+comes a bss section with all the variables, then all the data
+elements, then a text section with all the compiled functions.  To my
+knowledge, this is adequate for the platforms on which COLA already
+runs, but of course it would be good to be able to provide something
+akin to linker scripts in the future to allow much more flexible
+layout.
+
+Have fun,
+
+Michael FIG <[EMAIL PROTECTED]>, 2008-04-17
diff -r 531fb2c16da1 function/examples2/slink/main.k
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/function/examples2/slink/main.k	Wed Apr 23 23:40:24 2008 -0600
@@ -0,0 +1,26 @@
+(define (slink printf))
+(printf "Hello from constructor\n")
+(define zot 0x123456)
+;;(slink mylist '(1 2 3 "foo" 0.3456))
+(define baz zot)
+(define (slink zot_addr) zot)
+
+(define (slink hello)
+  (lambda (progname argc)
+; FIXME: For when we can import only macros from "syntax.k"
+;    (printf "Have an int: 0x%x@(0x%x==0x%x), and a copy [EMAIL PROTECTED]"
+;	    zot (addrof zot) zot_addr baz (addrof baz))
+    (printf "Have an int: [EMAIL PROTECTED], and a copy 0x%x\n"
+	    zot zot_addr baz)
+    (printf "Goodbye, world (%s with %d arguments)!\n" progname argc)))
+
+(define test2
+  (lambda ()
+    (printf "Another test from constructor\n")))
+
+(define (slink main)
+  (lambda (argc argv)
+    (hello (long@ argv) (- argc 1))
+    0))
+
+(test2)
diff -r 531fb2c16da1 function/examples2/slink/slink.k
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/function/examples2/slink/slink.k	Wed Apr 23 23:40:24 2008 -0600
@@ -0,0 +1,46 @@
+(define slink-compile
+  (lambda (path)
+    (let ((pathstr [String value_: path])
+	  (filename pathstr)
+	  (file [File openIfPresent: filename]))
+      (or file (let ()
+		 (set filename [[[Options libdir] , '"/"] , pathstr])
+		 (set file [File openIfPresent: filename])))
+      (or file (let ()
+		 (set filename [[[Options progdir] , '"/"] , pathstr])
+		 (set file [File openIfPresent: filename])))
+      (if file
+	  (let ((outname [pathstr , '".s"]))
+	    [StdErr nextPutAll: '";; slink-compile "]
+	    [StdErr nextPutAll: filename]
+            [StdErr cr]
+
+	    (let ((parser [ColaFunctionGrammar parserOn: file])
+		  (CodeGenerator (import "CodeGenerator"))
+		  (gen [[CodeGenerator default] static])
+		  (SlinkEnvironment (import "SlinkEnvironment"))
+		  (env [SlinkEnvironment new])
+		  (Compiler (import "Compiler"))
+		  (CompilerOptions (import "CompilerOptions"))
+		  (File (import "File"))
+		  (out [File create: outname])
+		  (expr 0))
+
+;	      [CompilerOptions verboseTree: '1]
+	      (while (set expr [parser next])
+		[Compiler compile: expr for: gen with: env])
+;	      [CompilerOptions verboseTree: 0]
+
+	      [StdErr nextPutAll: '";; write output to "]
+	      [StdErr nextPutAll: outname]
+	      [StdErr cr]
+
+	      [gen toStream: out]
+	      [out close])
+
+	    [StdErr nextPutAll: '";; slink-compile is finished"]
+	    [StdErr cr])
+          (let ()
+	    [StdErr nextPutAll: '";; cannot open "]
+	    [StdErr nextPutAll: pathstr]
+	    [StdErr cr])))))
diff -r 531fb2c16da1 function/examples2/slink/test.k
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/function/examples2/slink/test.k	Wed Apr 23 23:40:24 2008 -0600
@@ -0,0 +1,9 @@
+((define (slink hello) (lambda (msg) (printf "hello %s\n" msg))) "the first time")
+(define zot hello)
+(define (slink zorgar) (let () 42))
+(printf "these should match %x == %x but this %d == 42!\n" hello zot zorgar)
+(hello "the second time")
+(zot "the third time")
+
+(load "main.k")
+(hello "from test.k" 666)
diff -r 531fb2c16da1 function/jolt2/CodeGenerator-arm.st
--- a/function/jolt2/CodeGenerator-arm.st	Wed Apr 23 12:20:22 2008 -0600
+++ b/function/jolt2/CodeGenerator-arm.st	Wed Apr 23 23:40:24 2008 -0600
@@ -29,9 +29,9 @@
 
 ARMCodeGenerator : CodeGenerator ( tempsSize registerList r0 r1 ip sp lr pc )
 
-ARMCodeGenerator new
-[
-    self := super new.
+ARMCodeGenerator newScope
+[
+    self := super newScope.
     tempsSize := 0.
     ccrs
 	add: (r0 := Register withClass: I4 name:  'r0' encoding:  0);
diff -r 531fb2c16da1 function/jolt2/CodeGenerator-i386.st
--- a/function/jolt2/CodeGenerator-i386.st	Wed Apr 23 12:20:22 2008 -0600
+++ b/function/jolt2/CodeGenerator-i386.st	Wed Apr 23 23:40:24 2008 -0600
@@ -29,9 +29,9 @@
 
 Intel32CodeGenerator : CodeGenerator ( tempsSize eax ecx edx ebx esp ebp esi edi cx cl )
 
-Intel32CodeGenerator new
-[
-    self := super new.
+Intel32CodeGenerator newScope
+[
+    self := super newScope.
     tempsSize := 0.
     ccrs
 	add: (eax := Register withClass: I4 name: '%eax' encoding: 0x40);
@@ -153,62 +153,123 @@ Intel32CodeGenerator emit: call argument
 
 "----------------------------------------------------------------"
 
-StaticIntel32CodeGenerator : Intel32CodeGenerator ()
-
-StaticIntel32CodeGenerator addrgp4  :d :v	[ StdOut nextPutAll: '	movl	'; nextPut: $$; print: v; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator addrjp4  :d :l	[ StdOut nextPutAll: '	movl	$L'; print: l ordinal; nextPut: $,; print: d; cr ]
-
-StaticIntel32CodeGenerator addlI: i R: d	[ StdOut nextPutAll: '	addl	'; nextPut: $$; print: i; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator addlI_: i R: d	[ StdOut nextPutAll: '	addl	'; nextPut: $$; print: (SmallInteger value_: i); nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator addlR: s R: d	[ StdOut nextPutAll: '	addl	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator andlR: s R: d	[ StdOut nextPutAll: '	andl	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator callMb: b		[ StdOut nextPutAll: '	call	('; print: b; nextPutAll: ')\n' ]
-StaticIntel32CodeGenerator cltd			[ StdOut nextPutAll: '	cltd\n' ]
-StaticIntel32CodeGenerator cmplI: i R: d	[ StdOut nextPutAll: '	cmpl	'; nextPut: $$; print: i; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator cmplI_: i Md: d b: b	[ StdOut nextPutAll: '	cmpl	'; nextPut: $$; print: (SmallInteger value_: i); nextPut: $,; print: d; nextPut: $(; print: b; nextPut: $); cr]
-StaticIntel32CodeGenerator cmplR: s R: d	[ StdOut nextPutAll: '	cmpl	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator define: l		[ StdOut nextPutAll: 'L'; print: l ordinal; nextPut: $:; cr ]
-StaticIntel32CodeGenerator idivlR: s		[ StdOut nextPutAll: '	idivl	'; print: s; cr ]
-StaticIntel32CodeGenerator imullR: s R: d	[ StdOut nextPutAll: '	imull	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator jeL: l		[ StdOut nextPutAll: '	je	L'; print: l ordinal; cr ]
-StaticIntel32CodeGenerator jgeL: l		[ StdOut nextPutAll: '	jge	L'; print: l ordinal; cr ]
-StaticIntel32CodeGenerator jmpL: l		[ StdOut nextPutAll: '	jmp	L'; print: l ordinal; cr ]
-StaticIntel32CodeGenerator jmpMb: b		[ StdOut nextPutAll: '	jmp	*'; print: b; cr ]
-StaticIntel32CodeGenerator jneL: l		[ StdOut nextPutAll: '	jne	L'; print: l ordinal; cr ]
-StaticIntel32CodeGenerator lealMd: d b: b R: r	[ StdOut nextPutAll: '	leal	'; print: d; nextPut: $(; print: b; nextPutAll: '),'; print: r; cr]
-StaticIntel32CodeGenerator lealMd_: d b: b R: r	[ StdOut nextPutAll: '	leal	'; print: (SmallInteger value_: d); nextPut: $(; print: b; nextPutAll: '),'; print: r; cr]
-StaticIntel32CodeGenerator movbR: r Mb: b	[ StdOut nextPutAll: '	movb	'; print: r; nextPutAll: ',('; print: b; nextPut: $); cr ]
-StaticIntel32CodeGenerator movlI_: i R: d	[ StdOut nextPutAll: '	movl	'; nextPut: $$; print: (SmallInteger value_: i); nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator movlMb: b R: r	[ StdOut nextPutAll: '	movl	('; print: b; nextPutAll: '),'; print: r; cr]
-StaticIntel32CodeGenerator movlMd: d b: b R: r	[ StdOut nextPutAll: '	movl	'; print: d; nextPut: $(; print: b; nextPutAll: '),'; print: r; cr]
-StaticIntel32CodeGenerator movlMd_: d R: r	[ StdOut nextPutAll: '	movl	'; print: (SmallInteger value_: d); nextPut: $,; print: r; cr ]
-StaticIntel32CodeGenerator movlR: r Mb: b	[ StdOut nextPutAll: '	movl	'; print: r; nextPutAll: ',('; print: b; nextPut: $); cr ]
-StaticIntel32CodeGenerator movlR: s Md: d b: b	[ StdOut nextPutAll: '	movl	'; print: s; nextPut: $,; print: d; nextPut: $(; print: b; nextPut: $); cr]
-StaticIntel32CodeGenerator movlR: s R: d	[ s == d ifFalse: [StdOut nextPutAll: '	movl	'; print: s; nextPut: $,; print: d; cr] ]
-StaticIntel32CodeGenerator movsblMb: s R: d	[ StdOut nextPutAll: '	movsbl	('; print: s; nextPutAll: '),'; print: d; cr ]
-StaticIntel32CodeGenerator movswlMb: s R: d	[ StdOut nextPutAll: '	movswl	('; print: s; nextPutAll: '),'; print: d; cr ]
-StaticIntel32CodeGenerator movwR: r Mb: b	[ StdOut nextPutAll: '	movw	'; print: r; nextPutAll: ',('; print: b; nextPut: $); cr ]
-StaticIntel32CodeGenerator neglR: d		[ StdOut nextPutAll: '	negl	'; print: d; cr ]
-StaticIntel32CodeGenerator notlR: d		[ StdOut nextPutAll: '	notl	'; print: d; cr ]
-StaticIntel32CodeGenerator orlR: s R: d		[ StdOut nextPutAll: '	orl	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator poplR: d		[ StdOut nextPutAll: '	popl	'; print: d; cr ]
-StaticIntel32CodeGenerator pushlR: s		[ StdOut nextPutAll: '	pushl	'; print: s; cr ]
-StaticIntel32CodeGenerator ret			[ StdOut nextPutAll: '	ret\n' ]
-StaticIntel32CodeGenerator sallR: s R: d	[ StdOut nextPutAll: '	sall	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator sarlR: s R: d	[ StdOut nextPutAll: '	sarl	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator seteR: d		[ StdOut nextPutAll: '	sete	'; print: d; cr ]
-StaticIntel32CodeGenerator setgR: d		[ StdOut nextPutAll: '	setg	'; print: d; cr ]
-StaticIntel32CodeGenerator setgeR: d		[ StdOut nextPutAll: '	setge	'; print: d; cr ]
-StaticIntel32CodeGenerator setlR: d		[ StdOut nextPutAll: '	setl	'; print: d; cr ]
-StaticIntel32CodeGenerator setleR: d		[ StdOut nextPutAll: '	setle	'; print: d; cr ]
-StaticIntel32CodeGenerator setneR: d		[ StdOut nextPutAll: '	setne	'; print: d; cr ]
-StaticIntel32CodeGenerator shllR: s R: d	[ StdOut nextPutAll: '	shll	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator shrlR: s R: d	[ StdOut nextPutAll: '	shrl	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator sublI: i R: d	[ StdOut nextPutAll: '	subl	'; nextPut: $$; print: i; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator sublI_: i R: d	[ StdOut nextPutAll: '	subl	'; nextPut: $$; print: (SmallInteger value_: i); nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator sublR: s R: d	[ StdOut nextPutAll: '	subl	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator testlR: s R: d	[ StdOut nextPutAll: '	testl	'; print: s; nextPut: $,; print: d; cr ]
-StaticIntel32CodeGenerator xorlR: s R: d	[ StdOut nextPutAll: '	xorl	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator : Intel32CodeGenerator (bss data text ctor lambdas extern)
+StaticIntel32CodeGenerator new
+[
+   self := super new.
+   bss := IdentitySet new.
+   data := WriteStream on: (String new: 8192).
+   ctor := WriteStream on: (String new: 8192).
+   lambdas := WriteStream on: (String new: 8192).
+   text := ctor.
+]
+
+StaticIntel32CodeGenerator newScope
+[
+   | newGen saveBss saveData saveCtor saveLambdas saveText |
+   saveBss := bss.
+   saveData := data.
+   saveCtor := ctor.
+   saveLambdas := lambdas.
+   saveText := text.
+   self := super newScope.
+   bss := saveBss.
+   data := saveData.
+   ctor := saveCtor.
+   lambdas := saveLambdas.
+   text := saveText.
+]
+
+StaticIntel32CodeGenerator toStream: out
+[
+   | hdr dataPfx ctorPtr label textPfx ctorPfx ctorSfx |
+   hdr := '# Generated by COLA ', self versionString, '\n'.
+
+   dataPfx := data position == 0 ifTrue: [''] ifFalse: ['\t.data\n'].
+   textPfx := (ctor position + lambdas position) == 0 ifTrue: [''] ifFalse: ['\n\t.text\n'].
+   
+   ctor position == 0
+       ifTrue: [ctorPtr := ''. ctorPfx := ''. ctorSfx := '']
+       ifFalse: [ label := 'L', Label new ordinal asString.
+       		 ctorPtr := '\n\t.section .ctors\n\t.long ', label, '\n'.
+                 ctorPfx := label, ':\n'.
+		 ctorSfx := '\tret\n'].
+
+   out nextPutAll: hdr.
+   bss do: [:elt | out nextPutAll: '\t.lcomm '; nextPutAll: elt asString; nextPutAll: ', 4'; cr].
+
+   out nextPutAll: dataPfx.
+   out nextPutAll: (String size: data position value_: data collection _stringValue).
+
+   out nextPutAll: ctorPtr.
+
+   out nextPutAll: textPfx.
+
+   out nextPutAll: ctorPfx.
+   out nextPutAll: (String size: ctor position value_: ctor collection _stringValue).
+   out nextPutAll: ctorSfx.
+
+   out nextPutAll: (String size: lambdas position value_: lambdas collection _stringValue).
+]
+
+StaticIntel32CodeGenerator define: l
+[
+   text == ctor ifFalse: [text nextPutAll: 'L'; print: l ordinal; nextPut: $:; cr]
+]
+
+StaticIntel32CodeGenerator addrgp4  :d :v	[ text nextPutAll: '	movl	$'; print: v; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator addlI: i R: d	[ text nextPutAll: '	addl	'; nextPut: $$; print: i; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator addlI_: i R: d	[ text nextPutAll: '	addl	'; nextPut: $$; print: (SmallInteger value_: i); nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator addlR: s R: d	[ text nextPutAll: '	addl	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator andlR: s R: d	[ text nextPutAll: '	andl	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator callMb: b		[ text nextPutAll: '	call	*'; print: b; cr ]
+StaticIntel32CodeGenerator cltd			[ text nextPutAll: '	cltd'; cr ]
+StaticIntel32CodeGenerator cmplI: i R: d	[ text nextPutAll: '	cmpl	'; nextPut: $$; print: i; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator cmplI_: i Md: d b: b	[ text nextPutAll: '	cmpl	'; nextPut: $$; print: (SmallInteger value_: i); nextPut: $,; print: d; nextPut: $(; print: b; nextPut: $); cr]
+StaticIntel32CodeGenerator cmplR: s R: d	[ text nextPutAll: '	cmpl	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator idivlR: s		[ text nextPutAll: '	idivl	'; print: s; cr ]
+StaticIntel32CodeGenerator imullR: s R: d	[ text nextPutAll: '	imull	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator jeL: l		[ text nextPutAll: '	je	L'; print: l ordinal; cr ]
+StaticIntel32CodeGenerator jgeL: l		[ text nextPutAll: '	jge	L'; print: l ordinal; cr ]
+StaticIntel32CodeGenerator jmpL: l		[ text nextPutAll: '	jmp	L'; print: l ordinal; cr ]
+StaticIntel32CodeGenerator jmpMb: b		[ text nextPutAll: '	jmp	*'; print: b; cr ]
+StaticIntel32CodeGenerator jneL: l		[ text nextPutAll: '	jne	L'; print: l ordinal; cr ]
+StaticIntel32CodeGenerator lealMd: d b: b R: r	[ text nextPutAll: '	leal	'; print: d; nextPut: $(; print: b; nextPutAll: '),'; print: r; cr]
+StaticIntel32CodeGenerator lealMd_: d b: b R: r	[ text nextPutAll: '	leal	'; print: (SmallInteger value_: d); nextPut: $(; print: b; nextPutAll: '),'; print: r; cr]
+StaticIntel32CodeGenerator lealS: s R: r	[ text nextPutAll: '	leal	'; nextPutAll: s; nextPut: $,; print: r; cr]
+StaticIntel32CodeGenerator movbR: r Mb: b	[ text nextPutAll: '	movb	'; print: r; nextPutAll: ',('; print: b; nextPut: $); cr ]
+StaticIntel32CodeGenerator movlI_: i R: d	[ text nextPutAll: '	movl	'; nextPut: $$; print: (SmallInteger value_: i); nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator movlMb: b R: r	[ text nextPutAll: '	movl	('; print: b; nextPutAll: '),'; print: r; cr]
+StaticIntel32CodeGenerator movlMd: d b: b R: r	[ text nextPutAll: '	movl	'; print: d; nextPut: $(; print: b; nextPutAll: '),'; print: r; cr]
+StaticIntel32CodeGenerator movlMd_: d R: r	[ text nextPutAll: '	movl	'; print: (SmallInteger value_: d); nextPut: $,; print: r; cr ]
+StaticIntel32CodeGenerator movlR: r Mb: b	[ text nextPutAll: '	movl	'; print: r; nextPutAll: ',('; print: b; nextPut: $); cr ]
+StaticIntel32CodeGenerator movlR: s Md: d b: b	[ text nextPutAll: '	movl	'; print: s; nextPut: $,; print: d; nextPut: $(; print: b; nextPut: $); cr]
+StaticIntel32CodeGenerator movlR: s R: d	[ s == d ifFalse: [text nextPutAll: '	movl	'; print: s; nextPut: $,; print: d; cr] ]
+StaticIntel32CodeGenerator movlS: s R: d	[ text nextPutAll: '	movl	'; nextPutAll: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator movsblMb: s R: d	[ text nextPutAll: '	movsbl	('; print: s; nextPutAll: '),'; print: d; cr ]
+StaticIntel32CodeGenerator movswlMb: s R: d	[ text nextPutAll: '	movswl	('; print: s; nextPutAll: '),'; print: d; cr ]
+StaticIntel32CodeGenerator movwR: r Mb: b	[ text nextPutAll: '	movw	'; print: r; nextPutAll: ',('; print: b; nextPut: $); cr ]
+StaticIntel32CodeGenerator neglR: d		[ text nextPutAll: '	negl	'; print: d; cr ]
+StaticIntel32CodeGenerator notlR: d		[ text nextPutAll: '	notl	'; print: d; cr ]
+StaticIntel32CodeGenerator orlR: s R: d		[ text nextPutAll: '	orl	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator poplR: d		[ text nextPutAll: '	popl	'; print: d; cr ]
+StaticIntel32CodeGenerator pushlR: s		[ text nextPutAll: '	pushl	'; print: s; cr ]
+StaticIntel32CodeGenerator ret			[ text == ctor ifFalse: [text nextPutAll: '	ret'; cr] ]
+StaticIntel32CodeGenerator sallR: s R: d	[ text nextPutAll: '	sall	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator sarlR: s R: d	[ text nextPutAll: '	sarl	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator seteR: d		[ text nextPutAll: '	sete	'; print: d; cr ]
+StaticIntel32CodeGenerator setgR: d		[ text nextPutAll: '	setg	'; print: d; cr ]
+StaticIntel32CodeGenerator setgeR: d		[ text nextPutAll: '	setge	'; print: d; cr ]
+StaticIntel32CodeGenerator setlR: d		[ text nextPutAll: '	setl	'; print: d; cr ]
+StaticIntel32CodeGenerator setleR: d		[ text nextPutAll: '	setle	'; print: d; cr ]
+StaticIntel32CodeGenerator setneR: d		[ text nextPutAll: '	setne	'; print: d; cr ]
+StaticIntel32CodeGenerator shllR: s R: d	[ text nextPutAll: '	shll	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator shrlR: s R: d	[ text nextPutAll: '	shrl	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator sublI: i R: d	[ text nextPutAll: '	subl	'; nextPut: $$; print: i; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator sublI_: i R: d	[ text nextPutAll: '	subl	'; nextPut: $$; print: (SmallInteger value_: i); nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator sublR: s R: d	[ text nextPutAll: '	subl	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator testlR: s R: d	[ text nextPutAll: '	testl	'; print: s; nextPut: $,; print: d; cr ]
+StaticIntel32CodeGenerator xorlR: s R: d	[ text nextPutAll: '	xorl	'; print: s; nextPut: $,; print: d; cr ]
 
 Intel32CodeGenerator spilli4:  reg to:   tmp	[ self movlR:  reg        Md: tmp offset b: esp ]
 Intel32CodeGenerator reloadi4: reg from: tmp	[ self movlMd: tmp offset  b: esp        R: reg ]
@@ -299,7 +360,7 @@ CodeGenerator versionString	[ ^self defa
 
 CodeGenerator default		[ ^Intel32CodeGenerator ]
 
-Intel32CodeGenerator static	[ ^StaticIntel32CodeGenerator ]
+Intel32CodeGenerator static	[ ^StaticIntel32CodeGenerator new ]
 Intel32CodeGenerator dynamic	[ ^DynamicIntel32CodeGenerator ]
 
 Intel32CodeGenerator versionString
@@ -315,15 +376,63 @@ CodeGenerator		    isDynamic	[ ^false ]
 CodeGenerator		    isDynamic	[ ^false ]
 DynamicIntel32CodeGenerator isDynamic	[ ^true ]
 
-StaticIntel32CodeGenerator defineVariable: name
-[
-    StdOut nextPutAll: '	.data\n'.
-    StdOut nextPutAll: name; nextPutAll: ':	.long	_'; nextPutAll: name; cr.
-    StdOut nextPutAll: '	.text\n'.
-]
-
-DynamicIntel32CodeGenerator defineVariable: name
-[
+StaticIntel32CodeGenerator slinkName: name
+[
+    | uscore |
+    {
+#if defined(__MACH__) || defined(__CYGWIN__) || defined(__WIN32__)
+        v_uscore = 1;
+#endif
+    }.
+    ^uscore ifTrue: ['_', name] ifFalse: [name]
+]
+
+StaticIntel32CodeGenerator slinkVariable: name [ bss add: name ]
+StaticIntel32CodeGenerator slinkImport: name []
+StaticIntel32CodeGenerator slinkExport: name translate: aForm with: aCompiler
+[
+    | ext result |
+    extern := self slinkName: name.
+    result := aForm translate: aCompiler.
+    (extern and: [result name == #slink or: [result name == #slinki]])
+       ifTrue: [data nextPutAll: '\n\t.globl '; nextPutAll: extern; cr;
+       	             nextPutAll: '\t.set '; nextPutAll: extern; nextPut: $,; nextPutAll: result arg; cr.
+       	        extern := nil].
+    ^nil
+]
+
+StaticIntel32CodeGenerator compileLambda: form with: aCompiler
+[
+   | save label |
+   save := text.
+   text == ctor ifTrue: [text := lambdas].
+   extern ifTrue: [ text cr; nextPutAll: '\t.globl '; nextPutAll: extern; cr;
+   	  	         nextPutAll: extern; nextPut: $:; cr.
+		    extern := nil ].
+   label := aCompiler compileLambda: form.
+   text := save.
+   ^SLINK new arg: ('L', label ordinal asString)
+]
+
+StaticIntel32CodeGenerator translateData_: _bytes length: aLength
+[
+    | name comma s |
+    extern
+       ifTrue: [ name := extern.
+                 data cr; nextPutAll: '\t.globl '; nextPutAll: name; cr.
+    	         extern := nil ]
+       ifFalse: [ name := 'L', (Label new ordinal asString) ].
+
+    s := String size: aLength value_: _bytes.
+    data nextPutAll: name; nextPut: $:.
+    0 to: aLength - 1 do:
+        [:i | i \\ 8 == 0 ifTrue: [data cr; nextPutAll: '\t.byte '. comma := ''].
+	      data nextPutAll: comma; nextPutAll: '0x'; print_x: (s at: i) _integerValue.
+	      comma := ', '
+	].
+    data cr.
+
+    ^SLINK new arg: name
 ]
 
 "----------------------------------------------------------------"
@@ -353,6 +462,8 @@ Intel32Grammar := [
 	at: #VOID add: #(label		)	do: [:op :gen | gen define: op ];
 	at: #REG  add: #(cnsti4	 	)	do: [:op :gen | gen movlI_:   op arg	      R: op output ];
 	at: #REG  add: #(cnstp4	 	)	do: [:op :gen | gen movlI_:   op arg	      R: op output ];
+	at: #REG  add: #(slink	 	)	do: [:op :gen | gen lealS:    op arg	      R: op output ];
+	at: #REG  add: #(slinki	 	)	do: [:op :gen | gen movlS:    op arg	      R: op output ];
 	at: #REG  add: #(parami4 	)	do: [:op :gen | ];
 	at: #REG  add: #(addrfp4 	)	do: [:op :gen | gen movlR:    gen ebp	      R: op output ];
 	at: #REG  add: #(addrgp4 	)	do: [:op :gen | gen movlI_:   op arg _address R: op output ];
@@ -367,7 +478,7 @@ Intel32Grammar := [
 								    movlR:    gen ecx	      R: op output ];
 	at: #REG  add: #(comi4 	 REG	)	do: [:op :gen | gen notlR:    op output ];
 	at: #REG  add: #(negi4 	 REG	)	do: [:op :gen | gen neglR:    op output ];
-	at: #REG  add: #(calli4	 REG	)	do: [:op :gen | gen calli4: op ];
+	at: #REG  add: #(calli4	 REG	)	do: [:op :gen | gen calli4: op];
 	at: #REG  add: #(asgni1  REG REG)	do: [:op :gen | gen movlR:    op lhs output   R: gen ecx;
 								    movbR:    gen cl	     Mb: op rhs output ];
 	at: #REG  add: #(asgni2  REG REG)	do: [:op :gen | gen movlR:    op lhs output   R: gen ecx;
@@ -452,7 +563,7 @@ StaticIntel32CodeGenerator generate: tre
 StaticIntel32CodeGenerator generate: tree
 [
     self finaliseFrame.
-    tree printOn: StdOut indent: 0.  StdOut cr.
+    "tree printOn: StdOut indent: 0.  StdOut cr."
     tree generate: self.
     ^Array with: 0 with: 0.
 ]
diff -r 531fb2c16da1 function/jolt2/CodeGenerator-ppc.st
--- a/function/jolt2/CodeGenerator-ppc.st	Wed Apr 23 12:20:22 2008 -0600
+++ b/function/jolt2/CodeGenerator-ppc.st	Wed Apr 23 23:40:24 2008 -0600
@@ -39,9 +39,9 @@ PowerPCRegister location	[ ^location ]
 
 PowerPCCodeGenerator : CodeGenerator ( r0 r1 r2 r3 r11 r12 )
 
-PowerPCCodeGenerator new
-[
-    self := super new.
+PowerPCCodeGenerator newScope
+[
+    self := super newScope.
     r0           := PowerPCRegister withClass: I4 name: 'r0'  encoding:  0.
     r1           := PowerPCRegister withClass: I4 name: 'r1'  encoding:  1.
     r2           := PowerPCRegister withClass: I4 name: 'r2'  encoding:  2.
diff -r 531fb2c16da1 function/jolt2/CodeGenerator.st
--- a/function/jolt2/CodeGenerator.st	Wed Apr 23 12:20:22 2008 -0600
+++ b/function/jolt2/CodeGenerator.st	Wed Apr 23 23:40:24 2008 -0600
@@ -28,11 +28,16 @@ CodeGenerator : Object ( ccrs csrs spill
 
 CodeGenerator withLabels: labelCollection
 [
-    self := self new.
+    self := self newScope.
     labels := labelCollection.
 ]
 
 CodeGenerator new
+[
+    self := self newScope
+]
+
+CodeGenerator newScope
 [
     self := super new.
     ccrs     	   := RegisterSet new.
@@ -111,6 +116,36 @@ CodeGenerator relocateLabels_: _addr
     labels do: [:label | label relocate_: _addr]
 ]
 
+CodeGenerator slinkVariable: name []
+CodeGenerator slinkImport: name [^name _dlsym]
+CodeGenerator slinkExport: name translate: aForm with: aCompiler
+[
+   | entry value |
+   aForm isSymbol ifTrue: [aForm := Expression with: #addrof with: aForm].
+   entry := aCompiler compile: aForm.
+   value := entry call.
+   entry free.
+   ^value
+]
+
+CodeGenerator compileLambda: form with: aCompiler
+[
+   ^ADDRJP4 new arg: (aCompiler compileLambda: form)
+]
+
+CodeGenerator translateData_: _bytes length: aLength
+[
+    | _mem |
+    {
+        size_t size= ((long)v_aLength) >> 1;
+        char *mem= malloc(size + 1);
+        memcpy(mem, v__bytes, size);
+        mem[size]= '\0';
+        v__mem= (oop)mem;
+    }.
+    ^CNSTP4 new arg: _mem
+]
+
 CodeGenerator enter :e		[ self emitPrologue ]
 CodeGenerator parami4 :s	[]
 CodeGenerator drop :s		[]
diff -r 531fb2c16da1 function/jolt2/Compiler.st
--- a/function/jolt2/Compiler.st	Wed Apr 23 12:20:22 2008 -0600
+++ b/function/jolt2/Compiler.st	Wed Apr 23 23:40:24 2008 -0600
@@ -37,6 +37,7 @@ Variable withName: nameSymbol
 ]
 
 Variable translateRvalue: compiler	[ ^INDIRI4 new lhs: (self translateLvalue: compiler) ]
+Variable name [ ^name ]
 
 
 GlobalVariable : Variable ( _storage )
@@ -61,6 +62,30 @@ GlobalVariable translateLvalue: compiler
 
 GlobalVariable printOn: aStream			[ aStream print: name; nextPut: $=; print_x: _storage ]
 
+
+SlinkConstant : Variable ()
+
+SlinkConstant translateLvalue: compiler
+[
+    compiler error: 'cannot write: ', name.
+]
+SlinkConstant translateRvalue: compiler
+[
+    ^SLINK new arg: name asString
+]
+
+SlinkVariable : Variable ()
+
+SlinkVariable translateLvalue: compiler
+[
+    ^SLINK new arg: name asString
+]
+SlinkVariable translateRvalue: compiler
+[
+    ^SLINKI new arg: name asString
+]
+
+SlinkVariable printOn: aStream			[ aStream print: name ]
 
 LocalVariable : Variable ( location )
 
@@ -115,6 +140,8 @@ Environment : SlotDictionary ( syntax ac
 
 Environment new		[ ^super basicNew ]
 
+Environment isGlobal	[ ^false ]
+
 Environment lookupVariable: name	[ ^(active ifTrue: [active at: name ifAbsent: []]) ifNil: [self at: name ifAbsent: []] ]
 Environment lookupSyntax: name		[ ^ syntax ifTrue: [syntax at: name ifAbsent: []] ]
 
@@ -132,9 +159,16 @@ Environment defineActive: name
 
 GlobalEnvironment : Environment ()
 
+GlobalEnvironment isGlobal	[ ^true ]
 GlobalEnvironment defineVariable: name			[ ^self at: name put: (GlobalVariable withName: name) ]
 GlobalEnvironment defineVariable: name value_: _value	[ ^self at: name put: (GlobalVariable withName: name value_: _value) ]
-
+GlobalEnvironment defineSlink: name value_: _value	[ ^self defineVariable: name value_: _value ]
+
+SlinkEnvironment : Environment ()
+
+SlinkEnvironment isGlobal	[ ^true ]
+SlinkEnvironment defineVariable: name			[ ^self at: name put: (SlinkVariable withName: name) ]
+SlinkEnvironment defineSlink: name value_: _value	[ ^self at: name put: (SlinkConstant withName: name) ]
 
 LocalEnvironment : Environment ( parent )
 
@@ -151,6 +185,7 @@ LocalEnvironment lookupSyntax: name	[ ^(
 
 LocalEnvironment defineVariable: name	[ ^self at: name put: (LocalVariable withName: name) ]
 LocalEnvironment defineParameter: name	[ ^self at: name put: (ParameterVariable withName: name) ]
+LocalEnvironment defineSlink: name value_: _value [ ^parent defineSlink: name value_: _value ]
 
 
 TheGlobalEnvironment := [ GlobalEnvironment new ]
@@ -171,10 +206,10 @@ Symbol _dlsym_: _string	{ _return (oop)_
 
 Compiler : Object ( environment allLabels generatorType breaks continues postProcessors labels )
 
-Compiler withGeneratorType: genType
+Compiler withGeneratorType: genType withEnvironment: theEnv
 [
     self := super new.
-    environment := TheGlobalEnvironment.
+    environment := theEnv.
     allLabels := OrderedCollection new.
     generatorType := genType.
     breaks := OrderedCollection new.
@@ -204,6 +239,7 @@ Compiler lookupVariable: name
 
 Compiler defineActive: name	[ ^environment defineActive: name ]
 Compiler defineVariable: name	[ ^environment defineVariable: name ]
+Compiler defineSlink: name value_: _value [ ^environment defineSlink: name value_: _value ]
 Compiler defineParameter: name	[ ^environment defineParameter: name ]
 
 Compiler defineSyntax: name	[ ^environment defineSyntax: name ]
@@ -262,7 +298,7 @@ SyntaxTable := [
 	at: #return		put: #xReturn:;
 	at: #label		put: #xLabel:;
 	at: #goto		put: #xGoto:;
-	at: #extern		put: #xExtern:;
+	at: #'define-slink'	put: #xDefineSlink:;
 	yourself
 ]
 
@@ -282,12 +318,12 @@ Compiler translateInteger: anInteger
 
 Compiler translateFloat: aFloat
 [
-    ^CNSTP4 new arg: aFloat
+    ^generatorType translateData_: aFloat length: (SmallInteger value_: aFloat _sizeof)
 ]
 
 Compiler translateString: aString
 [
-    ^CNSTP4 new arg: aString _strdup
+    ^generatorType translateData_: aString _stringValue length: aString size + 1
 ]
 
 Compiler translateSymbol: aSymbol
@@ -628,7 +664,7 @@ Compiler xQuote: expr
 Compiler xQuote: expr
 [
     | literal |
-    expr size == 2 ifFalse: [self errorAgumentCount: expr].
+    expr size == 2 ifFalse: [self errorArgumentCount: expr].
     literal := expr second.
     (literal isSmallInteger or: [literal isNil]) ifFalse: [CompilerLiterals addLast: literal].
     ^CNSTP4 new  arg: literal
@@ -671,7 +707,7 @@ Compiler defineVariable: name from: form
 [
     | var value |
     (form size <= 3)			ifFalse:  [self errorSyntax: form].
-    var := self lookupVariable: name	ifAbsent: [self defineVariable: name].
+    var := self lookupVariable: name	ifAbsent: [generatorType slinkVariable: name. self defineVariable: name].
     value := form size == 3
 	ifTrue:  [form third translate: self]
 	ifFalse: [CNSTI4 new arg: nil].
@@ -680,7 +716,7 @@ Compiler defineVariable: name from: form
     ^ASGNI4 new lhs: value; rhs: (var translateLvalue: self).
 ]
 
-Compiler defineAccessor: accessor from: expr	"(define (foo bar...) baz) -> (set-foo bar... baz)"
+Compiler defineAccessor: accessor from: expr	"(define (foo bar...) baz) -> (define-foo bar... baz)"
 [
     | setter syntax |
     (accessor isArray and: [accessor size > 0 and: [accessor first isSymbol]]) ifFalse: [self errorSyntax: accessor].
@@ -830,13 +866,15 @@ Compiler xLet: form
 
 Compiler xLambda: form
 [
-    ^ADDRJP4 new arg: (self compileLambda: form)
+    ^generatorType compileLambda: form with: self
 ]
 
 Compiler compileLambda: form
 [
-    | block entry last gen stats |
-    self := self withGeneratorType: generatorType.
+    | block entry last gen stats topEnv |
+    topEnv := environment.
+    [ topEnv isGlobal not ] whileTrue: [ topEnv := topEnv parent ].
+    self := self withGeneratorType: generatorType withEnvironment: topEnv.
     (block := Block new)
 	scope:	self beginScope;
 	add:	(entry := self newLabel);
@@ -889,14 +927,16 @@ Compiler xGoto: form
     ^BRA new destination: label
 ]
 
-Compiler xExtern: form
-[
-    | name var |
-    (form size == 2 and: [(name := form second) isSymbol]) ifFalse: [self errorSyntax: form].
-    var := self lookupVariable: name ifAbsent: [self defineVariable: name].
-    var value_: name _dlsym.
-    generatorType defineVariable: name.
-    ^CNSTP4 new arg: var _value
+"(define-slink SYMBOL): Import SYMBOL from the system linker
+ (define-slink SYMBOL EXPRESSION): Export SYMBOL to the system linker, with value EXPRESSION"
+Compiler xDefineSlink: form
+[
+    | name addr |
+    (form size <= 3 and: [(name := form second) isSymbol]) ifFalse: [self errorSyntax: form].
+    form size == 2
+      ifTrue: [ addr := generatorType slinkImport: name ]
+      ifFalse: [ addr := generatorType slinkExport: name translate: form third with: self ].
+    ^(self defineSlink: name value_: addr) translateRvalue: self.
 ]
 
 Compiler xCompile: form
@@ -952,10 +992,15 @@ Compiler postProcess: aFunction				[ pos
 
 "----------------------------------------------------------------"
 
-Compiler compile: anObject for: codeGeneratorType
+Compiler compile: anObject
+[
+    ^self compile: anObject for: generatorType with: environment
+]
+
+Compiler compile: anObject for: codeGeneratorType with: anEnvironment
 [
     | block entry tree gen |
-    self := self withGeneratorType: codeGeneratorType.
+    self := self withGeneratorType: codeGeneratorType withEnvironment: anEnvironment.
     (block := Block new)
 	add: (entry := self newLabel);
 	add: ENTER new.
@@ -981,7 +1026,12 @@ Compiler compile: anObject for: codeGene
 
 Object compile
 [
-    Compiler compile: self for: CodeGenerator default static
+    ^self compileWith: SlinkEnvironment new
+]
+
+Object compileWith: anEnvironment
+[
+    Compiler compile: self for: CodeGenerator default static with: anEnvironment
 ]
 
 Object eval
@@ -993,7 +1043,7 @@ Object _eval
 [
     | entry value |
     CompilerOptions verboseList ifTrue: [self compile].
-    entry := Compiler compile: self for: CodeGenerator default dynamic.
+    entry := Compiler compile: self for: CodeGenerator default dynamic with: TheGlobalEnvironment.
     value := entry call.
     entry free.
     ^value
diff -r 531fb2c16da1 function/jolt2/Instruction.st
--- a/function/jolt2/Instruction.st	Wed Apr 23 12:20:22 2008 -0600
+++ b/function/jolt2/Instruction.st	Wed Apr 23 23:40:24 2008 -0600
@@ -511,6 +511,8 @@ INDIRI2	: Unary ()		INDIRI2	name [ ^#ind
 INDIRI2	: Unary ()		INDIRI2	name [ ^#indiri2 ]
 INDIRI4	: Unary ()		INDIRI4	name [ ^#indiri4 ]
 LEI4    : Binary ()		LEI4    name [ ^#lei4	 ]
+SLINK	: Leaf ()		SLINK	name [ ^#slink	 ]
+SLINKI	: Leaf ()		SLINKI	name [ ^#slinki	 ]
 LTI4    : Binary ()		LTI4    name [ ^#lti4	 ]
 MODI4   : Binary ()		MODI4   name [ ^#modi4	 ]
 MULI4   : Binary ()		MULI4   name [ ^#muli4	 ]
diff -r 531fb2c16da1 function/jolt2/boot.k
--- a/function/jolt2/boot.k	Wed Apr 23 12:20:22 2008 -0600
+++ b/function/jolt2/boot.k	Wed Apr 23 23:40:24 2008 -0600
@@ -157,6 +157,7 @@
   (lambda (path)
     (let ((file [File openIfPresent: [String value_: path]]))
       (or file (set file [File openIfPresent: [[[Options libdir] , '"/"] , [String value_: path]]]))
+      (or file (set file [File openIfPresent: [[[Options progdir] , '"/"] , [String value_: path]]]))
       (if file
 	  (let ()
 	    (herald path)
@@ -194,7 +195,7 @@
 ;; Add features that aren't present in the original grammar.
 (define ColaFunctionGrammar (import "ColaFunctionGrammar"))
 (define Integer (import "Integer"))
-['{
+(define new-grammar '{
      // Add character literals ($CHAR)
      atom = number | charLiteral | identifier | string
      charLiteral = '$' char->0				<- [self @ '0]
@@ -217,7 +218,10 @@
      ;
      EXTENDS: ColaFunctionGrammar // Import from the default grammar.
      expression // Start term
-  } name: 'JoltBurgCompatibleFunctionGrammar]
+  })
+
+[new-grammar name: 'ColaFunctionGrammar]
+(export "ColaFunctionGrammar" new-grammar)
 
 (load "syntax.k")
 (load "debug.k")
diff -r 531fb2c16da1 function/objects/File.st
--- a/function/objects/File.st	Wed Apr 23 12:20:22 2008 -0600
+++ b/function/objects/File.st	Wed Apr 23 23:40:24 2008 -0600
@@ -22,6 +22,8 @@
 
 { include "tag.h" }
 
+{ include <errno.h> }
+
 File : Object ( _fd name )
 
 File isFile	[ ^true ]
@@ -54,6 +56,7 @@ File println: anObject				[ self print: 
 File println: anObject				[ self print: anObject; cr ]
 File print: aNumber base: base			[ aNumber printOn: self base: base ]
 File print: aNumber base: base width: width	[ aNumber printOn: self base: base width: width ]
+File print_x: o					[ self print: (Integer value_: o) base: 16 ]
 File cr						[ self nextPut: $\n ]
 File cr: n					[ n timesRepeat: [self cr] ]
 File space					[ self nextPut: $   ]
@@ -77,15 +80,23 @@ File next: size putAll: aString
     | _bytes _size |
     _bytes := aString _bytes.
     _size  := size _integerValue.
-    { _return _O(write((int)self->v__fd, (void *)v__bytes, (size_t)v__size)); }.
-]
-
-File print_x: _pointer
-{
-    char buf[1024];
-    int size= sprintf(buf, "%x", (int)v__pointer);
-    _return _O(write((int)self->v__fd, (void *)buf, (size_t)size));
-}
+    {
+       size_t position= 0;
+       size_t remaining= (size_t)v__size;
+       while (remaining)
+         {
+	   int count= write((int)self->v__fd, ((char *)v__bytes) + position, remaining);
+           if (count >= 0)
+	     {
+	       position += count;
+	       remaining -= count;
+	     }
+	   else if (errno != EINTR)
+             break;
+	 }
+       _return _O(position);
+    }
+]
 
 File  read: aCollection				[ ^self read: aCollection size: aCollection size ]
 File  read: aCollection size: size		[ ^self read: aCollection at: 0 size: size ]
_______________________________________________
fonc mailing list
fonc@vpri.org
http://vpri.org/mailman/listinfo/fonc

Reply via email to