Hi,

Nathan Cain <[EMAIL PROTECTED]> writes:

> I was hoping to toy with this some, and start in on adapting an arm
> backend...

Cool!  I'd be more than happy to help with this process, if you need
any assistance at all.  I think most of it should be relatively
straightforward by staring at the patch to CodeGenerator-i386.st.

> unfortunately, the patch does not want to apply, as it seems to
> expect a different jolt2/boot.k then what is in svn r407.  Perhaps I
> need another of your patches as well, beyond just jolt2-fixes?
> Could you tell me which?

Actually, I just described the patch requirements really badly.  The
idea is:

$ svn checkout -r407 ...
$ cd idst
$ patch -p0 < ../jolt2-fixes.patch
$ patch -p0 < ../jolt2-slink.patch

I've attached new versions of these patches that fix a few issues
(forgot the '{...} grammar syntax in jolt2-fixes.patch, mangle Jolt
names that can't be directly expressed in the output) and demonstrates
the use of (syntax ...) in function/examples2/slink/main.k.

Good luck,

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

Get jolt2 and examples2 to work.

diff -r 2e8939abc3c6 function/examples/cairo/Makefile
--- a/function/examples/cairo/Makefile	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/examples/cairo/Makefile	Fri Apr 25 16:12:38 2008 -0600
@@ -6,7 +6,7 @@ run test : cairolib.so .FORCE
 	$(JOLT) boot.k main.k
 
 cairolib.so : cairolib.st
-	$(IDC) $(CAIROINC) -I../../objects -s $<
+	$(IDC) -g -k $(CAIROINC) -I../../objects -s $<
 
 clean : .FORCE
 	rm -f *~ *.so *.o
diff -r 2e8939abc3c6 function/examples/cairo/libcairo.k
--- a/function/examples/cairo/libcairo.k	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/examples/cairo/libcairo.k	Fri Apr 25 16:12:38 2008 -0600
@@ -1,5 +1,4 @@
 (dlopen "libcairo")
-(define cairolib (dlopen "cairolib"))
-((_dlsym cairolib "__id__init__"))
+[Object _import: "cairolib"]
 
 (define libcairo	(import "libcairo"))
diff -r 2e8939abc3c6 function/examples/regexp/Makefile
--- a/function/examples/regexp/Makefile	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/examples/regexp/Makefile	Fri Apr 25 16:12:38 2008 -0600
@@ -12,55 +12,55 @@ test1 : .FORCE
 test1 : .FORCE
 	time egrep   'break|continue|for|while|switch|case|return|static|extern' < tests/test.c | tee out.e | wc -l
 	time $(GREP) 'break|continue|for|while|switch|case|return|static|extern' < tests/test.c | tee out.p | wc -l
-	diff out.e out.p
+	cmp out.e out.p
 	rm out.e out.p
 
 test2 : .FORCE
 	time egrep   'd?e?l?t?a?' < tests/termcap | tee out.e | wc -l
 	time $(GREP) 'd?e?l?t?a?' < tests/termcap | tee out.p | wc -l
-	diff out.e out.p
+	cmp out.e out.p
 	rm out.e out.p
 
 test3 : .FORCE
 	time egrep   'd?e+l*t?a+' < tests/termcap | tee out.e | wc -l
 	time $(GREP) 'd?e+l*t?a+' < tests/termcap | tee out.p | wc -l
-	diff out.e out.p
+	cmp out.e out.p
 	rm out.e out.p
 
 test4 : .FORCE
 	time egrep   'd?e+l*t?a+' < tests/termcap | tee out.e | wc -l
 	time $(GREP) 'd?e+l*t?a+' < tests/termcap | tee out.p | wc -l
-	diff out.e out.p
+	cmp out.e out.p
 	rm out.e out.p
 
 test5 : .FORCE
 	time egrep   'p[aeiou]t'  < tests/termcap | tee out.e | wc -l
 	time $(GREP) 'p[aeiou]t'  < tests/termcap | tee out.p | wc -l
-	diff out.e out.p
+	cmp out.e out.p
 	rm out.e out.p
 
 test6 : .FORCE
 	time egrep   'p[^aeiou]t' < tests/termcap | tee out.e | wc -l
 	time $(GREP) 'p[^aeiou]t' < tests/termcap | tee out.p | wc -l
-	diff out.e out.p
+	cmp out.e out.p
 	rm out.e out.p
 
 test7 : .FORCE
 	time egrep   '19[0-9]+'   < tests/termcap | tee out.e | wc -l
 	time $(GREP) '19[0-9]+'   < tests/termcap | tee out.p | wc -l
-	diff out.e out.p
+	cmp out.e out.p
 	rm out.e out.p
 
 test8 : .FORCE
 	time egrep   '19[^0-9]+'  < tests/termcap | tee out.e | wc -l
 	time $(GREP) '19[^0-9]+'  < tests/termcap | tee out.p | wc -l
-	diff out.e out.p
+	cmp out.e out.p
 	rm out.e out.p
 
 test9 : .FORCE
 	time egrep   '..a.....b'  < tests/termcap | tee out.e | wc -l
 	time $(GREP) '..a.....b'  < tests/termcap | tee out.p | wc -l
-	diff out.e out.p
+	cmp out.e out.p
 	rm out.e out.p
 
 
diff -r 2e8939abc3c6 function/jolt2/ColaGrammar.st
--- a/function/jolt2/ColaGrammar.st	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/jolt2/ColaGrammar.st	Fri Apr 25 16:12:38 2008 -0600
@@ -17,6 +17,7 @@ ColaParsingGrammar	:= [ Grammar new ]
 	at: #comment	put: ( '//' parse , (#eol parse not , PeAny) zeroMore , #eol parse);
 	at: #_		put: ( _ := ( (#space parse | #comment parse) zeroMore ) ).
     g	at: #pling	put: '!'  parse , _;
+    	at: #EXTENDS	put: 'EXTENDS:' parse , _;
     	at: #lparen	put: '('  parse , _;
     	at: #rparen	put: ')'  parse , _;
     	at: #query	put: '?'  parse , _;
@@ -67,9 +68,11 @@ ColaParsingGrammar	:= [ Grammar new ]
 						     | ( ( #larrow parse , #number   parse <- [:p | ([EMAIL PROTECTED]) <- p result] ->0 ) zeroOne  <- [:p | [EMAIL PROTECTED] ) ) ).
     g	at: #sequence	put: ( #suffix   parse ->0 , (                 #suffix   parse <- [:p | ([EMAIL PROTECTED]) ,  p result] ->0 ) zeroMore <- [:p | [EMAIL PROTECTED] ).
     g	at: #expression	put: ( #sequence parse ->0 , ( #bar parse    , #sequence parse <- [:p | ([EMAIL PROTECTED]) |  p result] ->0 ) zeroMore <- [:p | [EMAIL PROTECTED] ).
-    g	at: #grammar	put: ( [Grammar new] setResult ->0
+    g	at: #grammar	put: ( [Grammar new] setResult ->0 , _
 			     , ( #identifier parse ->1 , #equal parse , #expression parse , #semicolon parse zeroOne	<- [:p | [EMAIL PROTECTED] at: [EMAIL PROTECTED] put: p result]	) zeroMore
+			     , ( #EXTENDS parse , ( ColaFunctionGrammar-#expression ) <- [:p | [EMAIL PROTECTED] extends: p result _eval] , _		) zeroMore
 			     , ( #expression parse									<- [:p | [EMAIL PROTECTED] startRule: p result]	) zeroOne
+			     
 			     ) <- [:p | ([EMAIL PROTECTED]) finalise "println"].
 ]
 
@@ -88,9 +91,9 @@ ColaParsingGrammar	:= [ Grammar new ]
 	at: #other	put: '-+!#$%&*./:<=>[EMAIL PROTECTED]|~'	parseClass.
     g	at: #identifier	put: ( ( #alpha parse | #other parse ) , ( #alpha parse | #digit parse | #other parse ) zeroMore ) textResult <- [:p | p result asSymbol].
     g	at: #decimal	put: ( #digit parse oneMore textResult							<- [:p | p result inject: 0 into: [:n :c | n * 10 + c digitValue]] );	
-	at: #heximal	put: ( ( '0x' parse , ( #digit parse | #hex parse ) oneMore ) textResult		<- [:p | p result inject: 0 into: [:n :c | n * 16 + c digitValue]] );
+	at: #heximal	put: ( '0x' parse , ( ( #digit parse | #hex parse ) oneMore textResult		<- [:p | p result inject: 0 into: [:n :c | n * 16 + c digitValue]] ) );
 	at: #posfloat	put: ( #decimal parse -> 0 , '.' parse , ( #digit parse oneMore textResult ) -> 1	<- [:p | ([EMAIL PROTECTED] reverseInject: 0.0 into: [:n :c | n / 10.0 + c digitValue]) / 10.0 + ([EMAIL PROTECTED])] );
-	at: #posnumber	put: ( #decimal parse | #heximal parse | #posfloat parse );
+	at: #posnumber	put: ( #heximal parse | #posfloat parse | #decimal parse );
 	at: #number	put: ( ( '-' parse          , #posnumber parse						<- [:p | p result negated] )
 			     | ( '+' parse zeroMore , #posnumber parse ) ).
     g	at: #plainChar	put: ( PeAny textResult <- [:p | p last] );
@@ -109,8 +112,8 @@ ColaParsingGrammar	:= [ Grammar new ]
     g	at: #unary	put: ( ( #alpha parse , ( #alpha parse | #digit parse ) zeroMore ) textResult, _ );
 	at: #binary	put: ( ( '-+!%&*,/<=>[EMAIL PROTECTED]|~' parseClass oneMore ) textResult , _ );
 	at: #keyword	put: ( ( #alpha parse , ( #alpha parse | #digit parse ) zeroMore , ':' parse ) textResult , _ ).
-    g	at: #unymsg	put: ( #unary   parse ->0						<- [:p | Array with: [EMAIL PROTECTED] );
-	at: #binmsg	put: ( #binary  parse ->0 , #expr parse ->1 , _				<- [:p | Array with: [EMAIL PROTECTED] with: [EMAIL PROTECTED] );
+    g	at: #unymsg	put: ( #unary   parse ->0						<- [:p | OrderedCollection with: [EMAIL PROTECTED] );
+	at: #binmsg	put: ( #binary  parse ->0 , #expr parse ->1 , _				<- [:p | OrderedCollection with: [EMAIL PROTECTED] with: [EMAIL PROTECTED] );
 	at: #keyarg	put: ( #keyword parse ->0 , #expr parse ->1 , _				<- [:p | OrderedCollection with: [EMAIL PROTECTED] with: [EMAIL PROTECTED] );
 	at: #keymsg	put: ( #keyarg  parse ->0 , ( #keyword parse ->1 , #expr parse ->2 , _	<- [:p | ([EMAIL PROTECTED]) first: ([EMAIL PROTECTED]) first, ([EMAIL PROTECTED]); add: ([EMAIL PROTECTED]); yourself]
 							  ) zeroMore				<- [:p | ([EMAIL PROTECTED])]
@@ -129,7 +132,7 @@ ColaParsingGrammar	:= [ Grammar new ]
 	at: #expression	put: _ , ( #expr parse | #eof parse | #error parse ).
 ]
 
-"mutually recursive rules between the above grammars can now be resolve"
+"mutually recursive rules between the above grammars can now be resolved"
 
 [
     ColaParsingGrammar startSymbol: #grammar.
diff -r 2e8939abc3c6 function/jolt2/Compiler.st
--- a/function/jolt2/Compiler.st	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/jolt2/Compiler.st	Fri Apr 25 16:12:38 2008 -0600
@@ -919,7 +919,7 @@ Compiler xEvaluate: form
 
 Compiler errorUndefined: aSymbol	[ self error: 'undefined: ', aSymbol ]
 Compiler errorSyntax: form		[ self error: 'syntax error: ', form printString ]
-Compiler errorArgumentCount: form	[ self error: 'wrong number of aguments: ', form printString ]
+Compiler errorArgumentCount: form	[ self error: 'wrong number of arguments: ', form printString ]
 Compiler errorLoop: form		[ self error: 'no loop: ', form printString ]
 
 "----------------------------------------------------------------"
diff -r 2e8939abc3c6 function/jolt2/Grammar.st
--- a/function/jolt2/Grammar.st	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/jolt2/Grammar.st	Fri Apr 25 16:12:38 2008 -0600
@@ -39,6 +39,11 @@ Grammar startRule: pe
     startRule := PeRule withValue: pe name: #'<start>'.
     dirty := true.
     self finalise.
+]
+
+Grammar extends: aGrammar
+[
+    aGrammar do: [:assoc | self at: assoc key ifAbsentPut: assoc value].
 ]
 
 Grammar finalise
diff -r 2e8939abc3c6 function/jolt2/Makefile
--- a/function/jolt2/Makefile	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/jolt2/Makefile	Fri Apr 25 16:12:38 2008 -0600
@@ -28,7 +28,10 @@ all : main$(OBJEXT)
 all : main$(OBJEXT)
 
 test : main$(OBJEXT) .FORCE
-	./main$(OBJEXT) boot.k sanaras.k
+	./main$(OBJEXT) -L../jolt-burg boot.k sanaras.k
+
+test-old: main$(OBJEXT) .FORCE
+	cd ../examples && $(MAKE) test JOLT="../../jolt2/main$(OBJEXT) -L../../jolt-burg"
 
 .SUFFIXES :
 
diff -r 2e8939abc3c6 function/jolt2/Options.st
--- a/function/jolt2/Options.st	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/jolt2/Options.st	Fri Apr 25 16:12:38 2008 -0600
@@ -20,13 +20,15 @@
 
 { import: Objects }
 
-Options : Object ( verbose compile list libdir )
+Options : Object ( verbose compile list libdir progdir )
 
 Options verbose		[ ^verbose ]
 Options compile		[ ^compile ]
 Options list		[ ^list ]
 Options libdir: aString	[  libdir := aString ]
 Options libdir		[ ^libdir ]
+Options progdir: aDir	[  progdir := aDir ]
+Options progdir		[ ^progdir ]
 
 Options new
 [
diff -r 2e8939abc3c6 function/jolt2/Parser.st
--- a/function/jolt2/Parser.st	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/jolt2/Parser.st	Fri Apr 25 16:12:38 2008 -0600
@@ -113,5 +113,5 @@ Parser errorContents
 
 Parser setResultFromFunction_: _function
 {
-    self->v_result= ((oop(*)())v__function)(v__closure, self, self, self->v_result);
+    self->v_result= ((oop(*)())v__function)(v__closure, v_stateful_self, v_self, self->v_result);
 }
diff -r 2e8939abc3c6 function/jolt2/boot.k
--- a/function/jolt2/boot.k	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/jolt2/boot.k	Fri Apr 25 16:12:38 2008 -0600
@@ -191,16 +191,53 @@
 		    | error )
       } match: node]))
 
-;; methods
-
-(define add-method	; type selector implementation
-  (lambda (type selector implementation)
-    [[type _vtable] methodAt: selector put: implementation with: 0]))
-
-(syntax define-send ; selector type args... expr
-  (lambda (form compiler)
-    (let ((selector [form second])
-	  (type     [form third])
-	  (args     [form copyFrom: '3 to: [[form size] - '2]])
-	  (expr     [form last]))
-      `(add-method ,type ,selector (lambda (_closure _self self ,@args) ,expr)))))
+;; 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 | grammar
+     charLiteral = '$' char->0				<- [self @ '0]
+
+     // Add octal character escapes ("\\([0-3]?[0-7])?[0-7]").
+     escapeSeq = '\\' (escapeChar | octalChar | plainChar)
+     oct = [0-7]
+     octalChar = (([0-3] oct oct) | (oct oct) | oct) $	<- [Integer fromString: [self result] base: '8]
+
+     // Binary integers.
+     posnumber = heximal | binimal | posfloat | decimal
+     binimal = '0b' [0-1]+ $				<- [Integer fromString: [self result] base: '2]
+
+     // Variadic message sends ([obj msg expr...]).
+     send = '[' _ expr->0 _ message->1 _ (expr->2 _	<- [[self @ '1] add: [self @ '2]])*
+	    ']'	<- [Expression	with: 'send
+				with: [Expression with: 'quote with: [[[self @ '1] first] asSymbol]]
+				with: [self @ '0]
+				withAll: [self @ '1] from: '1]
+     ;
+     EXTENDS: ColaFunctionGrammar // Import from the default grammar.
+     expression // Start term
+  })
+
+[new-grammar name: 'ColaFunctionGrammar]
+(export "ColaFunctionGrammar" new-grammar)
+
+(load "syntax.k")
+(load "debug.k")
+(load "object.k")
+
+(define *package-list* [IdentitySet new])
+
+(define %require
+  (lambda (package)
+    (or [*package-list* includes: [package asSymbol]]
+	(let ()
+	  (load [[[package asString] , '".k"] _stringValue])
+	  [*package-list* add: [package asSymbol]]))))
+
+(syntax require
+  (lambda (node comp)
+    (let ((requires [WriteStream on: [Expression new: '8]]))
+      (for (i '1 2 [[node size] - '1])
+	[requires nextPut: `(%require ,[node at: i])])
+      `(let () ,@[requires contents]))))
diff -r 2e8939abc3c6 function/jolt2/main.st
--- a/function/jolt2/main.st	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/jolt2/main.st	Fri Apr 25 16:12:38 2008 -0600
@@ -91,7 +91,10 @@ ColaEvaluator map: aBlock
 
 ColaEvaluator readFileNamed: fileName
 [
-    self readFile: (fileName = '-' ifTrue: [StdIn] ifFalse: [File open: fileName])
+    self readFile: (fileName = '-' ifTrue: [StdIn]
+    	 	   	     ifFalse: [((File openIfPresent: fileName)
+			     	        ifNil: [File openIfPresent: Options progdir, '/', fileName])
+					ifNil: [File open: Options libdir, '/', fileName]])
 ]
 
 ColaEvaluator readFile: aFile
@@ -108,9 +111,14 @@ ColaEvaluator readFile: aFile
 
 
 [
-    | done |
+    | done args arg |
     "ColaFunctionGrammar println."
+    Options progdir: (OS argumentAt: 0) dirname.
     Options libdir: '.'.
-    OS arguments do: [:arg | (Options parseOption: arg) ifFalse: [ColaEvaluator readFileNamed: (done := arg)]].
+    args := OS arguments.
+    [args notEmpty]
+        whileTrue:
+           [ arg := args removeFirst.
+	     (Options parseOption: arg) ifFalse: [ColaEvaluator readFileNamed: (done := arg)]].
     done ifFalse: [ColaEvaluator readFile: StdIn].
 ]
diff -r 2e8939abc3c6 function/objects/SequenceableCollection.st
--- a/function/objects/SequenceableCollection.st	Wed Apr 23 23:45:22 2008 -0600
+++ b/function/objects/SequenceableCollection.st	Fri Apr 25 16:12:38 2008 -0600
@@ -216,6 +216,12 @@ SequenceableCollection inject: result in
 SequenceableCollection inject: result into: binaryBlock
 [
     self do: [:element | result := binaryBlock value: result value: element].
+    ^result
+]
+
+SequenceableCollection reverseInject: result into: binaryBlock
+[
+    self reverseDo: [:element | result := binaryBlock value: result value: element].
     ^result
 ]
 
Generate assembler from Jolt code.

diff -r 1e71558180f0 function/examples2/slink/README
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/function/examples2/slink/README	Fri Apr 25 16:12:05 2008 -0600
@@ -0,0 +1,75 @@
+SLINK 0.3
+*********
+
+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).
+
+I'm in the process of creating a "compiler-stage" syntax which
+immediately evaluates its child expressions in the compiler instead of
+compiling them.  Marking up boot.k will make it possible to be used
+for slink-compile as well.
+
+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]>, 2008-04-17
diff -r 1e71558180f0 function/examples2/slink/main.k
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/function/examples2/slink/main.k	Fri Apr 25 16:12:05 2008 -0600
@@ -0,0 +1,37 @@
+(syntax syntax-test
+   (lambda (node compiler)
+     (printf "Here's a little test of compile-time syntax.\n")
+     '(printf "Here's a little test of runtime syntax.\n")))
+
+;; FIXME: Eventually slink-compile should include this for us.
+(syntax addrof	; (addrof varName)  =>  address of varName
+  (lambda (node compiler)
+    (or (and [[node size] = '2]
+	     [[node second] isSymbol])
+	[compiler errorSyntax: node])
+    [[compiler lookupVariable: [node second]] translateLvalue: compiler]))
+
+(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)
+    (printf "Have an int: 0x%x@(0x%x==0x%x), and a copy [EMAIL PROTECTED]"
+	    zot (addrof zot) zot_addr baz (addrof baz))
+    (syntax-test)
+    (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 1e71558180f0 function/examples2/slink/slink.k
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/function/examples2/slink/slink.k	Fri Apr 25 16:12:05 2008 -0600
@@ -0,0 +1,63 @@
+(define slink-require
+  (lambda (filename compiler generator environment package-list)
+    (let ((path filename)
+	  (file [File openIfPresent: filename]))
+      (or file
+	  (let ()
+	    (set path [[[Options libdir] , '"/"] , filename])
+	    (set file [File openIfPresent: path])))
+      (or file
+	  (let ()
+	    (set path [[[Options progdir] , '"/"] , filename])
+	    (set file [File openIfPresent: path])))
+      (if file
+	  (let ((parser [ColaFunctionGrammar parserOn: file])
+		(expr 0))
+	    [StdOut nextPutAll: '"; compiling: "] [StdOut nextPutAll: path] [StdOut cr]
+	    (while (set expr [parser next])
+	      (or (and [[expr size] = '2]
+		       [[expr first] = 'require]
+		       [[expr second] isArray]
+		       (let ((qpackage [expr second]))
+			 (and [[qpackage size] = '2]
+			      [[qpackage first] = 'quote]
+			      [[qpackage second] isSymbol]
+			      (let ((package [qpackage second]))
+				(or [package-list includes: package]
+				    (let ((filename [[package asString] , '".k"]))
+				      ;; Allow code to require other packages with (require 'package).
+				      (slink-require filename compiler generator environment package-list)
+				      [package-list add: package]))))))
+		  [compiler compile: expr for: generator with: environment])))
+	(let ()
+	  [StdErr nextPutAll: '";; cannot open "]
+	  [StdErr nextPutAll: filename]
+	  [StdErr cr])))))
+
+
+(define slink-compile
+  (lambda (path)
+    (let ((pathstr [String value_: path])
+	  (outname [pathstr , '".s"])
+	  (CodeGenerator (import "CodeGenerator"))
+	  (gen [[CodeGenerator default] static])
+	  (SlinkEnvironment (import "SlinkEnvironment"))
+	  (env [SlinkEnvironment new])
+	  (Compiler (import "Compiler"))
+	  (CompilerOptions (import "CompilerOptions"))
+	  (package-list [IdentitySet new]))
+
+      [StdErr nextPutAll: '";; slink-compile "] [StdErr nextPutAll: pathstr]
+      [StdErr nextPutAll: '" starting"] [StdErr cr]
+
+      ;; [CompilerOptions verboseTree: '1]
+      ;(slink-require '"sboot.k" Compiler gen env package-list)
+      (slink-require pathstr Compiler gen env package-list)
+      ;; [CompilerOptions verboseTree: 0]
+
+      (let ((out [File create: outname]))
+	[StdOut nextPutAll: '"; write output to "] [StdOut nextPutAll: outname] [StdOut cr]
+	[gen toStream: out]
+	[out close])
+      [StdErr nextPutAll: '";; slink-compile "] [StdErr nextPutAll: pathstr]
+      [StdErr nextPutAll: '" finished"] [StdErr cr])))
diff -r 1e71558180f0 function/examples2/slink/test.k
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/function/examples2/slink/test.k	Fri Apr 25 16:12:05 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 1e71558180f0 function/jolt2/CodeGenerator-arm.st
--- a/function/jolt2/CodeGenerator-arm.st	Thu Apr 24 23:17:10 2008 -0600
+++ b/function/jolt2/CodeGenerator-arm.st	Fri Apr 25 16:12:05 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 1e71558180f0 function/jolt2/CodeGenerator-i386.st
--- a/function/jolt2/CodeGenerator-i386.st	Thu Apr 24 23:17:10 2008 -0600
+++ b/function/jolt2/CodeGenerator-i386.st	Fri Apr 25 16:12:05 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: (self slinkName: 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,83 @@ 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
-[
+NameManglingTable : Array ()
+[
+    "For (relative) readability:
+         _a-zA-Z0-9 -> _a-zA-Z0-9
+	 .          -> _<hex-value>_"
+    NameManglingTable := Array new: 256.
+    NameManglingTable atAllPut: #'mangleOther:to:'.
+    '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
+	do: [:char | NameManglingTable at: char put: #'mangleLetter:to:'].
+]
+
+Intel32CodeGenerator slinkName: name
+[
+    | uscore mangled |
+    {
+#if defined(__MACH__) || defined(__CYGWIN__) || defined(__WIN32__)
+        v_uscore = 1;
+#endif
+    }.
+    mangled := (String new: name size * 2) writeStream.
+    uscore ifTrue: [mangled nextPut: $_].
+    name do: [:char | self perform: (NameManglingTable at: char) with: char with: mangled].
+    ^mangled contents
+]
+
+Intel32CodeGenerator mangleLetter: aCharacter to: aStream	[ aStream nextPut: aCharacter ]
+Intel32CodeGenerator mangleOther: aCharacter to: aStream
+[
+    aStream nextPut: $_; print: aCharacter base: 16; nextPut: $_.
+]
+
+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 +482,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:    (gen slinkName: op arg)	      R: op output ];
+	at: #REG  add: #(slinki	 	)	do: [:op :gen | gen movlS:    (gen slinkName: 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 +498,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 +583,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 1e71558180f0 function/jolt2/CodeGenerator-ppc.st
--- a/function/jolt2/CodeGenerator-ppc.st	Thu Apr 24 23:17:10 2008 -0600
+++ b/function/jolt2/CodeGenerator-ppc.st	Fri Apr 25 16:12:05 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 1e71558180f0 function/jolt2/CodeGenerator.st
--- a/function/jolt2/CodeGenerator.st	Thu Apr 24 23:17:10 2008 -0600
+++ b/function/jolt2/CodeGenerator.st	Fri Apr 25 16:12:05 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 1e71558180f0 function/jolt2/Compiler.st
--- a/function/jolt2/Compiler.st	Thu Apr 24 23:17:10 2008 -0600
+++ b/function/jolt2/Compiler.st	Fri Apr 25 16:12:05 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 1e71558180f0 function/jolt2/Instruction.st
--- a/function/jolt2/Instruction.st	Thu Apr 24 23:17:10 2008 -0600
+++ b/function/jolt2/Instruction.st	Fri Apr 25 16:12:06 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 1e71558180f0 function/jolt2/boot.k
--- a/function/jolt2/boot.k	Thu Apr 24 23:17:10 2008 -0600
+++ b/function/jolt2/boot.k	Fri Apr 25 16:12:06 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)
@@ -227,6 +228,10 @@
 (load "object.k")
 
 (define *package-list* [IdentitySet new])
+[*package-list* add: 'syntax]
+[*package-list* add: 'debug]
+[*package-list* add: 'object]
+[*package-list* add: 'boot]
 
 (define %require
   (lambda (package)
diff -r 1e71558180f0 function/objects/File.st
--- a/function/objects/File.st	Thu Apr 24 23:17:10 2008 -0600
+++ b/function/objects/File.st	Fri Apr 25 16:12:06 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