From b974133285990ffb7ffc9e427c3503bc08b42281 Mon Sep 17 00:00:00 2001
From: Chris Double <chris.double@double.co.nz>
Date: Tue, 3 Jun 2008 11:01:04 +1200
Subject: [PATCH 01/85] Re-add jni library to unmaintained

---
 unmaintained/jni/jni-internals.factor | 357 ++++++++++++++++++++++++++
 unmaintained/jni/jni.factor           |  22 ++
 unmaintained/jni/load.factor          |   4 +
 3 files changed, 383 insertions(+)
 create mode 100644 unmaintained/jni/jni-internals.factor
 create mode 100644 unmaintained/jni/jni.factor
 create mode 100644 unmaintained/jni/load.factor

diff --git a/unmaintained/jni/jni-internals.factor b/unmaintained/jni/jni-internals.factor
new file mode 100644
index 0000000000..49bc57b108
--- /dev/null
+++ b/unmaintained/jni/jni-internals.factor
@@ -0,0 +1,357 @@
+! Copyright (C) 2006 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+IN: jni-internals
+USING: kernel alien arrays sequences ;
+
+LIBRARY: jvm
+
+TYPEDEF: int jint
+TYPEDEF: uchar jboolean
+TYPEDEF: void* JNIEnv
+
+C-STRUCT: jdk-init-args
+	{ "jint" "version" }
+	{ "void*" "properties" }
+	{ "jint" "check-source" }
+	{ "jint" "native-stack-size" }
+	{ "jint" "java-stack-size" }
+	{ "jint" "min-heap-size" }
+	{ "jint" "max-heap-size" }
+	{ "jint" "verify-mode" }
+	{ "char*" "classpath" }
+	{ "void*" "vprintf" }
+	{ "void*" "exit" }
+	{ "void*" "abort" }
+	{ "jint" "enable-class-gc" }
+	{ "jint" "enable-verbose-gc" }
+	{ "jint" "disable-async-gc" }
+	{ "jint" "verbose" }
+	{ "jboolean" "debugging" }
+	{ "jint" "debug-port" } ;
+
+C-STRUCT: JNIInvokeInterface
+	{ "void*" "reserved0" }
+	{ "void*" "reserved1" }
+	{ "void*" "reserved2" }
+	{ "void*" "DestroyJavaVM" }
+	{ "void*" "AttachCurrentThread" }
+	{ "void*" "DetachCurrentThread" }
+	{ "void*" "GetEnv" }
+	{ "void*" "AttachCurrentThreadAsDaemon" } ;
+
+C-STRUCT: JavaVM
+	{ "JNIInvokeInterface*" "functions" } ;
+
+C-STRUCT: JNINativeInterface
+    { "void*" "reserved0" }
+    { "void*" "reserved1" }
+    { "void*" "reserved2" }
+    { "void*" "reserved3" }
+    { "void*" "GetVersion" }
+    { "void*" "DefineClass" }
+    { "void*" "FindClass" }
+    { "void*" "FromReflectedMethod" }
+    { "void*" "FromReflectedField" }
+    { "void*" "ToReflectedMethod" }
+    { "void*" "GetSuperclass" }
+    { "void*" "IsAssignableFrom" }
+    { "void*" "ToReflectedField" }
+    { "void*" "Throw" }
+    { "void*" "ThrowNew" }
+    { "void*" "ExceptionOccurred" }
+    { "void*" "ExceptionDescribe" }
+    { "void*" "ExceptionClear" }
+    { "void*" "FatalError" }
+    { "void*" "PushLocalFrame" }
+    { "void*" "PopLocalFrame" }
+    { "void*" "NewGlobalRef" }
+    { "void*" "DeleteGlobalRef" }
+    { "void*" "DeleteLocalRef" }
+    { "void*" "IsSameObject" }
+    { "void*" "NewLocalRef" }
+    { "void*" "EnsureLocalCapacity" }
+    { "void*" "AllocObject" }
+    { "void*" "NewObject" }
+    { "void*" "NewObjectV" }
+    { "void*" "NewObjectA" }
+    { "void*" "GetObjectClass" }
+    { "void*" "IsInstanceOf" }
+    { "void*" "GetMethodID" }
+    { "void*" "CallObjectMethod" }
+    { "void*" "CallObjectMethodV" }
+    { "void*" "CallObjectMethodA" }
+    { "void*" "CallBooleanMethod" }
+    { "void*" "CallBooleanMethodV" }
+    { "void*" "CallBooleanMethodA" }
+    { "void*" "CallByteMethod" }
+    { "void*" "CallByteMethodV" }
+    { "void*" "CallByteMethodA" }
+    { "void*" "CallCharMethod" }
+    { "void*" "CallCharMethodV" }
+    { "void*" "CallCharMethodA" }
+    { "void*" "CallShortMethod" }
+    { "void*" "CallShortMethodV" }
+    { "void*" "CallShortMethodA" }
+    { "void*" "CallIntMethod" }
+    { "void*" "CallIntMethodV" }
+    { "void*" "CallIntMethodA" }
+    { "void*" "CallLongMethod" }
+    { "void*" "CallLongMethodV" }
+    { "void*" "CallLongMethodA" }
+    { "void*" "CallFloatMethod" }
+    { "void*" "CallFloatMethodV" }
+    { "void*" "CallFloatMethodA" }
+    { "void*" "CallDoubleMethod" }
+    { "void*" "CallDoubleMethodV" }
+    { "void*" "CallDoubleMethodA" }
+    { "void*" "CallVoidMethod" }
+    { "void*" "CallVoidMethodV" }
+    { "void*" "CallVoidMethodA" }
+    { "void*" "CallNonvirtualObjectMethod" }
+    { "void*" "CallNonvirtualObjectMethodV" }
+    { "void*" "CallNonvirtualObjectMethodA" }
+    { "void*" "CallNonvirtualBooleanMethod" }
+    { "void*" "CallNonvirtualBooleanMethodV" }
+    { "void*" "CallNonvirtualBooleanMethodA" }
+    { "void*" "CallNonvirtualByteMethod" }
+    { "void*" "CallNonvirtualByteMethodV" }
+    { "void*" "CallNonvirtualByteMethodA" }
+    { "void*" "CallNonvirtualCharMethod" }
+    { "void*" "CallNonvirtualCharMethodV" }
+    { "void*" "CallNonvirtualCharMethodA" }
+    { "void*" "CallNonvirtualShortMethod" }
+    { "void*" "CallNonvirtualShortMethodV" }
+    { "void*" "CallNonvirtualShortMethodA" }
+    { "void*" "CallNonvirtualIntMethod" }
+    { "void*" "CallNonvirtualIntMethodV" }
+    { "void*" "CallNonvirtualIntMethodA" }
+    { "void*" "CallNonvirtualLongMethod" }
+    { "void*" "CallNonvirtualLongMethodV" }
+    { "void*" "CallNonvirtualLongMethodA" }
+    { "void*" "CallNonvirtualFloatMethod" }
+    { "void*" "CallNonvirtualFloatMethodV" }
+    { "void*" "CallNonvirtualFloatMethodA" }
+    { "void*" "CallNonvirtualDoubleMethod" }
+    { "void*" "CallNonvirtualDoubleMethodV" }
+    { "void*" "CallNonvirtualDoubleMethodA" }
+    { "void*" "CallNonvirtualVoidMethod" }
+    { "void*" "CallNonvirtualVoidMethodV" }
+    { "void*" "CallNonvirtualVoidMethodA" }
+    { "void*" "GetFieldID" }
+    { "void*" "GetObjectField" }
+    { "void*" "GetBooleanField" }
+    { "void*" "GetByteField" }
+    { "void*" "GetCharField" }
+    { "void*" "GetShortField" }
+    { "void*" "GetIntField" }
+    { "void*" "GetLongField" }
+    { "void*" "GetFloatField" }
+    { "void*" "GetDoubleField" }
+    { "void*" "SetObjectField" }
+    { "void*" "SetBooleanField" }
+    { "void*" "SetByteField" }
+    { "void*" "SetCharField" }
+    { "void*" "SetShortField" }
+    { "void*" "SetIntField" }
+    { "void*" "SetLongField" }
+    { "void*" "SetFloatField" }
+    { "void*" "SetDoubleField" }
+    { "void*" "GetStaticMethodID" }
+    { "void*" "CallStaticObjectMethod" }
+    { "void*" "CallStaticObjectMethodV" }
+    { "void*" "CallStaticObjectMethodA" }
+    { "void*" "CallStaticBooleanMethod" }
+    { "void*" "CallStaticBooleanMethodV" }
+    { "void*" "CallStaticBooleanMethodA" }
+    { "void*" "CallStaticByteMethod" }
+    { "void*" "CallStaticByteMethodV" }
+    { "void*" "CallStaticByteMethodA" }
+    { "void*" "CallStaticCharMethod" }
+    { "void*" "CallStaticCharMethodV" }
+    { "void*" "CallStaticCharMethodA" }
+    { "void*" "CallStaticShortMethod" }
+    { "void*" "CallStaticShortMethodV" }
+    { "void*" "CallStaticShortMethodA" }
+    { "void*" "CallStaticIntMethod" }
+    { "void*" "CallStaticIntMethodV" }
+    { "void*" "CallStaticIntMethodA" }
+    { "void*" "CallStaticLongMethod" }
+    { "void*" "CallStaticLongMethodV" }
+    { "void*" "CallStaticLongMethodA" }
+    { "void*" "CallStaticFloatMethod" }
+    { "void*" "CallStaticFloatMethodV" }
+    { "void*" "CallStaticFloatMethodA" }
+    { "void*" "CallStaticDoubleMethod" }
+    { "void*" "CallStaticDoubleMethodV" }
+    { "void*" "CallStaticDoubleMethodA" }
+    { "void*" "CallStaticVoidMethod" }
+    { "void*" "CallStaticVoidMethodV" }
+    { "void*" "CallStaticVoidMethodA" }
+    { "void*" "GetStaticFieldID" }
+    { "void*" "GetStaticObjectField" }
+    { "void*" "GetStaticBooleanField" }
+    { "void*" "GetStaticByteField" }
+    { "void*" "GetStaticCharField" }
+    { "void*" "GetStaticShortField" }
+    { "void*" "GetStaticIntField" }
+    { "void*" "GetStaticLongField" }
+    { "void*" "GetStaticFloatField" }
+    { "void*" "GetStaticDoubleField" }
+    { "void*" "SetStaticObjectField" }
+    { "void*" "SetStaticBooleanField" }
+    { "void*" "SetStaticByteField" }
+    { "void*" "SetStaticCharField" }
+    { "void*" "SetStaticShortField" }
+    { "void*" "SetStaticIntField" }
+    { "void*" "SetStaticLongField" }
+    { "void*" "SetStaticFloatField" }
+    { "void*" "SetStaticDoubleField" }
+    { "void*" "NewString" }
+    { "void*" "GetStringLength" }
+    { "void*" "GetStringChars" }
+    { "void*" "ReleaseStringChars" }
+    { "void*" "NewStringUTF" }
+    { "void*" "GetStringUTFLength" }
+    { "void*" "GetStringUTFChars" }
+    { "void*" "ReleaseStringUTFChars" }
+    { "void*" "GetArrayLength" }
+    { "void*" "NewObjectArray" }
+    { "void*" "GetObjectArrayElement" }
+    { "void*" "SetObjectArrayElement" }
+    { "void*" "NewBooleanArray" }
+    { "void*" "NewByteArray" }
+    { "void*" "NewCharArray" }
+    { "void*" "NewShortArray" }
+    { "void*" "NewIntArray" }
+    { "void*" "NewLongArray" }
+    { "void*" "NewFloatArray" }
+    { "void*" "NewDoubleArray" }
+    { "void*" "GetBooleanArrayElements" }
+    { "void*" "GetByteArrayElements" }
+    { "void*" "GetCharArrayElements" }
+    { "void*" "GetShortArrayElements" }
+    { "void*" "GetIntArrayElements" }
+    { "void*" "GetLongArrayElements" }
+    { "void*" "GetFloatArrayElements" }
+    { "void*" "GetDoubleArrayElements" }
+    { "void*" "ReleaseBooleanArrayElements" }
+    { "void*" "ReleaseByteArrayElements" }
+    { "void*" "ReleaseCharArrayElements" }
+    { "void*" "ReleaseShortArrayElements" }
+    { "void*" "ReleaseIntArrayElements" }
+    { "void*" "ReleaseLongArrayElements" }
+    { "void*" "ReleaseFloatArrayElements" }
+    { "void*" "ReleaseDoubleArrayElements" }
+    { "void*" "GetBooleanArrayRegion" }
+    { "void*" "GetByteArrayRegion" }
+    { "void*" "GetCharArrayRegion" }
+    { "void*" "GetShortArrayRegion" }
+    { "void*" "GetIntArrayRegion" }
+    { "void*" "GetLongArrayRegion" }
+    { "void*" "GetFloatArrayRegion" }
+    { "void*" "GetDoubleArrayRegion" }
+    { "void*" "SetBooleanArrayRegion" }
+    { "void*" "SetByteArrayRegion" }
+    { "void*" "SetCharArrayRegion" }
+    { "void*" "SetShortArrayRegion" }
+    { "void*" "SetIntArrayRegion" }
+    { "void*" "SetLongArrayRegion" }
+    { "void*" "SetFloatArrayRegion" }
+    { "void*" "SetDoubleArrayRegion" }
+    { "void*" "RegisterNatives" }
+    { "void*" "UnregisterNatives" }
+    { "void*" "MonitorEnter" }
+    { "void*" "MonitorExit" }
+    { "void*" "GetJavaVM" }
+    { "void*" "GetStringRegion" }
+    { "void*" "GetStringUTFRegion" }
+    { "void*" "GetPrimitiveArrayCritical" }
+    { "void*" "ReleasePrimitiveArrayCritical" }
+    { "void*" "GetStringCritical" }
+    { "void*" "ReleaseStringCritical" }
+    { "void*" "NewWeakGlobalRef" }
+    { "void*" "DeleteWeakGlobalRef" }
+    { "void*" "ExceptionCheck" }
+    { "void*" "NewDirectByteBuffer" }
+    { "void*" "GetDirectBufferAddress" }
+    { "void*" "GetDirectBufferCapacity" } ;
+
+C-STRUCT: JNIEnv
+	{ "JNINativeInterface*" "functions" } ;
+
+FUNCTION: jint JNI_GetDefaultJavaVMInitArgs ( jdk-init-args* args ) ;
+FUNCTION: jint JNI_CreateJavaVM ( void** pvm, void** penv, void* args ) ;
+
+: <jdk-init-args> ( -- jdk-init-args )
+  "jdk-init-args" <c-object>  HEX: 00010004 over set-jdk-init-args-version ;
+
+: jni1 ( -- init-args int )
+  <jdk-init-args> dup JNI_GetDefaultJavaVMInitArgs ;
+
+: jni2 ( -- vm env int )
+  f <void*> f <void*> [
+    jni1 drop JNI_CreateJavaVM
+  ] 2keep rot dup 0 = [
+    >r >r 0 swap void*-nth r> 0 swap void*-nth r> 
+  ] when ;
+
+: (destroy-java-vm) 
+  "int" { "void*" } "cdecl" alien-indirect ;
+
+: (attach-current-thread) 
+  "int" { "void*" "void*" "void*" } "cdecl" alien-indirect ;
+
+: (detach-current-thread) 
+  "int" { "void*" } "cdecl" alien-indirect ;
+
+: (get-env) 
+  "int" { "void*" "void*" "int" } "cdecl" alien-indirect ;
+
+: (attach-current-thread-as-daemon) 
+  "int" { "void*" "void*" "void*" } "cdecl" alien-indirect ;
+
+: destroy-java-vm ( javavm -- int )
+  dup JavaVM-functions JNIInvokeInterface-DestroyJavaVM (destroy-java-vm) ;
+
+: (get-version) 
+  "jint" { "JNIEnv*" } "cdecl" alien-indirect ;
+
+: get-version ( jnienv -- int )
+  dup JNIEnv-functions JNINativeInterface-GetVersion (get-version) ;
+  
+: (find-class) 
+  "void*" { "JNINativeInterface*" "char*" } "cdecl" alien-indirect ;
+
+: find-class ( name jnienv -- int )
+  dup swapd JNIEnv-functions JNINativeInterface-FindClass (find-class) ;
+
+: (get-static-field-id) 
+  "void*" { "JNINativeInterface*" "void*" "char*" "char*" } "cdecl" alien-indirect ;
+
+: get-static-field-id ( class name sig jnienv -- int )
+  dup >r >r 3array r> swap first3 r> JNIEnv-functions JNINativeInterface-GetStaticFieldID (get-static-field-id) ;
+
+: (get-static-object-field) 
+  "void*" { "JNINativeInterface*" "void*" "void*" } "cdecl" alien-indirect ;
+
+: get-static-object-field ( class id jnienv -- int )
+  dup >r >r 2array r> swap first2 r> JNIEnv-functions JNINativeInterface-GetStaticObjectField (get-static-object-field) ;
+
+: (get-method-id) 
+  "void*" { "JNINativeInterface*" "void*" "char*" "char*" } "cdecl" alien-indirect ;
+
+: get-method-id ( class name sig jnienv -- int )
+  dup >r >r 3array r> swap first3 r> JNIEnv-functions JNINativeInterface-GetMethodID (get-method-id) ;
+
+: (new-string) 
+  "void*" { "JNINativeInterface*" "char*" "int" } "cdecl" alien-indirect ;
+
+: new-string ( str jnienv -- str )
+  dup >r >r dup length 2array r> swap first2 r> JNIEnv-functions JNINativeInterface-NewString (new-string) ;
+
+: (call1) 
+  "void" { "JNINativeInterface*" "void*" "void*" "int" } "cdecl" alien-indirect ;
+
+: call1 ( obj method-id jstr jnienv -- )
+  dup >r >r 3array r> swap first3 r> JNIEnv-functions JNINativeInterface-CallObjectMethod (call1) ;
+
diff --git a/unmaintained/jni/jni.factor b/unmaintained/jni/jni.factor
new file mode 100644
index 0000000000..86e1670c50
--- /dev/null
+++ b/unmaintained/jni/jni.factor
@@ -0,0 +1,22 @@
+! Copyright (C) 2006 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+IN: jni
+USING: kernel jni-internals namespaces ;
+
+! High level interface for JNI to be added here...
+
+: test0 ( -- )
+  jni2 drop nip "env" set ;
+
+: test1 ( -- system )
+  "java/lang/System" "env" get find-class ;
+
+: test2 ( system -- system.out )
+  dup "out" "Ljava/io/PrintStream;" "env" get get-static-field-id 
+  "env" get get-static-object-field ;
+
+: test3 ( int system.out -- )
+  "java/io/PrintStream" "env" get find-class ! jstr out class
+  "println" "(I)V" "env" get get-method-id ! jstr out id
+  rot "env" get call1 ;
+  
\ No newline at end of file
diff --git a/unmaintained/jni/load.factor b/unmaintained/jni/load.factor
new file mode 100644
index 0000000000..f5fd45c8d9
--- /dev/null
+++ b/unmaintained/jni/load.factor
@@ -0,0 +1,4 @@
+! Copyright (C) 2006 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+PROVIDE: libs/jni
+{ +files+ { "jni-internals.factor" "jni.factor" } } ;

From 1b8943a8e0476d7f68542924b3a3079dc1d2d361 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Mon, 16 Jun 2008 17:39:14 +1200
Subject: [PATCH 02/85] Add failing peg.ebnf tests

---
 extra/peg/ebnf/ebnf-tests.factor | 33 ++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index faaa63f4bd..425c05f391 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -365,3 +365,36 @@ main = Primary
   "ab c ab c" [EBNF a="a" "b" foo=(a "c")* EBNF] call ast>>
 ] unit-test
 
+{ V{ "a" "a" "a" } } [
+  "aaa" [EBNF a=('a')* b=!('b') a:x => [[ drop x ]] EBNF] call ast>>
+] unit-test
+
+{ t } [
+  "aaa" [EBNF a=('a')* b=!('b') a:x => [[ drop x ]] EBNF] call ast>>
+  "aaa" [EBNF a=('a')* b=!('b') (a):x => [[ drop x ]] EBNF] call ast>> =
+] unit-test
+
+{ V{ "a" "a" "a" } } [
+  "aaa" [EBNF a=('a')* b=a:x => [[ drop x ]] EBNF] call ast>>
+] unit-test
+
+{ t } [
+  "aaa" [EBNF a=('a')* b=a:x => [[ drop x ]] EBNF] call ast>>
+  "aaa" [EBNF a=('a')* b=(a):x => [[ drop x ]] EBNF] call ast>> =
+] unit-test
+
+{ t } [
+  "number=(digit)+:n 'a'" 'ebnf' parse remaining>> length zero?
+] unit-test
+
+{ t } [
+  "number=(digit)+ 'a'" 'ebnf' parse remaining>> length zero?
+] unit-test
+
+{ t } [
+  "number=digit+ 'a'" 'ebnf' parse remaining>> length zero?
+] unit-test
+
+{ t } [
+  "number=digit+:n 'a'" 'ebnf' parse remaining>> length zero?
+] unit-test
\ No newline at end of file

From f1219c906aab7aa0d84b27694e998f2960c30775 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Tue, 17 Jun 2008 15:25:47 +1200
Subject: [PATCH 03/85] Check stack effect of actions in ebnf. Do implicit drop
 if needed

---
 extra/peg/ebnf/ebnf.factor | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index fc10a65024..44765cc60c 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -2,8 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel compiler.units parser words arrays strings math.parser sequences 
        quotations vectors namespaces math assocs continuations peg
-       peg.parsers unicode.categories multiline combinators.lib 
-       splitting accessors effects sequences.deep peg.search ;
+       peg.parsers unicode.categories multiline combinators combinators.lib 
+       splitting accessors effects sequences.deep peg.search inference ;
 IN: peg.ebnf
 
 TUPLE: ebnf-non-terminal symbol ;
@@ -340,9 +340,16 @@ M: ebnf-var build-locals ( code ast -- )
 M: object build-locals ( code ast -- )
   drop ;
    
+: check-action-effect ( quot -- quot )
+  dup infer {
+    { [ dup (( a -- b )) effect<= ] [ drop ] }
+    { [ dup (( -- b )) effect<= ] [ drop [ drop ] prepose ] }
+    [ "Bad effect: " swap effect>string append throw ]
+  } cond ;
+ 
 M: ebnf-action (transform) ( ast -- parser )
   [ parser>> (transform) ] [ code>> ] [ parser>> ] tri build-locals 
-  string-lines parse-lines action ;
+  string-lines parse-lines check-action-effect action ;
 
 M: ebnf-semantic (transform) ( ast -- parser )
   [ parser>> (transform) ] [ code>> ] [ parser>> ] tri build-locals 

From dfa4926a84f5fbec165fe398fe7ed78e3666f298 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Tue, 17 Jun 2008 22:47:38 +1200
Subject: [PATCH 04/85] Print ebnf quotation on error. Fix generated local
 quotation

---
 extra/peg/ebnf/ebnf.factor | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 44765cc60c..335607b463 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -3,7 +3,8 @@
 USING: kernel compiler.units parser words arrays strings math.parser sequences 
        quotations vectors namespaces math assocs continuations peg
        peg.parsers unicode.categories multiline combinators combinators.lib 
-       splitting accessors effects sequences.deep peg.search inference ;
+       splitting accessors effects sequences.deep peg.search inference 
+       io.streams.string io prettyprint ;
 IN: peg.ebnf
 
 TUPLE: ebnf-non-terminal symbol ;
@@ -324,7 +325,7 @@ M: ebnf-sequence build-locals ( code ast -- code )
         ] 2each
         " | " %
         %  
-        " ]" %     
+        " nip ]" %     
     ] "" make 
   ] if ;
 
@@ -334,7 +335,7 @@ M: ebnf-var build-locals ( code ast -- )
     name>> % " [ dup ] " %
     " | " %
     %  
-    " ]" %     
+    " nip ]" %     
   ] "" make ;
 
 M: object build-locals ( code ast -- )
@@ -344,7 +345,12 @@ M: object build-locals ( code ast -- )
   dup infer {
     { [ dup (( a -- b )) effect<= ] [ drop ] }
     { [ dup (( -- b )) effect<= ] [ drop [ drop ] prepose ] }
-    [ "Bad effect: " swap effect>string append throw ]
+    [
+      [ 
+        "Bad effect: " write effect>string write 
+        " for quotation " write pprint
+      ] with-string-writer throw
+    ]
   } cond ;
  
 M: ebnf-action (transform) ( ast -- parser )

From 479fa6a5b5a3ea5ebec18d4eba8ae30579531c60 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Wed, 18 Jun 2008 15:07:23 +1200
Subject: [PATCH 05/85] Add support for calling foreign peg.ebnf rules

---
 extra/peg/ebnf/ebnf.factor | 43 +++++++++++++++++++++++++++++++++-----
 1 file changed, 38 insertions(+), 5 deletions(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 335607b463..4828ace9af 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -1,14 +1,19 @@
 ! Copyright (C) 2007 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel compiler.units parser words arrays strings math.parser sequences 
+USING: kernel compiler.units words arrays strings math.parser sequences 
        quotations vectors namespaces math assocs continuations peg
        peg.parsers unicode.categories multiline combinators combinators.lib 
        splitting accessors effects sequences.deep peg.search inference 
-       io.streams.string io prettyprint ;
+       io.streams.string io prettyprint parser ;
 IN: peg.ebnf
 
+: rule ( name word -- parser )
+  #! Given an EBNF word produced from EBNF: return the EBNF rule
+  "ebnf-parser" word-prop at ;
+
 TUPLE: ebnf-non-terminal symbol ;
 TUPLE: ebnf-terminal symbol ;
+TUPLE: ebnf-foreign word rule ;
 TUPLE: ebnf-any-character ;
 TUPLE: ebnf-range pattern ;
 TUPLE: ebnf-ensure group ;
@@ -27,6 +32,7 @@ TUPLE: ebnf rules ;
 
 C: <ebnf-non-terminal> ebnf-non-terminal
 C: <ebnf-terminal> ebnf-terminal
+C: <ebnf-foreign> ebnf-foreign
 C: <ebnf-any-character> ebnf-any-character
 C: <ebnf-range> ebnf-range
 C: <ebnf-ensure> ebnf-ensure
@@ -88,6 +94,8 @@ C: <ebnf> ebnf
       [ dup CHAR: ? = ]
       [ dup CHAR: : = ]
       [ dup CHAR: ~ = ]
+      [ dup CHAR: < = ]
+      [ dup CHAR: > = ]
     } 0|| not nip    
   ] satisfy repeat1 [ >string <ebnf-non-terminal> ] action ;
 
@@ -96,6 +104,24 @@ C: <ebnf> ebnf
   #! and it represents the literal value of the identifier.
   'identifier' [ <ebnf-terminal> ] action ;
 
+: 'foreign-name' ( -- parser )
+  #! Parse a valid foreign parser name
+  [
+    {
+      [ dup blank?    ]
+      [ dup CHAR: > = ]
+    } 0|| not nip    
+  ] satisfy repeat1 [ >string ] action ;
+
+: 'foreign' ( -- parser )
+  #! A foreign call is a call to a rule in another ebnf grammar
+  [
+    "<foreign" syntax ,
+    'foreign-name' sp ,
+    'foreign-name' sp optional ,
+    ">" syntax ,
+  ] seq* [ first2 <ebnf-foreign> ] action ;
+
 : 'any-character' ( -- parser )
   #! A parser to match the symbol for any character match.
   [ CHAR: . = ] satisfy [ drop <ebnf-any-character> ] action ;
@@ -117,6 +143,7 @@ C: <ebnf> ebnf
     [ 
       'non-terminal' ,
       'terminal' ,
+      'foreign' ,
       'range-parser' ,
       'any-character' ,
     ] choice* ,
@@ -367,6 +394,15 @@ M: ebnf-var (transform) ( ast -- parser )
 M: ebnf-terminal (transform) ( ast -- parser )
   symbol>> token ;
 
+M: ebnf-foreign (transform) ( ast -- parser )
+  dup word>> search
+  [ "Foreign word " swap word>> append " not found" append throw ] unless*
+  swap rule>> dup [
+    swap rule  
+  ] [
+    execute
+  ] if ;
+
 : parser-not-found ( name -- * )
   [
     "Parser " % % " not found." %
@@ -411,6 +447,3 @@ M: ebnf-non-terminal (transform) ( ast -- parser )
   ";EBNF" parse-multiline-string replace-escapes
   ebnf>quot swapd 1 1 <effect> define-declared "ebnf-parser" set-word-prop ; parsing
 
-: rule ( name word -- parser )
-  #! Given an EBNF word produced from EBNF: return the EBNF rule
-  "ebnf-parser" word-prop at ;
\ No newline at end of file

From 0841dbb4ad4567652a0acc53d3a0e1d4b24b4855 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Wed, 18 Jun 2008 15:21:10 +1200
Subject: [PATCH 06/85] Fix ebnf unit test

---
 extra/peg/ebnf/ebnf-tests.factor | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index 425c05f391..04cc01c9d0 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -164,23 +164,23 @@ IN: peg.ebnf.tests
 ] unit-test
 
 { 6 } [
-  "4+2" [EBNF num=[0-9] => [[ digit> ]] foo=num:x '+' num:y => [[ drop x y + ]] EBNF] call ast>>
+  "4+2" [EBNF num=[0-9] => [[ digit> ]] foo=num:x '+' num:y => [[ x y + ]] EBNF] call ast>>
 ] unit-test
 
 { 6 } [
-  "4+2" [EBNF foo=[0-9]:x '+' [0-9]:y => [[ drop x digit> y digit> + ]] EBNF] call ast>>
+  "4+2" [EBNF foo=[0-9]:x '+' [0-9]:y => [[ x digit> y digit> + ]] EBNF] call ast>>
 ] unit-test
 
 { 10 } [
-  { 1 2 3 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ drop x y + ]] | num EBNF] call ast>>
+  { 1 2 3 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ x y + ]] | num EBNF] call ast>>
 ] unit-test
 
 { f } [
-  { "a" 2 3 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ drop x y + ]] | num EBNF] call 
+  { "a" 2 3 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ x y + ]] | num EBNF] call 
 ] unit-test
 
 { 3 } [
-  { 1 2 "a" 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ drop x y + ]] | num EBNF] call ast>>
+  { 1 2 "a" 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ x y + ]] | num EBNF] call ast>>
 ] unit-test
 
 { f } [
@@ -251,7 +251,7 @@ IN: peg.ebnf.tests
 ] unit-test
 
 { t } [
-  "abcd='9' | ('8'):x => [[ drop x ]]" 'ebnf' parse parse-result-remaining empty?
+  "abcd='9' | ('8'):x => [[ x ]]" 'ebnf' parse parse-result-remaining empty?
 ] unit-test
 
 EBNF: primary 
@@ -366,21 +366,21 @@ main = Primary
 ] unit-test
 
 { V{ "a" "a" "a" } } [
-  "aaa" [EBNF a=('a')* b=!('b') a:x => [[ drop x ]] EBNF] call ast>>
+  "aaa" [EBNF a=('a')* b=!('b') a:x => [[ x ]] EBNF] call ast>>
 ] unit-test
 
 { t } [
-  "aaa" [EBNF a=('a')* b=!('b') a:x => [[ drop x ]] EBNF] call ast>>
-  "aaa" [EBNF a=('a')* b=!('b') (a):x => [[ drop x ]] EBNF] call ast>> =
+  "aaa" [EBNF a=('a')* b=!('b') a:x => [[ x ]] EBNF] call ast>>
+  "aaa" [EBNF a=('a')* b=!('b') (a):x => [[ x ]] EBNF] call ast>> =
 ] unit-test
 
 { V{ "a" "a" "a" } } [
-  "aaa" [EBNF a=('a')* b=a:x => [[ drop x ]] EBNF] call ast>>
+  "aaa" [EBNF a=('a')* b=a:x => [[ x ]] EBNF] call ast>>
 ] unit-test
 
 { t } [
-  "aaa" [EBNF a=('a')* b=a:x => [[ drop x ]] EBNF] call ast>>
-  "aaa" [EBNF a=('a')* b=(a):x => [[ drop x ]] EBNF] call ast>> =
+  "aaa" [EBNF a=('a')* b=a:x => [[ x ]] EBNF] call ast>>
+  "aaa" [EBNF a=('a')* b=(a):x => [[ x ]] EBNF] call ast>> =
 ] unit-test
 
 { t } [

From f4f4ea7eb6fd5b78f635ecbc019649db1a1dd817 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Wed, 18 Jun 2008 17:34:21 +1200
Subject: [PATCH 07/85] Fix peg.ebnf unit test failures

---
 extra/peg/ebnf/ebnf.factor | 68 ++++++++++++++++++++++++--------------
 1 file changed, 43 insertions(+), 25 deletions(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 4828ace9af..215eabdd37 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -49,6 +49,10 @@ C: <ebnf-var> ebnf-var
 C: <ebnf-semantic> ebnf-semantic
 C: <ebnf> ebnf
 
+: filter-hidden ( seq -- seq )
+  #! Remove elements that produce no AST from sequence
+  [ ebnf-ensure-not? not ] filter [ ebnf-ensure? not ] filter ;
+
 : syntax ( string -- parser )
   #! Parses the string, ignoring white space, and
   #! does not put the result in the AST.
@@ -140,12 +144,18 @@ C: <ebnf> ebnf
   #! The latter indicates that it is the beginning of a
   #! new rule.
   [
-    [ 
-      'non-terminal' ,
-      'terminal' ,
-      'foreign' ,
-      'range-parser' ,
-      'any-character' ,
+    [
+      [ 
+        'non-terminal' ,
+        'terminal' ,
+        'foreign' ,
+        'range-parser' ,
+        'any-character' ,
+      ] choice* 
+      [ dup , "*" token hide , ] seq* [ first <ebnf-repeat0> ] action ,
+      [ dup , "+" token hide , ] seq* [ first <ebnf-repeat1> ] action ,
+      [ dup , "?[" token ensure-not , "?" token hide , ] seq* [ first <ebnf-optional> ] action ,
+      ,
     ] choice* ,
     [
       "=" syntax ensure-not ,
@@ -153,6 +163,8 @@ C: <ebnf> ebnf
     ] choice* ,
   ] seq* [ first ] action ;
 
+DEFER: 'action'
+
 : 'element' ( -- parser )
   [
     [ ('element') , ":" syntax , "a-zA-Z" range-pattern repeat1 [ >string ] action , ] seq* [ first2 <ebnf-var> ] action ,
@@ -256,7 +268,7 @@ DEFER: 'choice'
   ] choice* ;
   
 : 'choice' ( -- parser )
-  'actioned-sequence' sp "|" token sp list-of [ 
+  'actioned-sequence' sp repeat1 [ dup length 1 = [ first ] [ <ebnf-sequence> ] if  ] action "|" token sp list-of [ 
     dup length 1 = [ first ] [ <ebnf-choice> ] if
   ] action ;
  
@@ -337,23 +349,29 @@ M: ebnf-whitespace (transform) ( ast -- parser )
 GENERIC: build-locals ( code ast -- code )
 
 M: ebnf-sequence build-locals ( code ast -- code )
-  elements>> dup [ ebnf-var? ] filter empty? [
-    drop 
-  ] [ 
-    [
-      "USING: locals sequences ;  [let* | " %
-        dup length swap [
-          dup ebnf-var? [
-            name>> % 
-            " [ " % # " over nth ] " %
-          ] [
-            2drop
-          ] if
-        ] 2each
-        " | " %
-        %  
-        " nip ]" %     
-    ] "" make 
+  #! Note the need to filter out this ebnf items that
+  #! leave nothing in the AST
+  elements>> filter-hidden dup length 1 = [ 
+    first build-locals 
+  ]  [
+    dup [ ebnf-var? ] filter empty? [
+      drop 
+    ] [ 
+      [
+        "USING: locals sequences ;  [let* | " %
+          dup length swap [
+            dup ebnf-var? [
+              name>> % 
+              " [ " % # " over nth ] " %
+            ] [
+              2drop
+            ] if
+          ] 2each
+          " | " %
+          %  
+          " nip ]" %     
+      ] "" make 
+    ] if
   ] if ;
 
 M: ebnf-var build-locals ( code ast -- )
@@ -381,7 +399,7 @@ M: object build-locals ( code ast -- )
   } cond ;
  
 M: ebnf-action (transform) ( ast -- parser )
-  [ parser>> (transform) ] [ code>> ] [ parser>> ] tri build-locals 
+  [ parser>> (transform) ] [ code>> ] [ parser>> ] tri build-locals  
   string-lines parse-lines check-action-effect action ;
 
 M: ebnf-semantic (transform) ( ast -- parser )

From b338fc8feaa04050cac2e10be76a4d7cf812c4b3 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Tue, 17 Jun 2008 21:55:53 +1200
Subject: [PATCH 08/85] Javascript parser

---
 extra/peg/javascript/javascript.factor | 247 +++++++++++++++++++++++++
 1 file changed, 247 insertions(+)
 create mode 100644 extra/peg/javascript/javascript.factor

diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
new file mode 100644
index 0000000000..33fd6dd069
--- /dev/null
+++ b/extra/peg/javascript/javascript.factor
@@ -0,0 +1,247 @@
+! Copyright (C) 2007 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel arrays strings math.parser sequences sequences.deep
+peg peg.ebnf peg.parsers memoize namespaces math ;
+IN: peg.javascript
+
+#! Grammar for JavaScript. Based on OMeta-JS example from:
+#! http://jarrett.cs.ucla.edu/ometa-js/#JavaScript_Compiler 
+
+USE: prettyprint
+
+TUPLE: ast-keyword value ;
+TUPLE: ast-name value ;
+TUPLE: ast-number value ;
+TUPLE: ast-string value ;
+TUPLE: ast-cond-expr condition then else ;
+TUPLE: ast-set lhs rhs ;
+TUPLE: ast-get value ;
+TUPLE: ast-mset lhs rhs operator ;
+TUPLE: ast-binop lhs rhs operator ;
+TUPLE: ast-unop expr operator ;
+TUPLE: ast-postop expr operator ;
+TUPLE: ast-preop expr operator ;
+TUPLE: ast-getp index expr ;
+TUPLE: ast-send method expr args ;
+TUPLE: ast-call expr args ;
+TUPLE: ast-this ;
+TUPLE: ast-new name args ;
+TUPLE: ast-array values ;
+TUPLE: ast-json bindings ;
+TUPLE: ast-binding name value ;
+TUPLE: ast-func fs body ;
+TUPLE: ast-var name value ;
+TUPLE: ast-begin statements ;
+TUPLE: ast-if condition true false ;
+TUPLE: ast-while condition statements ;
+TUPLE: ast-do-while statements condition ;
+TUPLE: ast-for i c u statements ;
+TUPLE: ast-for-in v e statements ;
+TUPLE: ast-switch expr statements ;
+TUPLE: ast-break ;
+TUPLE: ast-continue ;
+TUPLE: ast-throw e ;
+TUPLE: ast-try t e c f ;
+TUPLE: ast-return e ;
+TUPLE: ast-case c cs ;
+TUPLE: ast-default cs ;
+C: <ast-name> ast-name
+C: <ast-keyword> ast-keyword
+C: <ast-number> ast-number
+C: <ast-string> ast-string
+C: <ast-cond-expr> ast-cond-expr
+C: <ast-set> ast-set
+C: <ast-get> ast-get
+C: <ast-mset> ast-mset
+C: <ast-binop> ast-binop
+C: <ast-unop> ast-unop
+C: <ast-preop> ast-preop
+C: <ast-postop> ast-postop
+C: <ast-getp> ast-getp
+C: <ast-send> ast-send
+C: <ast-call> ast-call
+C: <ast-this> ast-this
+C: <ast-new> ast-new
+C: <ast-array> ast-array
+C: <ast-json> ast-json
+C: <ast-binding> ast-binding
+C: <ast-func> ast-func
+C: <ast-var> ast-var
+C: <ast-begin> ast-begin
+C: <ast-if> ast-if
+C: <ast-while> ast-while
+C: <ast-do-while> ast-do-while
+C: <ast-for> ast-for
+C: <ast-for-in> ast-for-in
+C: <ast-switch> ast-switch
+C: <ast-break> ast-break
+C: <ast-continue> ast-continue
+C: <ast-throw> ast-throw
+C: <ast-try> ast-try
+C: <ast-return> ast-return
+C: <ast-case> ast-case
+C: <ast-default> ast-default
+
+EBNF: javascript
+Letter            = [a-zA-Z]
+Digit             = [0-9]
+Digits            = (Digit)+
+SingleLineComment = "//" (!("\n") .)* "\n" => [[ drop ignore ]]
+MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ drop ignore ]]
+Space             = " " | "\t" | "\n" | SingleLineComment | MultiLineComment
+Spaces            = (Space)* => [[ drop ignore ]]
+NameFirst         = Letter | "$" | "_"
+NameRest          = NameFirst | Digit
+iName             = NameFirst (NameRest)* => [[ first2 swap prefix >string ]]
+Keyword           =  ("break"
+                    | "case"
+                    | "catch"
+                    | "continue"
+                    | "default"
+                    | "delete"
+                    | "do"
+                    | "else"
+                    | "finally"
+                    | "for"
+                    | "function"
+                    | "if"
+                    | "in"
+                    | "instanceof"
+                    | "new"
+                    | "return"
+                    | "switch"
+                    | "this"
+                    | "throw"
+                    | "try"
+                    | "typeof"
+                    | "var"
+                    | "void"
+                    | "while"
+                    | "with") => [[ <ast-keyword> ]]
+Name              = !(Keyword) (iName):n => [[ drop n <ast-name> ]]
+Number            =   Digits:ws '.' Digits:fs => [[ drop ws "." fs 3array concat >string string>number <ast-number> ]]
+                    | Digits => [[ >string string>number <ast-number> ]]  
+
+EscapeChar        =   "\\n" => [[ drop 10 ]] 
+                    | "\\r" => [[ drop 13 ]]
+                    | "\\t" => [[ drop 9 ]]
+StringChars1       = (EscapeChar | !('"""') .)* => [[ >string ]]
+StringChars2       = (EscapeChar | !('"') .)* => [[ >string ]]
+StringChars3       = (EscapeChar | !("'") .)* => [[ >string ]]
+Str                =   '"""' StringChars1:cs '"""' => [[ drop cs <ast-string> ]]
+                     | '"' StringChars2:cs '"' => [[ drop cs <ast-string> ]]
+                     | "'" StringChars3:cs "'" => [[ drop cs <ast-string> ]]
+Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | ";"
+                     | "?"   | ":"   | "!==" | "~="  | "===" | "=="  | "="   | ">="
+                     | ">"   | "<="  | "<"   | "++"  | "+="  | "+"   | "--"  | "-="
+                     | "-"   | "*="  | "*"   | "/="  | "/"   | "%="  | "%"   | "&&="
+                     | "&&"  | "||=" | "||"  | "."   | "!"
+Tok                = Spaces (Name | Keyword | Number | Str | Special )
+Toks               = (Tok)* Spaces 
+SpacesNoNl         = (!("\n") Space)* => [[ drop ignore ]]
+
+Expr               =   OrExpr:e "?" Expr:t ":" Expr:f   => [[ drop e t f <ast-cond-expr> ]]
+                     | OrExpr:e "=" Expr:rhs            => [[ drop e rhs <ast-set> ]]
+                     | OrExpr:e "+=" Expr:rhs           => [[ drop e rhs "+" <ast-mset> ]]
+                     | OrExpr:e "-=" Expr:rhs           => [[ drop e rhs "-" <ast-mset> ]]
+                     | OrExpr:e "*=" Expr:rhs           => [[ drop e rhs "*" <ast-mset> ]]
+                     | OrExpr:e "/=" Expr:rhs           => [[ drop e rhs "/" <ast-mset> ]]
+                     | OrExpr:e "%=" Expr:rhs           => [[ drop e rhs "%" <ast-mset> ]]
+                     | OrExpr:e "&&=" Expr:rhs          => [[ drop e rhs "&&" <ast-mset> ]]
+                     | OrExpr:e "||=" Expr:rhs          => [[ drop e rhs "||" <ast-mset> ]]
+                     | OrExpr:e                         => [[ drop e ]]
+
+OrExpr             =   OrExpr:x "||" AndExpr:y          => [[ drop x y "||" <ast-binop> ]]
+                     | AndExpr
+AndExpr            =   AndExpr:x "&&" EqExpr:y          => [[ drop x y "&&" <ast-binop> ]]
+                     | EqExpr
+EqExpr             =   EqExpr:x "==" RelExpr:y          => [[ drop x y "==" <ast-binop> ]]
+                     | EqExpr:x "!=" RelExpr:y          => [[ drop x y "!=" <ast-binop> ]]
+                     | EqExpr:x "===" RelExpr:y         => [[ drop x y "===" <ast-binop> ]]
+                     | EqExpr:x "!==" RelExpr:y         => [[ drop x y "!==" <ast-binop> ]]
+                     | RelExpr
+RelExpr            =   RelExpr:x ">" AddExpr:y          => [[ drop x y ">" <ast-binop> ]]
+                     | RelExpr:x ">=" AddExpr:y         => [[ drop x y ">=" <ast-binop> ]]
+                     | RelExpr:x "<" AddExpr:y          => [[ drop x y "<" <ast-binop> ]]
+                     | RelExpr:x "<=" AddExpr:y         => [[ drop x y "<=" <ast-binop> ]]
+                     | RelExpr:x "instanceof" AddExpr:y => [[ drop x y "instanceof" <ast-binop> ]]
+                     | AddExpr
+AddExpr            =   AddExpr:x "+" MulExpr:y          => [[ drop x y "+" <ast-binop> ]]
+                     | AddExpr:x "-" MulExpr:y          => [[ drop x y "-" <ast-binop> ]]
+                     | MulExpr
+MulExpr            =   MulExpr:x "*" MulExpr:y          => [[ drop x y "*" <ast-binop> ]]
+                     | MulExpr:x "/" MulExpr:y          => [[ drop x y "/" <ast-binop> ]]
+                     | MulExpr:x "%" MulExpr:y          => [[ drop x y "%" <ast-binop> ]]
+                     | Unary
+Unary              =   "-" Postfix:p                    => [[ drop p "-" <ast-unop> ]]
+                     | "+" Postfix:p                    => [[ drop p ]]
+                     | "++" Postfix:p                   => [[ drop p "++" <ast-preop> ]]
+                     | "--" Postfix:p                   => [[ drop p "--" <ast-preop> ]]
+                     | "!" Postfix:p                    => [[ drop p "!" <ast-unop> ]]
+                     | Postfix
+Postfix            =   PrimExpr:p SpacesNoNl "++"       => [[ drop p "++" <ast-postop> ]]
+                     | PrimExpr:p SpacesNoNl "--"       => [[ drop p "--" <ast-postop> ]]
+                     | PrimExpr
+Args               =   Expr ("," Expr)*                      => [[ first2 swap prefix ]]
+PrimExpr           =   PrimExpr:p "[" Expr:i "]"             => [[ drop i p <ast-getp> ]]
+                     | PrimExpr:p "." Name:m "(" Args:as ")" => [[ drop m p as <ast-send> ]]
+                     | PrimExpr:p "." Name:f                 => [[ drop f p <ast-getp> ]]
+                     | PrimExpr:p "(" Args:as ")"            => [[ drop p as <ast-call> ]]
+                     | PrimExprHd
+PrimExprHd         =   "(" Expr:e ")"                        => [[ drop e ]]
+                     | "this"                                => [[ drop <ast-this> ]]
+                     | Name                                  => [[ <ast-get> ]]
+                     | Number                                => [[ <ast-number> ]]
+                     | Str                                   => [[ <ast-string> ]]
+                     | "function" FuncRest:fr                => [[ drop fr ]]
+                     | "new" Name:n "(" Args:as ")"          => [[ drop n as <ast-new> ]]
+                     | "[" Args:es "]"                       => [[ drop es <ast-array> ]]
+                     | Json
+JsonBindings        = JsonBinding ("," JsonBinding)*          => [[ first2 swap prefix ]]
+Json               = "{" JsonBindings:bs "}"                  => [[ drop bs <ast-json> ]]
+JsonBinding        = JsonPropName:n ":" Expr:v               => [[ drop n v <ast-binding> ]]
+JsonPropName       = Name | Number | Str
+Formal             = Spaces Name
+Formals            = Formal ("," Formal)*                    => [[ first2 swap prefix ]]
+FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ drop fs body <ast-func> ]]
+Sc                 = SpacesNoNl ("\n" | "}")| ";"
+Binding            =   Name:n "=" Expr:v                      => [[ drop n v <ast-var> ]]
+                     | Name:n                                 => [[ drop n "undefined" <ast-get> <ast-var> ]]
+Block              = "{" SrcElems:ss "}"                      => [[ drop ss ]]
+Bindings           = Binding ("," Binding)*                   => [[ first2 swap prefix ]]
+For1               =   "var" Binding => [[ second ]] 
+                     | Expr 
+                     | Spaces => [[ "undefined" <ast-get> ]] 
+For2               =   Expr
+                     | Spaces => [[ "true" <ast-get> ]] 
+For3               =   Expr
+                     | Spaces => [[ "undefined" <ast-get> ]] 
+ForIn1             =   "var" Name:n => [[ drop n "undefined" <ast-get> <ast-var> ]]
+                     | Expr
+Switch1            =   "case" Expr:c ":" SrcElems:cs => [[ drop c cs <ast-case> ]]
+                     | "default" ":" SrcElems:cs => [[ drop cs <ast-default> ]]  
+SwitchBody         = (Switch1)*
+Finally            =   "finally" Block:b => [[ drop b ]]
+                     | Spaces => [[ drop "undefined" <ast-get> ]]
+Stmt               =   Block                     
+                     | "var" Bindings:bs Sc                   => [[ drop bs <ast-begin> ]]
+                     | "if" "(" Expr:c ")" Stmt:t "else" Stmt:f => [[ drop c t f <ast-if> ]]
+                     | "if" "(" Expr:c ")" Stmt:t               => [[ drop c t "undefined" <ast-get> <ast-if> ]]
+                     | "while" "(" Expr:c ")" Stmt:s            => [[ drop c s <ast-while> ]]
+                     | "do" Stmt:s "while" "(" Expr:c ")" Sc    => [[ drop s c <ast-do-while> ]]
+                     | "for" "(" For1:i ";" For2:c ";" For3:u ")" Stmt:s => [[ drop i c u s <ast-for> ]]
+                     | "for" "(" ForIn1:v "in" Expr:e ")" Stmt:s => [[ drop v e s <ast-for-in> ]]
+                     | "switch" "(" Expr:e ")" "{" SwitchBody:cs "}" => [[ drop e cs <ast-switch> ]]
+                     | "break" Sc                                    => [[ drop <ast-break> ]]
+                     | "continue" Sc                                 => [[ drop <ast-continue> ]]
+                     | "throw" SpacesNoNl Expr:e Sc                  => [[ drop e <ast-throw> ]]
+                     | "try" Block:t "catch" "(" Name:e ")" Block:c Finally:f => [[ drop t e c f <ast-try> ]]
+                     | "return" Expr:e Sc                            => [[ drop e <ast-return> ]]
+                     | "return" Sc                                   => [[ drop "undefined" <ast-get> <ast-return> ]]
+                     | Expr:e Sc                                     => [[ drop e ]]
+                     | ";"                                           => [[ drop "undefined" <ast-get> ]]
+SrcElem            =   "function" Name:n FuncRest:f                  => [[ drop n f <ast-var> ]]
+                     | Stmt
+SrcElems           = (SrcElem)*                                      => [[ <ast-begin> ]]
+TopLevel           = SrcElems Spaces                               
+;EBNF
\ No newline at end of file

From 79dfe2806a873b9bef9f405bb8f222eab4b86f50 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Tue, 17 Jun 2008 22:07:57 +1200
Subject: [PATCH 09/85] Remove javascript boa constructors

---
 extra/peg/javascript/javascript.factor | 190 ++++++++++---------------
 1 file changed, 77 insertions(+), 113 deletions(-)

diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index 33fd6dd069..5c76c45f4c 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -45,42 +45,6 @@ TUPLE: ast-try t e c f ;
 TUPLE: ast-return e ;
 TUPLE: ast-case c cs ;
 TUPLE: ast-default cs ;
-C: <ast-name> ast-name
-C: <ast-keyword> ast-keyword
-C: <ast-number> ast-number
-C: <ast-string> ast-string
-C: <ast-cond-expr> ast-cond-expr
-C: <ast-set> ast-set
-C: <ast-get> ast-get
-C: <ast-mset> ast-mset
-C: <ast-binop> ast-binop
-C: <ast-unop> ast-unop
-C: <ast-preop> ast-preop
-C: <ast-postop> ast-postop
-C: <ast-getp> ast-getp
-C: <ast-send> ast-send
-C: <ast-call> ast-call
-C: <ast-this> ast-this
-C: <ast-new> ast-new
-C: <ast-array> ast-array
-C: <ast-json> ast-json
-C: <ast-binding> ast-binding
-C: <ast-func> ast-func
-C: <ast-var> ast-var
-C: <ast-begin> ast-begin
-C: <ast-if> ast-if
-C: <ast-while> ast-while
-C: <ast-do-while> ast-do-while
-C: <ast-for> ast-for
-C: <ast-for-in> ast-for-in
-C: <ast-switch> ast-switch
-C: <ast-break> ast-break
-C: <ast-continue> ast-continue
-C: <ast-throw> ast-throw
-C: <ast-try> ast-try
-C: <ast-return> ast-return
-C: <ast-case> ast-case
-C: <ast-default> ast-default
 
 EBNF: javascript
 Letter            = [a-zA-Z]
@@ -117,10 +81,10 @@ Keyword           =  ("break"
                     | "var"
                     | "void"
                     | "while"
-                    | "with") => [[ <ast-keyword> ]]
-Name              = !(Keyword) (iName):n => [[ drop n <ast-name> ]]
-Number            =   Digits:ws '.' Digits:fs => [[ drop ws "." fs 3array concat >string string>number <ast-number> ]]
-                    | Digits => [[ >string string>number <ast-number> ]]  
+                    | "with") => [[ ast-keyword boa ]]
+Name              = !(Keyword) (iName):n => [[ drop n ast-name boa ]]
+Number            =   Digits:ws '.' Digits:fs => [[ drop ws "." fs 3array concat >string string>number ast-number boa ]]
+                    | Digits => [[ >string string>number ast-number boa ]]  
 
 EscapeChar        =   "\\n" => [[ drop 10 ]] 
                     | "\\r" => [[ drop 13 ]]
@@ -128,9 +92,9 @@ EscapeChar        =   "\\n" => [[ drop 10 ]]
 StringChars1       = (EscapeChar | !('"""') .)* => [[ >string ]]
 StringChars2       = (EscapeChar | !('"') .)* => [[ >string ]]
 StringChars3       = (EscapeChar | !("'") .)* => [[ >string ]]
-Str                =   '"""' StringChars1:cs '"""' => [[ drop cs <ast-string> ]]
-                     | '"' StringChars2:cs '"' => [[ drop cs <ast-string> ]]
-                     | "'" StringChars3:cs "'" => [[ drop cs <ast-string> ]]
+Str                =   '"""' StringChars1:cs '"""' => [[ drop cs ast-string boa ]]
+                     | '"' StringChars2:cs '"' => [[ drop cs ast-string boa ]]
+                     | "'" StringChars3:cs "'" => [[ drop cs ast-string boa ]]
 Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | ";"
                      | "?"   | ":"   | "!==" | "~="  | "===" | "=="  | "="   | ">="
                      | ">"   | "<="  | "<"   | "++"  | "+="  | "+"   | "--"  | "-="
@@ -140,108 +104,108 @@ Tok                = Spaces (Name | Keyword | Number | Str | Special )
 Toks               = (Tok)* Spaces 
 SpacesNoNl         = (!("\n") Space)* => [[ drop ignore ]]
 
-Expr               =   OrExpr:e "?" Expr:t ":" Expr:f   => [[ drop e t f <ast-cond-expr> ]]
-                     | OrExpr:e "=" Expr:rhs            => [[ drop e rhs <ast-set> ]]
-                     | OrExpr:e "+=" Expr:rhs           => [[ drop e rhs "+" <ast-mset> ]]
-                     | OrExpr:e "-=" Expr:rhs           => [[ drop e rhs "-" <ast-mset> ]]
-                     | OrExpr:e "*=" Expr:rhs           => [[ drop e rhs "*" <ast-mset> ]]
-                     | OrExpr:e "/=" Expr:rhs           => [[ drop e rhs "/" <ast-mset> ]]
-                     | OrExpr:e "%=" Expr:rhs           => [[ drop e rhs "%" <ast-mset> ]]
-                     | OrExpr:e "&&=" Expr:rhs          => [[ drop e rhs "&&" <ast-mset> ]]
-                     | OrExpr:e "||=" Expr:rhs          => [[ drop e rhs "||" <ast-mset> ]]
+Expr               =   OrExpr:e "?" Expr:t ":" Expr:f   => [[ drop e t f ast-cond-expr boa ]]
+                     | OrExpr:e "=" Expr:rhs            => [[ drop e rhs ast-set boa ]]
+                     | OrExpr:e "+=" Expr:rhs           => [[ drop e rhs "+" ast-mset boa ]]
+                     | OrExpr:e "-=" Expr:rhs           => [[ drop e rhs "-" ast-mset boa ]]
+                     | OrExpr:e "*=" Expr:rhs           => [[ drop e rhs "*" ast-mset boa ]]
+                     | OrExpr:e "/=" Expr:rhs           => [[ drop e rhs "/" ast-mset boa ]]
+                     | OrExpr:e "%=" Expr:rhs           => [[ drop e rhs "%" ast-mset boa ]]
+                     | OrExpr:e "&&=" Expr:rhs          => [[ drop e rhs "&&" ast-mset boa ]]
+                     | OrExpr:e "||=" Expr:rhs          => [[ drop e rhs "||" ast-mset boa ]]
                      | OrExpr:e                         => [[ drop e ]]
 
-OrExpr             =   OrExpr:x "||" AndExpr:y          => [[ drop x y "||" <ast-binop> ]]
+OrExpr             =   OrExpr:x "||" AndExpr:y          => [[ drop x y "||" ast-binop boa ]]
                      | AndExpr
-AndExpr            =   AndExpr:x "&&" EqExpr:y          => [[ drop x y "&&" <ast-binop> ]]
+AndExpr            =   AndExpr:x "&&" EqExpr:y          => [[ drop x y "&&" ast-binop boa ]]
                      | EqExpr
-EqExpr             =   EqExpr:x "==" RelExpr:y          => [[ drop x y "==" <ast-binop> ]]
-                     | EqExpr:x "!=" RelExpr:y          => [[ drop x y "!=" <ast-binop> ]]
-                     | EqExpr:x "===" RelExpr:y         => [[ drop x y "===" <ast-binop> ]]
-                     | EqExpr:x "!==" RelExpr:y         => [[ drop x y "!==" <ast-binop> ]]
+EqExpr             =   EqExpr:x "==" RelExpr:y          => [[ drop x y "==" ast-binop boa ]]
+                     | EqExpr:x "!=" RelExpr:y          => [[ drop x y "!=" ast-binop boa ]]
+                     | EqExpr:x "===" RelExpr:y         => [[ drop x y "===" ast-binop boa ]]
+                     | EqExpr:x "!==" RelExpr:y         => [[ drop x y "!==" ast-binop boa ]]
                      | RelExpr
-RelExpr            =   RelExpr:x ">" AddExpr:y          => [[ drop x y ">" <ast-binop> ]]
-                     | RelExpr:x ">=" AddExpr:y         => [[ drop x y ">=" <ast-binop> ]]
-                     | RelExpr:x "<" AddExpr:y          => [[ drop x y "<" <ast-binop> ]]
-                     | RelExpr:x "<=" AddExpr:y         => [[ drop x y "<=" <ast-binop> ]]
-                     | RelExpr:x "instanceof" AddExpr:y => [[ drop x y "instanceof" <ast-binop> ]]
+RelExpr            =   RelExpr:x ">" AddExpr:y          => [[ drop x y ">" ast-binop boa ]]
+                     | RelExpr:x ">=" AddExpr:y         => [[ drop x y ">=" ast-binop boa ]]
+                     | RelExpr:x "<" AddExpr:y          => [[ drop x y "<" ast-binop boa ]]
+                     | RelExpr:x "<=" AddExpr:y         => [[ drop x y "<=" ast-binop boa ]]
+                     | RelExpr:x "instanceof" AddExpr:y => [[ drop x y "instanceof" ast-binop boa ]]
                      | AddExpr
-AddExpr            =   AddExpr:x "+" MulExpr:y          => [[ drop x y "+" <ast-binop> ]]
-                     | AddExpr:x "-" MulExpr:y          => [[ drop x y "-" <ast-binop> ]]
+AddExpr            =   AddExpr:x "+" MulExpr:y          => [[ drop x y "+" ast-binop boa ]]
+                     | AddExpr:x "-" MulExpr:y          => [[ drop x y "-" ast-binop boa ]]
                      | MulExpr
-MulExpr            =   MulExpr:x "*" MulExpr:y          => [[ drop x y "*" <ast-binop> ]]
-                     | MulExpr:x "/" MulExpr:y          => [[ drop x y "/" <ast-binop> ]]
-                     | MulExpr:x "%" MulExpr:y          => [[ drop x y "%" <ast-binop> ]]
+MulExpr            =   MulExpr:x "*" MulExpr:y          => [[ drop x y "*" ast-binop boa ]]
+                     | MulExpr:x "/" MulExpr:y          => [[ drop x y "/" ast-binop boa ]]
+                     | MulExpr:x "%" MulExpr:y          => [[ drop x y "%" ast-binop boa ]]
                      | Unary
-Unary              =   "-" Postfix:p                    => [[ drop p "-" <ast-unop> ]]
+Unary              =   "-" Postfix:p                    => [[ drop p "-" ast-unop boa ]]
                      | "+" Postfix:p                    => [[ drop p ]]
-                     | "++" Postfix:p                   => [[ drop p "++" <ast-preop> ]]
-                     | "--" Postfix:p                   => [[ drop p "--" <ast-preop> ]]
-                     | "!" Postfix:p                    => [[ drop p "!" <ast-unop> ]]
+                     | "++" Postfix:p                   => [[ drop p "++" ast-preop boa ]]
+                     | "--" Postfix:p                   => [[ drop p "--" ast-preop boa ]]
+                     | "!" Postfix:p                    => [[ drop p "!" ast-unop boa ]]
                      | Postfix
-Postfix            =   PrimExpr:p SpacesNoNl "++"       => [[ drop p "++" <ast-postop> ]]
-                     | PrimExpr:p SpacesNoNl "--"       => [[ drop p "--" <ast-postop> ]]
+Postfix            =   PrimExpr:p SpacesNoNl "++"       => [[ drop p "++" ast-postop boa ]]
+                     | PrimExpr:p SpacesNoNl "--"       => [[ drop p "--" ast-postop boa ]]
                      | PrimExpr
 Args               =   Expr ("," Expr)*                      => [[ first2 swap prefix ]]
-PrimExpr           =   PrimExpr:p "[" Expr:i "]"             => [[ drop i p <ast-getp> ]]
-                     | PrimExpr:p "." Name:m "(" Args:as ")" => [[ drop m p as <ast-send> ]]
-                     | PrimExpr:p "." Name:f                 => [[ drop f p <ast-getp> ]]
-                     | PrimExpr:p "(" Args:as ")"            => [[ drop p as <ast-call> ]]
+PrimExpr           =   PrimExpr:p "[" Expr:i "]"             => [[ drop i p ast-getp boa ]]
+                     | PrimExpr:p "." Name:m "(" Args:as ")" => [[ drop m p as ast-send boa ]]
+                     | PrimExpr:p "." Name:f                 => [[ drop f p ast-getp boa ]]
+                     | PrimExpr:p "(" Args:as ")"            => [[ drop p as ast-call boa ]]
                      | PrimExprHd
 PrimExprHd         =   "(" Expr:e ")"                        => [[ drop e ]]
-                     | "this"                                => [[ drop <ast-this> ]]
-                     | Name                                  => [[ <ast-get> ]]
-                     | Number                                => [[ <ast-number> ]]
-                     | Str                                   => [[ <ast-string> ]]
+                     | "this"                                => [[ drop ast-this boa ]]
+                     | Name                                  => [[ ast-get boa ]]
+                     | Number                                => [[ ast-number boa ]]
+                     | Str                                   => [[ ast-string boa ]]
                      | "function" FuncRest:fr                => [[ drop fr ]]
-                     | "new" Name:n "(" Args:as ")"          => [[ drop n as <ast-new> ]]
-                     | "[" Args:es "]"                       => [[ drop es <ast-array> ]]
+                     | "new" Name:n "(" Args:as ")"          => [[ drop n as ast-new boa ]]
+                     | "[" Args:es "]"                       => [[ drop es ast-array boa ]]
                      | Json
 JsonBindings        = JsonBinding ("," JsonBinding)*          => [[ first2 swap prefix ]]
-Json               = "{" JsonBindings:bs "}"                  => [[ drop bs <ast-json> ]]
-JsonBinding        = JsonPropName:n ":" Expr:v               => [[ drop n v <ast-binding> ]]
+Json               = "{" JsonBindings:bs "}"                  => [[ drop bs ast-json boa ]]
+JsonBinding        = JsonPropName:n ":" Expr:v               => [[ drop n v ast-binding boa ]]
 JsonPropName       = Name | Number | Str
 Formal             = Spaces Name
 Formals            = Formal ("," Formal)*                    => [[ first2 swap prefix ]]
-FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ drop fs body <ast-func> ]]
+FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ drop fs body ast-func boa ]]
 Sc                 = SpacesNoNl ("\n" | "}")| ";"
-Binding            =   Name:n "=" Expr:v                      => [[ drop n v <ast-var> ]]
-                     | Name:n                                 => [[ drop n "undefined" <ast-get> <ast-var> ]]
+Binding            =   Name:n "=" Expr:v                      => [[ drop n v ast-var boa ]]
+                     | Name:n                                 => [[ drop n "undefined" ast-get boa ast-var boa ]]
 Block              = "{" SrcElems:ss "}"                      => [[ drop ss ]]
 Bindings           = Binding ("," Binding)*                   => [[ first2 swap prefix ]]
 For1               =   "var" Binding => [[ second ]] 
                      | Expr 
-                     | Spaces => [[ "undefined" <ast-get> ]] 
+                     | Spaces => [[ "undefined" ast-get boa ]] 
 For2               =   Expr
-                     | Spaces => [[ "true" <ast-get> ]] 
+                     | Spaces => [[ "true" ast-get boa ]] 
 For3               =   Expr
-                     | Spaces => [[ "undefined" <ast-get> ]] 
-ForIn1             =   "var" Name:n => [[ drop n "undefined" <ast-get> <ast-var> ]]
+                     | Spaces => [[ "undefined" ast-get boa ]] 
+ForIn1             =   "var" Name:n => [[ drop n "undefined" ast-get boa ast-var boa ]]
                      | Expr
-Switch1            =   "case" Expr:c ":" SrcElems:cs => [[ drop c cs <ast-case> ]]
-                     | "default" ":" SrcElems:cs => [[ drop cs <ast-default> ]]  
+Switch1            =   "case" Expr:c ":" SrcElems:cs => [[ drop c cs ast-case boa ]]
+                     | "default" ":" SrcElems:cs => [[ drop cs ast-default boa ]]  
 SwitchBody         = (Switch1)*
 Finally            =   "finally" Block:b => [[ drop b ]]
-                     | Spaces => [[ drop "undefined" <ast-get> ]]
+                     | Spaces => [[ drop "undefined" ast-get boa ]]
 Stmt               =   Block                     
-                     | "var" Bindings:bs Sc                   => [[ drop bs <ast-begin> ]]
-                     | "if" "(" Expr:c ")" Stmt:t "else" Stmt:f => [[ drop c t f <ast-if> ]]
-                     | "if" "(" Expr:c ")" Stmt:t               => [[ drop c t "undefined" <ast-get> <ast-if> ]]
-                     | "while" "(" Expr:c ")" Stmt:s            => [[ drop c s <ast-while> ]]
-                     | "do" Stmt:s "while" "(" Expr:c ")" Sc    => [[ drop s c <ast-do-while> ]]
-                     | "for" "(" For1:i ";" For2:c ";" For3:u ")" Stmt:s => [[ drop i c u s <ast-for> ]]
-                     | "for" "(" ForIn1:v "in" Expr:e ")" Stmt:s => [[ drop v e s <ast-for-in> ]]
-                     | "switch" "(" Expr:e ")" "{" SwitchBody:cs "}" => [[ drop e cs <ast-switch> ]]
-                     | "break" Sc                                    => [[ drop <ast-break> ]]
-                     | "continue" Sc                                 => [[ drop <ast-continue> ]]
-                     | "throw" SpacesNoNl Expr:e Sc                  => [[ drop e <ast-throw> ]]
-                     | "try" Block:t "catch" "(" Name:e ")" Block:c Finally:f => [[ drop t e c f <ast-try> ]]
-                     | "return" Expr:e Sc                            => [[ drop e <ast-return> ]]
-                     | "return" Sc                                   => [[ drop "undefined" <ast-get> <ast-return> ]]
+                     | "var" Bindings:bs Sc                   => [[ drop bs ast-begin boa ]]
+                     | "if" "(" Expr:c ")" Stmt:t "else" Stmt:f => [[ drop c t f ast-if boa ]]
+                     | "if" "(" Expr:c ")" Stmt:t               => [[ drop c t "undefined" ast-get boa ast-if boa ]]
+                     | "while" "(" Expr:c ")" Stmt:s            => [[ drop c s ast-while boa ]]
+                     | "do" Stmt:s "while" "(" Expr:c ")" Sc    => [[ drop s c ast-do-while boa ]]
+                     | "for" "(" For1:i ";" For2:c ";" For3:u ")" Stmt:s => [[ drop i c u s ast-for boa ]]
+                     | "for" "(" ForIn1:v "in" Expr:e ")" Stmt:s => [[ drop v e s ast-for-in boa ]]
+                     | "switch" "(" Expr:e ")" "{" SwitchBody:cs "}" => [[ drop e cs ast-switch boa ]]
+                     | "break" Sc                                    => [[ drop ast-break boa ]]
+                     | "continue" Sc                                 => [[ drop ast-continue boa ]]
+                     | "throw" SpacesNoNl Expr:e Sc                  => [[ drop e ast-throw boa ]]
+                     | "try" Block:t "catch" "(" Name:e ")" Block:c Finally:f => [[ drop t e c f ast-try boa ]]
+                     | "return" Expr:e Sc                            => [[ drop e ast-return boa ]]
+                     | "return" Sc                                   => [[ drop "undefined" ast-get boa ast-return boa ]]
                      | Expr:e Sc                                     => [[ drop e ]]
-                     | ";"                                           => [[ drop "undefined" <ast-get> ]]
-SrcElem            =   "function" Name:n FuncRest:f                  => [[ drop n f <ast-var> ]]
+                     | ";"                                           => [[ drop "undefined" ast-get boa ]]
+SrcElem            =   "function" Name:n FuncRest:f                  => [[ drop n f ast-var boa ]]
                      | Stmt
-SrcElems           = (SrcElem)*                                      => [[ <ast-begin> ]]
+SrcElems           = (SrcElem)*                                      => [[ ast-begin boa ]]
 TopLevel           = SrcElems Spaces                               
 ;EBNF
\ No newline at end of file

From 55216a990dc5eaf37dee3345426454876994e70a Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Tue, 17 Jun 2008 22:47:05 +1200
Subject: [PATCH 10/85] Remove drop from actions

---
 extra/peg/javascript/javascript.factor | 164 ++++++++++++-------------
 1 file changed, 82 insertions(+), 82 deletions(-)

diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index 5c76c45f4c..54b9d8aa0a 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -50,10 +50,10 @@ EBNF: javascript
 Letter            = [a-zA-Z]
 Digit             = [0-9]
 Digits            = (Digit)+
-SingleLineComment = "//" (!("\n") .)* "\n" => [[ drop ignore ]]
-MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ drop ignore ]]
+SingleLineComment = "//" (!("\n") .)* "\n" => [[ ignore ]]
+MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ ignore ]]
 Space             = " " | "\t" | "\n" | SingleLineComment | MultiLineComment
-Spaces            = (Space)* => [[ drop ignore ]]
+Spaces            = (Space)* => [[ ignore ]]
 NameFirst         = Letter | "$" | "_"
 NameRest          = NameFirst | Digit
 iName             = NameFirst (NameRest)* => [[ first2 swap prefix >string ]]
@@ -82,19 +82,19 @@ Keyword           =  ("break"
                     | "void"
                     | "while"
                     | "with") => [[ ast-keyword boa ]]
-Name              = !(Keyword) (iName):n => [[ drop n ast-name boa ]]
-Number            =   Digits:ws '.' Digits:fs => [[ drop ws "." fs 3array concat >string string>number ast-number boa ]]
+Name              = !(Keyword) (iName):n => [[ n ast-name boa ]]
+Number            =   Digits:ws '.' Digits:fs => [[ ws "." fs 3array concat >string string>number ast-number boa ]]
                     | Digits => [[ >string string>number ast-number boa ]]  
 
-EscapeChar        =   "\\n" => [[ drop 10 ]] 
-                    | "\\r" => [[ drop 13 ]]
-                    | "\\t" => [[ drop 9 ]]
+EscapeChar        =   "\\n" => [[ 10 ]] 
+                    | "\\r" => [[ 13 ]]
+                    | "\\t" => [[ 9 ]]
 StringChars1       = (EscapeChar | !('"""') .)* => [[ >string ]]
 StringChars2       = (EscapeChar | !('"') .)* => [[ >string ]]
 StringChars3       = (EscapeChar | !("'") .)* => [[ >string ]]
-Str                =   '"""' StringChars1:cs '"""' => [[ drop cs ast-string boa ]]
-                     | '"' StringChars2:cs '"' => [[ drop cs ast-string boa ]]
-                     | "'" StringChars3:cs "'" => [[ drop cs ast-string boa ]]
+Str                =   '"""' StringChars1:cs '"""' => [[ cs ast-string boa ]]
+                     | '"' StringChars2:cs '"' => [[ cs ast-string boa ]]
+                     | "'" StringChars3:cs "'" => [[ cs ast-string boa ]]
 Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | ";"
                      | "?"   | ":"   | "!==" | "~="  | "===" | "=="  | "="   | ">="
                      | ">"   | "<="  | "<"   | "++"  | "+="  | "+"   | "--"  | "-="
@@ -102,76 +102,76 @@ Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | "
                      | "&&"  | "||=" | "||"  | "."   | "!"
 Tok                = Spaces (Name | Keyword | Number | Str | Special )
 Toks               = (Tok)* Spaces 
-SpacesNoNl         = (!("\n") Space)* => [[ drop ignore ]]
+SpacesNoNl         = (!("\n") Space)* => [[ ignore ]]
 
-Expr               =   OrExpr:e "?" Expr:t ":" Expr:f   => [[ drop e t f ast-cond-expr boa ]]
-                     | OrExpr:e "=" Expr:rhs            => [[ drop e rhs ast-set boa ]]
-                     | OrExpr:e "+=" Expr:rhs           => [[ drop e rhs "+" ast-mset boa ]]
-                     | OrExpr:e "-=" Expr:rhs           => [[ drop e rhs "-" ast-mset boa ]]
-                     | OrExpr:e "*=" Expr:rhs           => [[ drop e rhs "*" ast-mset boa ]]
-                     | OrExpr:e "/=" Expr:rhs           => [[ drop e rhs "/" ast-mset boa ]]
-                     | OrExpr:e "%=" Expr:rhs           => [[ drop e rhs "%" ast-mset boa ]]
-                     | OrExpr:e "&&=" Expr:rhs          => [[ drop e rhs "&&" ast-mset boa ]]
-                     | OrExpr:e "||=" Expr:rhs          => [[ drop e rhs "||" ast-mset boa ]]
-                     | OrExpr:e                         => [[ drop e ]]
+Expr               =   OrExpr:e "?" Expr:t ":" Expr:f   => [[ e t f ast-cond-expr boa ]]
+                     | OrExpr:e "=" Expr:rhs            => [[ e rhs ast-set boa ]]
+                     | OrExpr:e "+=" Expr:rhs           => [[ e rhs "+" ast-mset boa ]]
+                     | OrExpr:e "-=" Expr:rhs           => [[ e rhs "-" ast-mset boa ]]
+                     | OrExpr:e "*=" Expr:rhs           => [[ e rhs "*" ast-mset boa ]]
+                     | OrExpr:e "/=" Expr:rhs           => [[ e rhs "/" ast-mset boa ]]
+                     | OrExpr:e "%=" Expr:rhs           => [[ e rhs "%" ast-mset boa ]]
+                     | OrExpr:e "&&=" Expr:rhs          => [[ e rhs "&&" ast-mset boa ]]
+                     | OrExpr:e "||=" Expr:rhs          => [[ e rhs "||" ast-mset boa ]]
+                     | OrExpr:e                         => [[ e ]]
 
-OrExpr             =   OrExpr:x "||" AndExpr:y          => [[ drop x y "||" ast-binop boa ]]
+OrExpr             =   OrExpr:x "||" AndExpr:y          => [[ x y "||" ast-binop boa ]]
                      | AndExpr
-AndExpr            =   AndExpr:x "&&" EqExpr:y          => [[ drop x y "&&" ast-binop boa ]]
+AndExpr            =   AndExpr:x "&&" EqExpr:y          => [[ x y "&&" ast-binop boa ]]
                      | EqExpr
-EqExpr             =   EqExpr:x "==" RelExpr:y          => [[ drop x y "==" ast-binop boa ]]
-                     | EqExpr:x "!=" RelExpr:y          => [[ drop x y "!=" ast-binop boa ]]
-                     | EqExpr:x "===" RelExpr:y         => [[ drop x y "===" ast-binop boa ]]
-                     | EqExpr:x "!==" RelExpr:y         => [[ drop x y "!==" ast-binop boa ]]
+EqExpr             =   EqExpr:x "==" RelExpr:y          => [[ x y "==" ast-binop boa ]]
+                     | EqExpr:x "!=" RelExpr:y          => [[ x y "!=" ast-binop boa ]]
+                     | EqExpr:x "===" RelExpr:y         => [[ x y "===" ast-binop boa ]]
+                     | EqExpr:x "!==" RelExpr:y         => [[ x y "!==" ast-binop boa ]]
                      | RelExpr
-RelExpr            =   RelExpr:x ">" AddExpr:y          => [[ drop x y ">" ast-binop boa ]]
-                     | RelExpr:x ">=" AddExpr:y         => [[ drop x y ">=" ast-binop boa ]]
-                     | RelExpr:x "<" AddExpr:y          => [[ drop x y "<" ast-binop boa ]]
-                     | RelExpr:x "<=" AddExpr:y         => [[ drop x y "<=" ast-binop boa ]]
-                     | RelExpr:x "instanceof" AddExpr:y => [[ drop x y "instanceof" ast-binop boa ]]
+RelExpr            =   RelExpr:x ">" AddExpr:y          => [[ x y ">" ast-binop boa ]]
+                     | RelExpr:x ">=" AddExpr:y         => [[ x y ">=" ast-binop boa ]]
+                     | RelExpr:x "<" AddExpr:y          => [[ x y "<" ast-binop boa ]]
+                     | RelExpr:x "<=" AddExpr:y         => [[ x y "<=" ast-binop boa ]]
+                     | RelExpr:x "instanceof" AddExpr:y => [[ x y "instanceof" ast-binop boa ]]
                      | AddExpr
-AddExpr            =   AddExpr:x "+" MulExpr:y          => [[ drop x y "+" ast-binop boa ]]
-                     | AddExpr:x "-" MulExpr:y          => [[ drop x y "-" ast-binop boa ]]
+AddExpr            =   AddExpr:x "+" MulExpr:y          => [[ x y "+" ast-binop boa ]]
+                     | AddExpr:x "-" MulExpr:y          => [[ x y "-" ast-binop boa ]]
                      | MulExpr
-MulExpr            =   MulExpr:x "*" MulExpr:y          => [[ drop x y "*" ast-binop boa ]]
-                     | MulExpr:x "/" MulExpr:y          => [[ drop x y "/" ast-binop boa ]]
-                     | MulExpr:x "%" MulExpr:y          => [[ drop x y "%" ast-binop boa ]]
+MulExpr            =   MulExpr:x "*" MulExpr:y          => [[ x y "*" ast-binop boa ]]
+                     | MulExpr:x "/" MulExpr:y          => [[ x y "/" ast-binop boa ]]
+                     | MulExpr:x "%" MulExpr:y          => [[ x y "%" ast-binop boa ]]
                      | Unary
-Unary              =   "-" Postfix:p                    => [[ drop p "-" ast-unop boa ]]
-                     | "+" Postfix:p                    => [[ drop p ]]
-                     | "++" Postfix:p                   => [[ drop p "++" ast-preop boa ]]
-                     | "--" Postfix:p                   => [[ drop p "--" ast-preop boa ]]
-                     | "!" Postfix:p                    => [[ drop p "!" ast-unop boa ]]
+Unary              =   "-" Postfix:p                    => [[ p "-" ast-unop boa ]]
+                     | "+" Postfix:p                    => [[ p ]]
+                     | "++" Postfix:p                   => [[ p "++" ast-preop boa ]]
+                     | "--" Postfix:p                   => [[ p "--" ast-preop boa ]]
+                     | "!" Postfix:p                    => [[ p "!" ast-unop boa ]]
                      | Postfix
-Postfix            =   PrimExpr:p SpacesNoNl "++"       => [[ drop p "++" ast-postop boa ]]
-                     | PrimExpr:p SpacesNoNl "--"       => [[ drop p "--" ast-postop boa ]]
+Postfix            =   PrimExpr:p SpacesNoNl "++"       => [[ p "++" ast-postop boa ]]
+                     | PrimExpr:p SpacesNoNl "--"       => [[ p "--" ast-postop boa ]]
                      | PrimExpr
 Args               =   Expr ("," Expr)*                      => [[ first2 swap prefix ]]
-PrimExpr           =   PrimExpr:p "[" Expr:i "]"             => [[ drop i p ast-getp boa ]]
-                     | PrimExpr:p "." Name:m "(" Args:as ")" => [[ drop m p as ast-send boa ]]
-                     | PrimExpr:p "." Name:f                 => [[ drop f p ast-getp boa ]]
-                     | PrimExpr:p "(" Args:as ")"            => [[ drop p as ast-call boa ]]
+PrimExpr           =   PrimExpr:p "[" Expr:i "]"             => [[ i p ast-getp boa ]]
+                     | PrimExpr:p "." Name:m "(" Args:as ")" => [[ m p as ast-send boa ]]
+                     | PrimExpr:p "." Name:f                 => [[ f p ast-getp boa ]]
+                     | PrimExpr:p "(" Args:as ")"            => [[ p as ast-call boa ]]
                      | PrimExprHd
-PrimExprHd         =   "(" Expr:e ")"                        => [[ drop e ]]
-                     | "this"                                => [[ drop ast-this boa ]]
+PrimExprHd         =   "(" Expr:e ")"                        => [[ e ]]
+                     | "this"                                => [[ ast-this boa ]]
                      | Name                                  => [[ ast-get boa ]]
                      | Number                                => [[ ast-number boa ]]
                      | Str                                   => [[ ast-string boa ]]
-                     | "function" FuncRest:fr                => [[ drop fr ]]
-                     | "new" Name:n "(" Args:as ")"          => [[ drop n as ast-new boa ]]
-                     | "[" Args:es "]"                       => [[ drop es ast-array boa ]]
+                     | "function" FuncRest:fr                => [[ fr ]]
+                     | "new" Name:n "(" Args:as ")"          => [[ n as ast-new boa ]]
+                     | "[" Args:es "]"                       => [[ es ast-array boa ]]
                      | Json
 JsonBindings        = JsonBinding ("," JsonBinding)*          => [[ first2 swap prefix ]]
-Json               = "{" JsonBindings:bs "}"                  => [[ drop bs ast-json boa ]]
-JsonBinding        = JsonPropName:n ":" Expr:v               => [[ drop n v ast-binding boa ]]
+Json               = "{" JsonBindings:bs "}"                  => [[ bs ast-json boa ]]
+JsonBinding        = JsonPropName:n ":" Expr:v               => [[ n v ast-binding boa ]]
 JsonPropName       = Name | Number | Str
 Formal             = Spaces Name
 Formals            = Formal ("," Formal)*                    => [[ first2 swap prefix ]]
-FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ drop fs body ast-func boa ]]
+FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ fs body ast-func boa ]]
 Sc                 = SpacesNoNl ("\n" | "}")| ";"
-Binding            =   Name:n "=" Expr:v                      => [[ drop n v ast-var boa ]]
-                     | Name:n                                 => [[ drop n "undefined" ast-get boa ast-var boa ]]
-Block              = "{" SrcElems:ss "}"                      => [[ drop ss ]]
+Binding            =   Name:n "=" Expr:v                      => [[ n v ast-var boa ]]
+                     | Name:n                                 => [[ n "undefined" ast-get boa ast-var boa ]]
+Block              = "{" SrcElems:ss "}"                      => [[ ss ]]
 Bindings           = Binding ("," Binding)*                   => [[ first2 swap prefix ]]
 For1               =   "var" Binding => [[ second ]] 
                      | Expr 
@@ -180,31 +180,31 @@ For2               =   Expr
                      | Spaces => [[ "true" ast-get boa ]] 
 For3               =   Expr
                      | Spaces => [[ "undefined" ast-get boa ]] 
-ForIn1             =   "var" Name:n => [[ drop n "undefined" ast-get boa ast-var boa ]]
+ForIn1             =   "var" Name:n => [[ n "undefined" ast-get boa ast-var boa ]]
                      | Expr
-Switch1            =   "case" Expr:c ":" SrcElems:cs => [[ drop c cs ast-case boa ]]
-                     | "default" ":" SrcElems:cs => [[ drop cs ast-default boa ]]  
+Switch1            =   "case" Expr:c ":" SrcElems:cs => [[ c cs ast-case boa ]]
+                     | "default" ":" SrcElems:cs => [[ cs ast-default boa ]]  
 SwitchBody         = (Switch1)*
-Finally            =   "finally" Block:b => [[ drop b ]]
-                     | Spaces => [[ drop "undefined" ast-get boa ]]
+Finally            =   "finally" Block:b => [[ b ]]
+                     | Spaces => [[ "undefined" ast-get boa ]]
 Stmt               =   Block                     
-                     | "var" Bindings:bs Sc                   => [[ drop bs ast-begin boa ]]
-                     | "if" "(" Expr:c ")" Stmt:t "else" Stmt:f => [[ drop c t f ast-if boa ]]
-                     | "if" "(" Expr:c ")" Stmt:t               => [[ drop c t "undefined" ast-get boa ast-if boa ]]
-                     | "while" "(" Expr:c ")" Stmt:s            => [[ drop c s ast-while boa ]]
-                     | "do" Stmt:s "while" "(" Expr:c ")" Sc    => [[ drop s c ast-do-while boa ]]
-                     | "for" "(" For1:i ";" For2:c ";" For3:u ")" Stmt:s => [[ drop i c u s ast-for boa ]]
-                     | "for" "(" ForIn1:v "in" Expr:e ")" Stmt:s => [[ drop v e s ast-for-in boa ]]
-                     | "switch" "(" Expr:e ")" "{" SwitchBody:cs "}" => [[ drop e cs ast-switch boa ]]
-                     | "break" Sc                                    => [[ drop ast-break boa ]]
-                     | "continue" Sc                                 => [[ drop ast-continue boa ]]
-                     | "throw" SpacesNoNl Expr:e Sc                  => [[ drop e ast-throw boa ]]
-                     | "try" Block:t "catch" "(" Name:e ")" Block:c Finally:f => [[ drop t e c f ast-try boa ]]
-                     | "return" Expr:e Sc                            => [[ drop e ast-return boa ]]
-                     | "return" Sc                                   => [[ drop "undefined" ast-get boa ast-return boa ]]
-                     | Expr:e Sc                                     => [[ drop e ]]
-                     | ";"                                           => [[ drop "undefined" ast-get boa ]]
-SrcElem            =   "function" Name:n FuncRest:f                  => [[ drop n f ast-var boa ]]
+                     | "var" Bindings:bs Sc                   => [[ bs ast-begin boa ]]
+                     | "if" "(" Expr:c ")" Stmt:t "else" Stmt:f => [[ c t f ast-if boa ]]
+                     | "if" "(" Expr:c ")" Stmt:t               => [[ c t "undefined" ast-get boa ast-if boa ]]
+                     | "while" "(" Expr:c ")" Stmt:s            => [[ c s ast-while boa ]]
+                     | "do" Stmt:s "while" "(" Expr:c ")" Sc    => [[ s c ast-do-while boa ]]
+                     | "for" "(" For1:i ";" For2:c ";" For3:u ")" Stmt:s => [[ i c u s ast-for boa ]]
+                     | "for" "(" ForIn1:v "in" Expr:e ")" Stmt:s => [[ v e s ast-for-in boa ]]
+                     | "switch" "(" Expr:e ")" "{" SwitchBody:cs "}" => [[ e cs ast-switch boa ]]
+                     | "break" Sc                                    => [[ ast-break boa ]]
+                     | "continue" Sc                                 => [[ ast-continue boa ]]
+                     | "throw" SpacesNoNl Expr:e Sc                  => [[ e ast-throw boa ]]
+                     | "try" Block:t "catch" "(" Name:e ")" Block:c Finally:f => [[ t e c f ast-try boa ]]
+                     | "return" Expr:e Sc                            => [[ e ast-return boa ]]
+                     | "return" Sc                                   => [[ "undefined" ast-get boa ast-return boa ]]
+                     | Expr:e Sc                                     => [[ e ]]
+                     | ";"                                           => [[ "undefined" ast-get boa ]]
+SrcElem            =   "function" Name:n FuncRest:f                  => [[ n f ast-var boa ]]
                      | Stmt
 SrcElems           = (SrcElem)*                                      => [[ ast-begin boa ]]
 TopLevel           = SrcElems Spaces                               

From 258951d954343a8e9289425ca9c1180ba285023c Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Tue, 17 Jun 2008 22:59:13 +1200
Subject: [PATCH 11/85] Split out javascript tokenizer

---
 extra/peg/javascript/javascript.factor | 58 ++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index 54b9d8aa0a..3db962420a 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -46,6 +46,64 @@ TUPLE: ast-return e ;
 TUPLE: ast-case c cs ;
 TUPLE: ast-default cs ;
 
+EBNF: tokenizer 
+Letter            = [a-zA-Z]
+Digit             = [0-9]
+Digits            = (Digit)+
+SingleLineComment = "//" (!("\n") .)* "\n" => [[ ignore ]]
+MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ ignore ]]
+Space             = " " | "\t" | "\n" | SingleLineComment | MultiLineComment
+Spaces            = (Space)* => [[ ignore ]]
+NameFirst         = Letter | "$" | "_"
+NameRest          = NameFirst | Digit
+iName             = NameFirst (NameRest)* => [[ first2 swap prefix >string ]]
+Keyword           =  ("break"
+                    | "case"
+                    | "catch"
+                    | "continue"
+                    | "default"
+                    | "delete"
+                    | "do"
+                    | "else"
+                    | "finally"
+                    | "for"
+                    | "function"
+                    | "if"
+                    | "in"
+                    | "instanceof"
+                    | "new"
+                    | "return"
+                    | "switch"
+                    | "this"
+                    | "throw"
+                    | "try"
+                    | "typeof"
+                    | "var"
+                    | "void"
+                    | "while"
+                    | "with") => [[ ast-keyword boa ]]
+Name              = !(Keyword) (iName):n => [[ n ast-name boa ]]
+Number            =   Digits:ws '.' Digits:fs => [[ ws "." fs 3array concat >string string>number ast-number boa ]]
+                    | Digits => [[ >string string>number ast-number boa ]]  
+
+EscapeChar        =   "\\n" => [[ 10 ]] 
+                    | "\\r" => [[ 13 ]]
+                    | "\\t" => [[ 9 ]]
+StringChars1       = (EscapeChar | !('"""') .)* => [[ >string ]]
+StringChars2       = (EscapeChar | !('"') .)* => [[ >string ]]
+StringChars3       = (EscapeChar | !("'") .)* => [[ >string ]]
+Str                =   '"""' StringChars1:cs '"""' => [[ cs ast-string boa ]]
+                     | '"' StringChars2:cs '"' => [[ cs ast-string boa ]]
+                     | "'" StringChars3:cs "'" => [[ cs ast-string boa ]]
+Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | ";"
+                     | "?"   | ":"   | "!==" | "~="  | "===" | "=="  | "="   | ">="
+                     | ">"   | "<="  | "<"   | "++"  | "+="  | "+"   | "--"  | "-="
+                     | "-"   | "*="  | "*"   | "/="  | "/"   | "%="  | "%"   | "&&="
+                     | "&&"  | "||=" | "||"  | "."   | "!"
+Tok                = Spaces (Name | Keyword | Number | Str | Special )
+Toks               = (Tok)* Spaces 
+;EBNF
+
 EBNF: javascript
 Letter            = [a-zA-Z]
 Digit             = [0-9]

From 4050ebcbde098f0b09a34a2123a12dbdc78d134c Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Tue, 17 Jun 2008 23:42:28 +1200
Subject: [PATCH 12/85] Javascript parser now works on token sequence

---
 extra/peg/ebnf/ebnf.factor             |  2 +-
 extra/peg/javascript/javascript.factor | 66 ++++----------------------
 2 files changed, 9 insertions(+), 59 deletions(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 215eabdd37..36b3742b64 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -410,7 +410,7 @@ M: ebnf-var (transform) ( ast -- parser )
   parser>> (transform) ;
 
 M: ebnf-terminal (transform) ( ast -- parser )
-  symbol>> token ;
+  symbol>> [ token ] keep [ = ] curry satisfy 2choice ;
 
 M: ebnf-foreign (transform) ( ast -- parser )
   dup word>> search
diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index 3db962420a..c9bef2f6d3 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -1,7 +1,7 @@
 ! Copyright (C) 2007 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel arrays strings math.parser sequences sequences.deep
-peg peg.ebnf peg.parsers memoize namespaces math ;
+peg peg.ebnf peg.parsers memoize namespaces math accessors ;
 IN: peg.javascript
 
 #! Grammar for JavaScript. Based on OMeta-JS example from:
@@ -81,7 +81,7 @@ Keyword           =  ("break"
                     | "var"
                     | "void"
                     | "while"
-                    | "with") => [[ ast-keyword boa ]]
+                    | "with") 
 Name              = !(Keyword) (iName):n => [[ n ast-name boa ]]
 Number            =   Digits:ws '.' Digits:fs => [[ ws "." fs 3array concat >string string>number ast-number boa ]]
                     | Digits => [[ >string string>number ast-number boa ]]  
@@ -105,61 +105,11 @@ Toks               = (Tok)* Spaces
 ;EBNF
 
 EBNF: javascript
-Letter            = [a-zA-Z]
-Digit             = [0-9]
-Digits            = (Digit)+
-SingleLineComment = "//" (!("\n") .)* "\n" => [[ ignore ]]
-MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ ignore ]]
-Space             = " " | "\t" | "\n" | SingleLineComment | MultiLineComment
+Space             = " " | "\t" | "\n" 
 Spaces            = (Space)* => [[ ignore ]]
-NameFirst         = Letter | "$" | "_"
-NameRest          = NameFirst | Digit
-iName             = NameFirst (NameRest)* => [[ first2 swap prefix >string ]]
-Keyword           =  ("break"
-                    | "case"
-                    | "catch"
-                    | "continue"
-                    | "default"
-                    | "delete"
-                    | "do"
-                    | "else"
-                    | "finally"
-                    | "for"
-                    | "function"
-                    | "if"
-                    | "in"
-                    | "instanceof"
-                    | "new"
-                    | "return"
-                    | "switch"
-                    | "this"
-                    | "throw"
-                    | "try"
-                    | "typeof"
-                    | "var"
-                    | "void"
-                    | "while"
-                    | "with") => [[ ast-keyword boa ]]
-Name              = !(Keyword) (iName):n => [[ n ast-name boa ]]
-Number            =   Digits:ws '.' Digits:fs => [[ ws "." fs 3array concat >string string>number ast-number boa ]]
-                    | Digits => [[ >string string>number ast-number boa ]]  
-
-EscapeChar        =   "\\n" => [[ 10 ]] 
-                    | "\\r" => [[ 13 ]]
-                    | "\\t" => [[ 9 ]]
-StringChars1       = (EscapeChar | !('"""') .)* => [[ >string ]]
-StringChars2       = (EscapeChar | !('"') .)* => [[ >string ]]
-StringChars3       = (EscapeChar | !("'") .)* => [[ >string ]]
-Str                =   '"""' StringChars1:cs '"""' => [[ cs ast-string boa ]]
-                     | '"' StringChars2:cs '"' => [[ cs ast-string boa ]]
-                     | "'" StringChars3:cs "'" => [[ cs ast-string boa ]]
-Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | ";"
-                     | "?"   | ":"   | "!==" | "~="  | "===" | "=="  | "="   | ">="
-                     | ">"   | "<="  | "<"   | "++"  | "+="  | "+"   | "--"  | "-="
-                     | "-"   | "*="  | "*"   | "/="  | "/"   | "%="  | "%"   | "&&="
-                     | "&&"  | "||=" | "||"  | "."   | "!"
-Tok                = Spaces (Name | Keyword | Number | Str | Special )
-Toks               = (Tok)* Spaces 
+Name               = . ?[ ast-name?   ]?   => [[ value>> ]] 
+Number             = . ?[ ast-number? ]?   => [[ value>> ]]
+String             = . ?[ ast-string? ]?   => [[ value>> ]]
 SpacesNoNl         = (!("\n") Space)* => [[ ignore ]]
 
 Expr               =   OrExpr:e "?" Expr:t ":" Expr:f   => [[ e t f ast-cond-expr boa ]]
@@ -214,7 +164,7 @@ PrimExprHd         =   "(" Expr:e ")"                        => [[ e ]]
                      | "this"                                => [[ ast-this boa ]]
                      | Name                                  => [[ ast-get boa ]]
                      | Number                                => [[ ast-number boa ]]
-                     | Str                                   => [[ ast-string boa ]]
+                     | String                                => [[ ast-string boa ]]
                      | "function" FuncRest:fr                => [[ fr ]]
                      | "new" Name:n "(" Args:as ")"          => [[ n as ast-new boa ]]
                      | "[" Args:es "]"                       => [[ es ast-array boa ]]
@@ -222,7 +172,7 @@ PrimExprHd         =   "(" Expr:e ")"                        => [[ e ]]
 JsonBindings        = JsonBinding ("," JsonBinding)*          => [[ first2 swap prefix ]]
 Json               = "{" JsonBindings:bs "}"                  => [[ bs ast-json boa ]]
 JsonBinding        = JsonPropName:n ":" Expr:v               => [[ n v ast-binding boa ]]
-JsonPropName       = Name | Number | Str
+JsonPropName       = Name | Number | String
 Formal             = Spaces Name
 Formals            = Formal ("," Formal)*                    => [[ first2 swap prefix ]]
 FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ fs body ast-func boa ]]

From e99ff9fa6b996ba1fcf6199cfe5979bcfe221757 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Tue, 17 Jun 2008 23:57:51 +1200
Subject: [PATCH 13/85] Fix list AST in javascript parser

---
 extra/peg/javascript/javascript.factor | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index c9bef2f6d3..c4d87e3ce5 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -154,7 +154,7 @@ Unary              =   "-" Postfix:p                    => [[ p "-" ast-unop boa
 Postfix            =   PrimExpr:p SpacesNoNl "++"       => [[ p "++" ast-postop boa ]]
                      | PrimExpr:p SpacesNoNl "--"       => [[ p "--" ast-postop boa ]]
                      | PrimExpr
-Args               =   Expr ("," Expr)*                      => [[ first2 swap prefix ]]
+Args               =   Expr ("," Expr => [[ second ]])*      => [[ first2 swap prefix ]]
 PrimExpr           =   PrimExpr:p "[" Expr:i "]"             => [[ i p ast-getp boa ]]
                      | PrimExpr:p "." Name:m "(" Args:as ")" => [[ m p as ast-send boa ]]
                      | PrimExpr:p "." Name:f                 => [[ f p ast-getp boa ]]
@@ -169,18 +169,18 @@ PrimExprHd         =   "(" Expr:e ")"                        => [[ e ]]
                      | "new" Name:n "(" Args:as ")"          => [[ n as ast-new boa ]]
                      | "[" Args:es "]"                       => [[ es ast-array boa ]]
                      | Json
-JsonBindings        = JsonBinding ("," JsonBinding)*          => [[ first2 swap prefix ]]
+JsonBindings        = JsonBinding ("," JsonBinding => [[ second ]])*  => [[ first2 swap prefix ]]
 Json               = "{" JsonBindings:bs "}"                  => [[ bs ast-json boa ]]
 JsonBinding        = JsonPropName:n ":" Expr:v               => [[ n v ast-binding boa ]]
 JsonPropName       = Name | Number | String
 Formal             = Spaces Name
-Formals            = Formal ("," Formal)*                    => [[ first2 swap prefix ]]
+Formals            = Formal ("," Formal => [[ second ]])*     => [[ first2 swap prefix ]]
 FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ fs body ast-func boa ]]
 Sc                 = SpacesNoNl ("\n" | "}")| ";"
 Binding            =   Name:n "=" Expr:v                      => [[ n v ast-var boa ]]
                      | Name:n                                 => [[ n "undefined" ast-get boa ast-var boa ]]
 Block              = "{" SrcElems:ss "}"                      => [[ ss ]]
-Bindings           = Binding ("," Binding)*                   => [[ first2 swap prefix ]]
+Bindings           = Binding ("," Binding => [[ second ]])*   => [[ first2 swap prefix ]]
 For1               =   "var" Binding => [[ second ]] 
                      | Expr 
                      | Spaces => [[ "undefined" ast-get boa ]] 

From 7694dfd68827394d5df1e61bcc0a3acba7db9e0c Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Wed, 18 Jun 2008 00:10:14 +1200
Subject: [PATCH 14/85] Allow zero arguments in javascript list handling

---
 extra/peg/javascript/javascript.factor | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index c4d87e3ce5..5368881377 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -154,7 +154,7 @@ Unary              =   "-" Postfix:p                    => [[ p "-" ast-unop boa
 Postfix            =   PrimExpr:p SpacesNoNl "++"       => [[ p "++" ast-postop boa ]]
                      | PrimExpr:p SpacesNoNl "--"       => [[ p "--" ast-postop boa ]]
                      | PrimExpr
-Args               =   Expr ("," Expr => [[ second ]])*      => [[ first2 swap prefix ]]
+Args               =   (Expr ("," Expr => [[ second ]])* => [[ first2 swap prefix ]])?
 PrimExpr           =   PrimExpr:p "[" Expr:i "]"             => [[ i p ast-getp boa ]]
                      | PrimExpr:p "." Name:m "(" Args:as ")" => [[ m p as ast-send boa ]]
                      | PrimExpr:p "." Name:f                 => [[ f p ast-getp boa ]]
@@ -169,18 +169,18 @@ PrimExprHd         =   "(" Expr:e ")"                        => [[ e ]]
                      | "new" Name:n "(" Args:as ")"          => [[ n as ast-new boa ]]
                      | "[" Args:es "]"                       => [[ es ast-array boa ]]
                      | Json
-JsonBindings        = JsonBinding ("," JsonBinding => [[ second ]])*  => [[ first2 swap prefix ]]
+JsonBindings        = (JsonBinding ("," JsonBinding => [[ second ]])* => [[ first2 swap prefix ]])?
 Json               = "{" JsonBindings:bs "}"                  => [[ bs ast-json boa ]]
 JsonBinding        = JsonPropName:n ":" Expr:v               => [[ n v ast-binding boa ]]
 JsonPropName       = Name | Number | String
 Formal             = Spaces Name
-Formals            = Formal ("," Formal => [[ second ]])*     => [[ first2 swap prefix ]]
+Formals            = (Formal ("," Formal => [[ second ]])*  => [[ first2 swap prefix ]])?
 FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ fs body ast-func boa ]]
 Sc                 = SpacesNoNl ("\n" | "}")| ";"
 Binding            =   Name:n "=" Expr:v                      => [[ n v ast-var boa ]]
                      | Name:n                                 => [[ n "undefined" ast-get boa ast-var boa ]]
 Block              = "{" SrcElems:ss "}"                      => [[ ss ]]
-Bindings           = Binding ("," Binding => [[ second ]])*   => [[ first2 swap prefix ]]
+Bindings           = (Binding ("," Binding => [[ second ]])* => [[ first2 swap prefix ]])?
 For1               =   "var" Binding => [[ second ]] 
                      | Expr 
                      | Spaces => [[ "undefined" ast-get boa ]] 

From 778573106c10aeddf03ed7384ea6270f3ea07123 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Wed, 18 Jun 2008 12:16:47 +1200
Subject: [PATCH 15/85] Fix Sc rule

---
 extra/peg/javascript/javascript.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index 5368881377..bdf5f4b369 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -176,7 +176,7 @@ JsonPropName       = Name | Number | String
 Formal             = Spaces Name
 Formals            = (Formal ("," Formal => [[ second ]])*  => [[ first2 swap prefix ]])?
 FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ fs body ast-func boa ]]
-Sc                 = SpacesNoNl ("\n" | "}")| ";"
+Sc                 = SpacesNoNl ("\n" | &("}"))| ";"
 Binding            =   Name:n "=" Expr:v                      => [[ n v ast-var boa ]]
                      | Name:n                                 => [[ n "undefined" ast-get boa ast-var boa ]]
 Block              = "{" SrcElems:ss "}"                      => [[ ss ]]

From a5719e33976ae6ebfc75ab81edd6d56dd0f0ee0a Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Wed, 18 Jun 2008 21:30:21 +1200
Subject: [PATCH 16/85] Add javascript tests. Minor changes to javascript
 grammar

---
 extra/peg/javascript/javascript-tests.factor | 42 ++++++++++++++++++++
 extra/peg/javascript/javascript.factor       | 16 ++++----
 2 files changed, 50 insertions(+), 8 deletions(-)
 create mode 100644 extra/peg/javascript/javascript-tests.factor

diff --git a/extra/peg/javascript/javascript-tests.factor b/extra/peg/javascript/javascript-tests.factor
new file mode 100644
index 0000000000..70410a3838
--- /dev/null
+++ b/extra/peg/javascript/javascript-tests.factor
@@ -0,0 +1,42 @@
+! Copyright (C) 2008 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+!
+USING: kernel tools.test peg peg.javascript accessors ;
+IN: peg.javascript.tests
+
+\ javascript must-infer
+
+{
+  V{
+    T{ ast-number f 123 }
+    ";"
+    T{ ast-string f "hello" }
+    ";"
+    T{ ast-name f "foo" }
+    "("
+    T{ ast-name f "x" }
+    ")"
+    ";"
+  }    
+} [
+  "123; 'hello'; foo(x);" tokenizer ast>>
+] unit-test
+
+{
+  T{
+      ast-begin
+      f
+      V{
+          T{ ast-number f 123 }
+          T{ ast-string f "hello" }
+          T{
+              ast-call
+              f
+              T{ ast-get f "foo" }
+              V{ T{ ast-get f "x" } }
+          }
+      }
+  }
+} [
+  "123; 'hello'; foo(x);" tokenizer ast>> javascript ast>>
+] unit-test
\ No newline at end of file
diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index bdf5f4b369..030d2f1728 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -1,4 +1,4 @@
-! Copyright (C) 2007 Chris Double.
+! Copyright (C) 2008 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel arrays strings math.parser sequences sequences.deep
 peg peg.ebnf peg.parsers memoize namespaces math accessors ;
@@ -49,14 +49,14 @@ TUPLE: ast-default cs ;
 EBNF: tokenizer 
 Letter            = [a-zA-Z]
 Digit             = [0-9]
-Digits            = (Digit)+
+Digits            = Digit+
 SingleLineComment = "//" (!("\n") .)* "\n" => [[ ignore ]]
 MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ ignore ]]
 Space             = " " | "\t" | "\n" | SingleLineComment | MultiLineComment
-Spaces            = (Space)* => [[ ignore ]]
+Spaces            = Space* => [[ ignore ]]
 NameFirst         = Letter | "$" | "_"
 NameRest          = NameFirst | Digit
-iName             = NameFirst (NameRest)* => [[ first2 swap prefix >string ]]
+iName             = NameFirst NameRest* => [[ first2 swap prefix >string ]]
 Keyword           =  ("break"
                     | "case"
                     | "catch"
@@ -101,12 +101,12 @@ Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | "
                      | "-"   | "*="  | "*"   | "/="  | "/"   | "%="  | "%"   | "&&="
                      | "&&"  | "||=" | "||"  | "."   | "!"
 Tok                = Spaces (Name | Keyword | Number | Str | Special )
-Toks               = (Tok)* Spaces 
+Toks               = Tok* Spaces 
 ;EBNF
 
 EBNF: javascript
 Space             = " " | "\t" | "\n" 
-Spaces            = (Space)* => [[ ignore ]]
+Spaces            = Space* => [[ ignore ]]
 Name               = . ?[ ast-name?   ]?   => [[ value>> ]] 
 Number             = . ?[ ast-number? ]?   => [[ value>> ]]
 String             = . ?[ ast-string? ]?   => [[ value>> ]]
@@ -192,7 +192,7 @@ ForIn1             =   "var" Name:n => [[ n "undefined" ast-get boa ast-var boa
                      | Expr
 Switch1            =   "case" Expr:c ":" SrcElems:cs => [[ c cs ast-case boa ]]
                      | "default" ":" SrcElems:cs => [[ cs ast-default boa ]]  
-SwitchBody         = (Switch1)*
+SwitchBody         = Switch1*
 Finally            =   "finally" Block:b => [[ b ]]
                      | Spaces => [[ "undefined" ast-get boa ]]
 Stmt               =   Block                     
@@ -214,6 +214,6 @@ Stmt               =   Block
                      | ";"                                           => [[ "undefined" ast-get boa ]]
 SrcElem            =   "function" Name:n FuncRest:f                  => [[ n f ast-var boa ]]
                      | Stmt
-SrcElems           = (SrcElem)*                                      => [[ ast-begin boa ]]
+SrcElems           = SrcElem*                                      => [[ ast-begin boa ]]
 TopLevel           = SrcElems Spaces                               
 ;EBNF
\ No newline at end of file

From 8f140402b3a6d94fc0e770b0c731e9ceb2f92c6c Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 18 Jun 2008 05:58:05 -0500
Subject: [PATCH 17/85] Move short to core

---
 core/sequences/sequences.factor | 2 ++
 extra/sequences/lib/lib.factor  | 3 ---
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/core/sequences/sequences.factor b/core/sequences/sequences.factor
index 02a7191f0a..2d05d3c2ef 100755
--- a/core/sequences/sequences.factor
+++ b/core/sequences/sequences.factor
@@ -206,6 +206,8 @@ M: slice virtual@ [ slice-from + ] [ slice-seq ] bi ;
 
 M: slice length dup slice-to swap slice-from - ;
 
+: short ( seq n -- seq n' ) over length min ; inline
+
 : head-slice ( seq n -- slice ) (head) <slice> ;
 
 : tail-slice ( seq n -- slice ) (tail) <slice> ;
diff --git a/extra/sequences/lib/lib.factor b/extra/sequences/lib/lib.factor
index 56488818ab..3ac60c2ae3 100755
--- a/extra/sequences/lib/lib.factor
+++ b/extra/sequences/lib/lib.factor
@@ -234,9 +234,6 @@ PRIVATE>
 : remove-nth ( seq n -- seq' )
     cut-slice rest-slice append ;
 
-: short ( seq n -- seq n' )
-    over length min ; inline
-
 : if-seq ( seq quot1 quot2 -- )
     [ f like ] 2dip if* ; inline
 

From 03730f30387564b70686a85a800b25b4a089b6c3 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 18 Jun 2008 05:58:16 -0500
Subject: [PATCH 18/85] Fix see of M::

---
 extra/locals/locals-tests.factor | 13 ++++++++++++-
 extra/locals/locals.factor       |  4 ++--
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/extra/locals/locals-tests.factor b/extra/locals/locals-tests.factor
index 4e670cdac0..025e175bc2 100755
--- a/extra/locals/locals-tests.factor
+++ b/extra/locals/locals-tests.factor
@@ -1,6 +1,6 @@
 USING: locals math sequences tools.test hashtables words kernel
 namespaces arrays strings prettyprint io.streams.string parser
-accessors ;
+accessors generic ;
 IN: locals.tests
 
 :: foo ( a b -- a a ) a a ;
@@ -265,3 +265,14 @@ M:: fixnum next-method-test ( a -- b ) a call-next-method 1 + ;
     [ \ a-word-with-locals see ] with-string-writer
     new-definition =
 ] unit-test
+
+: method-definition "USING: locals locals.tests sequences ;\nM:: sequence method-with-locals ( a -- y ) a reverse ;\n" ;
+
+GENERIC: method-with-locals ( x -- y )
+
+M:: sequence method-with-locals ( a -- y ) a reverse ;
+
+[ t ] [
+    [ \ sequence \ method-with-locals method see ] with-string-writer
+    method-definition =
+] unit-test
diff --git a/extra/locals/locals.factor b/extra/locals/locals.factor
index 028502560f..cc6a7d093e 100755
--- a/extra/locals/locals.factor
+++ b/extra/locals/locals.factor
@@ -405,8 +405,8 @@ M: lambda-memoized reset-word
 
 M: lambda-method synopsis*
     dup dup dup definer.
-    "method-specializer" word-prop pprint*
-    "method-generic" word-prop pprint*
+    "method-class" word-prop pprint-word
+    "method-generic" word-prop pprint-word
     method-stack-effect effect>string comment. ;
 
 PRIVATE>

From 42f421d9884fabe528eac295aab83d532b2601fc Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 18 Jun 2008 05:58:26 -0500
Subject: [PATCH 19/85] Implement missing input stream protocol methods

---
 .../tools/interactor/interactor-tests.factor  | 46 ++++++++++++++++++-
 extra/ui/tools/interactor/interactor.factor   | 21 +++++++--
 2 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/extra/ui/tools/interactor/interactor-tests.factor b/extra/ui/tools/interactor/interactor-tests.factor
index f8d5e33df9..37f43faa8b 100755
--- a/extra/ui/tools/interactor/interactor-tests.factor
+++ b/extra/ui/tools/interactor/interactor-tests.factor
@@ -1,7 +1,7 @@
 IN: ui.tools.interactor.tests
 USING: ui.tools.interactor ui.gadgets.panes namespaces
 ui.gadgets.editors concurrency.promises threads listener
-tools.test kernel calendar parser accessors ;
+tools.test kernel calendar parser accessors calendar io ;
 
 \ <interactor> must-infer
 
@@ -41,3 +41,47 @@ tools.test kernel calendar parser accessors ;
 [ ] [ 1000 sleep ] unit-test
 
 [ ] [ "interactor" get interactor-eof ] unit-test
+
+[ ] [ <pane> <pane-stream> <interactor> "interactor" set ] unit-test
+
+: text "Hello world.\nThis is a test." ;
+
+[ ] [ text "interactor" get set-editor-string ] unit-test
+
+[ ] [ <promise> "promise" set ] unit-test
+
+[ ] [
+    [
+        "interactor" get register-self
+        "interactor" get contents "promise" get fulfill
+    ] in-thread
+] unit-test
+
+[ ] [ 100 sleep ] unit-test
+
+[ ] [ "interactor" get evaluate-input ] unit-test
+
+[ ] [ 100 sleep ] unit-test
+    
+[ ] [ "interactor" get interactor-eof ] unit-test
+
+[ t ] [ "promise" get 2 seconds ?promise-timeout text = ] unit-test
+
+[ ] [ <pane> <pane-stream> <interactor> "interactor" set ] unit-test
+
+[ ] [ text "interactor" get set-editor-string ] unit-test
+
+[ ] [ <promise> "promise" set ] unit-test
+
+[ ] [
+    [
+        "interactor" get register-self
+        "interactor" get stream-read1 "promise" get fulfill
+    ] in-thread
+] unit-test
+
+[ ] [ 100 sleep ] unit-test
+
+[ ] [ "interactor" get evaluate-input ] unit-test
+
+[ CHAR: H ] [ "promise" get 2 seconds ?promise-timeout ] unit-test
diff --git a/extra/ui/tools/interactor/interactor.factor b/extra/ui/tools/interactor/interactor.factor
index 400169908b..72bd4e43a3 100755
--- a/extra/ui/tools/interactor/interactor.factor
+++ b/extra/ui/tools/interactor/interactor.factor
@@ -6,7 +6,8 @@ models namespaces parser prettyprint quotations sequences
 strings threads listener classes.tuple ui.commands ui.gadgets
 ui.gadgets.editors ui.gadgets.presentations ui.gadgets.worlds
 ui.gestures definitions calendar concurrency.flags
-concurrency.mailboxes ui.tools.workspace accessors sets ;
+concurrency.mailboxes ui.tools.workspace accessors sets
+destructors ;
 IN: ui.tools.interactor
 
 ! If waiting is t, we're waiting for user input, and invoking
@@ -110,9 +111,11 @@ M: interactor model-changed
         } cleave
     ] [ drop f ] if ;
 
+: interactor-read ( interactor -- lines )
+    [ interactor-yield ] [ interactor-finish ] bi ;
+
 M: interactor stream-readln
-    [ interactor-yield ] [ interactor-finish ] bi
-    dup [ first ] when ;
+    interactor-read dup [ first ] when ;
 
 : interactor-call ( quot interactor -- )
     dup interactor-busy? [
@@ -124,12 +127,22 @@ M: interactor stream-read
     swap dup zero? [
         2drop ""
     ] [
-        >r stream-readln dup length r> min head
+        >r interactor-read dup [ "\n" join ] when r> short head
     ] if ;
 
 M: interactor stream-read-partial
     stream-read ;
 
+M: interactor stream-read1
+    dup interactor-read {
+        { [ dup not ] [ 2drop f ] }
+        { [ dup empty? ] [ drop stream-read1 ] }
+        { [ dup first empty? ] [ 2drop CHAR: \n ] }
+        [ nip first first ]
+    } cond ;
+
+M: interactor dispose drop ;
+
 : go-to-error ( interactor error -- )
     [ line>> 1- ] [ column>> ] bi 2array
     over set-caret

From fea65df1dfeb1f56bf40fb232aae99c430b2d731 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Wed, 18 Jun 2008 23:07:26 +1200
Subject: [PATCH 20/85] Fix ebnf foreign call breakage and add tests

---
 extra/peg/ebnf/ebnf-tests.factor | 36 +++++++++++++++++++++++++++++++-
 extra/peg/ebnf/ebnf.factor       |  6 +++---
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index 04cc01c9d0..73db626685 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 !
 USING: kernel tools.test peg peg.ebnf words math math.parser 
-       sequences accessors ;
+       sequences accessors peg.parsers ;
 IN: peg.ebnf.tests
 
 { T{ ebnf-non-terminal f "abc" } } [
@@ -397,4 +397,38 @@ main = Primary
 
 { t } [
   "number=digit+:n 'a'" 'ebnf' parse remaining>> length zero?
+] unit-test
+
+<<
+EBNF: parser1 
+foo='a' 
+;EBNF
+>>
+
+EBNF: parser2
+foo=<foreign parser1 foo> 'b'
+;EBNF
+
+EBNF: parser3
+foo=<foreign parser1> 'c'
+;EBNF
+
+EBNF: parser4
+foo=<foreign any-char> 'd'
+;EBNF
+
+{ "a" } [
+  "a" parser1 ast>>
+] unit-test
+
+{ V{ "a" "b" } } [
+  "ab" parser2 ast>>
+] unit-test
+
+{ V{ "a" "c" } } [
+  "ac" parser3 ast>>
+] unit-test
+
+{ V{ CHAR: a "d" } } [
+  "ad" parser4 ast>>
 ] unit-test
\ No newline at end of file
diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 36b3742b64..2ee0958051 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -415,11 +415,11 @@ M: ebnf-terminal (transform) ( ast -- parser )
 M: ebnf-foreign (transform) ( ast -- parser )
   dup word>> search
   [ "Foreign word " swap word>> append " not found" append throw ] unless*
-  swap rule>> dup [
-    swap rule  
+  swap rule>> [ main ] unless* dupd swap rule [
+    nip
   ] [
     execute
-  ] if ;
+  ] if* ;
 
 : parser-not-found ( name -- * )
   [

From ea6974d5dac52706a67666a50ecaf22c915280eb Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Wed, 18 Jun 2008 23:50:25 +1200
Subject: [PATCH 21/85] Add \r to whitespace in javascript tokenizer

---
 extra/peg/javascript/javascript.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index 030d2f1728..127b13130a 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -52,7 +52,7 @@ Digit             = [0-9]
 Digits            = Digit+
 SingleLineComment = "//" (!("\n") .)* "\n" => [[ ignore ]]
 MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ ignore ]]
-Space             = " " | "\t" | "\n" | SingleLineComment | MultiLineComment
+Space             = " " | "\t" | "\r" | "\n" | SingleLineComment | MultiLineComment
 Spaces            = Space* => [[ ignore ]]
 NameFirst         = Letter | "$" | "_"
 NameRest          = NameFirst | Digit

From 6f8e2a4b0ddf74ea0f7bd43aed53984faaceab9e Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 00:42:11 +1200
Subject: [PATCH 22/85] Refactor JavaScript parser

---
 extra/peg/javascript/ast/ast.factor           |  42 ++++
 extra/peg/javascript/ast/authors.txt          |   1 +
 extra/peg/javascript/ast/summary.txt          |   1 +
 extra/peg/javascript/ast/tags.txt             |   3 +
 extra/peg/javascript/authors.txt              |   1 +
 extra/peg/javascript/javascript-docs.factor   |  14 ++
 extra/peg/javascript/javascript-tests.factor  |  39 +--
 extra/peg/javascript/javascript.factor        | 225 +-----------------
 extra/peg/javascript/parser/authors.txt       |   1 +
 .../peg/javascript/parser/parser-tests.factor |  27 +++
 extra/peg/javascript/parser/parser.factor     | 121 ++++++++++
 extra/peg/javascript/parser/summary.txt       |   1 +
 extra/peg/javascript/parser/tags.txt          |   3 +
 extra/peg/javascript/summary.txt              |   1 +
 extra/peg/javascript/tags.txt                 |   3 +
 extra/peg/javascript/tokenizer/authors.txt    |   1 +
 extra/peg/javascript/tokenizer/summary.txt    |   1 +
 extra/peg/javascript/tokenizer/tags.txt       |   3 +
 .../tokenizer/tokenizer-tests.factor          |  23 ++
 .../peg/javascript/tokenizer/tokenizer.factor |  68 ++++++
 20 files changed, 330 insertions(+), 249 deletions(-)
 create mode 100644 extra/peg/javascript/ast/ast.factor
 create mode 100644 extra/peg/javascript/ast/authors.txt
 create mode 100644 extra/peg/javascript/ast/summary.txt
 create mode 100644 extra/peg/javascript/ast/tags.txt
 create mode 100644 extra/peg/javascript/authors.txt
 create mode 100644 extra/peg/javascript/javascript-docs.factor
 create mode 100644 extra/peg/javascript/parser/authors.txt
 create mode 100644 extra/peg/javascript/parser/parser-tests.factor
 create mode 100644 extra/peg/javascript/parser/parser.factor
 create mode 100644 extra/peg/javascript/parser/summary.txt
 create mode 100644 extra/peg/javascript/parser/tags.txt
 create mode 100644 extra/peg/javascript/summary.txt
 create mode 100644 extra/peg/javascript/tags.txt
 create mode 100644 extra/peg/javascript/tokenizer/authors.txt
 create mode 100644 extra/peg/javascript/tokenizer/summary.txt
 create mode 100644 extra/peg/javascript/tokenizer/tags.txt
 create mode 100644 extra/peg/javascript/tokenizer/tokenizer-tests.factor
 create mode 100644 extra/peg/javascript/tokenizer/tokenizer.factor

diff --git a/extra/peg/javascript/ast/ast.factor b/extra/peg/javascript/ast/ast.factor
new file mode 100644
index 0000000000..b857dc51bb
--- /dev/null
+++ b/extra/peg/javascript/ast/ast.factor
@@ -0,0 +1,42 @@
+! Copyright (C) 2008 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel ;
+IN: peg.javascript.ast
+
+TUPLE: ast-keyword value ;
+TUPLE: ast-name value ;
+TUPLE: ast-number value ;
+TUPLE: ast-string value ;
+TUPLE: ast-regexp value ;
+TUPLE: ast-cond-expr condition then else ;
+TUPLE: ast-set lhs rhs ;
+TUPLE: ast-get value ;
+TUPLE: ast-mset lhs rhs operator ;
+TUPLE: ast-binop lhs rhs operator ;
+TUPLE: ast-unop expr operator ;
+TUPLE: ast-postop expr operator ;
+TUPLE: ast-preop expr operator ;
+TUPLE: ast-getp index expr ;
+TUPLE: ast-send method expr args ;
+TUPLE: ast-call expr args ;
+TUPLE: ast-this ;
+TUPLE: ast-new name args ;
+TUPLE: ast-array values ;
+TUPLE: ast-json bindings ;
+TUPLE: ast-binding name value ;
+TUPLE: ast-func fs body ;
+TUPLE: ast-var name value ;
+TUPLE: ast-begin statements ;
+TUPLE: ast-if condition true false ;
+TUPLE: ast-while condition statements ;
+TUPLE: ast-do-while statements condition ;
+TUPLE: ast-for i c u statements ;
+TUPLE: ast-for-in v e statements ;
+TUPLE: ast-switch expr statements ;
+TUPLE: ast-break ;
+TUPLE: ast-continue ;
+TUPLE: ast-throw e ;
+TUPLE: ast-try t e c f ;
+TUPLE: ast-return e ;
+TUPLE: ast-case c cs ;
+TUPLE: ast-default cs ;
diff --git a/extra/peg/javascript/ast/authors.txt b/extra/peg/javascript/ast/authors.txt
new file mode 100644
index 0000000000..44b06f94bc
--- /dev/null
+++ b/extra/peg/javascript/ast/authors.txt
@@ -0,0 +1 @@
+Chris Double
diff --git a/extra/peg/javascript/ast/summary.txt b/extra/peg/javascript/ast/summary.txt
new file mode 100644
index 0000000000..543a2e6373
--- /dev/null
+++ b/extra/peg/javascript/ast/summary.txt
@@ -0,0 +1 @@
+Abstract Syntax Tree for JavaScript parser
diff --git a/extra/peg/javascript/ast/tags.txt b/extra/peg/javascript/ast/tags.txt
new file mode 100644
index 0000000000..c2aac2932f
--- /dev/null
+++ b/extra/peg/javascript/ast/tags.txt
@@ -0,0 +1,3 @@
+text
+javascript
+parsing
diff --git a/extra/peg/javascript/authors.txt b/extra/peg/javascript/authors.txt
new file mode 100644
index 0000000000..44b06f94bc
--- /dev/null
+++ b/extra/peg/javascript/authors.txt
@@ -0,0 +1 @@
+Chris Double
diff --git a/extra/peg/javascript/javascript-docs.factor b/extra/peg/javascript/javascript-docs.factor
new file mode 100644
index 0000000000..5fdc3e8587
--- /dev/null
+++ b/extra/peg/javascript/javascript-docs.factor
@@ -0,0 +1,14 @@
+! Copyright (C) 2007 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+USING: help.markup help.syntax ;
+IN: peg.javascript
+
+HELP: parse-javascript
+{ $values 
+  { "string" "a string" } 
+  { "ast" "a JavaScript abstract syntax tree" } 
+}
+{ $description 
+    "Parse the input string using the JavaScript parser. Throws an error if "
+    "the string does not contain valid JavaScript. Returns the abstract syntax tree "
+    "if successful." } ;
diff --git a/extra/peg/javascript/javascript-tests.factor b/extra/peg/javascript/javascript-tests.factor
index 70410a3838..0d6899714d 100644
--- a/extra/peg/javascript/javascript-tests.factor
+++ b/extra/peg/javascript/javascript-tests.factor
@@ -1,42 +1,11 @@
 ! Copyright (C) 2008 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
 !
-USING: kernel tools.test peg peg.javascript accessors ;
+USING: kernel tools.test peg.javascript peg.javascript.ast accessors ;
 IN: peg.javascript.tests
 
-\ javascript must-infer
+\ parse-javascript must-infer
 
-{
-  V{
-    T{ ast-number f 123 }
-    ";"
-    T{ ast-string f "hello" }
-    ";"
-    T{ ast-name f "foo" }
-    "("
-    T{ ast-name f "x" }
-    ")"
-    ";"
-  }    
-} [
-  "123; 'hello'; foo(x);" tokenizer ast>>
-] unit-test
-
-{
-  T{
-      ast-begin
-      f
-      V{
-          T{ ast-number f 123 }
-          T{ ast-string f "hello" }
-          T{
-              ast-call
-              f
-              T{ ast-get f "foo" }
-              V{ T{ ast-get f "x" } }
-          }
-      }
-  }
-} [
-  "123; 'hello'; foo(x);" tokenizer ast>> javascript ast>>
+{ T{ ast-begin f V{ T{ ast-number f 123 } } } } [
+  "123;" parse-javascript
 ] unit-test
\ No newline at end of file
diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index 127b13130a..23a4b4f7f0 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -1,219 +1,16 @@
 ! Copyright (C) 2008 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel arrays strings math.parser sequences sequences.deep
-peg peg.ebnf peg.parsers memoize namespaces math accessors ;
+USING: kernel accessors peg.javascript.tokenizer peg.javascript.parser ;
 IN: peg.javascript
 
-#! Grammar for JavaScript. Based on OMeta-JS example from:
-#! http://jarrett.cs.ucla.edu/ometa-js/#JavaScript_Compiler 
+: parse-javascript ( string -- ast )
+  tokenizer [
+    ast>> javascript [
+      ast>>
+    ] [
+      "Unable to parse JavaScript" throw
+    ] if*
+  ] [
+    "Unable to tokenize JavaScript" throw
+  ] if* ;
 
-USE: prettyprint
-
-TUPLE: ast-keyword value ;
-TUPLE: ast-name value ;
-TUPLE: ast-number value ;
-TUPLE: ast-string value ;
-TUPLE: ast-cond-expr condition then else ;
-TUPLE: ast-set lhs rhs ;
-TUPLE: ast-get value ;
-TUPLE: ast-mset lhs rhs operator ;
-TUPLE: ast-binop lhs rhs operator ;
-TUPLE: ast-unop expr operator ;
-TUPLE: ast-postop expr operator ;
-TUPLE: ast-preop expr operator ;
-TUPLE: ast-getp index expr ;
-TUPLE: ast-send method expr args ;
-TUPLE: ast-call expr args ;
-TUPLE: ast-this ;
-TUPLE: ast-new name args ;
-TUPLE: ast-array values ;
-TUPLE: ast-json bindings ;
-TUPLE: ast-binding name value ;
-TUPLE: ast-func fs body ;
-TUPLE: ast-var name value ;
-TUPLE: ast-begin statements ;
-TUPLE: ast-if condition true false ;
-TUPLE: ast-while condition statements ;
-TUPLE: ast-do-while statements condition ;
-TUPLE: ast-for i c u statements ;
-TUPLE: ast-for-in v e statements ;
-TUPLE: ast-switch expr statements ;
-TUPLE: ast-break ;
-TUPLE: ast-continue ;
-TUPLE: ast-throw e ;
-TUPLE: ast-try t e c f ;
-TUPLE: ast-return e ;
-TUPLE: ast-case c cs ;
-TUPLE: ast-default cs ;
-
-EBNF: tokenizer 
-Letter            = [a-zA-Z]
-Digit             = [0-9]
-Digits            = Digit+
-SingleLineComment = "//" (!("\n") .)* "\n" => [[ ignore ]]
-MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ ignore ]]
-Space             = " " | "\t" | "\r" | "\n" | SingleLineComment | MultiLineComment
-Spaces            = Space* => [[ ignore ]]
-NameFirst         = Letter | "$" | "_"
-NameRest          = NameFirst | Digit
-iName             = NameFirst NameRest* => [[ first2 swap prefix >string ]]
-Keyword           =  ("break"
-                    | "case"
-                    | "catch"
-                    | "continue"
-                    | "default"
-                    | "delete"
-                    | "do"
-                    | "else"
-                    | "finally"
-                    | "for"
-                    | "function"
-                    | "if"
-                    | "in"
-                    | "instanceof"
-                    | "new"
-                    | "return"
-                    | "switch"
-                    | "this"
-                    | "throw"
-                    | "try"
-                    | "typeof"
-                    | "var"
-                    | "void"
-                    | "while"
-                    | "with") 
-Name              = !(Keyword) (iName):n => [[ n ast-name boa ]]
-Number            =   Digits:ws '.' Digits:fs => [[ ws "." fs 3array concat >string string>number ast-number boa ]]
-                    | Digits => [[ >string string>number ast-number boa ]]  
-
-EscapeChar        =   "\\n" => [[ 10 ]] 
-                    | "\\r" => [[ 13 ]]
-                    | "\\t" => [[ 9 ]]
-StringChars1       = (EscapeChar | !('"""') .)* => [[ >string ]]
-StringChars2       = (EscapeChar | !('"') .)* => [[ >string ]]
-StringChars3       = (EscapeChar | !("'") .)* => [[ >string ]]
-Str                =   '"""' StringChars1:cs '"""' => [[ cs ast-string boa ]]
-                     | '"' StringChars2:cs '"' => [[ cs ast-string boa ]]
-                     | "'" StringChars3:cs "'" => [[ cs ast-string boa ]]
-Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | ";"
-                     | "?"   | ":"   | "!==" | "~="  | "===" | "=="  | "="   | ">="
-                     | ">"   | "<="  | "<"   | "++"  | "+="  | "+"   | "--"  | "-="
-                     | "-"   | "*="  | "*"   | "/="  | "/"   | "%="  | "%"   | "&&="
-                     | "&&"  | "||=" | "||"  | "."   | "!"
-Tok                = Spaces (Name | Keyword | Number | Str | Special )
-Toks               = Tok* Spaces 
-;EBNF
-
-EBNF: javascript
-Space             = " " | "\t" | "\n" 
-Spaces            = Space* => [[ ignore ]]
-Name               = . ?[ ast-name?   ]?   => [[ value>> ]] 
-Number             = . ?[ ast-number? ]?   => [[ value>> ]]
-String             = . ?[ ast-string? ]?   => [[ value>> ]]
-SpacesNoNl         = (!("\n") Space)* => [[ ignore ]]
-
-Expr               =   OrExpr:e "?" Expr:t ":" Expr:f   => [[ e t f ast-cond-expr boa ]]
-                     | OrExpr:e "=" Expr:rhs            => [[ e rhs ast-set boa ]]
-                     | OrExpr:e "+=" Expr:rhs           => [[ e rhs "+" ast-mset boa ]]
-                     | OrExpr:e "-=" Expr:rhs           => [[ e rhs "-" ast-mset boa ]]
-                     | OrExpr:e "*=" Expr:rhs           => [[ e rhs "*" ast-mset boa ]]
-                     | OrExpr:e "/=" Expr:rhs           => [[ e rhs "/" ast-mset boa ]]
-                     | OrExpr:e "%=" Expr:rhs           => [[ e rhs "%" ast-mset boa ]]
-                     | OrExpr:e "&&=" Expr:rhs          => [[ e rhs "&&" ast-mset boa ]]
-                     | OrExpr:e "||=" Expr:rhs          => [[ e rhs "||" ast-mset boa ]]
-                     | OrExpr:e                         => [[ e ]]
-
-OrExpr             =   OrExpr:x "||" AndExpr:y          => [[ x y "||" ast-binop boa ]]
-                     | AndExpr
-AndExpr            =   AndExpr:x "&&" EqExpr:y          => [[ x y "&&" ast-binop boa ]]
-                     | EqExpr
-EqExpr             =   EqExpr:x "==" RelExpr:y          => [[ x y "==" ast-binop boa ]]
-                     | EqExpr:x "!=" RelExpr:y          => [[ x y "!=" ast-binop boa ]]
-                     | EqExpr:x "===" RelExpr:y         => [[ x y "===" ast-binop boa ]]
-                     | EqExpr:x "!==" RelExpr:y         => [[ x y "!==" ast-binop boa ]]
-                     | RelExpr
-RelExpr            =   RelExpr:x ">" AddExpr:y          => [[ x y ">" ast-binop boa ]]
-                     | RelExpr:x ">=" AddExpr:y         => [[ x y ">=" ast-binop boa ]]
-                     | RelExpr:x "<" AddExpr:y          => [[ x y "<" ast-binop boa ]]
-                     | RelExpr:x "<=" AddExpr:y         => [[ x y "<=" ast-binop boa ]]
-                     | RelExpr:x "instanceof" AddExpr:y => [[ x y "instanceof" ast-binop boa ]]
-                     | AddExpr
-AddExpr            =   AddExpr:x "+" MulExpr:y          => [[ x y "+" ast-binop boa ]]
-                     | AddExpr:x "-" MulExpr:y          => [[ x y "-" ast-binop boa ]]
-                     | MulExpr
-MulExpr            =   MulExpr:x "*" MulExpr:y          => [[ x y "*" ast-binop boa ]]
-                     | MulExpr:x "/" MulExpr:y          => [[ x y "/" ast-binop boa ]]
-                     | MulExpr:x "%" MulExpr:y          => [[ x y "%" ast-binop boa ]]
-                     | Unary
-Unary              =   "-" Postfix:p                    => [[ p "-" ast-unop boa ]]
-                     | "+" Postfix:p                    => [[ p ]]
-                     | "++" Postfix:p                   => [[ p "++" ast-preop boa ]]
-                     | "--" Postfix:p                   => [[ p "--" ast-preop boa ]]
-                     | "!" Postfix:p                    => [[ p "!" ast-unop boa ]]
-                     | Postfix
-Postfix            =   PrimExpr:p SpacesNoNl "++"       => [[ p "++" ast-postop boa ]]
-                     | PrimExpr:p SpacesNoNl "--"       => [[ p "--" ast-postop boa ]]
-                     | PrimExpr
-Args               =   (Expr ("," Expr => [[ second ]])* => [[ first2 swap prefix ]])?
-PrimExpr           =   PrimExpr:p "[" Expr:i "]"             => [[ i p ast-getp boa ]]
-                     | PrimExpr:p "." Name:m "(" Args:as ")" => [[ m p as ast-send boa ]]
-                     | PrimExpr:p "." Name:f                 => [[ f p ast-getp boa ]]
-                     | PrimExpr:p "(" Args:as ")"            => [[ p as ast-call boa ]]
-                     | PrimExprHd
-PrimExprHd         =   "(" Expr:e ")"                        => [[ e ]]
-                     | "this"                                => [[ ast-this boa ]]
-                     | Name                                  => [[ ast-get boa ]]
-                     | Number                                => [[ ast-number boa ]]
-                     | String                                => [[ ast-string boa ]]
-                     | "function" FuncRest:fr                => [[ fr ]]
-                     | "new" Name:n "(" Args:as ")"          => [[ n as ast-new boa ]]
-                     | "[" Args:es "]"                       => [[ es ast-array boa ]]
-                     | Json
-JsonBindings        = (JsonBinding ("," JsonBinding => [[ second ]])* => [[ first2 swap prefix ]])?
-Json               = "{" JsonBindings:bs "}"                  => [[ bs ast-json boa ]]
-JsonBinding        = JsonPropName:n ":" Expr:v               => [[ n v ast-binding boa ]]
-JsonPropName       = Name | Number | String
-Formal             = Spaces Name
-Formals            = (Formal ("," Formal => [[ second ]])*  => [[ first2 swap prefix ]])?
-FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ fs body ast-func boa ]]
-Sc                 = SpacesNoNl ("\n" | &("}"))| ";"
-Binding            =   Name:n "=" Expr:v                      => [[ n v ast-var boa ]]
-                     | Name:n                                 => [[ n "undefined" ast-get boa ast-var boa ]]
-Block              = "{" SrcElems:ss "}"                      => [[ ss ]]
-Bindings           = (Binding ("," Binding => [[ second ]])* => [[ first2 swap prefix ]])?
-For1               =   "var" Binding => [[ second ]] 
-                     | Expr 
-                     | Spaces => [[ "undefined" ast-get boa ]] 
-For2               =   Expr
-                     | Spaces => [[ "true" ast-get boa ]] 
-For3               =   Expr
-                     | Spaces => [[ "undefined" ast-get boa ]] 
-ForIn1             =   "var" Name:n => [[ n "undefined" ast-get boa ast-var boa ]]
-                     | Expr
-Switch1            =   "case" Expr:c ":" SrcElems:cs => [[ c cs ast-case boa ]]
-                     | "default" ":" SrcElems:cs => [[ cs ast-default boa ]]  
-SwitchBody         = Switch1*
-Finally            =   "finally" Block:b => [[ b ]]
-                     | Spaces => [[ "undefined" ast-get boa ]]
-Stmt               =   Block                     
-                     | "var" Bindings:bs Sc                   => [[ bs ast-begin boa ]]
-                     | "if" "(" Expr:c ")" Stmt:t "else" Stmt:f => [[ c t f ast-if boa ]]
-                     | "if" "(" Expr:c ")" Stmt:t               => [[ c t "undefined" ast-get boa ast-if boa ]]
-                     | "while" "(" Expr:c ")" Stmt:s            => [[ c s ast-while boa ]]
-                     | "do" Stmt:s "while" "(" Expr:c ")" Sc    => [[ s c ast-do-while boa ]]
-                     | "for" "(" For1:i ";" For2:c ";" For3:u ")" Stmt:s => [[ i c u s ast-for boa ]]
-                     | "for" "(" ForIn1:v "in" Expr:e ")" Stmt:s => [[ v e s ast-for-in boa ]]
-                     | "switch" "(" Expr:e ")" "{" SwitchBody:cs "}" => [[ e cs ast-switch boa ]]
-                     | "break" Sc                                    => [[ ast-break boa ]]
-                     | "continue" Sc                                 => [[ ast-continue boa ]]
-                     | "throw" SpacesNoNl Expr:e Sc                  => [[ e ast-throw boa ]]
-                     | "try" Block:t "catch" "(" Name:e ")" Block:c Finally:f => [[ t e c f ast-try boa ]]
-                     | "return" Expr:e Sc                            => [[ e ast-return boa ]]
-                     | "return" Sc                                   => [[ "undefined" ast-get boa ast-return boa ]]
-                     | Expr:e Sc                                     => [[ e ]]
-                     | ";"                                           => [[ "undefined" ast-get boa ]]
-SrcElem            =   "function" Name:n FuncRest:f                  => [[ n f ast-var boa ]]
-                     | Stmt
-SrcElems           = SrcElem*                                      => [[ ast-begin boa ]]
-TopLevel           = SrcElems Spaces                               
-;EBNF
\ No newline at end of file
diff --git a/extra/peg/javascript/parser/authors.txt b/extra/peg/javascript/parser/authors.txt
new file mode 100644
index 0000000000..44b06f94bc
--- /dev/null
+++ b/extra/peg/javascript/parser/authors.txt
@@ -0,0 +1 @@
+Chris Double
diff --git a/extra/peg/javascript/parser/parser-tests.factor b/extra/peg/javascript/parser/parser-tests.factor
new file mode 100644
index 0000000000..933d4cf10e
--- /dev/null
+++ b/extra/peg/javascript/parser/parser-tests.factor
@@ -0,0 +1,27 @@
+! Copyright (C) 2008 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+!
+USING: kernel tools.test peg peg.javascript.ast peg.javascript.tokenizer  
+       peg.javascript.parser accessors ;
+IN: peg.javascript.parser.tests
+
+\ javascript must-infer
+
+{
+  T{
+      ast-begin
+      f
+      V{
+          T{ ast-number f 123 }
+          T{ ast-string f "hello" }
+          T{
+              ast-call
+              f
+              T{ ast-get f "foo" }
+              V{ T{ ast-get f "x" } }
+          }
+      }
+  }
+} [
+  "123; 'hello'; foo(x);" tokenizer ast>> javascript ast>>
+] unit-test
\ No newline at end of file
diff --git a/extra/peg/javascript/parser/parser.factor b/extra/peg/javascript/parser/parser.factor
new file mode 100644
index 0000000000..a38cf4aea8
--- /dev/null
+++ b/extra/peg/javascript/parser/parser.factor
@@ -0,0 +1,121 @@
+! Copyright (C) 2008 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors peg peg.ebnf peg.javascript.ast ;
+IN: peg.javascript.parser
+
+#! Grammar for JavaScript. Based on OMeta-JS example from:
+#! http://jarrett.cs.ucla.edu/ometa-js/#JavaScript_Compiler 
+
+EBNF: javascript
+Space             = " " | "\t" | "\n" 
+Spaces            = Space* => [[ ignore ]]
+Name               = . ?[ ast-name?   ]?   => [[ value>> ]] 
+Number             = . ?[ ast-number? ]?   => [[ value>> ]]
+String             = . ?[ ast-string? ]?   => [[ value>> ]]
+SpacesNoNl         = (!("\n") Space)* => [[ ignore ]]
+
+Expr               =   OrExpr:e "?" Expr:t ":" Expr:f   => [[ e t f ast-cond-expr boa ]]
+                     | OrExpr:e "=" Expr:rhs            => [[ e rhs ast-set boa ]]
+                     | OrExpr:e "+=" Expr:rhs           => [[ e rhs "+" ast-mset boa ]]
+                     | OrExpr:e "-=" Expr:rhs           => [[ e rhs "-" ast-mset boa ]]
+                     | OrExpr:e "*=" Expr:rhs           => [[ e rhs "*" ast-mset boa ]]
+                     | OrExpr:e "/=" Expr:rhs           => [[ e rhs "/" ast-mset boa ]]
+                     | OrExpr:e "%=" Expr:rhs           => [[ e rhs "%" ast-mset boa ]]
+                     | OrExpr:e "&&=" Expr:rhs          => [[ e rhs "&&" ast-mset boa ]]
+                     | OrExpr:e "||=" Expr:rhs          => [[ e rhs "||" ast-mset boa ]]
+                     | OrExpr:e                         => [[ e ]]
+
+OrExpr             =   OrExpr:x "||" AndExpr:y          => [[ x y "||" ast-binop boa ]]
+                     | AndExpr
+AndExpr            =   AndExpr:x "&&" EqExpr:y          => [[ x y "&&" ast-binop boa ]]
+                     | EqExpr
+EqExpr             =   EqExpr:x "==" RelExpr:y          => [[ x y "==" ast-binop boa ]]
+                     | EqExpr:x "!=" RelExpr:y          => [[ x y "!=" ast-binop boa ]]
+                     | EqExpr:x "===" RelExpr:y         => [[ x y "===" ast-binop boa ]]
+                     | EqExpr:x "!==" RelExpr:y         => [[ x y "!==" ast-binop boa ]]
+                     | RelExpr
+RelExpr            =   RelExpr:x ">" AddExpr:y          => [[ x y ">" ast-binop boa ]]
+                     | RelExpr:x ">=" AddExpr:y         => [[ x y ">=" ast-binop boa ]]
+                     | RelExpr:x "<" AddExpr:y          => [[ x y "<" ast-binop boa ]]
+                     | RelExpr:x "<=" AddExpr:y         => [[ x y "<=" ast-binop boa ]]
+                     | RelExpr:x "instanceof" AddExpr:y => [[ x y "instanceof" ast-binop boa ]]
+                     | AddExpr
+AddExpr            =   AddExpr:x "+" MulExpr:y          => [[ x y "+" ast-binop boa ]]
+                     | AddExpr:x "-" MulExpr:y          => [[ x y "-" ast-binop boa ]]
+                     | MulExpr
+MulExpr            =   MulExpr:x "*" MulExpr:y          => [[ x y "*" ast-binop boa ]]
+                     | MulExpr:x "/" MulExpr:y          => [[ x y "/" ast-binop boa ]]
+                     | MulExpr:x "%" MulExpr:y          => [[ x y "%" ast-binop boa ]]
+                     | Unary
+Unary              =   "-" Postfix:p                    => [[ p "-" ast-unop boa ]]
+                     | "+" Postfix:p                    => [[ p ]]
+                     | "++" Postfix:p                   => [[ p "++" ast-preop boa ]]
+                     | "--" Postfix:p                   => [[ p "--" ast-preop boa ]]
+                     | "!" Postfix:p                    => [[ p "!" ast-unop boa ]]
+                     | Postfix
+Postfix            =   PrimExpr:p SpacesNoNl "++"       => [[ p "++" ast-postop boa ]]
+                     | PrimExpr:p SpacesNoNl "--"       => [[ p "--" ast-postop boa ]]
+                     | PrimExpr
+Args               =   (Expr ("," Expr => [[ second ]])* => [[ first2 swap prefix ]])?
+PrimExpr           =   PrimExpr:p "[" Expr:i "]"             => [[ i p ast-getp boa ]]
+                     | PrimExpr:p "." Name:m "(" Args:as ")" => [[ m p as ast-send boa ]]
+                     | PrimExpr:p "." Name:f                 => [[ f p ast-getp boa ]]
+                     | PrimExpr:p "(" Args:as ")"            => [[ p as ast-call boa ]]
+                     | PrimExprHd
+PrimExprHd         =   "(" Expr:e ")"                        => [[ e ]]
+                     | "this"                                => [[ ast-this boa ]]
+                     | Name                                  => [[ ast-get boa ]]
+                     | Number                                => [[ ast-number boa ]]
+                     | String                                => [[ ast-string boa ]]
+                     | "function" FuncRest:fr                => [[ fr ]]
+                     | "new" Name:n "(" Args:as ")"          => [[ n as ast-new boa ]]
+                     | "[" Args:es "]"                       => [[ es ast-array boa ]]
+                     | Json
+JsonBindings        = (JsonBinding ("," JsonBinding => [[ second ]])* => [[ first2 swap prefix ]])?
+Json               = "{" JsonBindings:bs "}"                  => [[ bs ast-json boa ]]
+JsonBinding        = JsonPropName:n ":" Expr:v               => [[ n v ast-binding boa ]]
+JsonPropName       = Name | Number | String
+Formal             = Spaces Name
+Formals            = (Formal ("," Formal => [[ second ]])*  => [[ first2 swap prefix ]])?
+FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ fs body ast-func boa ]]
+Sc                 = SpacesNoNl ("\n" | &("}"))| ";"
+Binding            =   Name:n "=" Expr:v                      => [[ n v ast-var boa ]]
+                     | Name:n                                 => [[ n "undefined" ast-get boa ast-var boa ]]
+Block              = "{" SrcElems:ss "}"                      => [[ ss ]]
+Bindings           = (Binding ("," Binding => [[ second ]])* => [[ first2 swap prefix ]])?
+For1               =   "var" Binding => [[ second ]] 
+                     | Expr 
+                     | Spaces => [[ "undefined" ast-get boa ]] 
+For2               =   Expr
+                     | Spaces => [[ "true" ast-get boa ]] 
+For3               =   Expr
+                     | Spaces => [[ "undefined" ast-get boa ]] 
+ForIn1             =   "var" Name:n => [[ n "undefined" ast-get boa ast-var boa ]]
+                     | Expr
+Switch1            =   "case" Expr:c ":" SrcElems:cs => [[ c cs ast-case boa ]]
+                     | "default" ":" SrcElems:cs => [[ cs ast-default boa ]]  
+SwitchBody         = Switch1*
+Finally            =   "finally" Block:b => [[ b ]]
+                     | Spaces => [[ "undefined" ast-get boa ]]
+Stmt               =   Block                     
+                     | "var" Bindings:bs Sc                   => [[ bs ast-begin boa ]]
+                     | "if" "(" Expr:c ")" Stmt:t "else" Stmt:f => [[ c t f ast-if boa ]]
+                     | "if" "(" Expr:c ")" Stmt:t               => [[ c t "undefined" ast-get boa ast-if boa ]]
+                     | "while" "(" Expr:c ")" Stmt:s            => [[ c s ast-while boa ]]
+                     | "do" Stmt:s "while" "(" Expr:c ")" Sc    => [[ s c ast-do-while boa ]]
+                     | "for" "(" For1:i ";" For2:c ";" For3:u ")" Stmt:s => [[ i c u s ast-for boa ]]
+                     | "for" "(" ForIn1:v "in" Expr:e ")" Stmt:s => [[ v e s ast-for-in boa ]]
+                     | "switch" "(" Expr:e ")" "{" SwitchBody:cs "}" => [[ e cs ast-switch boa ]]
+                     | "break" Sc                                    => [[ ast-break boa ]]
+                     | "continue" Sc                                 => [[ ast-continue boa ]]
+                     | "throw" SpacesNoNl Expr:e Sc                  => [[ e ast-throw boa ]]
+                     | "try" Block:t "catch" "(" Name:e ")" Block:c Finally:f => [[ t e c f ast-try boa ]]
+                     | "return" Expr:e Sc                            => [[ e ast-return boa ]]
+                     | "return" Sc                                   => [[ "undefined" ast-get boa ast-return boa ]]
+                     | Expr:e Sc                                     => [[ e ]]
+                     | ";"                                           => [[ "undefined" ast-get boa ]]
+SrcElem            =   "function" Name:n FuncRest:f                  => [[ n f ast-var boa ]]
+                     | Stmt
+SrcElems           = SrcElem*                                      => [[ ast-begin boa ]]
+TopLevel           = SrcElems Spaces                               
+;EBNF
\ No newline at end of file
diff --git a/extra/peg/javascript/parser/summary.txt b/extra/peg/javascript/parser/summary.txt
new file mode 100644
index 0000000000..bae5a461d2
--- /dev/null
+++ b/extra/peg/javascript/parser/summary.txt
@@ -0,0 +1 @@
+JavaScript Parser
diff --git a/extra/peg/javascript/parser/tags.txt b/extra/peg/javascript/parser/tags.txt
new file mode 100644
index 0000000000..c2aac2932f
--- /dev/null
+++ b/extra/peg/javascript/parser/tags.txt
@@ -0,0 +1,3 @@
+text
+javascript
+parsing
diff --git a/extra/peg/javascript/summary.txt b/extra/peg/javascript/summary.txt
new file mode 100644
index 0000000000..12f092dcf7
--- /dev/null
+++ b/extra/peg/javascript/summary.txt
@@ -0,0 +1 @@
+JavaScript parser
diff --git a/extra/peg/javascript/tags.txt b/extra/peg/javascript/tags.txt
new file mode 100644
index 0000000000..c2aac2932f
--- /dev/null
+++ b/extra/peg/javascript/tags.txt
@@ -0,0 +1,3 @@
+text
+javascript
+parsing
diff --git a/extra/peg/javascript/tokenizer/authors.txt b/extra/peg/javascript/tokenizer/authors.txt
new file mode 100644
index 0000000000..44b06f94bc
--- /dev/null
+++ b/extra/peg/javascript/tokenizer/authors.txt
@@ -0,0 +1 @@
+Chris Double
diff --git a/extra/peg/javascript/tokenizer/summary.txt b/extra/peg/javascript/tokenizer/summary.txt
new file mode 100644
index 0000000000..ce94386ed9
--- /dev/null
+++ b/extra/peg/javascript/tokenizer/summary.txt
@@ -0,0 +1 @@
+Tokenizer for JavaScript language
diff --git a/extra/peg/javascript/tokenizer/tags.txt b/extra/peg/javascript/tokenizer/tags.txt
new file mode 100644
index 0000000000..c2aac2932f
--- /dev/null
+++ b/extra/peg/javascript/tokenizer/tags.txt
@@ -0,0 +1,3 @@
+text
+javascript
+parsing
diff --git a/extra/peg/javascript/tokenizer/tokenizer-tests.factor b/extra/peg/javascript/tokenizer/tokenizer-tests.factor
new file mode 100644
index 0000000000..1300b3c9c7
--- /dev/null
+++ b/extra/peg/javascript/tokenizer/tokenizer-tests.factor
@@ -0,0 +1,23 @@
+! Copyright (C) 2008 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+!
+USING: kernel tools.test peg peg.javascript.ast peg.javascript.tokenizer accessors ;
+IN: peg.javascript.tokenizer.tests
+
+\ tokenizer must-infer
+
+{
+  V{
+    T{ ast-number f 123 }
+    ";"
+    T{ ast-string f "hello" }
+    ";"
+    T{ ast-name f "foo" }
+    "("
+    T{ ast-name f "x" }
+    ")"
+    ";"
+  }    
+} [
+  "123; 'hello'; foo(x);" tokenizer ast>>
+] unit-test
diff --git a/extra/peg/javascript/tokenizer/tokenizer.factor b/extra/peg/javascript/tokenizer/tokenizer.factor
new file mode 100644
index 0000000000..d62bb9395b
--- /dev/null
+++ b/extra/peg/javascript/tokenizer/tokenizer.factor
@@ -0,0 +1,68 @@
+! Copyright (C) 2008 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel sequences strings arrays math.parser peg peg.ebnf peg.javascript.ast ;
+IN: peg.javascript.tokenizer
+
+#! Grammar for JavaScript. Based on OMeta-JS example from:
+#! http://jarrett.cs.ucla.edu/ometa-js/#JavaScript_Compiler 
+
+EBNF: tokenizer 
+Letter            = [a-zA-Z]
+Digit             = [0-9]
+Digits            = Digit+
+SingleLineComment = "//" (!("\n") .)* "\n" => [[ ignore ]]
+MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ ignore ]]
+Space             = " " | "\t" | "\r" | "\n" | SingleLineComment | MultiLineComment
+Spaces            = Space* => [[ ignore ]]
+NameFirst         = Letter | "$" | "_"
+NameRest          = NameFirst | Digit
+iName             = NameFirst NameRest* => [[ first2 swap prefix >string ]]
+Keyword           =  ("break"
+                    | "case"
+                    | "catch"
+                    | "continue"
+                    | "default"
+                    | "delete"
+                    | "do"
+                    | "else"
+                    | "finally"
+                    | "for"
+                    | "function"
+                    | "if"
+                    | "in"
+                    | "instanceof"
+                    | "new"
+                    | "return"
+                    | "switch"
+                    | "this"
+                    | "throw"
+                    | "try"
+                    | "typeof"
+                    | "var"
+                    | "void"
+                    | "while"
+                    | "with") 
+Name              = !(Keyword) (iName):n => [[ n ast-name boa ]]
+Number            =   Digits:ws '.' Digits:fs => [[ ws "." fs 3array concat >string string>number ast-number boa ]]
+                    | Digits => [[ >string string>number ast-number boa ]]  
+
+EscapeChar        =   "\\n" => [[ 10 ]] 
+                    | "\\r" => [[ 13 ]]
+                    | "\\t" => [[ 9 ]]
+StringChars1       = (EscapeChar | !('"""') .)* => [[ >string ]]
+StringChars2       = (EscapeChar | !('"') .)* => [[ >string ]]
+StringChars3       = (EscapeChar | !("'") .)* => [[ >string ]]
+Str                =   '"""' StringChars1:cs '"""' => [[ cs ast-string boa ]]
+                     | '"' StringChars2:cs '"' => [[ cs ast-string boa ]]
+                     | "'" StringChars3:cs "'" => [[ cs ast-string boa ]]
+RegExpBody         = (!("/" | "\n" | "\r") .)* => [[ >string ]]
+RegExp             = "/" RegExpBody:r "/" => [[ r ast-regexp boa ]]
+Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | ";"
+                     | "?"   | ":"   | "!==" | "~="  | "===" | "=="  | "="   | ">="
+                     | ">"   | "<="  | "<"   | "++"  | "+="  | "+"   | "--"  | "-="
+                     | "-"   | "*="  | "*"   | "/="  | "/"   | "%="  | "%"   | "&&="
+                     | "&&"  | "||=" | "||"  | "."   | "!"
+Tok                = Spaces (Name | Keyword | Number | Str | RegExp | Special )
+Toks               = Tok* Spaces 
+;EBNF
+

From fc7baebacbcedc177b16c5377991e156e9f62d26 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 00:51:47 +1200
Subject: [PATCH 23/85] Fix handling of _ and $ in Javascript names

---
 extra/peg/javascript/tokenizer/tokenizer.factor | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/extra/peg/javascript/tokenizer/tokenizer.factor b/extra/peg/javascript/tokenizer/tokenizer.factor
index d62bb9395b..420abff442 100644
--- a/extra/peg/javascript/tokenizer/tokenizer.factor
+++ b/extra/peg/javascript/tokenizer/tokenizer.factor
@@ -6,6 +6,8 @@ IN: peg.javascript.tokenizer
 #! Grammar for JavaScript. Based on OMeta-JS example from:
 #! http://jarrett.cs.ucla.edu/ometa-js/#JavaScript_Compiler 
 
+USE: prettyprint
+
 EBNF: tokenizer 
 Letter            = [a-zA-Z]
 Digit             = [0-9]
@@ -14,7 +16,7 @@ SingleLineComment = "//" (!("\n") .)* "\n" => [[ ignore ]]
 MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ ignore ]]
 Space             = " " | "\t" | "\r" | "\n" | SingleLineComment | MultiLineComment
 Spaces            = Space* => [[ ignore ]]
-NameFirst         = Letter | "$" | "_"
+NameFirst         = Letter | "$" => [[ CHAR: $ ]] | "_" => [[ CHAR: _ ]]
 NameRest          = NameFirst | Digit
 iName             = NameFirst NameRest* => [[ first2 swap prefix >string ]]
 Keyword           =  ("break"

From c26d87e11788c107d7467f38ae2a0bded3666c05 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 01:01:46 +1200
Subject: [PATCH 24/85] Fix handling of JavasScript names which partially match
 reserved words

---
 extra/peg/javascript/tokenizer/tokenizer.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extra/peg/javascript/tokenizer/tokenizer.factor b/extra/peg/javascript/tokenizer/tokenizer.factor
index 420abff442..70fabb10f6 100644
--- a/extra/peg/javascript/tokenizer/tokenizer.factor
+++ b/extra/peg/javascript/tokenizer/tokenizer.factor
@@ -44,7 +44,7 @@ Keyword           =  ("break"
                     | "void"
                     | "while"
                     | "with") 
-Name              = !(Keyword) (iName):n => [[ n ast-name boa ]]
+Name              = iName !(Keyword) => [[ ast-name boa ]]
 Number            =   Digits:ws '.' Digits:fs => [[ ws "." fs 3array concat >string string>number ast-number boa ]]
                     | Digits => [[ >string string>number ast-number boa ]]  
 

From 179ea21c11d95f257a5f3172dab4ffd7fa91ae5a Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 01:10:44 +1200
Subject: [PATCH 25/85] Add a couple of failing peg.ebnf tests

---
 extra/peg/ebnf/ebnf-tests.factor | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index 73db626685..ed38d37421 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -399,6 +399,16 @@ main = Primary
   "number=digit+:n 'a'" 'ebnf' parse remaining>> length zero?
 ] unit-test
 
+{ t } [
+  "foo=(name):n !(keyword) => [[ n ]]" 'rule' parse ast>>
+  "foo=name:n !(keyword) => [[ n ]]" 'rule' parse ast>> =
+] unit-test
+
+{ t } [
+  "foo=!(keyword) (name):n => [[ n ]]" 'rule' parse ast>>
+  "foo=!(keyword) name:n => [[ n ]]" 'rule' parse ast>> =
+] unit-test
+
 <<
 EBNF: parser1 
 foo='a' 
@@ -431,4 +441,4 @@ foo=<foreign any-char> 'd'
 
 { V{ CHAR: a "d" } } [
   "ad" parser4 ast>>
-] unit-test
\ No newline at end of file
+] unit-test

From fcd1e39834052d7df4548d4c411870a8417ec10c Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 01:20:33 +1200
Subject: [PATCH 26/85] More JavaScript fixes for keyword handling

---
 extra/peg/javascript/tokenizer/tokenizer.factor | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/extra/peg/javascript/tokenizer/tokenizer.factor b/extra/peg/javascript/tokenizer/tokenizer.factor
index 70fabb10f6..a1cff8a3db 100644
--- a/extra/peg/javascript/tokenizer/tokenizer.factor
+++ b/extra/peg/javascript/tokenizer/tokenizer.factor
@@ -43,8 +43,8 @@ Keyword           =  ("break"
                     | "var"
                     | "void"
                     | "while"
-                    | "with") 
-Name              = iName !(Keyword) => [[ ast-name boa ]]
+                    | "with") !(NameRest) 
+Name              = !(Keyword) iName  => [[ ast-name boa ]]
 Number            =   Digits:ws '.' Digits:fs => [[ ws "." fs 3array concat >string string>number ast-number boa ]]
                     | Digits => [[ >string string>number ast-number boa ]]  
 

From d58a085598e930566c003aaff406e5996f91c73f Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 01:24:17 +1200
Subject: [PATCH 27/85] Add additional javascript test

---
 extra/peg/javascript/parser/parser-tests.factor | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/extra/peg/javascript/parser/parser-tests.factor b/extra/peg/javascript/parser/parser-tests.factor
index 933d4cf10e..6741e059f9 100644
--- a/extra/peg/javascript/parser/parser-tests.factor
+++ b/extra/peg/javascript/parser/parser-tests.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 !
 USING: kernel tools.test peg peg.javascript.ast peg.javascript.tokenizer  
-       peg.javascript.parser accessors ;
+       peg.javascript.parser accessors multiline sequences math ;
 IN: peg.javascript.parser.tests
 
 \ javascript must-infer
@@ -24,4 +24,14 @@ IN: peg.javascript.parser.tests
   }
 } [
   "123; 'hello'; foo(x);" tokenizer ast>> javascript ast>>
-] unit-test
\ No newline at end of file
+] unit-test
+
+{ t } [ 
+<"
+function foldl(f, initial, seq) {
+   for(var i=0; i< seq.length; ++i)
+     initial = f(initial, seq[i]);
+   return initial;
+}
+"> tokenizer ast>> javascript remaining>> length zero?
+] unit-test

From d5e5e47944736585195b66aab7e997b0e7c9a666 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 01:39:51 +1200
Subject: [PATCH 28/85] Fix bug in javascript automatic semicolon insertion
 rule

---
 extra/peg/javascript/parser/parser-tests.factor | 11 +++++++++++
 extra/peg/javascript/parser/parser.factor       |  3 ++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/extra/peg/javascript/parser/parser-tests.factor b/extra/peg/javascript/parser/parser-tests.factor
index 6741e059f9..ec7a30845f 100644
--- a/extra/peg/javascript/parser/parser-tests.factor
+++ b/extra/peg/javascript/parser/parser-tests.factor
@@ -35,3 +35,14 @@ function foldl(f, initial, seq) {
 }
 "> tokenizer ast>> javascript remaining>> length zero?
 ] unit-test
+
+{ t } [ 
+<"
+ParseState.prototype.from = function(index) {
+    var r = new ParseState(this.input, this.index + index);
+    r.cache = this.cache;
+    r.length = this.length - index;
+    return r;
+}
+"> tokenizer ast>> javascript remaining>> length zero?
+] unit-test
diff --git a/extra/peg/javascript/parser/parser.factor b/extra/peg/javascript/parser/parser.factor
index a38cf4aea8..45aa0f022c 100644
--- a/extra/peg/javascript/parser/parser.factor
+++ b/extra/peg/javascript/parser/parser.factor
@@ -7,6 +7,7 @@ IN: peg.javascript.parser
 #! http://jarrett.cs.ucla.edu/ometa-js/#JavaScript_Compiler 
 
 EBNF: javascript
+End               = !(.)
 Space             = " " | "\t" | "\n" 
 Spaces            = Space* => [[ ignore ]]
 Name               = . ?[ ast-name?   ]?   => [[ value>> ]] 
@@ -78,7 +79,7 @@ JsonPropName       = Name | Number | String
 Formal             = Spaces Name
 Formals            = (Formal ("," Formal => [[ second ]])*  => [[ first2 swap prefix ]])?
 FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ fs body ast-func boa ]]
-Sc                 = SpacesNoNl ("\n" | &("}"))| ";"
+Sc                 = SpacesNoNl ("\n" | &("}") | End)| ";"
 Binding            =   Name:n "=" Expr:v                      => [[ n v ast-var boa ]]
                      | Name:n                                 => [[ n "undefined" ast-get boa ast-var boa ]]
 Block              = "{" SrcElems:ss "}"                      => [[ ss ]]

From 2b2ede0a89411421649af182bb69439bc6424b17 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 01:45:09 +1200
Subject: [PATCH 29/85] Add a javascript sc test

---
 extra/peg/javascript/parser/parser-tests.factor | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/extra/peg/javascript/parser/parser-tests.factor b/extra/peg/javascript/parser/parser-tests.factor
index ec7a30845f..d911a27285 100644
--- a/extra/peg/javascript/parser/parser-tests.factor
+++ b/extra/peg/javascript/parser/parser-tests.factor
@@ -26,6 +26,14 @@ IN: peg.javascript.parser.tests
   "123; 'hello'; foo(x);" tokenizer ast>> javascript ast>>
 ] unit-test
 
+{ t } [ 
+<"
+var x=5
+var y=10
+"> tokenizer ast>> javascript remaining>> length zero?
+] unit-test
+
+
 { t } [ 
 <"
 function foldl(f, initial, seq) {
@@ -46,3 +54,4 @@ ParseState.prototype.from = function(index) {
 }
 "> tokenizer ast>> javascript remaining>> length zero?
 ] unit-test
+

From 3e11a7f2040d89271113fcc5ffe2cbebd43afe52 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 18 Jun 2008 19:46:37 -0500
Subject: [PATCH 30/85] Debugging persistent vectors

---
 .../persistent-vectors-tests.factor           |  4 +++
 .../persistent-vectors.factor                 | 33 ++++++++++++-------
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/extra/persistent-vectors/persistent-vectors-tests.factor b/extra/persistent-vectors/persistent-vectors-tests.factor
index a4e4ad33fe..45eb894e67 100644
--- a/extra/persistent-vectors/persistent-vectors-tests.factor
+++ b/extra/persistent-vectors/persistent-vectors-tests.factor
@@ -48,6 +48,10 @@ random namespaces vectors math math.order ;
 [ ] [ PV{ } "1" set ] unit-test
 [ ] [ V{ } clone "2" set ] unit-test
 
+: push/pop-test ( vec -- vec' ) 3 swap ppush 3 swap ppush ppop ;
+
+[ ] [ PV{ } 10000 [ push/pop-test ] times drop ] unit-test
+
 [ t ] [
     100 [
         drop
diff --git a/extra/persistent-vectors/persistent-vectors.factor b/extra/persistent-vectors/persistent-vectors.factor
index f9f4b68933..c80de3b0cd 100644
--- a/extra/persistent-vectors/persistent-vectors.factor
+++ b/extra/persistent-vectors/persistent-vectors.factor
@@ -1,7 +1,7 @@
 ! Based on Clojure's PersistentVector by Rich Hickey.
 
 USING: math accessors kernel sequences.private sequences arrays
-combinators parser prettyprint.backend ;
+combinators combinators.lib parser prettyprint.backend ;
 IN: persistent-vectors
 
 ERROR: empty-error pvec ;
@@ -123,30 +123,39 @@ M: persistent-vector new-nth ( obj i pvec -- pvec' )
         ] if
     ] if ;
 
+: ppop-tail ( pvec -- pvec' )
+    [ clone [ ppop ] change-children ] change-tail ;
+
 : (ppop-contraction) ( node -- node' tail' )
     clone [ unclip-last swap ] change-children swap ;
 
 : ppop-contraction ( node -- node' tail' )
-    [ (ppop-contraction) ] [ level>> 1 = ] bi swap and ;
+    dup children>> length 1 =
+    [ children>> peek f swap ]
+    [ (ppop-contraction) ]
+    if ;
 
 : (ppop-new-tail) ( root -- root' tail' )
     dup level>> 1 > [
-        dup children>> peek (ppop-new-tail) over children>> empty?
-        [ 2drop ppop-contraction ] [ [ swap node-set-last ] dip ] if
+        dup children>> peek (ppop-new-tail) over
+        [ [ swap node-set-last ] dip ]
+        [ 2drop ppop-contraction ]
+        if
     ] [
         ppop-contraction
     ] if ;
 
-: ppop-tail ( pvec -- pvec' )
-    [ clone [ ppop ] change-children ] change-tail ;
+: trivial? ( node -- ? )
+    { [ level>> 1 > ] [ children>> length 1 = ] } 1&& ;
 
 : ppop-new-tail ( pvec -- pvec' )
-    dup root>> (ppop-new-tail)
-    [
-        dup [ level>> 1 > ] [ children>> length 1 = ] bi and 
-        [ children>> first ] when
-    ] dip
-    [ >>root ] [ >>tail ] bi* ;
+    dup root>> (ppop-new-tail) [
+        {
+            { [ dup not ] [ drop T{ node f { } 1 } ] }
+            { [ dup trivial? ] [ children>> first ] }
+            [ ]
+        } cond
+    ] dip [ >>root ] [ >>tail ] bi* ;
 
 PRIVATE>
 

From 04453b242157e5966971fd86dc62c86ab6a56757 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 14:23:18 +1200
Subject: [PATCH 31/85] Fix (foo):n usage

---
 extra/peg/ebnf/ebnf.factor | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 2ee0958051..d982d73229 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -232,14 +232,18 @@ DEFER: 'choice'
 : ('sequence') ( -- parser )
   #! A sequence of terminals and non-terminals, including
   #! groupings of those. 
-  [ 
-    'ensure-not' sp ,
-    'ensure' sp ,
-    'element' sp ,
-    'group' sp , 
-    'repeat0' sp ,
-    'repeat1' sp ,
-    'optional' sp , 
+  [
+    [ 
+      'ensure-not' sp ,
+      'ensure' sp ,
+      'element' sp ,
+      'group' sp , 
+      'repeat0' sp ,
+      'repeat1' sp ,
+      'optional' sp , 
+    ] choice* 
+    [ dup  , ":" syntax , "a-zA-Z" range-pattern repeat1 [ >string ] action , ] seq* [ first2 <ebnf-var> ] action ,
+    ,
   ] choice* ;
 
 : 'action' ( -- parser )

From 3dc3a6f8996d46f3717302407b197d3b0aa6da1a Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 14:31:14 +1200
Subject: [PATCH 32/85] Remove obsolete ebnf stuff

---
 extra/peg/ebnf/ebnf.factor | 2 --
 1 file changed, 2 deletions(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index d982d73229..08ac24e535 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -266,8 +266,6 @@ DEFER: 'choice'
 : 'actioned-sequence' ( -- parser )
   [
     [ 'sequence' , "=>" syntax , 'action' , ] seq* [ first2 <ebnf-action> ] action ,
-    [ 'sequence' , ":" syntax , "a-zA-Z" range-pattern repeat1 [ >string ] action , "=>" syntax , 'action' , ] seq* [ first3 >r <ebnf-var> r> <ebnf-action> ] action ,
-    [ 'sequence' , ":" syntax , "a-zA-Z" range-pattern repeat1 [ >string ] action , ] seq* [ first2 <ebnf-var> ] action ,
     'sequence' ,
   ] choice* ;
   

From c92224f5b9b94ea2bdc1224c10cf640921c283df Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 14:34:09 +1200
Subject: [PATCH 33/85] Put '..' around parser error messages

---
 extra/peg/ebnf/ebnf.factor | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 08ac24e535..2aec8b9aea 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -416,7 +416,7 @@ M: ebnf-terminal (transform) ( ast -- parser )
 
 M: ebnf-foreign (transform) ( ast -- parser )
   dup word>> search
-  [ "Foreign word " swap word>> append " not found" append throw ] unless*
+  [ "Foreign word '" swap word>> append "' not found" append throw ] unless*
   swap rule>> [ main ] unless* dupd swap rule [
     nip
   ] [
@@ -425,7 +425,7 @@ M: ebnf-foreign (transform) ( ast -- parser )
 
 : parser-not-found ( name -- * )
   [
-    "Parser " % % " not found." %
+    "Parser '" % % "' not found." %
   ] "" make throw ;
 
 M: ebnf-non-terminal (transform) ( ast -- parser )

From 9b7e2bacc960c03ff28780b0a469018a098b5540 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Thu, 19 Jun 2008 14:44:13 +1200
Subject: [PATCH 34/85] Throw an error if there are duplicate rules in ebnf

---
 extra/peg/ebnf/ebnf.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 2aec8b9aea..e78757be34 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -305,7 +305,7 @@ M: ebnf (transform) ( ast -- parser )
 M: ebnf-rule (transform) ( ast -- parser )
   dup elements>> 
   (transform) [
-    swap symbol>> set
+    swap symbol>> dup get [ "Rule '" over append "' defined more than once" append throw ] [ set ] if
   ] keep ;
 
 M: ebnf-sequence (transform) ( ast -- parser )

From beccf83f7ccb81ddf35f025d22450b8ae51bbca5 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 18 Jun 2008 22:29:48 -0500
Subject: [PATCH 35/85] Fix deploy tests

---
 extra/tools/deploy/deploy-tests.factor  | 22 +++++++++++++---------
 extra/tools/deploy/test/3/3.factor      |  5 ++---
 extra/tools/deploy/test/4/4.factor      |  7 +++++++
 extra/tools/deploy/test/4/deploy.factor | 15 +++++++++++++++
 4 files changed, 37 insertions(+), 12 deletions(-)
 create mode 100644 extra/tools/deploy/test/4/4.factor
 create mode 100644 extra/tools/deploy/test/4/deploy.factor

diff --git a/extra/tools/deploy/deploy-tests.factor b/extra/tools/deploy/deploy-tests.factor
index 8ff22fb1ad..5309784b7c 100755
--- a/extra/tools/deploy/deploy-tests.factor
+++ b/extra/tools/deploy/deploy-tests.factor
@@ -49,12 +49,16 @@ namespaces continuations layouts accessors ;
     cell 8 = 50 30 ? 100000 * small-enough?
 ] unit-test
 
-[ ] [
-    "tools.deploy.test.1" shake-and-bake
-    vm "-i=" "test.image" temp-file append 2array try-process
-] unit-test
-
-[ ] [
-    "tools.deploy.test.2" shake-and-bake
-    vm "-i=" "test.image" temp-file append 2array try-process
-] unit-test
+{
+    "tools.deploy.test.1"
+    "tools.deploy.test.2"
+    "tools.deploy.test.3"
+    "tools.deploy.test.4"
+} [
+    [ ] swap [
+        shake-and-bake
+        vm
+        "-i=" "test.image" temp-file append
+        2array try-process
+    ] curry unit-test
+] each
diff --git a/extra/tools/deploy/test/3/3.factor b/extra/tools/deploy/test/3/3.factor
index 69287db4e2..5919fa15db 100755
--- a/extra/tools/deploy/test/3/3.factor
+++ b/extra/tools/deploy/test/3/3.factor
@@ -1,8 +1,7 @@
 IN: tools.deploy.test.3
-USING: io.encodings.ascii io.files kernel ;
+USING: io.encodings.ascii io.encodings.string system kernel ;
 
 : deploy-test-3 ( -- )
-    "resource:extra/tools/deploy/test/3/3.factor"
-    ascii file-contents drop ;
+    "xyzthg" ascii encode drop ;
 
 MAIN: deploy-test-3
diff --git a/extra/tools/deploy/test/4/4.factor b/extra/tools/deploy/test/4/4.factor
new file mode 100644
index 0000000000..6831eae5d3
--- /dev/null
+++ b/extra/tools/deploy/test/4/4.factor
@@ -0,0 +1,7 @@
+IN: tools.deploy.test.4
+USING: io.encodings.8-bit io.encodings.string kernel ;
+
+: deploy-test-4 ( -- )
+    "xyzthg" latin7 encode drop ;
+
+MAIN: deploy-test-4
diff --git a/extra/tools/deploy/test/4/deploy.factor b/extra/tools/deploy/test/4/deploy.factor
new file mode 100644
index 0000000000..5250ad698a
--- /dev/null
+++ b/extra/tools/deploy/test/4/deploy.factor
@@ -0,0 +1,15 @@
+USING: tools.deploy.config ;
+H{
+    { deploy-math? f }
+    { deploy-ui? f }
+    { deploy-compiler? t }
+    { deploy-word-props? f }
+    { deploy-word-defs? f }
+    { deploy-io 2 }
+    { deploy-name "tools.deploy.test.4" }
+    { deploy-c-types? f }
+    { deploy-random? f }
+    { "stop-after-last-window?" t }
+    { deploy-threads? t }
+    { deploy-reflection 1 }
+}

From ce8c3cd38907ddcc248aaa33d10ef0a612d0c2c3 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 18 Jun 2008 22:30:54 -0500
Subject: [PATCH 36/85] Clean up UI a bit

---
 extra/boids/ui/ui.factor                      |  8 ++---
 extra/gesture-logger/gesture-logger.factor    |  6 ++--
 extra/lsys/ui/ui.factor                       |  6 ++--
 extra/ui/gadgets/buttons/buttons.factor       | 29 +++++++++---------
 extra/ui/gadgets/canvas/canvas.factor         |  2 +-
 extra/ui/gadgets/labelled/labelled.factor     |  2 +-
 extra/ui/gadgets/labels/labels.factor         | 28 ++++++++---------
 extra/ui/gadgets/lists/lists.factor           | 15 +++++-----
 extra/ui/gadgets/menus/menus.factor           |  6 ++--
 extra/ui/gadgets/panes/panes.factor           | 30 ++++++++-----------
 extra/ui/gadgets/scrollers/scrollers.factor   |  2 +-
 extra/ui/gadgets/sliders/sliders.factor       | 13 ++++----
 extra/ui/gadgets/status-bar/status-bar.factor | 10 +++----
 extra/ui/gadgets/theme/theme.factor           | 14 ++++-----
 14 files changed, 84 insertions(+), 87 deletions(-)

diff --git a/extra/boids/ui/ui.factor b/extra/boids/ui/ui.factor
index a1feac381d..0753f4eb06 100755
--- a/extra/boids/ui/ui.factor
+++ b/extra/boids/ui/ui.factor
@@ -104,11 +104,11 @@ VARS: population-label cohesion-label alignment-label separation-label ;
     C[ [ run ] in-thread ] slate> set-slate-graft
     C[ loop off ]          slate> set-slate-ungraft
 
-  "" <label> dup reverse-video-theme >population-label update-population-label
+  "" <label> reverse-video-theme >population-label update-population-label
 
-  "" <label> dup reverse-video-theme >cohesion-label   update-cohesion-label
-  "" <label> dup reverse-video-theme >alignment-label  update-alignment-label
-  "" <label> dup reverse-video-theme >separation-label update-separation-label
+  "" <label> reverse-video-theme >cohesion-label   update-cohesion-label
+  "" <label> reverse-video-theme >alignment-label  update-alignment-label
+  "" <label> reverse-video-theme >separation-label update-separation-label
 
   <frame>
 
diff --git a/extra/gesture-logger/gesture-logger.factor b/extra/gesture-logger/gesture-logger.factor
index b9de7c1b74..76615a3de5 100644
--- a/extra/gesture-logger/gesture-logger.factor
+++ b/extra/gesture-logger/gesture-logger.factor
@@ -8,9 +8,9 @@ TUPLE: gesture-logger stream ;
 
 : <gesture-logger> ( stream -- gadget )
     \ gesture-logger construct-gadget
-    [ set-gesture-logger-stream ] keep
-    { 100 100 } over set-rect-dim
-    dup black solid-interior ;
+    swap >>stream
+    { 100 100 } >>dim
+    black solid-interior ;
 
 M: gesture-logger handle-gesture*
     drop
diff --git a/extra/lsys/ui/ui.factor b/extra/lsys/ui/ui.factor
index c3b9190c3c..1365301897 100644
--- a/extra/lsys/ui/ui.factor
+++ b/extra/lsys/ui/ui.factor
@@ -100,17 +100,17 @@ DEFER: empty-model
 
 {
 
-[ "Load" <label> dup reverse-video-theme ]
+[ "Load" <label> reverse-video-theme ]
 
 [ "Models" <label> [ drop model-chooser ] closed-quot <bevel-button> ]
 [ "Scenes" <label> [ drop scene-chooser ] closed-quot <bevel-button> ]
 
-[ "Model" <label> dup reverse-video-theme ]
+[ "Model" <label> reverse-video-theme ]
 
 [ "Iterate" <label> [ drop iterate build-model ] closed-quot <bevel-button> ]
 [ "Build model" <label> [ drop build-model ] closed-quot <bevel-button> ]
 
-[ "Camera" <label> dup reverse-video-theme ]
+[ "Camera" <label> reverse-video-theme ]
 
 [ "Turn left" <label> [ 5 turn-left ] camera-action <bevel-button> ]
 [ "Turn right" <label> [ 5 turn-right ] camera-action <bevel-button> ]
diff --git a/extra/ui/gadgets/buttons/buttons.factor b/extra/ui/gadgets/buttons/buttons.factor
index e452e6c455..c36d2050c9 100755
--- a/extra/ui/gadgets/buttons/buttons.factor
+++ b/extra/ui/gadgets/buttons/buttons.factor
@@ -41,7 +41,7 @@ button H{
 
 : <button> ( gadget quot -- button )
     button new
-    [ set-button-quot ] keep
+    swap >>quot
     [ set-gadget-delegate ] keep ;
 
 TUPLE: button-paint plain rollover pressed selected ;
@@ -53,10 +53,10 @@ C: <button-paint> button-paint
 
 : button-paint ( button paint -- button paint )
     over find-button {
-        { [ dup button-pressed? ] [ drop button-paint-pressed ] }
-        { [ dup button-selected? ] [ drop button-paint-selected ] }
-        { [ dup button-rollover? ] [ drop button-paint-rollover ] }
-        [ drop button-paint-plain ]
+        { [ dup pressed?>> ] [ drop pressed>> ] }
+        { [ dup selected?>> ] [ drop selected>> ] }
+        { [ dup button-rollover? ] [ drop rollover>> ] }
+        [ drop plain>> ]
     } cond ;
 
 M: button-paint draw-interior
@@ -65,25 +65,26 @@ M: button-paint draw-interior
 M: button-paint draw-boundary
     button-paint draw-boundary ;
 
-: roll-button-theme ( button -- )
-    f black <solid> dup f <button-paint>
-    swap set-gadget-boundary ;
+: roll-button-theme ( button -- button )
+    f black <solid> dup f <button-paint> >>boundary ; inline
 
 : <roll-button> ( label quot -- button )
-    >r >label r>
-    <button> dup roll-button-theme ;
+    >r >label r> <button> roll-button-theme ;
 
-: bevel-button-theme ( gadget -- )
+: <bevel-button-paint> ( -- paint )
     plain-gradient
     rollover-gradient
     pressed-gradient
     selected-gradient
-    <button-paint> over set-gadget-interior
-    faint-boundary ;
+    <button-paint> ;
+
+: bevel-button-theme ( gadget -- gadget )
+    <bevel-button-paint> >>interior
+    faint-boundary ; inline
 
 : <bevel-button> ( label quot -- button )
     >r >label 5 <border> r>
-    <button> dup bevel-button-theme ;
+    <button> bevel-button-theme ;
 
 TUPLE: repeat-button ;
 
diff --git a/extra/ui/gadgets/canvas/canvas.factor b/extra/ui/gadgets/canvas/canvas.factor
index 15df44fda4..0a9f07ed6e 100644
--- a/extra/ui/gadgets/canvas/canvas.factor
+++ b/extra/ui/gadgets/canvas/canvas.factor
@@ -9,7 +9,7 @@ TUPLE: canvas dlist ;
 
 : <canvas> ( -- canvas )
     canvas construct-gadget
-    dup black solid-interior ;
+    black solid-interior ;
 
 : delete-canvas-dlist ( canvas -- )
     dup find-gl-context
diff --git a/extra/ui/gadgets/labelled/labelled.factor b/extra/ui/gadgets/labelled/labelled.factor
index 63ab2f1d6f..3013dcd0bd 100755
--- a/extra/ui/gadgets/labelled/labelled.factor
+++ b/extra/ui/gadgets/labelled/labelled.factor
@@ -13,7 +13,7 @@ TUPLE: labelled-gadget content ;
 : <labelled-gadget> ( gadget title -- newgadget )
     labelled-gadget new
     [
-        <label> dup reverse-video-theme f track,
+        <label> reverse-video-theme f track,
         g-> set-labelled-gadget-content 1 track,
     ] { 0 1 } build-track ;
 
diff --git a/extra/ui/gadgets/labels/labels.factor b/extra/ui/gadgets/labels/labels.factor
index 167aa26084..f800b12120 100755
--- a/extra/ui/gadgets/labels/labels.factor
+++ b/extra/ui/gadgets/labels/labels.factor
@@ -1,6 +1,6 @@
 ! Copyright (C) 2005, 2007 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays hashtables io kernel math namespaces
+USING: accessors arrays hashtables io kernel math namespaces
 opengl sequences strings splitting
 ui.gadgets ui.gadgets.tracks ui.gadgets.theme ui.render colors
 models ;
@@ -10,7 +10,7 @@ IN: ui.gadgets.labels
 TUPLE: label text font color ;
 
 : label-string ( label -- string )
-    label-text dup string? [ "\n" join ] unless ; inline
+    text>> dup string? [ "\n" join ] unless ; inline
 
 : set-label-string ( string label -- )
     CHAR: \n pick memq? [
@@ -19,21 +19,21 @@ TUPLE: label text font color ;
         set-label-text
     ] if ; inline
 
-: label-theme ( gadget -- )
-    black over set-label-color
-    sans-serif-font swap set-label-font ;
+: label-theme ( gadget -- gadget )
+    sans-serif-font >>font
+    black >>color ; inline
 
 : <label> ( string -- label )
     label construct-gadget
     [ set-label-string ] keep
-    dup label-theme ;
+    label-theme ;
 
 M: label pref-dim*
-    dup label-font open-font swap label-text text-dim ;
+    [ font>> open-font ] [ text>> ] bi text-dim ;
 
 M: label draw-gadget*
-    dup label-color gl-color
-    dup label-font swap label-text origin get draw-text ;
+    [ color>> gl-color ]
+    [ [ font>> ] [ text>> ] bi origin get draw-text ] bi ;
 
 M: label gadget-text* label-string % ;
 
@@ -45,12 +45,12 @@ M: label-control model-changed
 : <label-control> ( model -- gadget )
     "" <label> label-control construct-control ;
 
-: text-theme ( gadget -- )
-    black over set-label-color
-    monospace-font swap set-label-font ;
+: text-theme ( gadget -- gadget )
+    black >>color
+    monospace-font >>font ;
 
-: reverse-video-theme ( label -- )
-    white over set-label-color
+: reverse-video-theme ( label -- label )
+    white >>color
     black solid-interior ;
 
 GENERIC: >label ( obj -- gadget )
diff --git a/extra/ui/gadgets/lists/lists.factor b/extra/ui/gadgets/lists/lists.factor
index fd5234ab03..43c0539e91 100755
--- a/extra/ui/gadgets/lists/lists.factor
+++ b/extra/ui/gadgets/lists/lists.factor
@@ -1,6 +1,6 @@
 ! Copyright (C) 2006, 2007 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: ui.commands ui.gestures ui.render ui.gadgets
+USING: accessors ui.commands ui.gestures ui.render ui.gadgets
 ui.gadgets.labels ui.gadgets.scrollers
 kernel sequences models opengl math math.order namespaces
 ui.gadgets.presentations ui.gadgets.viewports ui.gadgets.packs
@@ -27,17 +27,18 @@ TUPLE: list index presenter color hook ;
     swap set-list-index ;
 
 : list-presentation-hook ( list -- quot )
-    list-hook [ [ [ list? ] is? ] find-parent ] prepend ;
+    hook>> [ [ [ list? ] is? ] find-parent ] prepend ;
 
 : <list-presentation> ( hook elt presenter -- gadget )
     keep <presentation>
-    [ set-presentation-hook ] keep
-    [ text-theme ] keep ;
+    swap >>hook
+    text-theme ; inline
 
 : <list-items> ( list -- seq )
-    dup list-presentation-hook
-    over list-presenter
-    rot control-value [
+    [ list-presentation-hook ]
+    [ presenter>> ]
+    [ control-value ]
+    tri [
         >r 2dup r> swap <list-presentation>
     ] map 2nip ;
 
diff --git a/extra/ui/gadgets/menus/menus.factor b/extra/ui/gadgets/menus/menus.factor
index 34051eaac0..153b4aeb6e 100644
--- a/extra/ui/gadgets/menus/menus.factor
+++ b/extra/ui/gadgets/menus/menus.factor
@@ -42,11 +42,11 @@ M: menu-glass layout* gadget-child prefer ;
     [ hand-clicked get find-world hide-glass ]
     3append <roll-button> ;
 
-: menu-theme ( gadget -- )
-    dup light-gray solid-interior
+: menu-theme ( gadget -- gadget )
+    light-gray solid-interior
     faint-boundary ;
 
 : <commands-menu> ( hook target commands -- gadget )
     [
         [ >r 2dup r> <menu-item> gadget, ] each 2drop
-    ] make-filled-pile 5 <border> dup menu-theme ;
+    ] make-filled-pile 5 <border> menu-theme ;
diff --git a/extra/ui/gadgets/panes/panes.factor b/extra/ui/gadgets/panes/panes.factor
index 880fb4450e..86d95e8ad0 100755
--- a/extra/ui/gadgets/panes/panes.factor
+++ b/extra/ui/gadgets/panes/panes.factor
@@ -182,7 +182,7 @@ M: pane-stream make-span-stream
     foreground [ over set-label-color ] apply-style ;
 
 : apply-background-style ( style gadget -- style gadget )
-    background [ dupd solid-interior ] apply-style ;
+    background [ solid-interior ] apply-style ;
 
 : specified-font ( style -- font )
     [ font swap at "monospace" or ] keep
@@ -207,15 +207,15 @@ M: pane-stream make-span-stream
 
 : apply-wrap-style ( style pane -- style pane )
     wrap-margin [
-        2dup <paragraph> swap set-pane-prototype
-        <paragraph> over set-pane-current
+        2dup <paragraph> >>prototype drop
+        <paragraph> >>current
     ] apply-style ;
 
 : apply-border-color-style ( style gadget -- style gadget )
-    border-color [ dupd solid-boundary ] apply-style ;
+    border-color [ solid-boundary ] apply-style ;
 
 : apply-page-color-style ( style gadget -- style gadget )
-    page-color [ dupd solid-interior ] apply-style ;
+    page-color [ solid-interior ] apply-style ;
 
 : apply-path-style ( style gadget -- style gadget )
     presented-path [ <editable-slot> ] apply-style ;
@@ -224,9 +224,7 @@ M: pane-stream make-span-stream
     border-width [ <border> ] apply-style ;
 
 : apply-printer-style ( style gadget -- style gadget )
-    presented-printer [
-        [ make-pane ] curry over set-editable-slot-printer
-    ] apply-style ;
+    presented-printer [ [ make-pane ] curry >>printer ] apply-style ;
 
 : style-pane ( style pane -- pane )
     apply-border-width-style
@@ -294,11 +292,8 @@ M: pack dispose drop ;
 M: paragraph dispose drop ;
 
 : gadget-write ( string gadget -- )
-    over empty? [
-        2drop
-    ] [
-        >r <label> dup text-theme r> add-gadget
-    ] if ;
+    over empty?
+    [ 2drop ] [ >r <label> text-theme r> add-gadget ] if ;
 
 M: pack stream-write gadget-write ;
 
@@ -372,11 +367,11 @@ M: f sloppy-pick-up*
 
 : extend-selection ( pane -- )
     hand-moved? [
-        dup pane-selecting? [
+        dup selecting?>> [
             dup move-caret
         ] [
             dup hand-clicked get child? [
-                t over set-pane-selecting?
+                t >>selecting?
                 dup hand-clicked set-global
                 dup move-caret
                 dup caret>mark
@@ -386,10 +381,9 @@ M: f sloppy-pick-up*
     ] when drop ;
 
 : end-selection ( pane -- )
-    f over set-pane-selecting?
+    f >>selecting?
     hand-moved? [
-        dup com-copy-selection
-        request-focus
+        [ com-copy-selection ] [ request-focus ] bi
     ] [
         relayout-1
     ] if ;
diff --git a/extra/ui/gadgets/scrollers/scrollers.factor b/extra/ui/gadgets/scrollers/scrollers.factor
index e513853d27..e58fbc5925 100755
--- a/extra/ui/gadgets/scrollers/scrollers.factor
+++ b/extra/ui/gadgets/scrollers/scrollers.factor
@@ -46,7 +46,7 @@ scroller H{
             y-model <y-slider> g-> set-scroller-y @right frame,
             viewport,
         ] with-gadget
-    ] keep t over set-gadget-root? dup faint-boundary ;
+    ] keep t >>root? faint-boundary ;
 
 : scroll ( value scroller -- )
     [
diff --git a/extra/ui/gadgets/sliders/sliders.factor b/extra/ui/gadgets/sliders/sliders.factor
index c781a9167d..eb22a5a823 100755
--- a/extra/ui/gadgets/sliders/sliders.factor
+++ b/extra/ui/gadgets/sliders/sliders.factor
@@ -1,6 +1,6 @@
 ! Copyright (C) 2005, 2007 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays ui.gestures ui.gadgets ui.gadgets.buttons
+USING: accessors arrays ui.gestures ui.gadgets ui.gadgets.buttons
 ui.gadgets.frames ui.gadgets.grids math.order
 ui.gadgets.theme ui.render kernel math namespaces sequences
 vectors models math.vectors math.functions quotations colors ;
@@ -65,14 +65,15 @@ thumb H{
     { T{ drag } [ do-drag ] }
 } set-gestures
 
-: thumb-theme ( thumb -- )
-    plain-gradient over set-gadget-interior faint-boundary ;
+: thumb-theme ( thumb -- thumb )
+    plain-gradient >>interior
+    faint-boundary ; inline
 
 : <thumb> ( vector -- thumb )
     thumb construct-gadget
-    t over set-gadget-root?
-    dup thumb-theme
-    [ set-gadget-orientation ] keep ;
+    swap >>orientation
+    t >>root?
+    thumb-theme ;
 
 : slide-by ( amount slider -- )
     gadget-model move-by ;
diff --git a/extra/ui/gadgets/status-bar/status-bar.factor b/extra/ui/gadgets/status-bar/status-bar.factor
index b528d6739c..417826a680 100755
--- a/extra/ui/gadgets/status-bar/status-bar.factor
+++ b/extra/ui/gadgets/status-bar/status-bar.factor
@@ -1,14 +1,14 @@
 ! Copyright (C) 2007, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: models sequences ui.gadgets.labels ui.gadgets.theme
-ui.gadgets.tracks ui.gadgets.worlds ui.gadgets ui kernel
-calendar ;
+USING: accessors models sequences ui.gadgets.labels
+ui.gadgets.theme ui.gadgets.tracks ui.gadgets.worlds ui.gadgets
+ui kernel calendar ;
 IN: ui.gadgets.status-bar
 
 : <status-bar> ( model -- gadget )
     1/10 seconds <delay> [ "" like ] <filter> <label-control>
-    dup reverse-video-theme
-    t over set-gadget-root? ;
+    reverse-video-theme
+    t >>root? ;
 
 : open-status-window ( gadget title -- )
     >r [
diff --git a/extra/ui/gadgets/theme/theme.factor b/extra/ui/gadgets/theme/theme.factor
index f0884f9486..68bd3b201a 100644
--- a/extra/ui/gadgets/theme/theme.factor
+++ b/extra/ui/gadgets/theme/theme.factor
@@ -2,17 +2,17 @@
 ! Copyright (C) 2006, 2007 Alex Chapman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays kernel sequences io.styles ui.gadgets ui.render
-colors ;
+colors accessors ;
 IN: ui.gadgets.theme
 
-: solid-interior ( gadget color -- )
-    <solid> swap set-gadget-interior ;
+: solid-interior ( gadget color -- gadget )
+    <solid> >>interior ; inline
 
-: solid-boundary ( gadget color -- )
-    <solid> swap set-gadget-boundary ;
+: solid-boundary ( gadget color -- gadget )
+    <solid> >>boundary ; inline
 
-: faint-boundary ( gadget -- )
-    gray solid-boundary ;
+: faint-boundary ( gadget -- gadget )
+    gray solid-boundary ; inline
 
 : selection-color ( -- color ) light-purple ;
 

From 9a89a97c5a4314c39d86e1fff6ddca19759eb362 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 18 Jun 2008 23:29:56 -0500
Subject: [PATCH 37/85] Fix deploy tests for real

---
 extra/io/encodings/8-bit/8-bit.factor   | 52 ++++++++++++-------------
 extra/tools/deploy/shaker/shaker.factor |  1 +
 extra/tools/deploy/test/4/4.factor      |  2 +-
 3 files changed, 27 insertions(+), 28 deletions(-)

diff --git a/extra/io/encodings/8-bit/8-bit.factor b/extra/io/encodings/8-bit/8-bit.factor
index 71c57ef68c..30eb745314 100755
--- a/extra/io/encodings/8-bit/8-bit.factor
+++ b/extra/io/encodings/8-bit/8-bit.factor
@@ -30,15 +30,12 @@ IN: io.encodings.8-bit
 } ;
 
 : encoding-file ( file-name -- stream )
-    "resource:extra/io/encodings/8-bit/" ".TXT"
-    swapd 3append ascii <file-reader> ;
-
-: tail-if ( seq n -- newseq )
-    2dup swap length <= [ tail ] [ drop ] if ;
+    "resource:extra/io/encodings/8-bit/" swap ".TXT"
+    3append ascii <file-reader> ;
 
 : process-contents ( lines -- assoc )
     [ "#" split1 drop ] map harvest
-    [ "\t" split 2 head [ 2 tail-if hex> ] map ] map ;
+    [ "\t" split 2 head [ 2 short tail hex> ] map ] map ;
 
 : byte>ch ( assoc -- array )
     256 replacement-char <array>
@@ -51,39 +48,40 @@ IN: io.encodings.8-bit
     lines process-contents
     [ byte>ch ] [ ch>byte ] bi ;
 
-TUPLE: 8-bit name decode encode ;
+SYMBOL: 8-bit-encodings
+
+TUPLE: 8-bit decode encode ;
 
 : encode-8-bit ( char stream assoc -- )
-    swapd at* [ encode-error ] unless swap stream-write1 ;
+    swap >r at*
+    [ r> stream-write1 ] [ r> drop encode-error ] if ; inline
 
-M: 8-bit encode-char
-    encode>> encode-8-bit ;
+M: 8-bit encode-char encode>> encode-8-bit ;
 
 : decode-8-bit ( stream array -- char/f )
-    swap stream-read1 dup
-    [ swap nth [ replacement-char ] unless* ]
-    [ nip ] if ;
+    >r stream-read1 dup
+    [ r> nth [ replacement-char ] unless* ] [ r> 2drop f ] if ; inline
 
-M: 8-bit decode-char
-    decode>> decode-8-bit ;
-
-: make-8-bit ( word byte>ch ch>byte -- )
-    [ 2drop ] [ 8-bit boa ] 3bi [ ] curry define ;
-
-: define-8-bit-encoding ( name stream -- )
-    >r in get create r> parse-file make-8-bit ;
+M: 8-bit decode-char decode>> decode-8-bit ;
 
 PREDICATE: 8-bit-encoding < word
-    word-def dup length 1 = [ first 8-bit? ] [ drop f ] if ;
+    8-bit-encodings get-global key? ;
 
-M: 8-bit-encoding <encoder> word-def first <encoder> ;
+M: 8-bit-encoding <encoder>
+    8-bit-encodings get-global at <encoder> ;
 
-M: 8-bit-encoding <decoder> word-def first <decoder> ;
+M: 8-bit-encoding <decoder>
+    8-bit-encodings get-global at <decoder> ;
 
 PRIVATE>
 
 [
-    "io.encodings.8-bit" in [
-        mappings [ encoding-file define-8-bit-encoding ] assoc-each
-    ] with-variable
+    mappings [
+        [ "io.encodings.8-bit" create ]
+        [ encoding-file parse-file 8-bit boa ]
+        bi*
+    ] assoc-map
+    [ 8-bit-encodings set-global ]
+    [ [ [ ] curry define ] assoc-each ]
+    bi
 ] with-compilation-unit
diff --git a/extra/tools/deploy/shaker/shaker.factor b/extra/tools/deploy/shaker/shaker.factor
index db0f478709..3df5485f4e 100755
--- a/extra/tools/deploy/shaker/shaker.factor
+++ b/extra/tools/deploy/shaker/shaker.factor
@@ -66,6 +66,7 @@ IN: tools.deploy.shaker
 
 : strip-word-defs ( words -- )
     "Stripping symbolic word definitions" show
+    [ "no-def-strip" word-prop not ] filter
     [ [ ] swap set-word-def ] each ;
 
 : strip-word-props ( retain-props words -- )
diff --git a/extra/tools/deploy/test/4/4.factor b/extra/tools/deploy/test/4/4.factor
index 6831eae5d3..a9ee71131c 100644
--- a/extra/tools/deploy/test/4/4.factor
+++ b/extra/tools/deploy/test/4/4.factor
@@ -2,6 +2,6 @@ IN: tools.deploy.test.4
 USING: io.encodings.8-bit io.encodings.string kernel ;
 
 : deploy-test-4 ( -- )
-    "xyzthg" latin7 encode drop ;
+    "xyzthg" \ latin7 encode drop ;
 
 MAIN: deploy-test-4

From 001e866b13e8fbc65d6d704b2e9794fca8eb9dc6 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Fri, 20 Jun 2008 11:49:08 +1200
Subject: [PATCH 38/85] Add yet another failing ebnf unit test

---
 extra/peg/ebnf/ebnf-tests.factor | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index ed38d37421..f613002fdf 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -442,3 +442,7 @@ foo=<foreign any-char> 'd'
 { V{ CHAR: a "d" } } [
   "ad" parser4 ast>>
 ] unit-test
+
+{ V{ "a" "\n" } } [
+  "a\n" [EBNF foo='a' '\n'  => [[ drop '\n' ]] EBNF] call ast>>
+] unit-test
\ No newline at end of file

From 91768f171c5bd8721d2a1c20a75478b9692857b0 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Fri, 20 Jun 2008 11:53:07 +1200
Subject: [PATCH 39/85] Rule 'x' defined more than once unit test

---
 extra/peg/ebnf/ebnf-tests.factor | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index f613002fdf..1824c0342a 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -445,4 +445,8 @@ foo=<foreign any-char> 'd'
 
 { V{ "a" "\n" } } [
   "a\n" [EBNF foo='a' '\n'  => [[ drop '\n' ]] EBNF] call ast>>
+] unit-test
+
+{ t } [
+  [EBNF foo='a' foo='b' EBNF] drop t
 ] unit-test
\ No newline at end of file

From 6bd761e4609a1ac2048e7bde627c4ccc384adc4a Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Fri, 20 Jun 2008 12:35:33 +1200
Subject: [PATCH 40/85] Another breaking unit test for ebnf

---
 extra/peg/ebnf/ebnf-tests.factor | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index 1824c0342a..0a16fc8007 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 !
 USING: kernel tools.test peg peg.ebnf words math math.parser 
-       sequences accessors peg.parsers ;
+       sequences accessors peg.parsers parser namespaces ;
 IN: peg.ebnf.tests
 
 { T{ ebnf-non-terminal f "abc" } } [
@@ -443,10 +443,17 @@ foo=<foreign any-char> 'd'
   "ad" parser4 ast>>
 ] unit-test
 
-{ V{ "a" "\n" } } [
-  "a\n" [EBNF foo='a' '\n'  => [[ drop '\n' ]] EBNF] call ast>>
+{ t } [
+ "USING: kernel peg.ebnf ; [EBNF foo='a' '\n'  => [[ drop '\n' ]] EBNF]" eval drop t
 ] unit-test
 
+[
+  "USING: peg.ebnf ; [EBNF foo='a' foo='b' EBNF]" eval 
+] must-fail
+
+
 { t } [
-  [EBNF foo='a' foo='b' EBNF] drop t
+  #! Rule lookup occurs in a namespace. This causes an incorrect duplicate rule
+  #! if a var in a namespace is set. This unit test is to remind me to fix this.
+  [ "fail" "foo" set "foo='a'" 'ebnf' parse ast>> transform drop t ] with-scope
 ] unit-test
\ No newline at end of file

From d22a24a90eef38975b6eb5bacfc010477730d453 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Fri, 20 Jun 2008 14:13:50 +1200
Subject: [PATCH 41/85] Fix some failing ebnf unit tests

---
 extra/peg/ebnf/ebnf-tests.factor |  2 +-
 extra/peg/ebnf/ebnf.factor       | 31 +++++++++++++++++++------------
 2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index 0a16fc8007..e3c6586c89 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -444,7 +444,7 @@ foo=<foreign any-char> 'd'
 ] unit-test
 
 { t } [
- "USING: kernel peg.ebnf ; [EBNF foo='a' '\n'  => [[ drop '\n' ]] EBNF]" eval drop t
+ "USING: kernel peg.ebnf ; [EBNF foo='a' '\n'  => [[ drop \"\n\" ]] EBNF]" eval drop t
 ] unit-test
 
 [
diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index e78757be34..cba48f5892 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -63,6 +63,20 @@ C: <ebnf> ebnf
   #! begin and end.
   [ syntax ] 2dip syntax pack ;
 
+: replace-escapes ( string -- string )
+  [
+    "\\t" token [ drop "\t" ] action ,
+    "\\n" token [ drop "\n" ] action ,
+    "\\r" token [ drop "\r" ] action ,
+  ] choice* replace ;
+
+: insert-escapes ( string -- string )
+  [
+    "\t" token [ drop "\\t" ] action ,
+    "\n" token [ drop "\\n" ] action ,
+    "\r" token [ drop "\\r" ] action ,
+  ] choice* replace ;
+
 : 'identifier' ( -- parser )
   #! Return a parser that parses an identifer delimited by
   #! a quotation character. The quotation can be single
@@ -71,7 +85,7 @@ C: <ebnf> ebnf
   [
     [ CHAR: " = not ] satisfy repeat1 "\"" "\"" surrounded-by ,
     [ CHAR: ' = not ] satisfy repeat1 "'" "'" surrounded-by ,
-  ] choice* [ >string ] action ;
+  ] choice* [ >string replace-escapes ] action ;
   
 : 'non-terminal' ( -- parser )
   #! A non-terminal is the name of another rule. It can
@@ -401,11 +415,11 @@ M: object build-locals ( code ast -- )
   } cond ;
  
 M: ebnf-action (transform) ( ast -- parser )
-  [ parser>> (transform) ] [ code>> ] [ parser>> ] tri build-locals  
+  [ parser>> (transform) ] [ code>> insert-escapes ] [ parser>> ] tri build-locals  
   string-lines parse-lines check-action-effect action ;
 
 M: ebnf-semantic (transform) ( ast -- parser )
-  [ parser>> (transform) ] [ code>> ] [ parser>> ] tri build-locals 
+  [ parser>> (transform) ] [ code>> insert-escapes ] [ parser>> ] tri build-locals 
   string-lines parse-lines semantic ;
 
 M: ebnf-var (transform) ( ast -- parser )
@@ -453,17 +467,10 @@ M: ebnf-non-terminal (transform) ( ast -- parser )
   parse-result-ast transform dup dup parser [ main swap at compile ] with-variable
   [ compiled-parse ] curry [ with-scope ] curry ;
 
-: replace-escapes ( string -- string )
-  [
-    "\\t" token [ drop "\t" ] action ,
-    "\\n" token [ drop "\n" ] action ,
-    "\\r" token [ drop "\r" ] action ,
-  ] choice* replace ;
-
-: [EBNF "EBNF]" parse-multiline-string replace-escapes ebnf>quot nip parsed ; parsing
+: [EBNF "EBNF]" parse-multiline-string ebnf>quot nip parsed ; parsing
 
 : EBNF: 
   CREATE-WORD dup 
-  ";EBNF" parse-multiline-string replace-escapes
+  ";EBNF" parse-multiline-string 
   ebnf>quot swapd 1 1 <effect> define-declared "ebnf-parser" set-word-prop ; parsing
 

From 7239c4d79f590997ddfa25ce3e6423c568b5cb62 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Fri, 20 Jun 2008 15:14:30 +1200
Subject: [PATCH 42/85] Make replace-escapes infer and fix remaining unit test
 breakage in ebnf

---
 extra/peg/ebnf/ebnf-tests.factor |  2 +-
 extra/peg/ebnf/ebnf.factor       | 15 ++++++++++++---
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index e3c6586c89..5a4ecc5c2f 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -448,7 +448,7 @@ foo=<foreign any-char> 'd'
 ] unit-test
 
 [
-  "USING: peg.ebnf ; [EBNF foo='a' foo='b' EBNF]" eval 
+  "USING: peg.ebnf ; [EBNF foo='a' foo='b' EBNF]" eval drop
 ] must-fail
 
 
diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index cba48f5892..8f36218b61 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -63,12 +63,17 @@ C: <ebnf> ebnf
   #! begin and end.
   [ syntax ] 2dip syntax pack ;
 
-: replace-escapes ( string -- string )
+#! Don't want to use 'replace' in an action since replace doesn't infer.
+#! Do the compilation of the peg at parse time and call (replace).
+PEG: escaper ( string -- ast )
   [
     "\\t" token [ drop "\t" ] action ,
     "\\n" token [ drop "\n" ] action ,
     "\\r" token [ drop "\r" ] action ,
-  ] choice* replace ;
+  ] choice* any-char-parser 2array choice repeat0 ;
+
+: replace-escapes ( string -- string )
+  escaper sift [ [ tree-write ] each ] with-string-writer ;
 
 : insert-escapes ( string -- string )
   [
@@ -319,7 +324,11 @@ M: ebnf (transform) ( ast -- parser )
 M: ebnf-rule (transform) ( ast -- parser )
   dup elements>> 
   (transform) [
-    swap symbol>> dup get [ "Rule '" over append "' defined more than once" append throw ] [ set ] if
+    swap symbol>> dup get { [ tuple? ] [ delegate parser? ] } 1&& [ 
+      "Rule '" over append "' defined more than once" append throw 
+    ] [ 
+      set 
+    ] if
   ] keep ;
 
 M: ebnf-sequence (transform) ( ast -- parser )

From b6b5f12732914b36a0939f1f0221eaf29f9867d0 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Fri, 20 Jun 2008 22:29:53 +1200
Subject: [PATCH 43/85] Provide ability to plug in tokenizers to ebnf parsers

---
 extra/peg/ebnf/ebnf.factor                    | 49 ++++++++++++++++---
 .../peg/javascript/tokenizer/tokenizer.factor |  2 +-
 2 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 8f36218b61..921ba7be67 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -11,6 +11,31 @@ IN: peg.ebnf
   #! Given an EBNF word produced from EBNF: return the EBNF rule
   "ebnf-parser" word-prop at ;
 
+TUPLE: tokenizer any one many ;
+
+: default-tokenizer ( -- tokenizer )
+  T{ tokenizer f 
+    [ [ drop t ] satisfy ]
+    [ token ]
+    [ [ = ] curry satisfy ]
+  } ;
+
+: parser-tokenizer ( parser -- tokenizer )
+  1quotation [ [ = ] curry satisfy ] dup tokenizer boa ;
+
+: rule-tokenizer ( name word -- tokenizer )
+  rule parser-tokenizer ;
+
+: tokenizer ( -- word )
+  \ tokenizer get [ default-tokenizer ] unless* ;
+
+: reset-tokenizer ( -- )
+  default-tokenizer \ tokenizer set-global ;
+
+: TOKENIZER: 
+  scan search [ "Tokenizer not found" throw ] unless*
+  execute \ tokenizer set-global ; parsing
+
 TUPLE: ebnf-non-terminal symbol ;
 TUPLE: ebnf-terminal symbol ;
 TUPLE: ebnf-foreign word rule ;
@@ -344,7 +369,7 @@ M: ebnf-choice (transform) ( ast -- parser )
   options>> [ (transform) ] map choice ;
 
 M: ebnf-any-character (transform) ( ast -- parser )
-  drop any-char ;
+  drop [ tokenizer any>> call ] box ;
 
 M: ebnf-range (transform) ( ast -- parser )
   pattern>> range-pattern ;
@@ -435,7 +460,7 @@ M: ebnf-var (transform) ( ast -- parser )
   parser>> (transform) ;
 
 M: ebnf-terminal (transform) ( ast -- parser )
-  symbol>> [ token ] keep [ = ] curry satisfy 2choice ;
+  symbol>> [ tokenizer one>> call ] curry box ;
 
 M: ebnf-foreign (transform) ( ast -- parser )
   dup word>> search
@@ -476,10 +501,22 @@ M: ebnf-non-terminal (transform) ( ast -- parser )
   parse-result-ast transform dup dup parser [ main swap at compile ] with-variable
   [ compiled-parse ] curry [ with-scope ] curry ;
 
-: [EBNF "EBNF]" parse-multiline-string ebnf>quot nip parsed ; parsing
+: [EBNF 
+  scan {
+    { "+" [ scan-word execute "" swap ] }
+    [ " " append default-tokenizer ]
+  } case \ tokenizer [
+    [ "EBNF]" parse-multiline-string ] [ drop "" ] recover append ebnf>quot nip parsed 
+  ] with-variable ; parsing
 
 : EBNF: 
-  CREATE-WORD dup 
-  ";EBNF" parse-multiline-string 
-  ebnf>quot swapd 1 1 <effect> define-declared "ebnf-parser" set-word-prop ; parsing
+  CREATE-WORD scan {
+    { "+" [ scan-word execute "" swap ] }
+    [ " " append default-tokenizer ]
+  } case \ tokenizer [
+    dupd [ ";EBNF" parse-multiline-string ] [ drop "" ] recover append 
+    ebnf>quot swapd 1 1 <effect> define-declared "ebnf-parser" set-word-prop 
+  ] with-variable ; parsing
+
+
 
diff --git a/extra/peg/javascript/tokenizer/tokenizer.factor b/extra/peg/javascript/tokenizer/tokenizer.factor
index a1cff8a3db..5bf6a639fa 100644
--- a/extra/peg/javascript/tokenizer/tokenizer.factor
+++ b/extra/peg/javascript/tokenizer/tokenizer.factor
@@ -8,7 +8,7 @@ IN: peg.javascript.tokenizer
 
 USE: prettyprint
 
-EBNF: tokenizer 
+EBNF: javascript-tokenizer 
 Letter            = [a-zA-Z]
 Digit             = [0-9]
 Digits            = Digit+

From eca8260799dde2a4da0df6ac78e83356ad34f3df Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Sat, 21 Jun 2008 00:28:13 +1200
Subject: [PATCH 44/85] peg.ebnf syntax for tokenizers

---
 extra/peg/ebnf/ebnf-tests.factor | 59 ++++++++++++++++++++++++++++++--
 extra/peg/ebnf/ebnf.factor       | 41 ++++++++++++++++------
 2 files changed, 87 insertions(+), 13 deletions(-)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index 5a4ecc5c2f..a90fa98436 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -2,7 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 !
 USING: kernel tools.test peg peg.ebnf words math math.parser 
-       sequences accessors peg.parsers parser namespaces ;
+       sequences accessors peg.parsers parser namespaces arrays 
+       strings ;
 IN: peg.ebnf.tests
 
 { T{ ebnf-non-terminal f "abc" } } [
@@ -451,9 +452,63 @@ foo=<foreign any-char> 'd'
   "USING: peg.ebnf ; [EBNF foo='a' foo='b' EBNF]" eval drop
 ] must-fail
 
-
 { t } [
   #! Rule lookup occurs in a namespace. This causes an incorrect duplicate rule
   #! if a var in a namespace is set. This unit test is to remind me to fix this.
   [ "fail" "foo" set "foo='a'" 'ebnf' parse ast>> transform drop t ] with-scope
+] unit-test
+
+#! Tokenizer tests
+{ V{ "a" CHAR: b } } [
+  "ab" [EBNF tokenizer=default foo="a" . EBNF] call ast>>
+] unit-test
+
+TUPLE: ast-number value ;
+
+EBNF: a-tokenizer 
+Letter            = [a-zA-Z]
+Digit             = [0-9]
+Digits            = Digit+
+SingleLineComment = "//" (!("\n") .)* "\n" => [[ ignore ]]
+MultiLineComment  = "/*" (!("*/") .)* "*/" => [[ ignore ]]
+Space             = " " | "\t" | "\r" | "\n" | SingleLineComment | MultiLineComment
+Spaces            = Space* => [[ ignore ]]
+Number            = Digits:ws '.' Digits:fs => [[ ws "." fs 3array concat >string string>number ast-number boa ]]
+                    | Digits => [[ >string string>number ast-number boa ]]  
+Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | ";"
+                     | "?"   | ":"   | "!==" | "~="  | "===" | "=="  | "="   | ">="
+                     | ">"   | "<="  | "<"   | "++"  | "+="  | "+"   | "--"  | "-="
+                     | "-"   | "*="  | "*"   | "/="  | "/"   | "%="  | "%"   | "&&="
+                     | "&&"  | "||=" | "||"  | "."   | "!"
+Tok                = Spaces (Number | Special )
+;EBNF
+
+{ V{ CHAR: 1 T{ ast-number f 23 } ";" CHAR: x } } [
+  "123;x" [EBNF bar = . 
+                tokenizer = <foreign a-tokenizer Tok>  foo=. 
+                tokenizer=default baz=. 
+                main = bar foo foo baz 
+          EBNF] call ast>>
+] unit-test
+
+{ V{ CHAR: 5 "+" CHAR: 2 } } [
+  "5+2" [EBNF 
+          space=(" " | "\n") 
+          number=[0-9] 
+          operator=("*" | "+") 
+          spaces=space* => [[ ignore ]] 
+          tokenizer=spaces (number | operator) 
+          main= . . . 
+        EBNF] call ast>> 
+] unit-test
+
+{ V{ CHAR: 5 "+" CHAR: 2 } } [
+  "5 + 2" [EBNF 
+          space=(" " | "\n") 
+          number=[0-9] 
+          operator=("*" | "+") 
+          spaces=space* => [[ ignore ]] 
+          tokenizer=spaces (number | operator) 
+          main= . . . 
+        EBNF] call ast>> 
 ] unit-test
\ No newline at end of file
diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 921ba7be67..25889fe44d 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -27,7 +27,7 @@ TUPLE: tokenizer any one many ;
   rule parser-tokenizer ;
 
 : tokenizer ( -- word )
-  \ tokenizer get [ default-tokenizer ] unless* ;
+  \ tokenizer get-global [ default-tokenizer ] unless* ;
 
 : reset-tokenizer ( -- )
   default-tokenizer \ tokenizer set-global ;
@@ -49,6 +49,7 @@ TUPLE: ebnf-repeat0 group ;
 TUPLE: ebnf-repeat1 group ;
 TUPLE: ebnf-optional group ;
 TUPLE: ebnf-whitespace group ;
+TUPLE: ebnf-tokenizer elements ;
 TUPLE: ebnf-rule symbol elements ;
 TUPLE: ebnf-action parser code ;
 TUPLE: ebnf-var parser name ;
@@ -68,6 +69,7 @@ C: <ebnf-repeat0> ebnf-repeat0
 C: <ebnf-repeat1> ebnf-repeat1
 C: <ebnf-optional> ebnf-optional
 C: <ebnf-whitespace> ebnf-whitespace
+C: <ebnf-tokenizer> ebnf-tokenizer
 C: <ebnf-rule> ebnf-rule
 C: <ebnf-action> ebnf-action
 C: <ebnf-var> ebnf-var
@@ -318,8 +320,17 @@ DEFER: 'choice'
     dup length 1 = [ first ] [ <ebnf-choice> ] if
   ] action ;
  
+: 'tokenizer' ( -- parser )
+  [
+    "tokenizer" syntax ,
+    "=" syntax ,
+    ">" token ensure-not ,
+    [ "default" token sp , 'choice' , ] choice* ,
+  ] seq* [ first <ebnf-tokenizer> ] action ;
+
 : 'rule' ( -- parser )
   [
+    "tokenizer" token ensure-not , 
     'non-terminal' [ symbol>> ] action  ,
     "=" syntax  ,
     ">" token ensure-not ,
@@ -327,7 +338,7 @@ DEFER: 'choice'
   ] seq* [ first2 <ebnf-rule> ] action ;
 
 : 'ebnf' ( -- parser )
-  'rule' sp repeat1 [ <ebnf> ] action ;
+  [ 'tokenizer' sp , 'rule' sp , ] choice* repeat1 [ <ebnf> ] action ;
 
 GENERIC: (transform) ( ast -- parser )
 
@@ -345,6 +356,14 @@ SYMBOL: ignore-ws
 
 M: ebnf (transform) ( ast -- parser )
   rules>> [ (transform) ] map peek ;
+
+M: ebnf-tokenizer (transform) ( ast -- parser )
+  elements>> dup "default" = [
+    drop default-tokenizer \ tokenizer set-global any-char
+  ] [
+  (transform) 
+  dup parser-tokenizer \ tokenizer set-global
+  ] if ;
   
 M: ebnf-rule (transform) ( ast -- parser )
   dup elements>> 
@@ -369,7 +388,7 @@ M: ebnf-choice (transform) ( ast -- parser )
   options>> [ (transform) ] map choice ;
 
 M: ebnf-any-character (transform) ( ast -- parser )
-  drop [ tokenizer any>> call ] box ;
+  drop tokenizer any>> call ;
 
 M: ebnf-range (transform) ( ast -- parser )
   pattern>> range-pattern ;
@@ -460,7 +479,7 @@ M: ebnf-var (transform) ( ast -- parser )
   parser>> (transform) ;
 
 M: ebnf-terminal (transform) ( ast -- parser )
-  symbol>> [ tokenizer one>> call ] curry box ;
+  symbol>> tokenizer one>> call ;
 
 M: ebnf-foreign (transform) ( ast -- parser )
   dup word>> search
@@ -505,18 +524,18 @@ M: ebnf-non-terminal (transform) ( ast -- parser )
   scan {
     { "+" [ scan-word execute "" swap ] }
     [ " " append default-tokenizer ]
-  } case \ tokenizer [
-    [ "EBNF]" parse-multiline-string ] [ drop "" ] recover append ebnf>quot nip parsed 
-  ] with-variable ; parsing
+  } case \ tokenizer set-global
+  [ "EBNF]" parse-multiline-string ] [ drop "" ] recover append ebnf>quot nip parsed 
+  reset-tokenizer ; parsing
 
 : EBNF: 
   CREATE-WORD scan {
     { "+" [ scan-word execute "" swap ] }
     [ " " append default-tokenizer ]
-  } case \ tokenizer [
-    dupd [ ";EBNF" parse-multiline-string ] [ drop "" ] recover append 
-    ebnf>quot swapd 1 1 <effect> define-declared "ebnf-parser" set-word-prop 
-  ] with-variable ; parsing
+  } case \ tokenizer set-global
+  dupd [ ";EBNF" parse-multiline-string ] [ drop "" ] recover append 
+  ebnf>quot swapd 1 1 <effect> define-declared "ebnf-parser" set-word-prop 
+  reset-tokenizer ; parsing
 
 
 

From 5433553571fd0c2382cb334fc94336515faa5c7d Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Sat, 21 Jun 2008 01:00:27 +1200
Subject: [PATCH 45/85] Remove EBNF: and [EBNF EBNF] +tokenizer syntax replaced
 with tokenizer support in ebnf grammar itself.

---
 extra/peg/ebnf/ebnf.factor                         | 14 ++------------
 extra/peg/javascript/javascript.factor             |  4 ++--
 extra/peg/javascript/parser/parser-tests.factor    | 10 +++++-----
 extra/peg/javascript/parser/parser.factor          |  2 +-
 .../javascript/tokenizer/tokenizer-tests.factor    |  4 ++--
 extra/peg/javascript/tokenizer/tokenizer.factor    |  2 +-
 6 files changed, 13 insertions(+), 23 deletions(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 25889fe44d..564b376b29 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -520,20 +520,10 @@ M: ebnf-non-terminal (transform) ( ast -- parser )
   parse-result-ast transform dup dup parser [ main swap at compile ] with-variable
   [ compiled-parse ] curry [ with-scope ] curry ;
 
-: [EBNF 
-  scan {
-    { "+" [ scan-word execute "" swap ] }
-    [ " " append default-tokenizer ]
-  } case \ tokenizer set-global
-  [ "EBNF]" parse-multiline-string ] [ drop "" ] recover append ebnf>quot nip parsed 
-  reset-tokenizer ; parsing
+: [EBNF "EBNF]" reset-tokenizer parse-multiline-string ebnf>quot nip parsed reset-tokenizer ; parsing
 
 : EBNF: 
-  CREATE-WORD scan {
-    { "+" [ scan-word execute "" swap ] }
-    [ " " append default-tokenizer ]
-  } case \ tokenizer set-global
-  dupd [ ";EBNF" parse-multiline-string ] [ drop "" ] recover append 
+  reset-tokenizer CREATE-WORD dup ";EBNF" parse-multiline-string  
   ebnf>quot swapd 1 1 <effect> define-declared "ebnf-parser" set-word-prop 
   reset-tokenizer ; parsing
 
diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index 23a4b4f7f0..d27a06e9d2 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -4,8 +4,8 @@ USING: kernel accessors peg.javascript.tokenizer peg.javascript.parser ;
 IN: peg.javascript
 
 : parse-javascript ( string -- ast )
-  tokenizer [
-    ast>> javascript [
+  tokenize-javascript [
+    ast>> parse-javascript [
       ast>>
     ] [
       "Unable to parse JavaScript" throw
diff --git a/extra/peg/javascript/parser/parser-tests.factor b/extra/peg/javascript/parser/parser-tests.factor
index d911a27285..b19bb314bb 100644
--- a/extra/peg/javascript/parser/parser-tests.factor
+++ b/extra/peg/javascript/parser/parser-tests.factor
@@ -5,7 +5,7 @@ USING: kernel tools.test peg peg.javascript.ast peg.javascript.tokenizer
        peg.javascript.parser accessors multiline sequences math ;
 IN: peg.javascript.parser.tests
 
-\ javascript must-infer
+\ parse-javascript must-infer
 
 {
   T{
@@ -23,14 +23,14 @@ IN: peg.javascript.parser.tests
       }
   }
 } [
-  "123; 'hello'; foo(x);" tokenizer ast>> javascript ast>>
+  "123; 'hello'; foo(x);" tokenize-javascript ast>> parse-javascript ast>>
 ] unit-test
 
 { t } [ 
 <"
 var x=5
 var y=10
-"> tokenizer ast>> javascript remaining>> length zero?
+"> tokenize-javascript ast>> parse-javascript remaining>> length zero?
 ] unit-test
 
 
@@ -41,7 +41,7 @@ function foldl(f, initial, seq) {
      initial = f(initial, seq[i]);
    return initial;
 }
-"> tokenizer ast>> javascript remaining>> length zero?
+"> tokenize-javascript ast>> parse-javascript remaining>> length zero?
 ] unit-test
 
 { t } [ 
@@ -52,6 +52,6 @@ ParseState.prototype.from = function(index) {
     r.length = this.length - index;
     return r;
 }
-"> tokenizer ast>> javascript remaining>> length zero?
+"> tokenize-javascript ast>> parse-javascript remaining>> length zero?
 ] unit-test
 
diff --git a/extra/peg/javascript/parser/parser.factor b/extra/peg/javascript/parser/parser.factor
index 45aa0f022c..1a074090f3 100644
--- a/extra/peg/javascript/parser/parser.factor
+++ b/extra/peg/javascript/parser/parser.factor
@@ -6,7 +6,7 @@ IN: peg.javascript.parser
 #! Grammar for JavaScript. Based on OMeta-JS example from:
 #! http://jarrett.cs.ucla.edu/ometa-js/#JavaScript_Compiler 
 
-EBNF: javascript
+EBNF: parse-javascript
 End               = !(.)
 Space             = " " | "\t" | "\n" 
 Spaces            = Space* => [[ ignore ]]
diff --git a/extra/peg/javascript/tokenizer/tokenizer-tests.factor b/extra/peg/javascript/tokenizer/tokenizer-tests.factor
index 1300b3c9c7..509ff4a0fe 100644
--- a/extra/peg/javascript/tokenizer/tokenizer-tests.factor
+++ b/extra/peg/javascript/tokenizer/tokenizer-tests.factor
@@ -4,7 +4,7 @@
 USING: kernel tools.test peg peg.javascript.ast peg.javascript.tokenizer accessors ;
 IN: peg.javascript.tokenizer.tests
 
-\ tokenizer must-infer
+\ tokenize-javascript must-infer
 
 {
   V{
@@ -19,5 +19,5 @@ IN: peg.javascript.tokenizer.tests
     ";"
   }    
 } [
-  "123; 'hello'; foo(x);" tokenizer ast>>
+  "123; 'hello'; foo(x);" tokenize-javascript ast>>
 ] unit-test
diff --git a/extra/peg/javascript/tokenizer/tokenizer.factor b/extra/peg/javascript/tokenizer/tokenizer.factor
index 5bf6a639fa..b72173f956 100644
--- a/extra/peg/javascript/tokenizer/tokenizer.factor
+++ b/extra/peg/javascript/tokenizer/tokenizer.factor
@@ -8,7 +8,7 @@ IN: peg.javascript.tokenizer
 
 USE: prettyprint
 
-EBNF: javascript-tokenizer 
+EBNF: tokenize-javascript 
 Letter            = [a-zA-Z]
 Digit             = [0-9]
 Digits            = Digit+

From 6b83ab9d9060f8972b43d7082253a3a957d1f96f Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Sat, 21 Jun 2008 01:49:07 +1200
Subject: [PATCH 46/85] Fix terminal parser with non-default tokenizers

---
 extra/peg/ebnf/ebnf-tests.factor                |  4 ++++
 extra/peg/ebnf/ebnf.factor                      |  7 ++++---
 extra/peg/javascript/javascript.factor          |  2 +-
 extra/peg/javascript/parser/parser-tests.factor | 14 +++++++-------
 extra/peg/javascript/parser/parser.factor       |  5 +++--
 5 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/extra/peg/ebnf/ebnf-tests.factor b/extra/peg/ebnf/ebnf-tests.factor
index a90fa98436..2269af6625 100644
--- a/extra/peg/ebnf/ebnf-tests.factor
+++ b/extra/peg/ebnf/ebnf-tests.factor
@@ -511,4 +511,8 @@ Tok                = Spaces (Number | Special )
           tokenizer=spaces (number | operator) 
           main= . . . 
         EBNF] call ast>> 
+] unit-test
+
+{ "++" } [
+  "++--" [EBNF tokenizer=("++" | "--") main="++" EBNF] call ast>>
 ] unit-test
\ No newline at end of file
diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 564b376b29..4725534178 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -15,13 +15,14 @@ TUPLE: tokenizer any one many ;
 
 : default-tokenizer ( -- tokenizer )
   T{ tokenizer f 
-    [ [ drop t ] satisfy ]
+    [ any-char ]
     [ token ]
-    [ [ = ] curry satisfy ]
+    [ [ = ] curry any-char swap semantic ]
   } ;
 
 : parser-tokenizer ( parser -- tokenizer )
-  1quotation [ [ = ] curry satisfy ] dup tokenizer boa ;
+  [ 1quotation ] keep
+  [ swap [ = ] curry semantic ] curry dup tokenizer boa ;
 
 : rule-tokenizer ( name word -- tokenizer )
   rule parser-tokenizer ;
diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index d27a06e9d2..791f63c56b 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -5,7 +5,7 @@ IN: peg.javascript
 
 : parse-javascript ( string -- ast )
   tokenize-javascript [
-    ast>> parse-javascript [
+    ast>> javascript [
       ast>>
     ] [
       "Unable to parse JavaScript" throw
diff --git a/extra/peg/javascript/parser/parser-tests.factor b/extra/peg/javascript/parser/parser-tests.factor
index b19bb314bb..fd0e27b6d4 100644
--- a/extra/peg/javascript/parser/parser-tests.factor
+++ b/extra/peg/javascript/parser/parser-tests.factor
@@ -1,11 +1,11 @@
 ! Copyright (C) 2008 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
 !
-USING: kernel tools.test peg peg.javascript.ast peg.javascript.tokenizer  
-       peg.javascript.parser accessors multiline sequences math ;
+USING: kernel tools.test peg peg.javascript.ast peg.javascript.parser 
+       accessors multiline sequences math ;
 IN: peg.javascript.parser.tests
 
-\ parse-javascript must-infer
+\ javascript must-infer
 
 {
   T{
@@ -23,14 +23,14 @@ IN: peg.javascript.parser.tests
       }
   }
 } [
-  "123; 'hello'; foo(x);" tokenize-javascript ast>> parse-javascript ast>>
+  "123; 'hello'; foo(x);" javascript ast>>
 ] unit-test
 
 { t } [ 
 <"
 var x=5
 var y=10
-"> tokenize-javascript ast>> parse-javascript remaining>> length zero?
+"> javascript remaining>> length zero?
 ] unit-test
 
 
@@ -41,7 +41,7 @@ function foldl(f, initial, seq) {
      initial = f(initial, seq[i]);
    return initial;
 }
-"> tokenize-javascript ast>> parse-javascript remaining>> length zero?
+"> javascript remaining>> length zero?
 ] unit-test
 
 { t } [ 
@@ -52,6 +52,6 @@ ParseState.prototype.from = function(index) {
     r.length = this.length - index;
     return r;
 }
-"> tokenize-javascript ast>> parse-javascript remaining>> length zero?
+"> javascript remaining>> length zero?
 ] unit-test
 
diff --git a/extra/peg/javascript/parser/parser.factor b/extra/peg/javascript/parser/parser.factor
index 1a074090f3..0239ce882c 100644
--- a/extra/peg/javascript/parser/parser.factor
+++ b/extra/peg/javascript/parser/parser.factor
@@ -1,12 +1,13 @@
 ! Copyright (C) 2008 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors peg peg.ebnf peg.javascript.ast ;
+USING: kernel accessors peg peg.ebnf peg.javascript.ast peg.javascript.tokenizer ;
 IN: peg.javascript.parser
 
 #! Grammar for JavaScript. Based on OMeta-JS example from:
 #! http://jarrett.cs.ucla.edu/ometa-js/#JavaScript_Compiler 
 
-EBNF: parse-javascript
+EBNF: javascript
+tokenizer         = <foreign tokenize-javascript Tok>
 End               = !(.)
 Space             = " " | "\t" | "\n" 
 Spaces            = Space* => [[ ignore ]]

From ff8e52190725b8b3f1790c7909380a88b713eafb Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Sat, 21 Jun 2008 02:06:58 +1200
Subject: [PATCH 47/85] Fix automatic semicolon insertion rule in JavaScript
 parser

---
 extra/peg/javascript/parser/parser.factor | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/extra/peg/javascript/parser/parser.factor b/extra/peg/javascript/parser/parser.factor
index 0239ce882c..f9a070dd86 100644
--- a/extra/peg/javascript/parser/parser.factor
+++ b/extra/peg/javascript/parser/parser.factor
@@ -6,7 +6,21 @@ IN: peg.javascript.parser
 #! Grammar for JavaScript. Based on OMeta-JS example from:
 #! http://jarrett.cs.ucla.edu/ometa-js/#JavaScript_Compiler 
 
+#! The interesting thing about this parser is the mixing of
+#! a default and non-default tokenizer. The JavaScript tokenizer
+#! removes all newlines. So when operating on tokens there is no
+#! need for newline and space skipping in the grammar. But JavaScript
+#! uses the newline in the 'automatic semicolon insertion' rule. 
+#!
+#! If a statement ends in a newline, sometimes the semicolon can be
+#! skipped. So we define an 'nl' rule using the default tokenizer. 
+#! This operates a character at a time. Using this 'nl' in the parser
+#! allows us to detect newlines when we need to for the semicolon
+#! insertion rule, but ignore it in all other places.
 EBNF: javascript
+tokenizer         = default 
+nl                = "\n"
+
 tokenizer         = <foreign tokenize-javascript Tok>
 End               = !(.)
 Space             = " " | "\t" | "\n" 
@@ -14,7 +28,7 @@ Spaces            = Space* => [[ ignore ]]
 Name               = . ?[ ast-name?   ]?   => [[ value>> ]] 
 Number             = . ?[ ast-number? ]?   => [[ value>> ]]
 String             = . ?[ ast-string? ]?   => [[ value>> ]]
-SpacesNoNl         = (!("\n") Space)* => [[ ignore ]]
+SpacesNoNl         = (!(nl) Space)* => [[ ignore ]]
 
 Expr               =   OrExpr:e "?" Expr:t ":" Expr:f   => [[ e t f ast-cond-expr boa ]]
                      | OrExpr:e "=" Expr:rhs            => [[ e rhs ast-set boa ]]
@@ -80,7 +94,7 @@ JsonPropName       = Name | Number | String
 Formal             = Spaces Name
 Formals            = (Formal ("," Formal => [[ second ]])*  => [[ first2 swap prefix ]])?
 FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ fs body ast-func boa ]]
-Sc                 = SpacesNoNl ("\n" | &("}") | End)| ";"
+Sc                 = SpacesNoNl (nl | &("}") | End)| ";"
 Binding            =   Name:n "=" Expr:v                      => [[ n v ast-var boa ]]
                      | Name:n                                 => [[ n "undefined" ast-get boa ast-var boa ]]
 Block              = "{" SrcElems:ss "}"                      => [[ ss ]]

From 4a47346bda1522f08a725a5c85f7516a0342c8b2 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Sat, 21 Jun 2008 02:09:46 +1200
Subject: [PATCH 48/85] Fix parse-javascript word for recent changes

---
 extra/peg/javascript/javascript.factor | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor
index 791f63c56b..8fe0538eae 100644
--- a/extra/peg/javascript/javascript.factor
+++ b/extra/peg/javascript/javascript.factor
@@ -4,13 +4,8 @@ USING: kernel accessors peg.javascript.tokenizer peg.javascript.parser ;
 IN: peg.javascript
 
 : parse-javascript ( string -- ast )
-  tokenize-javascript [
-    ast>> javascript [
-      ast>>
-    ] [
-      "Unable to parse JavaScript" throw
-    ] if*
+  javascript [
+    ast>>
   ] [
-    "Unable to tokenize JavaScript" throw
+    "Unable to parse JavaScript" throw
   ] if* ;
-

From e8f990454905d86241f824ba29452ed82d3a0c02 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Sat, 21 Jun 2008 02:21:54 +1200
Subject: [PATCH 49/85] Add \r to the JavaScript automatic semicolon insertion
 routine

---
 extra/peg/javascript/parser/parser.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extra/peg/javascript/parser/parser.factor b/extra/peg/javascript/parser/parser.factor
index f9a070dd86..15ab8ee1c4 100644
--- a/extra/peg/javascript/parser/parser.factor
+++ b/extra/peg/javascript/parser/parser.factor
@@ -19,7 +19,7 @@ IN: peg.javascript.parser
 #! insertion rule, but ignore it in all other places.
 EBNF: javascript
 tokenizer         = default 
-nl                = "\n"
+nl                = "\r" "\n" | "\n"
 
 tokenizer         = <foreign tokenize-javascript Tok>
 End               = !(.)

From 8fa0c80d4e93780d3a31623702fe721ea1c5e1d1 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Sat, 21 Jun 2008 02:29:47 +1200
Subject: [PATCH 50/85] Add regular expressions to JavaScript parser

---
 extra/peg/javascript/parser/parser.factor | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/extra/peg/javascript/parser/parser.factor b/extra/peg/javascript/parser/parser.factor
index 15ab8ee1c4..6abe2fb385 100644
--- a/extra/peg/javascript/parser/parser.factor
+++ b/extra/peg/javascript/parser/parser.factor
@@ -28,6 +28,7 @@ Spaces            = Space* => [[ ignore ]]
 Name               = . ?[ ast-name?   ]?   => [[ value>> ]] 
 Number             = . ?[ ast-number? ]?   => [[ value>> ]]
 String             = . ?[ ast-string? ]?   => [[ value>> ]]
+RegExp             = . ?[ ast-regexp? ]?   => [[ value>> ]]
 SpacesNoNl         = (!(nl) Space)* => [[ ignore ]]
 
 Expr               =   OrExpr:e "?" Expr:t ":" Expr:f   => [[ e t f ast-cond-expr boa ]]
@@ -83,6 +84,7 @@ PrimExprHd         =   "(" Expr:e ")"                        => [[ e ]]
                      | Name                                  => [[ ast-get boa ]]
                      | Number                                => [[ ast-number boa ]]
                      | String                                => [[ ast-string boa ]]
+                     | RegExp                                => [[ ast-regexp boa ]]
                      | "function" FuncRest:fr                => [[ fr ]]
                      | "new" Name:n "(" Args:as ")"          => [[ n as ast-new boa ]]
                      | "[" Args:es "]"                       => [[ es ast-array boa ]]
@@ -90,7 +92,7 @@ PrimExprHd         =   "(" Expr:e ")"                        => [[ e ]]
 JsonBindings        = (JsonBinding ("," JsonBinding => [[ second ]])* => [[ first2 swap prefix ]])?
 Json               = "{" JsonBindings:bs "}"                  => [[ bs ast-json boa ]]
 JsonBinding        = JsonPropName:n ":" Expr:v               => [[ n v ast-binding boa ]]
-JsonPropName       = Name | Number | String
+JsonPropName       = Name | Number | String | RegExp
 Formal             = Spaces Name
 Formals            = (Formal ("," Formal => [[ second ]])*  => [[ first2 swap prefix ]])?
 FuncRest           = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ fs body ast-func boa ]]

From c5a9ee0e160ca7fd087198bf50a750df7f8f2f81 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Sat, 21 Jun 2008 02:40:08 +1200
Subject: [PATCH 51/85] Add typeof, void and delete to JavaScript grammar

---
 extra/peg/javascript/parser/parser.factor | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/extra/peg/javascript/parser/parser.factor b/extra/peg/javascript/parser/parser.factor
index 6abe2fb385..5eb42daa31 100644
--- a/extra/peg/javascript/parser/parser.factor
+++ b/extra/peg/javascript/parser/parser.factor
@@ -69,6 +69,9 @@ Unary              =   "-" Postfix:p                    => [[ p "-" ast-unop boa
                      | "++" Postfix:p                   => [[ p "++" ast-preop boa ]]
                      | "--" Postfix:p                   => [[ p "--" ast-preop boa ]]
                      | "!" Postfix:p                    => [[ p "!" ast-unop boa ]]
+                     | "typeof" Postfix:p               => [[ p "typeof" ast-unop boa ]]
+                     | "void" Postfix:p                 => [[ p "void" ast-unop boa ]]
+                     | "delete" Postfix:p               => [[ p "delete" ast-unop boa ]]
                      | Postfix
 Postfix            =   PrimExpr:p SpacesNoNl "++"       => [[ p "++" ast-postop boa ]]
                      | PrimExpr:p SpacesNoNl "--"       => [[ p "--" ast-postop boa ]]

From a15783cabb4250bcab5376e6b2869e3aff270fbe Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Sat, 21 Jun 2008 10:32:15 +1200
Subject: [PATCH 52/85] Fix typo in != in JavaScript parser

---
 extra/peg/javascript/tokenizer/tokenizer.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extra/peg/javascript/tokenizer/tokenizer.factor b/extra/peg/javascript/tokenizer/tokenizer.factor
index b72173f956..195184a16c 100644
--- a/extra/peg/javascript/tokenizer/tokenizer.factor
+++ b/extra/peg/javascript/tokenizer/tokenizer.factor
@@ -60,7 +60,7 @@ Str                =   '"""' StringChars1:cs '"""' => [[ cs ast-string boa ]]
 RegExpBody         = (!("/" | "\n" | "\r") .)* => [[ >string ]]
 RegExp             = "/" RegExpBody:r "/" => [[ r ast-regexp boa ]]
 Special            =   "("   | ")"   | "{"   | "}"   | "["   | "]"   | ","   | ";"
-                     | "?"   | ":"   | "!==" | "~="  | "===" | "=="  | "="   | ">="
+                     | "?"   | ":"   | "!==" | "!="  | "===" | "=="  | "="   | ">="
                      | ">"   | "<="  | "<"   | "++"  | "+="  | "+"   | "--"  | "-="
                      | "-"   | "*="  | "*"   | "/="  | "/"   | "%="  | "%"   | "&&="
                      | "&&"  | "||=" | "||"  | "."   | "!"

From fa2cd6a709cbf793b83e805b58d00318e92d0d3a Mon Sep 17 00:00:00 2001
From: William Schlieper <schlieper@unc.edu>
Date: Fri, 20 Jun 2008 22:52:44 -0400
Subject: [PATCH 53/85] Added extra/graph-theory

---
 extra/graph-theory/graph-theory-docs.factor   | 135 ++++++++++++++++++
 extra/graph-theory/graph-theory.factor        |  92 ++++++++++++
 extra/graph-theory/reversals/reversals.factor |  22 +++
 extra/graph-theory/sparse/sparse.factor       |  35 +++++
 4 files changed, 284 insertions(+)
 create mode 100644 extra/graph-theory/graph-theory-docs.factor
 create mode 100644 extra/graph-theory/graph-theory.factor
 create mode 100644 extra/graph-theory/reversals/reversals.factor
 create mode 100644 extra/graph-theory/sparse/sparse.factor

diff --git a/extra/graph-theory/graph-theory-docs.factor b/extra/graph-theory/graph-theory-docs.factor
new file mode 100644
index 0000000000..82d8b9adf6
--- /dev/null
+++ b/extra/graph-theory/graph-theory-docs.factor
@@ -0,0 +1,135 @@
+! See http://factorcode.org/license.txt for BSD licence.
+USING: help.markup help.syntax ;
+
+IN: graph-theory
+
+ARTICLE: "graph-protocol" "Graph protocol"
+"All graphs must be instances of the graph mixin:"
+{ $subsection graph }
+"All graphs must implement a method on the following generic word:"
+{ $subsection vertices }
+"At least one of the following two generic words must have a method; the " { $link graph } " mixin has default definitions which are mutually recursive:"
+{ $subsection adjlist }
+{ $subsection adj? }
+"All mutable graphs must implement a method on the following generic word:"
+{ $subsection add-blank-vertex }
+"All mutable undirected graphs must implement a method on the following generic word:"
+{ $subsection add-edge }
+"Mutable directed graphs should not implement the above word, as it has a default definition defined in terms of the following generic word:"
+{ $subsection add-edge* }
+"The following two words have default definitions, but are available as generics to allow implementations to optimize them:"
+{ $subsection num-vertices }
+{ $subsection num-edges } ;
+
+HELP: graph
+{ $class-description "A mixin class whose instances are graphs.  Custom implementations of the graph protocol should be declared as instances of this mixin for all graph functionality to work correctly:"
+    { $code "INSTANCE: hex-board graph" }
+} ;
+
+{ vertices num-vertices num-edges } related-words
+
+HELP: vertices
+{ $values { "graph" graph } { "seq" "The vertices" } }
+{ $description "Returns the vertices of the graph." } ;
+
+HELP: num-vertices
+{ $values { "graph" graph } { "n" "The number of vertices" } }
+{ $description "Returns the number of vertices in the graph." } ;
+
+HELP: num-edges
+{ $values { "graph" "A graph" } { "n" "The number of edges" } }
+{ $description "Returns the number of edges in the graph." } ;
+
+{ adjlist adj? } related-words
+
+HELP: adjlist
+{ $values
+    { "from" "The index of a vertex" }
+    { "graph" "The graph to be examined" }
+    { "seq" "The adjacency list" } }
+{ $description "Returns a sequence of vertices that this vertex links to" } ;
+
+HELP: adj?
+{ $values
+    { "from" "The index of a vertex" }
+    { "to" "The index of a vertex" }
+    { "graph" "A graph" }
+    { "?" "A boolean" } }
+{ $description "Returns a boolean describing whether there is an edge in the graph between from and to." } ;
+
+{ add-blank-vertex add-blank-vertices add-edge add-edge* } related-words
+
+HELP: add-blank-vertex
+{ $values
+    { "index" "A vertex index" }
+    { "graph" "A graph" } }
+{ $description "Adds a vertex to the graph." } ;
+
+HELP: add-blank-vertices
+{ $values
+    { "seq" "A sequence of vertex indices" }
+    { "graph" "A graph" } }
+{ $description "Adds vertices with indices in seq to the graph." } ;
+
+HELP: add-edge*
+{ $values
+    { "from" "The index of a vertex" }
+    { "to" "The index of another vertex" }
+    { "graph" "A graph" } }
+{ $description "Adds a one-way edge to the graph, between from and to."
+  $nl 
+  "If you want to add a two-way edge, use " { $link add-edge } " instead." } ;
+
+HELP: add-edge
+{ $values
+    { "m" "The index of a vertex" }
+    { "n" "The index of another vertex" }
+    { "graph" "A graph" } }
+{ $description "Adds a two-way edge to the graph, between m and n."
+  $nl
+  "If you want to add a one-way edge, use " { $link add-edge* } " instead." } ;
+
+{ depth-first full-depth-first dag? topological-sort } related-words
+
+HELP: depth-first
+{ $values
+    { "v" "The vertex to start the search at" }
+    { "graph" "The graph to search" }
+    { "pre" "A quotation of the form ( n -- )" }
+    { "post" "A quotation of the form ( n -- )" }
+    { "?list" "A list of booleans describing the vertices visited in the search" }
+    { "?" "A boolean describing whether or not the end-search error was thrown" } }
+{ $description "Performs a depth-first search on " { $emphasis "graph" } ".  The variable " { $emphasis "graph" } " can be accessed in both quotations."
+  $nl
+  "The " { $emphasis "pre" } " quotation is run before the recursive application of depth-first."
+  $nl
+  "The " { $emphasis "post" } " quotation is run after the recursive application of depth-first."
+  $nl
+  { $emphasis "?list" } " is a list of booleans, " { $link t } " for every vertex visted during the search, and " { $link f } " for every vertex not visited." } ;
+
+HELP: full-depth-first
+{ $values
+    { "graph" "The graph to search" }
+    { "pre" "A quotation of the form ( n -- )" }
+    { "post" "A quotation of the form ( n -- )" }
+    { "tail" "A quotation of the form ( -- )" }
+    { "?" "A boolean describing whether or not the end-search error was thrown" } }
+{ $description "Performs a depth-first search on " { $emphasis "graph" } ".  The variable " { $emphasis "graph" } "can be accessed in both quotations."
+  $nl
+  "The " { $emphasis "pre" } " quotation is run before the recursive application of depth-first."
+  $nl
+  "The " { $emphasis "post" } " quotation is run after the recursive application of depth-first."
+  $nl
+  "The " { $emphasis "tail" } " quotation is run after each time the depth-first search runs out of nodes.  On an undirected graph this will be each connected subgroup but on a directed graph it can be more complex." } ;
+
+HELP: dag?
+{ $values
+    { "graph" graph }
+    { "?" "A boolean indicating if the graph is acyclic" } }
+{ $description "Using a depth-first search, determines if the specified directed graph is a directed acyclic graph.  An undirected graph will produce a false result, as the algorithm does not eliminate cycles of length 2, which will include any edge that goes both ways." } ;
+
+HELP: topological-sort
+{ $values
+    { "graph" graph }
+    { "seq/f" "Either a sequence of values or f" } }
+{ $description "Using a depth-first search, topologically sorts the specified directed graph.  Returns f if the graph contains any cycles, and a topologically sorted sequence otherwise." } ;
diff --git a/extra/graph-theory/graph-theory.factor b/extra/graph-theory/graph-theory.factor
new file mode 100644
index 0000000000..322f17d2dd
--- /dev/null
+++ b/extra/graph-theory/graph-theory.factor
@@ -0,0 +1,92 @@
+! Copyright (C) 2008 William Schlieper <schlieper@unc.edu>
+! See http://factorcode.org/license.txt for BSD license.
+
+USING: kernel combinators fry continuations sequences arrays vectors assocs hashtables heaps namespaces ;
+
+IN: graph-theory
+
+MIXIN: graph
+SYMBOL: visited?
+ERROR: end-search ;
+
+GENERIC: vertices ( graph -- seq ) flushable
+
+GENERIC: num-vertices ( graph -- n ) flushable
+
+GENERIC: num-edges ( graph -- n ) flushable
+
+GENERIC: adjlist ( from graph -- seq ) flushable
+
+GENERIC: adj? ( from to graph -- ? ) flushable
+
+GENERIC: add-blank-vertex ( index graph -- )
+
+GENERIC: delete-blank-vertex ( index graph -- )
+
+GENERIC: add-edge* ( from to graph -- )
+
+GENERIC: add-edge ( u v graph -- )
+
+GENERIC: delete-edge* ( from to graph -- )
+
+GENERIC: delete-edge ( u v graph -- )
+
+M: graph num-vertices
+    vertices length ;
+
+M: graph num-edges
+   [ vertices ] [ '[ , adjlist length ] map sum ] bi ;
+
+M: graph adjlist
+    [ vertices ] [ swapd '[ , swap , adj? ] filter ] bi ;
+
+M: graph adj?
+    swapd adjlist index >boolean ;
+
+M: graph add-edge
+    [ add-edge* ] [ swapd add-edge* ] 3bi ;
+
+M: graph delete-edge
+    [ delete-edge* ] [ swapd delete-edge* ] 3bi ;
+
+: add-blank-vertices ( seq graph -- )
+    '[ , add-blank-vertex ] each ;
+
+: delete-vertex ( index graph -- )
+    [ adjlist ]
+    [ '[ , , 3dup adj? [ delete-edge* ] [ 3drop ] if ] each ]
+    [ delete-blank-vertex ] 2tri ;
+
+<PRIVATE
+
+: search-wrap ( quot graph -- ? )
+    [ [ graph set ] [ vertices [ f 2array ] map >hashtable visited? set ] bi
+      [ t ] compose [ dup end-search? [ drop f ] [ rethrow ] if ] recover ] with-scope ; inline
+
+: (depth-first) ( v pre post -- )
+    { [ 2drop visited? get t -rot set-at ] 
+      [ drop call ]
+      [ [ graph get adjlist ] 2dip
+        '[ dup visited? get at [ drop ] [ , , (depth-first) ] if ] each ]
+      [ nip call ] } 3cleave ; inline
+
+PRIVATE>
+
+: depth-first ( v graph pre post -- ?list ? )
+    '[ , , (depth-first) visited? get ] swap search-wrap ; inline
+
+: full-depth-first ( graph pre post tail -- ? )
+    '[ [ visited? get [ nip not ] assoc-find ] 
+       [ drop , , (depth-first) @ ] 
+       [ 2drop ] while ] swap search-wrap ; inline
+
+: dag? ( graph -- ? )
+    V{ } clone swap [ 2dup swap push dupd
+                     '[ , swap graph get adj? not ] all? 
+                      [ end-search ] unless ]
+                    [ drop dup pop* ] [ ] full-depth-first nip ;
+
+: topological-sort ( graph -- seq/f )
+    dup dag?
+    [ V{ } swap [ drop ] [ prefix ] [ ] full-depth-first drop ]
+    [ drop f ] if ;
diff --git a/extra/graph-theory/reversals/reversals.factor b/extra/graph-theory/reversals/reversals.factor
new file mode 100644
index 0000000000..1ea1a3fbf5
--- /dev/null
+++ b/extra/graph-theory/reversals/reversals.factor
@@ -0,0 +1,22 @@
+! Copyright (C) 2008 William Schlieper <schlieper@unc.edu>
+! See http://factorcode.org/license.txt for BSD license.
+
+USING: accessors kernel graph-theory ;
+
+IN: graph-theory.reversals
+
+TUPLE: reversal graph ;
+
+GENERIC: reverse-graph ( graph -- reversal )
+
+M: graph reverse-graph reversal boa ;
+
+M: reversal reverse-graph graph>> ;
+
+INSTANCE: reversal graph
+
+M: reversal vertices
+    graph>> vertices ;
+
+M: reversal adj?
+    swapd graph>> adj? ;
diff --git a/extra/graph-theory/sparse/sparse.factor b/extra/graph-theory/sparse/sparse.factor
new file mode 100644
index 0000000000..33c5505f0a
--- /dev/null
+++ b/extra/graph-theory/sparse/sparse.factor
@@ -0,0 +1,35 @@
+! Copyright (C) 2008 William Schlieper <schlieper@unc.edu>
+! See http://factorcode.org/license.txt for BSD license.
+
+USING: accessors kernel sequences arrays vectors sets assocs hashtables graph-theory namespaces fry ;
+
+IN: graph-theory.sparse
+
+TUPLE: sparse-graph alist ; 
+
+: <sparse-graph> ( -- sparse-graph )
+    H{ } clone sparse-graph boa ;
+
+: >sparse-graph ( graph -- sparse-graph )
+    [ vertices ] keep
+    '[ dup , adjlist 2array ] map >hashtable sparse-graph boa ;
+
+INSTANCE: sparse-graph graph
+
+M: sparse-graph vertices
+    alist>> keys ;
+
+M: sparse-graph adjlist
+    alist>> at ;
+
+M: sparse-graph add-blank-vertex 
+    alist>> V{ } clone -rot set-at ;
+
+M: sparse-graph delete-blank-vertex
+    alist>> delete-at ;
+
+M: sparse-graph add-edge*
+    alist>> swapd at adjoin ;
+
+M: sparse-graph delete-edge*
+    alist>> swapd at delete ;

From 65cc3f40510c01ed5c4651749d8b1875a7e7b012 Mon Sep 17 00:00:00 2001
From: William Schlieper <schlieper@unc.edu>
Date: Fri, 20 Jun 2008 23:53:47 -0400
Subject: [PATCH 54/85] Added authors.txt, etc. to graph-theory

---
 extra/graph-theory/authors.txt | 1 +
 extra/graph-theory/summary.txt | 1 +
 extra/graph-theory/tags.txt    | 1 +
 3 files changed, 3 insertions(+)
 create mode 100644 extra/graph-theory/authors.txt
 create mode 100644 extra/graph-theory/summary.txt
 create mode 100644 extra/graph-theory/tags.txt

diff --git a/extra/graph-theory/authors.txt b/extra/graph-theory/authors.txt
new file mode 100644
index 0000000000..93667236de
--- /dev/null
+++ b/extra/graph-theory/authors.txt
@@ -0,0 +1 @@
+William Schlieper
diff --git a/extra/graph-theory/summary.txt b/extra/graph-theory/summary.txt
new file mode 100644
index 0000000000..3e1d791ab1
--- /dev/null
+++ b/extra/graph-theory/summary.txt
@@ -0,0 +1 @@
+Graph-theoretic algorithms
diff --git a/extra/graph-theory/tags.txt b/extra/graph-theory/tags.txt
new file mode 100644
index 0000000000..42d711b32b
--- /dev/null
+++ b/extra/graph-theory/tags.txt
@@ -0,0 +1 @@
+collections

From f0a1f8fe5fa709e318ccf1c3a4ac57a5408a3c29 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Sat, 21 Jun 2008 16:56:21 +1200
Subject: [PATCH 55/85] Fix JavaScript new expression

---
 extra/peg/javascript/parser/parser.factor | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/extra/peg/javascript/parser/parser.factor b/extra/peg/javascript/parser/parser.factor
index 5eb42daa31..d44bbcf675 100644
--- a/extra/peg/javascript/parser/parser.factor
+++ b/extra/peg/javascript/parser/parser.factor
@@ -89,7 +89,8 @@ PrimExprHd         =   "(" Expr:e ")"                        => [[ e ]]
                      | String                                => [[ ast-string boa ]]
                      | RegExp                                => [[ ast-regexp boa ]]
                      | "function" FuncRest:fr                => [[ fr ]]
-                     | "new" Name:n "(" Args:as ")"          => [[ n as ast-new boa ]]
+                     | "new" PrimExpr:n "(" Args:as ")"      => [[ n as ast-new boa ]]
+                     | "new" PrimExpr:n                      => [[ n f  ast-new boa ]]
                      | "[" Args:es "]"                       => [[ es ast-array boa ]]
                      | Json
 JsonBindings        = (JsonBinding ("," JsonBinding => [[ second ]])* => [[ first2 swap prefix ]])?

From 75814c35f4697d2c7970170808059769bda5c741 Mon Sep 17 00:00:00 2001
From: Chris Double <chris@bethia.(none)>
Date: Tue, 24 Jun 2008 10:50:41 +1200
Subject: [PATCH 56/85] Fix MulExpr to use Unary on rhs

---
 extra/peg/javascript/parser/parser.factor | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/extra/peg/javascript/parser/parser.factor b/extra/peg/javascript/parser/parser.factor
index d44bbcf675..b7df9908da 100644
--- a/extra/peg/javascript/parser/parser.factor
+++ b/extra/peg/javascript/parser/parser.factor
@@ -60,9 +60,9 @@ RelExpr            =   RelExpr:x ">" AddExpr:y          => [[ x y ">" ast-binop
 AddExpr            =   AddExpr:x "+" MulExpr:y          => [[ x y "+" ast-binop boa ]]
                      | AddExpr:x "-" MulExpr:y          => [[ x y "-" ast-binop boa ]]
                      | MulExpr
-MulExpr            =   MulExpr:x "*" MulExpr:y          => [[ x y "*" ast-binop boa ]]
-                     | MulExpr:x "/" MulExpr:y          => [[ x y "/" ast-binop boa ]]
-                     | MulExpr:x "%" MulExpr:y          => [[ x y "%" ast-binop boa ]]
+MulExpr            =   MulExpr:x "*" Unary:y            => [[ x y "*" ast-binop boa ]]
+                     | MulExpr:x "/" Unary:y            => [[ x y "/" ast-binop boa ]]
+                     | MulExpr:x "%" Unary:y            => [[ x y "%" ast-binop boa ]]
                      | Unary
 Unary              =   "-" Postfix:p                    => [[ p "-" ast-unop boa ]]
                      | "+" Postfix:p                    => [[ p ]]

From 6923b32ebfcc26f06c2cd60d89311078eb4365c5 Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info>
Date: Tue, 24 Jun 2008 08:35:06 -0500
Subject: [PATCH 57/85] Add combinators.short-circuit

---
 .../short-circuit/short-circuit.factor        | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 extra/combinators/short-circuit/short-circuit.factor

diff --git a/extra/combinators/short-circuit/short-circuit.factor b/extra/combinators/short-circuit/short-circuit.factor
new file mode 100644
index 0000000000..cda8ea4706
--- /dev/null
+++ b/extra/combinators/short-circuit/short-circuit.factor
@@ -0,0 +1,43 @@
+
+USING: kernel combinators quotations arrays sequences assocs macros fry ;
+
+IN: combinators.short-circuit
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: short-circuit ( quots quot default -- quot )
+    1quotation -rot { } map>assoc <reversed> alist>quot ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+MACRO: 0&& ( quots -- quot )
+  [ '[ drop @ dup not ] [ drop f ] 2array ] map
+  { [ t ] [ ] }                       suffix
+  '[ f , cond ] ;
+
+MACRO: 1&& ( quots -- quot )
+  [ '[ drop dup @ dup not ] [ drop drop f ] 2array ] map
+  { [ t ] [ nip ] }                                  suffix
+  '[ f , cond ] ;
+
+MACRO: 2&& ( quots -- quot )
+  [ '[ drop 2dup @ dup not ] [ drop 2drop f ] 2array ] map
+  { [ t ] [ 2nip ] }                                   suffix
+  '[ f , cond ] ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+MACRO: 0|| ( quots -- quot )
+  [ '[ drop @ dup ] [ ] 2array ] map
+  { [ drop t ] [ f ] } suffix
+  '[ f , cond ] ;
+
+MACRO: 1|| ( quots -- quot )
+  [ '[ drop dup @ dup ] [ nip ] 2array ] map
+  { [ drop drop t ] [ f ] }              suffix
+  '[ f , cond ] ;
+
+MACRO: 2|| ( quots -- quot )
+  [ '[ drop 2dup @ dup ] [ 2nip ] 2array ] map
+  { [ drop 2drop t ] [ f ] }               suffix
+  '[ f , cond ] ;

From e88b83b32f33a5831f29478b98f5c45470a1d9ac Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info>
Date: Tue, 24 Jun 2008 08:35:36 -0500
Subject: [PATCH 58/85] Update vocabs for combinators.short-circuit

---
 extra/combinators/lib/lib.factor         | 52 ++++++++++++------------
 extra/http/parsers/parsers.factor        |  2 +-
 extra/unicode/breaks/breaks.factor       |  2 +-
 extra/unicode/collation/collation.factor |  2 +-
 extra/unicode/data/data.factor           |  2 +-
 5 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/extra/combinators/lib/lib.factor b/extra/combinators/lib/lib.factor
index fe6b68638b..d9509b30f4 100755
--- a/extra/combinators/lib/lib.factor
+++ b/extra/combinators/lib/lib.factor
@@ -63,42 +63,42 @@ MACRO: napply ( n -- )
 ! short circuiting words
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: short-circuit ( quots quot default -- quot )
-    1quotation -rot { } map>assoc <reversed> alist>quot ;
+! : short-circuit ( quots quot default -- quot )
+!     1quotation -rot { } map>assoc <reversed> alist>quot ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-MACRO: 0&& ( quots -- quot )
-  [ '[ drop @ dup not ] [ drop f ] 2array ] map
-  { [ t ] [ ] }                       suffix
-  '[ f , cond ] ;
+! MACRO: 0&& ( quots -- quot )
+!   [ '[ drop @ dup not ] [ drop f ] 2array ] map
+!   { [ t ] [ ] }                       suffix
+!   '[ f , cond ] ;
 
-MACRO: 1&& ( quots -- quot )
-  [ '[ drop dup @ dup not ] [ drop drop f ] 2array ] map
-  { [ t ] [ nip ] }                                  suffix
-  '[ f , cond ] ;
+! MACRO: 1&& ( quots -- quot )
+!   [ '[ drop dup @ dup not ] [ drop drop f ] 2array ] map
+!   { [ t ] [ nip ] }                                  suffix
+!   '[ f , cond ] ;
 
-MACRO: 2&& ( quots -- quot )
-  [ '[ drop 2dup @ dup not ] [ drop 2drop f ] 2array ] map
-  { [ t ] [ 2nip ] }                                   suffix
-  '[ f , cond ] ;
+! MACRO: 2&& ( quots -- quot )
+!   [ '[ drop 2dup @ dup not ] [ drop 2drop f ] 2array ] map
+!   { [ t ] [ 2nip ] }                                   suffix
+!   '[ f , cond ] ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-MACRO: 0|| ( quots -- quot )
-  [ '[ drop @ dup ] [ ] 2array ] map
-  { [ drop t ] [ f ] } suffix
-  '[ f , cond ] ;
+! MACRO: 0|| ( quots -- quot )
+!   [ '[ drop @ dup ] [ ] 2array ] map
+!   { [ drop t ] [ f ] } suffix
+!   '[ f , cond ] ;
 
-MACRO: 1|| ( quots -- quot )
-  [ '[ drop dup @ dup ] [ nip ] 2array ] map
-  { [ drop drop t ] [ f ] }              suffix
-  '[ f , cond ] ;
+! MACRO: 1|| ( quots -- quot )
+!   [ '[ drop dup @ dup ] [ nip ] 2array ] map
+!   { [ drop drop t ] [ f ] }              suffix
+!   '[ f , cond ] ;
 
-MACRO: 2|| ( quots -- quot )
-  [ '[ drop 2dup @ dup ] [ 2nip ] 2array ] map
-  { [ drop 2drop t ] [ f ] }               suffix
-  '[ f , cond ] ;
+! MACRO: 2|| ( quots -- quot )
+!   [ '[ drop 2dup @ dup ] [ 2nip ] 2array ] map
+!   { [ drop 2drop t ] [ f ] }               suffix
+!   '[ f , cond ] ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 ! ifte
diff --git a/extra/http/parsers/parsers.factor b/extra/http/parsers/parsers.factor
index 33bfa4b202..bc6e1148c3 100644
--- a/extra/http/parsers/parsers.factor
+++ b/extra/http/parsers/parsers.factor
@@ -1,4 +1,4 @@
-USING: math math.order math.parser kernel combinators.lib
+USING: combinators.short-circuit math math.order math.parser kernel combinators.lib
 sequences sequences.deep peg peg.parsers assocs arrays
 hashtables strings unicode.case namespaces ascii ;
 IN: http.parsers
diff --git a/extra/unicode/breaks/breaks.factor b/extra/unicode/breaks/breaks.factor
index b70d79b872..745fb83c3c 100755
--- a/extra/unicode/breaks/breaks.factor
+++ b/extra/unicode/breaks/breaks.factor
@@ -1,4 +1,4 @@
-USING: unicode.categories kernel math combinators splitting
+USING: combinators.short-circuit unicode.categories kernel math combinators splitting
 sequences math.parser io.files io assocs arrays namespaces
 math.ranges unicode.normalize values io.encodings.ascii
 unicode.syntax unicode.data compiler.units alien.syntax sets
diff --git a/extra/unicode/collation/collation.factor b/extra/unicode/collation/collation.factor
index 216f80c79d..8deed708e6 100755
--- a/extra/unicode/collation/collation.factor
+++ b/extra/unicode/collation/collation.factor
@@ -1,4 +1,4 @@
-USING: sequences io.files io.encodings.ascii kernel values
+USING: combinators.short-circuit sequences io.files io.encodings.ascii kernel values
 splitting accessors math.parser ascii io assocs strings math
 namespaces sorting combinators math.order arrays
 unicode.normalize unicode.data combinators.lib locals
diff --git a/extra/unicode/data/data.factor b/extra/unicode/data/data.factor
index 5fb769e499..b6c6292e90 100755
--- a/extra/unicode/data/data.factor
+++ b/extra/unicode/data/data.factor
@@ -1,4 +1,4 @@
-USING: assocs math kernel sequences io.files hashtables
+USING: combinators.short-circuit assocs math kernel sequences io.files hashtables
 quotations splitting grouping arrays math.parser hash2 math.order
 byte-arrays words namespaces words compiler.units parser
 io.encodings.ascii values interval-maps ascii sets

From 8cd16e5bf8c65f0f0437c7e2ba2a9bf2bf9eee6b Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info>
Date: Tue, 24 Jun 2008 10:39:50 -0500
Subject: [PATCH 59/85] combinators.short-circuit: n&&-rewrite and n||-rewrite

---
 .../short-circuit/short-circuit.factor        | 47 +++++++++----------
 1 file changed, 21 insertions(+), 26 deletions(-)

diff --git a/extra/combinators/short-circuit/short-circuit.factor b/extra/combinators/short-circuit/short-circuit.factor
index cda8ea4706..1738e8ec38 100644
--- a/extra/combinators/short-circuit/short-circuit.factor
+++ b/extra/combinators/short-circuit/short-circuit.factor
@@ -1,5 +1,6 @@
 
-USING: kernel combinators quotations arrays sequences assocs macros fry ;
+USING: kernel combinators quotations arrays sequences assocs
+       locals shuffle macros fry newfx ;
 
 IN: combinators.short-circuit
 
@@ -10,34 +11,28 @@ IN: combinators.short-circuit
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-MACRO: 0&& ( quots -- quot )
-  [ '[ drop @ dup not ] [ drop f ] 2array ] map
-  { [ t ] [ ] }                       suffix
-  '[ f , cond ] ;
+:: n&&-rewrite ( quots N -- quot )
+   quots
+     [ '[ drop N ndup @ dup not ] [ drop N ndrop f ] 2array ]
+   map
+   [ t ] [ N nnip ] 2array suffix
+   '[ f , cond ] ;
 
-MACRO: 1&& ( quots -- quot )
-  [ '[ drop dup @ dup not ] [ drop drop f ] 2array ] map
-  { [ t ] [ nip ] }                                  suffix
-  '[ f , cond ] ;
-
-MACRO: 2&& ( quots -- quot )
-  [ '[ drop 2dup @ dup not ] [ drop 2drop f ] 2array ] map
-  { [ t ] [ 2nip ] }                                   suffix
-  '[ f , cond ] ;
+MACRO: 0&& ( quots -- quot ) 0 n&&-rewrite ;
+MACRO: 1&& ( quots -- quot ) 1 n&&-rewrite ;
+MACRO: 2&& ( quots -- quot ) 2 n&&-rewrite ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-MACRO: 0|| ( quots -- quot )
-  [ '[ drop @ dup ] [ ] 2array ] map
-  { [ drop t ] [ f ] } suffix
-  '[ f , cond ] ;
+:: n||-rewrite ( quots N -- quot )
+   quots
+     [ '[ drop N ndup @ dup ] [ N nnip ] 2array ]
+   map
+   [ drop N ndrop t ] [ f ] 2array suffix
+   '[ f , cond ] ;
 
-MACRO: 1|| ( quots -- quot )
-  [ '[ drop dup @ dup ] [ nip ] 2array ] map
-  { [ drop drop t ] [ f ] }              suffix
-  '[ f , cond ] ;
+MACRO: 0|| ( quots -- quot ) 0 n||-rewrite ;
+MACRO: 1|| ( quots -- quot ) 1 n||-rewrite ;
+MACRO: 2|| ( quots -- quot ) 2 n||-rewrite ;
 
-MACRO: 2|| ( quots -- quot )
-  [ '[ drop 2dup @ dup ] [ 2nip ] 2array ] map
-  { [ drop 2drop t ] [ f ] }               suffix
-  '[ f , cond ] ;
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

From e1b9e3485ae0f8524849902f5eed3473ca7a8183 Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info>
Date: Tue, 24 Jun 2008 10:40:27 -0500
Subject: [PATCH 60/85] combinators.short-circuit: tests

---
 .../short-circuit/short-circuit-tests.factor  | 32 +++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 extra/combinators/short-circuit/short-circuit-tests.factor

diff --git a/extra/combinators/short-circuit/short-circuit-tests.factor b/extra/combinators/short-circuit/short-circuit-tests.factor
new file mode 100644
index 0000000000..e392d67d2a
--- /dev/null
+++ b/extra/combinators/short-circuit/short-circuit-tests.factor
@@ -0,0 +1,32 @@
+
+USING: kernel math tools.test combinators.short-circuit ;
+
+IN: combinators.short-circuit.tests
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: must-be-t ( in -- ) [ t ] swap unit-test ;
+: must-be-f ( in -- ) [ f ] swap unit-test ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+[       { [ 1 ] [ 2 ] [ 3 ] }           0&&  3 = ] must-be-t
+[ 3     { [ 0 > ] [ odd? ] [ 2 + ] }    1&&  5 = ] must-be-t
+[ 10 20 { [ + 0 > ] [ - even? ] [ + ] } 2&& 30 = ] must-be-t
+
+[       { [ 1 ] [ f ] [ 3 ] } 0&&  3 = ]          must-be-f
+[ 3     { [ 0 > ] [ even? ] [ 2 + ] } 1&& ]       must-be-f
+[ 10 20 { [ + 0 > ] [ - odd? ] [ + ] } 2&& 30 = ] must-be-f
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+[ { [ 10 0 < ] [ f ] [ "factor" ] } 0|| "factor" = ] must-be-t
+
+[ 10 { [ odd? ] [ 100 > ] [ 1 + ] } 1|| 11 = ]       must-be-t
+
+[ 10 20 { [ + odd? ] [ + 100 > ] [ + ] } 2|| 30 = ]  must-be-t
+
+[ { [ 10 0 < ] [ f ] [ 0 1 = ] } 0|| ] must-be-f
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+

From 945fe1bc748cc0f136557cad63f43ef7bc074b5c Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info>
Date: Tue, 24 Jun 2008 10:40:55 -0500
Subject: [PATCH 61/85] Add combinators.short-circuit.smart

---
 .../short-circuit/smart/smart-tests.factor    | 32 +++++++++++++++++++
 .../short-circuit/smart/smart.factor          | 11 +++++++
 2 files changed, 43 insertions(+)
 create mode 100644 extra/combinators/short-circuit/smart/smart-tests.factor
 create mode 100644 extra/combinators/short-circuit/smart/smart.factor

diff --git a/extra/combinators/short-circuit/smart/smart-tests.factor b/extra/combinators/short-circuit/smart/smart-tests.factor
new file mode 100644
index 0000000000..7ec4a0e657
--- /dev/null
+++ b/extra/combinators/short-circuit/smart/smart-tests.factor
@@ -0,0 +1,32 @@
+
+USING: kernel math tools.test combinators.short-circuit.smart ;
+
+IN: combinators.short-circuit.smart.tests
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: must-be-t ( in -- ) [ t ] swap unit-test ;
+: must-be-f ( in -- ) [ f ] swap unit-test ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+[       { [ 1 ] [ 2 ] [ 3 ] }          &&  3 = ] must-be-t
+[ 3     { [ 0 > ] [ odd? ] [ 2 + ] }    &&  5 = ] must-be-t
+[ 10 20 { [ + 0 > ] [ - even? ] [ + ] } && 30 = ] must-be-t
+
+[       { [ 1 ] [ f ] [ 3 ] } &&  3 = ]          must-be-f
+[ 3     { [ 0 > ] [ even? ] [ 2 + ] } && ]       must-be-f
+[ 10 20 { [ + 0 > ] [ - odd? ] [ + ] } && 30 = ] must-be-f
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+[ { [ 10 0 < ] [ f ] [ "factor" ] } || "factor" = ] must-be-t
+
+[ 10 { [ odd? ] [ 100 > ] [ 1 + ] } || 11 = ]       must-be-t
+
+[ 10 20 { [ + odd? ] [ + 100 > ] [ + ] } || 30 = ]  must-be-t
+
+[ { [ 10 0 < ] [ f ] [ 0 1 = ] } || ] must-be-f
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
diff --git a/extra/combinators/short-circuit/smart/smart.factor b/extra/combinators/short-circuit/smart/smart.factor
new file mode 100644
index 0000000000..2cef957a6f
--- /dev/null
+++ b/extra/combinators/short-circuit/smart/smart.factor
@@ -0,0 +1,11 @@
+
+USING: kernel sequences math inference accessors macros
+       combinators.short-circuit ;
+
+IN: combinators.short-circuit.smart
+
+MACRO: && ( quots -- quot )
+  dup first infer [ in>> ] [ out>> ] bi - 1+ n&&-rewrite ;
+
+MACRO: || ( quots -- quot )
+  dup first infer [ in>> ] [ out>> ] bi - 1+ n||-rewrite ;

From bf238283daf7b2bee71e554100565e7fa90a6506 Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info>
Date: Tue, 24 Jun 2008 13:47:54 -0500
Subject: [PATCH 62/85] Update code for combinators.short-circuit

---
 extra/boids/boids.factor                      | 2 +-
 extra/boids/ui/ui.factor                      | 2 +-
 extra/dns/forwarding/forwarding.factor        | 2 +-
 extra/dns/server/server.factor                | 2 +-
 extra/ftp/server/server.factor                | 2 +-
 extra/inverse/inverse.factor                  | 2 +-
 extra/io/servers/connection/connection.factor | 2 +-
 extra/lcs/lcs.factor                          | 3 ++-
 extra/lisp/lisp.factor                        | 2 +-
 extra/lisp/parser/parser.factor               | 2 +-
 extra/lsys/strings/interpret/interpret.factor | 2 +-
 extra/lsys/strings/rewrite/rewrite.factor     | 2 +-
 extra/lsys/strings/strings.factor             | 2 +-
 extra/lsys/tortoise/graphics/graphics.factor  | 2 +-
 extra/lsys/ui/ui.factor                       | 3 ++-
 extra/math/text/english/english.factor        | 3 ++-
 extra/peg/ebnf/ebnf.factor                    | 3 ++-
 extra/project-euler/014/014.factor            | 2 +-
 extra/project-euler/017/017.factor            | 2 +-
 extra/project-euler/021/021.factor            | 3 ++-
 extra/project-euler/036/036.factor            | 2 +-
 extra/project-euler/043/043.factor            | 3 ++-
 extra/project-euler/052/052.factor            | 3 ++-
 extra/project-euler/project-euler.factor      | 2 +-
 extra/regexp/regexp.factor                    | 3 ++-
 extra/shell/shell.factor                      | 3 ++-
 extra/xmode/marker/marker.factor              | 3 ++-
 27 files changed, 37 insertions(+), 27 deletions(-)

diff --git a/extra/boids/boids.factor b/extra/boids/boids.factor
index 4151b44cfb..e6c97b90dd 100644
--- a/extra/boids/boids.factor
+++ b/extra/boids/boids.factor
@@ -1,5 +1,5 @@
 
-USING: kernel namespaces
+USING: combinators.short-circuit kernel namespaces
        math
        math.constants
        math.functions
diff --git a/extra/boids/ui/ui.factor b/extra/boids/ui/ui.factor
index a1feac381d..3b28e79bcf 100755
--- a/extra/boids/ui/ui.factor
+++ b/extra/boids/ui/ui.factor
@@ -1,5 +1,5 @@
 
-USING: kernel namespaces
+USING: combinators.short-circuit kernel namespaces
        math
        math.functions
        math.vectors
diff --git a/extra/dns/forwarding/forwarding.factor b/extra/dns/forwarding/forwarding.factor
index 039b969ddd..87f9821153 100644
--- a/extra/dns/forwarding/forwarding.factor
+++ b/extra/dns/forwarding/forwarding.factor
@@ -1,5 +1,5 @@
 
-USING: kernel
+USING: combinators.short-circuit kernel
        combinators
        vectors
        sequences
diff --git a/extra/dns/server/server.factor b/extra/dns/server/server.factor
index 04b3ecfbee..16677d8761 100644
--- a/extra/dns/server/server.factor
+++ b/extra/dns/server/server.factor
@@ -1,7 +1,7 @@
 
 USING: kernel combinators sequences sets math threads namespaces continuations
        debugger io io.sockets unicode.case accessors destructors
-       combinators.cleave combinators.lib
+       combinators.cleave combinators.lib combinators.short-circuit 
        newfx fry
        dns dns.util dns.misc ;
 
diff --git a/extra/ftp/server/server.factor b/extra/ftp/server/server.factor
index c71eadb72f..c5a5449b25 100644
--- a/extra/ftp/server/server.factor
+++ b/extra/ftp/server/server.factor
@@ -1,6 +1,6 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors combinators io io.encodings.8-bit
+USING: combinators.short-circuit accessors combinators io io.encodings.8-bit
 io.encodings io.encodings.binary io.encodings.utf8 io.files
 io.sockets kernel math.parser namespaces sequences
 ftp io.unix.launcher.parser unicode.case splitting assocs
diff --git a/extra/inverse/inverse.factor b/extra/inverse/inverse.factor
index ef1f575972..43507046d6 100755
--- a/extra/inverse/inverse.factor
+++ b/extra/inverse/inverse.factor
@@ -2,7 +2,7 @@ USING: kernel words inspector slots quotations sequences assocs
 math arrays inference effects shuffle continuations debugger
 classes.tuple namespaces vectors bit-arrays byte-arrays strings
 sbufs math.functions macros sequences.private combinators
-mirrors combinators.lib ;
+mirrors combinators.lib combinators.short-circuit ;
 IN: inverse
 
 TUPLE: fail ;
diff --git a/extra/io/servers/connection/connection.factor b/extra/io/servers/connection/connection.factor
index b062322142..0ff83261fb 100755
--- a/extra/io/servers/connection/connection.factor
+++ b/extra/io/servers/connection/connection.factor
@@ -6,7 +6,7 @@ quotations combinators combinators.lib logging calendar assocs
 fry accessors arrays io io.sockets io.encodings.ascii
 io.sockets.secure io.files io.streams.duplex io.timeouts
 io.encodings threads concurrency.combinators
-concurrency.semaphores ;
+concurrency.semaphores combinators.short-circuit ;
 IN: io.servers.connection
 
 TUPLE: threaded-server
diff --git a/extra/lcs/lcs.factor b/extra/lcs/lcs.factor
index 4b0fb53f5e..2fa0b6cc71 100755
--- a/extra/lcs/lcs.factor
+++ b/extra/lcs/lcs.factor
@@ -1,5 +1,6 @@
 USING: sequences kernel math locals math.order math.ranges
-accessors combinators.lib arrays namespaces combinators ;
+accessors combinators.lib arrays namespaces combinators
+combinators.short-circuit ;
 IN: lcs
 
 <PRIVATE
diff --git a/extra/lisp/lisp.factor b/extra/lisp/lisp.factor
index e3d942d390..109083de37 100644
--- a/extra/lisp/lisp.factor
+++ b/extra/lisp/lisp.factor
@@ -3,7 +3,7 @@
 USING: kernel peg sequences arrays strings combinators.lib
 namespaces combinators math locals locals.private locals.backend accessors
 vectors syntax lisp.parser assocs parser sequences.lib words
-quotations fry lists inspector ;
+quotations fry lists inspector combinators.short-circuit ;
 IN: lisp
 
 DEFER: convert-form
diff --git a/extra/lisp/parser/parser.factor b/extra/lisp/parser/parser.factor
index 8fadb00e65..428e1221da 100644
--- a/extra/lisp/parser/parser.factor
+++ b/extra/lisp/parser/parser.factor
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 James Cash
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel peg peg.ebnf peg.expr math.parser sequences arrays strings
-combinators.lib math fry accessors lists ;
+combinators.lib math fry accessors lists combinators.short-circuit ;
 
 IN: lisp.parser
 
diff --git a/extra/lsys/strings/interpret/interpret.factor b/extra/lsys/strings/interpret/interpret.factor
index bcd87ca137..1d992cc1e2 100644
--- a/extra/lsys/strings/interpret/interpret.factor
+++ b/extra/lsys/strings/interpret/interpret.factor
@@ -1,6 +1,6 @@
 
 USING: kernel sequences quotations assocs math math.parser
-       combinators.lib vars lsys.strings ;
+       combinators.lib vars lsys.strings combinators.short-circuit ;
 
 IN: lsys.strings.interpret
 
diff --git a/extra/lsys/strings/rewrite/rewrite.factor b/extra/lsys/strings/rewrite/rewrite.factor
index eb76dbd751..622a86c425 100644
--- a/extra/lsys/strings/rewrite/rewrite.factor
+++ b/extra/lsys/strings/rewrite/rewrite.factor
@@ -1,6 +1,6 @@
 
 USING: kernel sbufs strings sequences assocs math
-       combinators.lib vars lsys.strings ;
+       combinators.lib vars lsys.strings combinators.short-circuit ;
 
 IN: lsys.strings.rewrite
 
diff --git a/extra/lsys/strings/strings.factor b/extra/lsys/strings/strings.factor
index f184ca5dfc..603c6cc630 100644
--- a/extra/lsys/strings/strings.factor
+++ b/extra/lsys/strings/strings.factor
@@ -1,5 +1,5 @@
 
-USING: kernel sequences math combinators.lib ;
+USING: kernel sequences math combinators.lib combinators.short-circuit ;
 
 IN: lsys.strings
 
diff --git a/extra/lsys/tortoise/graphics/graphics.factor b/extra/lsys/tortoise/graphics/graphics.factor
index d75915ae8e..ab679c8369 100644
--- a/extra/lsys/tortoise/graphics/graphics.factor
+++ b/extra/lsys/tortoise/graphics/graphics.factor
@@ -2,7 +2,7 @@
 USING: kernel math vectors sequences opengl.gl math.vectors math.order
        math.matrices vars opengl self pos ori turtle lsys.tortoise
 
-       lsys.strings.interpret ;
+       lsys.strings.interpret combinators.short-circuit ;
 
        ! lsys.strings
 
diff --git a/extra/lsys/ui/ui.factor b/extra/lsys/ui/ui.factor
index c3b9190c3c..d15793c15a 100644
--- a/extra/lsys/ui/ui.factor
+++ b/extra/lsys/ui/ui.factor
@@ -16,7 +16,8 @@ USING: kernel namespaces threads math math.order math.vectors
        vars rewrite-closures
        self pos ori turtle opengl.camera
        lsys.tortoise lsys.tortoise.graphics
-       lsys.strings.rewrite lsys.strings.interpret ;
+       lsys.strings.rewrite lsys.strings.interpret
+       combinators.short-circuit ;
 
        ! lsys.strings
        ! lsys.strings.rewrite
diff --git a/extra/math/text/english/english.factor b/extra/math/text/english/english.factor
index 500e08f79d..b8256533bf 100755
--- a/extra/math/text/english/english.factor
+++ b/extra/math/text/english/english.factor
@@ -1,7 +1,8 @@
 ! Copyright (c) 2007 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: combinators.lib kernel math math.functions math.parser namespaces
-    sequences splitting grouping sequences.lib ;
+    sequences splitting grouping sequences.lib
+    combinators.short-circuit ;
 IN: math.text.english
 
 <PRIVATE
diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index fc10a65024..e3d44585a7 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -3,7 +3,8 @@
 USING: kernel compiler.units parser words arrays strings math.parser sequences 
        quotations vectors namespaces math assocs continuations peg
        peg.parsers unicode.categories multiline combinators.lib 
-       splitting accessors effects sequences.deep peg.search ;
+       splitting accessors effects sequences.deep peg.search
+       combinators.short-circuit ;
 IN: peg.ebnf
 
 TUPLE: ebnf-non-terminal symbol ;
diff --git a/extra/project-euler/014/014.factor b/extra/project-euler/014/014.factor
index ef8ef8c0f7..b99e34d36f 100644
--- a/extra/project-euler/014/014.factor
+++ b/extra/project-euler/014/014.factor
@@ -1,7 +1,7 @@
 ! Copyright (c) 2007 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays combinators.lib kernel math math.ranges namespaces sequences
-    sorting ;
+    sorting combinators.short-circuit ;
 IN: project-euler.014
 
 ! http://projecteuler.net/index.php?section=problems&id=14
diff --git a/extra/project-euler/017/017.factor b/extra/project-euler/017/017.factor
index ffff10d4fe..cf58e88ffe 100644
--- a/extra/project-euler/017/017.factor
+++ b/extra/project-euler/017/017.factor
@@ -1,7 +1,7 @@
 ! Copyright (c) 2007 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel math.ranges math.text.english sequences sequences.lib strings
-    ascii ;
+    ascii combinators.short-circuit ;
 IN: project-euler.017
 
 ! http://projecteuler.net/index.php?section=problems&id=17
diff --git a/extra/project-euler/021/021.factor b/extra/project-euler/021/021.factor
index e6eadba264..f09b0c0b42 100644
--- a/extra/project-euler/021/021.factor
+++ b/extra/project-euler/021/021.factor
@@ -1,7 +1,8 @@
 ! Copyright (c) 2007 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: combinators.lib kernel math math.functions math.ranges namespaces
-    project-euler.common sequences sequences.lib ;
+    project-euler.common sequences sequences.lib
+    combinators.short-circuit ;
 IN: project-euler.021
 
 ! http://projecteuler.net/index.php?section=problems&id=21
diff --git a/extra/project-euler/036/036.factor b/extra/project-euler/036/036.factor
index fbf6376eb3..4a4f906467 100644
--- a/extra/project-euler/036/036.factor
+++ b/extra/project-euler/036/036.factor
@@ -1,7 +1,7 @@
 ! Copyright (c) 2008 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: combinators.lib kernel math.parser math.ranges project-euler.common
-    sequences ;
+    sequences combinators.short-circuit ;
 IN: project-euler.036
 
 ! http://projecteuler.net/index.php?section=problems&id=36
diff --git a/extra/project-euler/043/043.factor b/extra/project-euler/043/043.factor
index 0c51146656..e095d94ead 100644
--- a/extra/project-euler/043/043.factor
+++ b/extra/project-euler/043/043.factor
@@ -1,7 +1,8 @@
 ! Copyright (c) 2008 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: combinators.lib hashtables kernel math math.combinatorics math.parser
-    math.ranges project-euler.common sequences sequences.lib sorting sets ;
+    math.ranges project-euler.common sequences sequences.lib sorting
+    sets combinators.short-circuit ;
 IN: project-euler.043
 
 ! http://projecteuler.net/index.php?section=problems&id=43
diff --git a/extra/project-euler/052/052.factor b/extra/project-euler/052/052.factor
index 6c4b605bd9..194530ea78 100644
--- a/extra/project-euler/052/052.factor
+++ b/extra/project-euler/052/052.factor
@@ -1,6 +1,7 @@
 ! Copyright (c) 2008 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: combinators.lib kernel math project-euler.common sequences sorting ;
+USING: combinators.lib kernel math project-euler.common sequences
+sorting combinators.short-circuit ;
 IN: project-euler.052
 
 ! http://projecteuler.net/index.php?section=problems&id=52
diff --git a/extra/project-euler/project-euler.factor b/extra/project-euler/project-euler.factor
index 9325e74d93..3101c900e3 100644
--- a/extra/project-euler/project-euler.factor
+++ b/extra/project-euler/project-euler.factor
@@ -17,7 +17,7 @@ USING: definitions io io.files kernel math math.parser project-euler.ave-time
     project-euler.052 project-euler.053 project-euler.056 project-euler.059
     project-euler.067 project-euler.075 project-euler.079 project-euler.092
     project-euler.097 project-euler.134 project-euler.169 project-euler.173
-    project-euler.175 ;
+    project-euler.175 combinators.short-circuit ;
 IN: project-euler
 
 <PRIVATE
diff --git a/extra/regexp/regexp.factor b/extra/regexp/regexp.factor
index 99e6b887c8..bdf0c411b2 100755
--- a/extra/regexp/regexp.factor
+++ b/extra/regexp/regexp.factor
@@ -1,7 +1,8 @@
 USING: arrays combinators kernel lists math math.parser
 namespaces parser parser-combinators parser-combinators.simple
 promises quotations sequences combinators.lib strings math.order
-assocs prettyprint.backend memoize unicode.case unicode.categories ;
+assocs prettyprint.backend memoize unicode.case unicode.categories
+combinators.short-circuit ;
 USE: io
 IN: regexp
 
diff --git a/extra/shell/shell.factor b/extra/shell/shell.factor
index 8ba5b66d5a..45c6f1fb4d 100644
--- a/extra/shell/shell.factor
+++ b/extra/shell/shell.factor
@@ -2,7 +2,8 @@
 USING: kernel parser words continuations namespaces debugger
        sequences combinators splitting prettyprint
        system io io.files io.launcher io.encodings.utf8 io.pipes sequences.deep
-       accessors multi-methods newfx shell.parser ;
+       accessors multi-methods newfx shell.parser
+       combinators.short-circuit ;
 
 IN: shell
 
diff --git a/extra/xmode/marker/marker.factor b/extra/xmode/marker/marker.factor
index 7d82842327..911397cc20 100755
--- a/extra/xmode/marker/marker.factor
+++ b/extra/xmode/marker/marker.factor
@@ -2,7 +2,8 @@ IN: xmode.marker
 USING: kernel namespaces xmode.rules xmode.tokens
 xmode.marker.state xmode.marker.context xmode.utilities
 xmode.catalog sequences math assocs combinators combinators.lib
-strings regexp splitting parser-combinators ascii unicode.case ;
+strings regexp splitting parser-combinators ascii unicode.case
+combinators.short-circuit ;
 
 ! Based on org.gjt.sp.jedit.syntax.TokenMarker
 

From 7aea2ec62ce089c1865d0637f87dbf5c96a878a6 Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info>
Date: Tue, 24 Jun 2008 18:07:41 -0500
Subject: [PATCH 63/85] combinators.lib tests: minor update

---
 extra/combinators/lib/lib-tests.factor | 29 --------------------------
 1 file changed, 29 deletions(-)

diff --git a/extra/combinators/lib/lib-tests.factor b/extra/combinators/lib/lib-tests.factor
index 78916bb027..680e3220b0 100755
--- a/extra/combinators/lib/lib-tests.factor
+++ b/extra/combinators/lib/lib-tests.factor
@@ -23,35 +23,6 @@ IN: combinators.lib.tests
     { "oof" "bar" } { [ reverse ] [ "x" swap "x" 3append ] } parallel-call
 ] unit-test
 
-! &&
-
-[ t ] [
-    3 {
-        [ dup number? ] [ dup odd? ] [ dup 0 > ]
-    } 0&& nip
-] unit-test
-
-[ f ] [
-    3 {
-        [ dup number? ] [ dup even? ] [ dup 0 > ]
-    } 0&& nip
-] unit-test
-
-! ||
-
-[ t ] [
-    4 {
-        [ dup array? ] [ dup number? ] [ 3 throw ]
-    } 0|| nip
-] unit-test
-
-[ f ] [
-    4 {
-        [ dup array? ] [ dup vector? ] [ dup float? ]
-    } 0|| nip
-] unit-test
-
-
 { 1 1 } [
     [ even? ] [ drop 1 ] [ drop 2 ] ifte
 ] must-infer-as

From ec3c47d9572328a0fa689831ef461083c91332a3 Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info>
Date: Tue, 24 Jun 2008 18:10:17 -0500
Subject: [PATCH 64/85] furnace.sessions: uses 0||

---
 extra/furnace/sessions/sessions.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extra/furnace/sessions/sessions.factor b/extra/furnace/sessions/sessions.factor
index 6e50417ea1..0ec9648a67 100755
--- a/extra/furnace/sessions/sessions.factor
+++ b/extra/furnace/sessions/sessions.factor
@@ -7,7 +7,7 @@ io.servers.connection
 db db.tuples db.types
 http http.server http.server.dispatchers http.server.filters
 html.elements
-furnace furnace.cache ;
+furnace furnace.cache combinators.short-circuit ;
 IN: furnace.sessions
 
 TUPLE: session < server-state namespace user-agent client changed? ;

From 74f2627526a5abc928c7a8e51da8c9337b270254 Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info>
Date: Tue, 24 Jun 2008 18:33:08 -0500
Subject: [PATCH 65/85] More short-circuit updates

---
 extra/furnace/auth/login/permits/permits.factor | 4 +++-
 extra/furnace/boilerplate/boilerplate.factor    | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/extra/furnace/auth/login/permits/permits.factor b/extra/furnace/auth/login/permits/permits.factor
index 49cf98e0e3..ae9458f4ac 100644
--- a/extra/furnace/auth/login/permits/permits.factor
+++ b/extra/furnace/auth/login/permits/permits.factor
@@ -1,6 +1,8 @@
 USING: accessors namespaces combinators.lib kernel
 db.tuples db.types
-furnace.auth furnace.sessions furnace.cache ;
+furnace.auth furnace.sessions furnace.cache
+combinators.short-circuit ;
+
 IN: furnace.auth.login.permits
 
 TUPLE: permit < server-state session uid ;
diff --git a/extra/furnace/boilerplate/boilerplate.factor b/extra/furnace/boilerplate/boilerplate.factor
index 0e2a673d9b..2bb97e7c14 100644
--- a/extra/furnace/boilerplate/boilerplate.factor
+++ b/extra/furnace/boilerplate/boilerplate.factor
@@ -7,7 +7,7 @@ html.templates.chloe
 locals
 http.server
 http.server.filters
-furnace ;
+furnace combinators.short-circuit ;
 IN: furnace.boilerplate
 
 TUPLE: boilerplate < filter-responder template init ;

From 6e0d35e6153bab5afdf8a1c4b95bfb3a8d2af599 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 25 Jun 2008 03:25:08 -0500
Subject: [PATCH 66/85] Split up huge parser vocabulary

---
 core/alien/syntax/syntax.factor               |   3 +-
 core/classes/classes.factor                   |   9 +
 core/classes/intersection/intersection.factor |   3 -
 core/classes/mixin/mixin.factor               |   2 +-
 core/classes/parser/parser.factor             |  15 +
 core/classes/predicate/predicate.factor       |   9 +-
 core/classes/tuple/parser/parser-docs.factor  |  14 +
 core/classes/tuple/parser/parser.factor       |  50 +++
 core/classes/tuple/tuple.factor               |  10 +-
 core/classes/union/union.factor               |   3 -
 core/continuations/continuations-docs.factor  |   8 +-
 core/cpu/x86/assembler/assembler.factor       |  20 +-
 core/cpu/x86/assembler/syntax/syntax.factor   |  15 +
 core/effects/parser/parser-docs.factor        |   9 +
 core/effects/parser/parser.factor             |  15 +
 core/generic/parser/parser.factor             |  33 ++
 core/lexer/lexer-docs.factor                  | 114 +++++++
 core/lexer/lexer.factor                       | 133 ++++++++
 core/listener/listener.factor                 |   4 +-
 core/parser/parser-docs.factor                | 152 +--------
 core/parser/parser-tests.factor               |   6 +
 core/parser/parser.factor                     | 318 +-----------------
 core/source-files/source-files.factor         |  27 +-
 core/strings/parser/parser-docs.factor        |  16 +
 core/strings/parser/parser.factor             |  62 ++++
 core/syntax/syntax.factor                     |  15 +-
 extra/bitfields/bitfields.factor              |   2 +-
 extra/bootstrap/unicode/unicode.factor        |   2 +-
 extra/cocoa/cocoa.factor                      |   3 +-
 extra/cpu/8080/emulator/emulator.factor       |   2 +-
 extra/editors/editors-docs.factor             |   4 +-
 extra/editors/editors.factor                  |  34 +-
 extra/gesture-logger/gesture-logger.factor    |   3 +-
 extra/help/handbook/handbook.factor           |   2 +-
 .../html/templates/chloe/syntax/syntax.factor |   2 +-
 extra/html/templates/fhtml/fhtml.factor       |   6 +-
 extra/http/http-tests.factor                  |   6 +
 extra/http/http.factor                        |   5 +-
 extra/io/encodings/8-bit/8-bit-docs.factor    |   9 +-
 extra/locals/locals.factor                    |   4 +-
 extra/match/match.factor                      |   2 +-
 extra/money/money.factor                      |   2 +-
 extra/mortar/mortar.factor                    |   2 +-
 extra/multiline/multiline.factor              |   2 +-
 extra/opengl/gl/extensions/extensions.factor  |   2 +-
 extra/openssl/libssl/libssl.factor            |   2 +-
 extra/qualified/qualified.factor              |   6 +-
 extra/regexp/regexp.factor                    |   2 +-
 extra/semantic-db/semantic-db.factor          |   2 +-
 extra/state-machine/state-machine.factor      |   2 +-
 extra/symbols/symbols.factor                  |   3 +-
 extra/tools/deploy/shaker/shaker.factor       |   6 +-
 extra/tuple-syntax/tuple-syntax.factor        |   2 +-
 extra/ui/tools/interactor/interactor.factor   |   6 +-
 extra/unicode/syntax/syntax.factor            |   2 +-
 extra/urls/urls.factor                        |  16 +-
 extra/vars/vars.factor                        |   2 +-
 extra/xml/generator/generator.factor          |   4 +-
 extra/xml/utilities/utilities.factor          |   2 +-
 extra/xmode/loader/syntax/syntax.factor       |   2 +-
 extra/xmode/utilities/utilities.factor        |   2 +-
 61 files changed, 642 insertions(+), 578 deletions(-)
 create mode 100644 core/classes/parser/parser.factor
 create mode 100644 core/classes/tuple/parser/parser-docs.factor
 create mode 100644 core/classes/tuple/parser/parser.factor
 create mode 100644 core/cpu/x86/assembler/syntax/syntax.factor
 create mode 100644 core/effects/parser/parser-docs.factor
 create mode 100644 core/effects/parser/parser.factor
 create mode 100644 core/generic/parser/parser.factor
 create mode 100644 core/lexer/lexer-docs.factor
 create mode 100644 core/lexer/lexer.factor
 create mode 100644 core/strings/parser/parser-docs.factor
 create mode 100644 core/strings/parser/parser.factor

diff --git a/core/alien/syntax/syntax.factor b/core/alien/syntax/syntax.factor
index def5b02ba0..a756734f7b 100755
--- a/core/alien/syntax/syntax.factor
+++ b/core/alien/syntax/syntax.factor
@@ -3,7 +3,8 @@
 USING: arrays alien alien.c-types alien.structs alien.arrays
 alien.strings kernel math namespaces parser sequences words
 quotations math.parser splitting grouping effects prettyprint
-prettyprint.sections prettyprint.backend assocs combinators ;
+prettyprint.sections prettyprint.backend assocs combinators
+lexer strings.parser ;
 IN: alien.syntax
 
 <PRIVATE
diff --git a/core/classes/classes.factor b/core/classes/classes.factor
index 0fef6de748..35ff475abf 100755
--- a/core/classes/classes.factor
+++ b/core/classes/classes.factor
@@ -65,6 +65,15 @@ GENERIC: rank-class ( class -- n )
 
 GENERIC: reset-class ( class -- )
 
+M: class reset-class
+    {
+        "class"
+        "metaclass"
+        "superclass"
+        "members"
+        "participants"
+    } reset-props ;
+
 M: word reset-class drop ;
 
 GENERIC: implementors ( class/classes -- seq )
diff --git a/core/classes/intersection/intersection.factor b/core/classes/intersection/intersection.factor
index 7ea8e24f0a..cc24280384 100644
--- a/core/classes/intersection/intersection.factor
+++ b/core/classes/intersection/intersection.factor
@@ -27,7 +27,4 @@ M: intersection-class update-class define-intersection-predicate ;
     [ drop update-classes ]
     2bi ;
 
-M: intersection-class reset-class
-    { "class" "metaclass" "participants" } reset-props ;
-
 M: intersection-class rank-class drop 2 ;
diff --git a/core/classes/mixin/mixin.factor b/core/classes/mixin/mixin.factor
index a2debe55a1..3924eb264c 100755
--- a/core/classes/mixin/mixin.factor
+++ b/core/classes/mixin/mixin.factor
@@ -7,7 +7,7 @@ IN: classes.mixin
 PREDICATE: mixin-class < union-class "mixin" word-prop ;
 
 M: mixin-class reset-class
-    { "class" "metaclass" "members" "mixin" } reset-props ;
+    [ call-next-method ] [ { "mixin" } reset-props ] bi ;
 
 M: mixin-class rank-class drop 3 ;
 
diff --git a/core/classes/parser/parser.factor b/core/classes/parser/parser.factor
new file mode 100644
index 0000000000..17a7b23552
--- /dev/null
+++ b/core/classes/parser/parser.factor
@@ -0,0 +1,15 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: parser words kernel classes compiler.units lexer ;
+IN: classes.parser
+
+: save-class-location ( class -- )
+    location remember-class ;
+
+: create-class-in ( word -- word )
+    current-vocab create
+    dup save-class-location
+    dup predicate-word dup set-word save-location ;
+
+: CREATE-CLASS ( -- word )
+    scan create-class-in ;
diff --git a/core/classes/predicate/predicate.factor b/core/classes/predicate/predicate.factor
index c8de36582e..7ea60149f8 100755
--- a/core/classes/predicate/predicate.factor
+++ b/core/classes/predicate/predicate.factor
@@ -24,11 +24,8 @@ PREDICATE: predicate-class < class
     ] 3tri ;
 
 M: predicate-class reset-class
-    {
-        "class"
-        "metaclass"
-        "predicate-definition"
-        "superclass"
-    } reset-props ;
+    [ call-next-method ]
+    [ { "predicate-definition" } reset-props ]
+    bi ;
 
 M: predicate-class rank-class drop 1 ;
diff --git a/core/classes/tuple/parser/parser-docs.factor b/core/classes/tuple/parser/parser-docs.factor
new file mode 100644
index 0000000000..f4ecb1461e
--- /dev/null
+++ b/core/classes/tuple/parser/parser-docs.factor
@@ -0,0 +1,14 @@
+IN: classes.tuple.parser
+USING: strings help.markup help.syntax ;
+
+HELP: invalid-slot-name
+{ $values { "name" string } }
+{ $description "Throws an " { $link invalid-slot-name } " error." }
+{ $error-description "Thrown by " { $link POSTPONE: TUPLE: } " and " { $link POSTPONE: ERROR: } " if a suspect token appears as a slot name." }
+{ $notes "The suspect tokens are chosen so that the following code raises this parse error, instead of silently greating a tuple with garbage slots:"
+    { $code
+        "TUPLE: my-mistaken-tuple slot-a slot-b"
+        ""
+        ": some-word ( a b c -- ) ... ;"
+    }
+} ;
diff --git a/core/classes/tuple/parser/parser.factor b/core/classes/tuple/parser/parser.factor
new file mode 100644
index 0000000000..ab3be109e1
--- /dev/null
+++ b/core/classes/tuple/parser/parser.factor
@@ -0,0 +1,50 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel sets namespaces sequences inspector parser
+lexer combinators words classes.parser classes.tuple ;
+IN: classes.tuple.parser
+
+: shadowed-slots ( superclass slots -- shadowed )
+    >r all-slot-names r> intersect ;
+
+: check-slot-shadowing ( class superclass slots -- )
+    shadowed-slots [
+        [
+            "Definition of slot ``" %
+            %
+            "'' in class ``" %
+            word-name %
+            "'' shadows a superclass slot" %
+        ] "" make note.
+    ] with each ;
+
+ERROR: invalid-slot-name name ;
+
+M: invalid-slot-name summary
+    drop
+    "Invalid slot name" ;
+
+: (parse-tuple-slots) ( -- )
+    #! This isn't meant to enforce any kind of policy, just
+    #! to check for mistakes of this form:
+    #!
+    #! TUPLE: blahblah foo bing
+    #!
+    #! : ...
+    scan {
+        { [ dup not ] [ unexpected-eof ] }
+        { [ dup { ":" "(" "<" } member? ] [ invalid-slot-name ] }
+        { [ dup ";" = ] [ drop ] }
+        [ , (parse-tuple-slots) ]
+    } cond ;
+
+: parse-tuple-slots ( -- seq )
+    [ (parse-tuple-slots) ] { } make ;
+
+: parse-tuple-definition ( -- class superclass slots )
+    CREATE-CLASS
+    scan {
+        { ";" [ tuple f ] }
+        { "<" [ scan-word parse-tuple-slots ] }
+        [ >r tuple parse-tuple-slots r> prefix ]
+    } case 3dup check-slot-shadowing ;
diff --git a/core/classes/tuple/tuple.factor b/core/classes/tuple/tuple.factor
index 5ba0b7e69c..b4a2302a9e 100755
--- a/core/classes/tuple/tuple.factor
+++ b/core/classes/tuple/tuple.factor
@@ -217,13 +217,9 @@ M: tuple-class reset-class
             [ writer-word method forget ] 2bi
         ] with each
     ] [
-        {
-            "class"
-            "metaclass"
-            "superclass"
-            "layout"
-            "slots"
-        } reset-props
+        [ call-next-method ]
+        [ { "layout" "slots" } reset-props ]
+        bi
     ] bi ;
 
 M: tuple-class rank-class drop 0 ;
diff --git a/core/classes/union/union.factor b/core/classes/union/union.factor
index 74e29cfb01..819e0ecb0b 100755
--- a/core/classes/union/union.factor
+++ b/core/classes/union/union.factor
@@ -28,7 +28,4 @@ M: union-class update-class define-union-predicate ;
 : define-union-class ( class members -- )
     [ (define-union-class) ] [ drop update-classes ] 2bi ;
 
-M: union-class reset-class
-    { "class" "metaclass" "members" } reset-props ;
-
 M: union-class rank-class drop 2 ;
diff --git a/core/continuations/continuations-docs.factor b/core/continuations/continuations-docs.factor
index 3cb7d8a71e..f176e6ee19 100755
--- a/core/continuations/continuations-docs.factor
+++ b/core/continuations/continuations-docs.factor
@@ -1,6 +1,6 @@
 USING: help.markup help.syntax kernel kernel.private
-continuations.private parser vectors arrays namespaces
-assocs words quotations ;
+continuations.private vectors arrays namespaces
+assocs words quotations lexer ;
 IN: continuations
 
 ARTICLE: "errors-restartable" "Restartable errors"
@@ -169,8 +169,8 @@ HELP: rethrow
     "This word is intended to be used in conjunction with " { $link recover } " to implement error handlers which perform an action and pass the error to the next outermost error handler."
 }
 { $examples
-    "The " { $link with-parser } " catches errors, annotates them with file name and line number information, and rethrows them:"
-    { $see with-parser }
+    "The " { $link with-lexer } " word catches errors, annotates them with the current line and column number, and rethrows them:"
+    { $see with-lexer }
 } ;
 
 HELP: throw-restarts
diff --git a/core/cpu/x86/assembler/assembler.factor b/core/cpu/x86/assembler/assembler.factor
index 452a102341..f8e0b0abb0 100755
--- a/core/cpu/x86/assembler/assembler.factor
+++ b/core/cpu/x86/assembler/assembler.factor
@@ -1,8 +1,9 @@
 ! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays generator.fixup io.binary kernel
-combinators kernel.private math namespaces parser sequences
-words system layouts math.order accessors ;
+combinators kernel.private math namespaces sequences
+words system layouts math.order accessors
+cpu.x86.assembler.syntax ;
 IN: cpu.x86.assembler
 
 ! A postfix assembler for x86 and AMD64.
@@ -12,21 +13,6 @@ IN: cpu.x86.assembler
 ! Beware!
 
 ! Register operands -- eg, ECX
-<<
-
-: define-register ( name num size -- )
-    >r >r "cpu.x86.assembler" create dup define-symbol r> r>
-    >r dupd "register" set-word-prop r>
-    "register-size" set-word-prop ;
-
-: define-registers ( names size -- )
-    >r dup length r> [ define-register ] curry 2each ;
-
-: REGISTERS: ( -- )
-    scan-word ";" parse-tokens swap define-registers ; parsing
-
->>
-
 REGISTERS: 8 AL CL DL BL ;
 
 REGISTERS: 16 AX CX DX BX SP BP SI DI ;
diff --git a/core/cpu/x86/assembler/syntax/syntax.factor b/core/cpu/x86/assembler/syntax/syntax.factor
new file mode 100644
index 0000000000..5940663d42
--- /dev/null
+++ b/core/cpu/x86/assembler/syntax/syntax.factor
@@ -0,0 +1,15 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel words sequences lexer parser ;
+IN: cpu.x86.assembler.syntax
+
+: define-register ( name num size -- )
+    >r >r "cpu.x86.assembler" create dup define-symbol r> r>
+    >r dupd "register" set-word-prop r>
+    "register-size" set-word-prop ;
+
+: define-registers ( names size -- )
+    >r dup length r> [ define-register ] curry 2each ;
+
+: REGISTERS: ( -- )
+    scan-word ";" parse-tokens swap define-registers ; parsing
diff --git a/core/effects/parser/parser-docs.factor b/core/effects/parser/parser-docs.factor
new file mode 100644
index 0000000000..6cb39d208d
--- /dev/null
+++ b/core/effects/parser/parser-docs.factor
@@ -0,0 +1,9 @@
+IN: effects.parser
+USING: strings effects help.markup help.syntax ;
+
+HELP: parse-effect
+{ $values { "end" string } { "effect" "an instance of " { $link effect } } }
+{ $description "Parses a stack effect from the current input line." }
+{ $examples "This word is used by " { $link POSTPONE: ( } " and " { $link POSTPONE: (( } " to parse stack effect declarations." }
+$parsing-note ;
+
diff --git a/core/effects/parser/parser.factor b/core/effects/parser/parser.factor
new file mode 100644
index 0000000000..8f28450de7
--- /dev/null
+++ b/core/effects/parser/parser.factor
@@ -0,0 +1,15 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: lexer sets sequences kernel splitting effects ;
+IN: effects.parser
+
+: parse-effect ( end -- effect )
+    parse-tokens dup { "(" "((" } intersect empty? [
+        { "--" } split1 dup [
+            <effect>
+        ] [
+            "Stack effect declaration must contain --" throw
+        ] if
+    ] [
+        "Stack effect declaration must not contain ( or ((" throw
+    ] if ;
diff --git a/core/generic/parser/parser.factor b/core/generic/parser/parser.factor
new file mode 100644
index 0000000000..ba9cd5244c
--- /dev/null
+++ b/core/generic/parser/parser.factor
@@ -0,0 +1,33 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: parser kernel words generic namespaces inspector ;
+IN: generic.parser
+
+ERROR: not-in-a-method-error ;
+
+M: not-in-a-method-error summary
+    drop "call-next-method can only be called in a method definition" ;
+
+: CREATE-GENERIC ( -- word ) CREATE dup reset-word ;
+
+: create-method-in ( class generic -- method )
+    create-method f set-word dup save-location ;
+
+: CREATE-METHOD ( -- method )
+    scan-word bootstrap-word scan-word create-method-in ;
+
+SYMBOL: current-class
+SYMBOL: current-generic
+
+: with-method-definition ( quot -- parsed )
+    [
+        >r
+        [ "method-class" word-prop current-class set ]
+        [ "method-generic" word-prop current-generic set ]
+        [ ] tri
+        r> call
+    ] with-scope ; inline
+
+: (M:) ( method def -- )
+    CREATE-METHOD [ parse-definition ] with-method-definition ;
+
diff --git a/core/lexer/lexer-docs.factor b/core/lexer/lexer-docs.factor
new file mode 100644
index 0000000000..b61fc82a25
--- /dev/null
+++ b/core/lexer/lexer-docs.factor
@@ -0,0 +1,114 @@
+IN: lexer
+USING: help.markup help.syntax kernel math sequences strings
+words quotations ;
+
+: $parsing-note ( children -- )
+    drop
+    "This word should only be called from parsing words."
+    $notes ;
+
+HELP: lexer
+{ $var-description "Stores the current " { $link lexer } " instance." }
+{ $class-description "An object for tokenizing parser input. It has the following slots:"
+    { $list
+        { { $snippet "text" } " - the lines being parsed; an array of strings" }
+        { { $snippet "line" } " - the line number being parsed; unlike most indices this is 1-based for friendlier error reporting and integration with text editors" }
+        { { $snippet "column" } " - the current column position, zero-based" }
+    }
+"Custom lexing can be implemented by delegating a tuple to an instance of this class and implementing the " { $link skip-word } " and " { $link skip-blank } " generic words." } ;
+
+HELP: <lexer>
+{ $values { "text" "a sequence of strings" } { "lexer" lexer } }
+{ $description "Creates a new lexer for tokenizing the given sequence of lines." } ;
+
+HELP: next-line
+{ $values { "lexer" lexer } }
+{ $description "Advances the lexer to the next input line, discarding the remainder of the current line." } ;
+
+HELP: lexer-error
+{ $error-description "Thrown when the lexer encounters invalid input. A lexer error wraps an underlying error together with line and column numbers." } ;
+
+HELP: <lexer-error>
+{ $values { "msg" "an error" } { "error" lexer-error } }
+{ $description "Creates a new " { $link lexer-error } ", filling in the location information from the current " { $link lexer } "." } ;
+
+HELP: skip
+{ $values { "i" "a starting index" } { "seq" sequence } { "?" "a boolean" } { "n" integer } }
+{ $description "Skips to the first space character (if " { $snippet "boolean" } " is " { $link f } ") or the first non-space character (otherwise)." } ;
+
+HELP: change-lexer-column
+{ $values { "lexer" lexer } { "quot" "a quotation with stack effect " { $snippet "( col line -- newcol )" } } }
+{ $description "Applies a quotation to the current column and line text to produce a new column, and moves the lexer position." } ;
+
+HELP: skip-blank
+{ $values { "lexer" lexer } }
+{ $contract "Skips whitespace characters." }
+{ $notes "Custom lexers can implement this generic word." } ;
+
+HELP: skip-word
+{ $values { "lexer" lexer } }
+{ $contract
+    "Skips until the end of the current token."
+    $nl
+    "The default implementation treats a single " { $snippet "\"" } " as a word by itself; otherwise it searches forward until a whitespace character or the end of the line."
+}
+{ $notes "Custom lexers can implement this generic word." } ;
+
+HELP: still-parsing-line?
+{ $values { "lexer" lexer } { "?" "a boolean" } }
+{ $description "Outputs " { $link f } " if the end of the current line has been reached, " { $link t } " otherwise." } ;
+
+HELP: parse-token
+{ $values { "lexer" lexer } { "str/f" "a " { $link string } " or " { $link f } } }
+{ $description "Reads the next token from the lexer. Tokens are delimited by whitespace, with the exception that " { $snippet "\"" } " is treated like a single token even when not followed by whitespace." } ;
+
+HELP: scan
+{ $values { "str/f" "a " { $link string } " or " { $link f } } }
+{ $description "Reads the next token from the lexer. See " { $link parse-token } " for details." }
+$parsing-note ;
+
+HELP: still-parsing?
+{ $values { "lexer" lexer } { "?" "a boolean" } }
+{ $description "Outputs " { $link f } " if end of input has been reached, " { $link t } " otherwise." } ;
+
+HELP: parse-tokens
+{ $values { "end" string } { "seq" "a new sequence of strings" } }
+{ $description "Reads a sequence of tokens until the first occurrence of " { $snippet "end" } ". The tokens remain as strings and are not processed in any way." }
+{ $examples "This word is used to implement " { $link POSTPONE: USING: } "." }
+$parsing-note ;
+
+HELP: unexpected
+{ $values { "want" "a " { $link word } " or " { $link f } } { "got" word } }
+{ $description "Throws an " { $link unexpected } " error." }
+{ $error-description "Thrown by the parser if an unmatched closing delimiter is encountered." }
+{ $examples
+    "Parsing the following snippet will throw this error:"
+    { $code "[ 1 2 3 }" }
+} ;
+
+HELP: unexpected-eof
+{ $values { "word" "a " { $link word } } }
+{ $description "Throws an " { $link unexpected } " error indicating the parser was looking for an occurrence of " { $snippet "word" } " but encountered end of file." } ;
+
+HELP: with-lexer
+{ $values { "lexer" lexer } { "quot" quotation } }
+{ $description "Calls the quotation with the " { $link lexer } " variable set to the given lexer. The quotation can make use of words such as " { $link scan } ". Any errors thrown by the quotation are wrapped in " { $link lexer-error } " instances." } ;
+
+HELP: lexer-factory
+{ $var-description "A variable holding a quotation with stack effect " { $snippet "( lines -- lexer )" } ". This quotation is called by the parser to create " { $link lexer } " instances. This variable can be rebound to a quotation which outputs a custom tuple delegating to " { $link lexer } " to customize syntax." } ;
+
+
+ARTICLE: "parser-lexer" "The lexer"
+"A variable that encapsulate internal parser state:"
+{ $subsection lexer }
+"Creating a default lexer:"
+{ $subsection <lexer> }
+"A word to test of the end of input has been reached:"
+{ $subsection still-parsing? }
+"A word to advance the lexer to the next line:"
+{ $subsection next-line }
+"Two generic words to override the lexer's token boundary detection:"
+{ $subsection skip-blank }
+{ $subsection skip-word }
+"Utility combinator:"
+{ $subsection with-lexer } ;
diff --git a/core/lexer/lexer.factor b/core/lexer/lexer.factor
new file mode 100644
index 0000000000..3d65fb95ca
--- /dev/null
+++ b/core/lexer/lexer.factor
@@ -0,0 +1,133 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel sequences accessors namespaces math words strings
+debugger io vectors arrays math.parser combinators inspector
+continuations ;
+IN: lexer
+
+TUPLE: lexer text line line-text line-length column ;
+
+: next-line ( lexer -- )
+    dup [ line>> ] [ text>> ] bi ?nth >>line-text
+    dup line-text>> length >>line-length
+    [ 1+ ] change-line
+    0 >>column
+    drop ;
+
+: new-lexer ( text class -- lexer )
+    new
+        0 >>line
+        swap >>text
+    dup next-line ; inline
+
+: <lexer> ( text -- lexer )
+    lexer new-lexer ;
+
+: skip ( i seq ? -- n )
+    over >r
+    [ swap CHAR: \s eq? xor ] curry find-from drop
+    [ r> drop ] [ r> length ] if* ;
+
+: change-lexer-column ( lexer quot -- )
+    swap
+    [ dup lexer-column swap lexer-line-text rot call ] keep
+    set-lexer-column ; inline
+
+GENERIC: skip-blank ( lexer -- )
+
+M: lexer skip-blank ( lexer -- )
+    [ t skip ] change-lexer-column ;
+
+GENERIC: skip-word ( lexer -- )
+
+M: lexer skip-word ( lexer -- )
+    [
+        2dup nth CHAR: " eq? [ drop 1+ ] [ f skip ] if
+    ] change-lexer-column ;
+
+: still-parsing? ( lexer -- ? )
+    dup lexer-line swap lexer-text length <= ;
+
+: still-parsing-line? ( lexer -- ? )
+    dup lexer-column swap lexer-line-length < ;
+
+: (parse-token) ( lexer -- str )
+    [ lexer-column ] keep
+    [ skip-word ] keep
+    [ lexer-column ] keep
+    lexer-line-text subseq ;
+
+:  parse-token ( lexer -- str/f )
+    dup still-parsing? [
+        dup skip-blank
+        dup still-parsing-line?
+        [ (parse-token) ] [ dup next-line parse-token ] if
+    ] [ drop f ] if ;
+
+: scan ( -- str/f ) lexer get parse-token ;
+
+ERROR: unexpected want got ;
+
+GENERIC: expected>string ( obj -- str )
+
+M: f expected>string drop "end of input" ;
+M: word expected>string word-name ;
+M: string expected>string ;
+
+M: unexpected error.
+    "Expected " write
+    dup unexpected-want expected>string write
+    " but got " write
+    unexpected-got expected>string print ;
+
+PREDICATE: unexpected-eof < unexpected
+    unexpected-got not ;
+
+: unexpected-eof ( word -- * ) f unexpected ;
+
+: (parse-tokens) ( accum end -- accum )
+    scan 2dup = [
+        2drop
+    ] [
+        [ pick push (parse-tokens) ] [ unexpected-eof ] if*
+    ] if ;
+
+: parse-tokens ( end -- seq )
+    100 <vector> swap (parse-tokens) >array ;
+
+TUPLE: lexer-error line column line-text error ;
+
+: <lexer-error> ( msg -- error )
+    \ lexer-error new
+        lexer get
+        [ line>> >>line ]
+        [ column>> >>column ]
+        [ line-text>> >>line-text ]
+        tri
+        swap >>error ;
+
+: lexer-dump ( error -- )
+    [ line>> number>string ": " append ]
+    [ line-text>> dup string? [ drop "" ] unless ]
+    [ column>> 0 or ] tri
+    pick length + CHAR: \s <string>
+    [ write ] [ print ] [ write "^" print ] tri* ;
+
+M: lexer-error error.
+    [ lexer-dump ] [ error>> error. ] bi ;
+
+M: lexer-error summary
+    error>> summary ;
+
+M: lexer-error compute-restarts
+    error>> compute-restarts ;
+
+M: lexer-error error-help
+    error>> error-help ;
+
+: with-lexer ( lexer quot -- newquot )
+    [ lexer set ] dip [ <lexer-error> rethrow ] recover ; inline
+
+SYMBOL: lexer-factory
+
+[ <lexer> ] lexer-factory set-global
diff --git a/core/listener/listener.factor b/core/listener/listener.factor
index e00e64f4bc..4e2a8c768e 100755
--- a/core/listener/listener.factor
+++ b/core/listener/listener.factor
@@ -1,7 +1,7 @@
 ! Copyright (C) 2003, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays hashtables io kernel math math.parser memory
-namespaces parser sequences strings io.styles
+namespaces parser lexer sequences strings io.styles
 vectors words generic system combinators continuations debugger
 definitions compiler.units accessors ;
 IN: listener
@@ -51,7 +51,7 @@ SYMBOL: error-hook
     listener-hook get call prompt.
     [ read-quot [ [ error-hook get call ] recover ] [ bye ] if* ]
     [
-        dup parse-error? [
+        dup lexer-error? [
             error-hook get call
         ] [
             rethrow
diff --git a/core/parser/parser-docs.factor b/core/parser/parser-docs.factor
index 2ec9f2de54..1aecfbd60d 100755
--- a/core/parser/parser-docs.factor
+++ b/core/parser/parser-docs.factor
@@ -1,7 +1,7 @@
 USING: help.markup help.syntax kernel sequences words
 math strings vectors quotations generic effects classes
 vocabs.loader definitions io vocabs source-files
-quotations namespaces compiler.units assocs ;
+quotations namespaces compiler.units assocs lexer ;
 IN: parser
 
 ARTICLE: "vocabulary-search-shadow" "Shadowing word names"
@@ -135,25 +135,6 @@ $nl
 { $subsection "defining-words" }
 { $subsection "parsing-tokens" } ;
 
-ARTICLE: "parser-lexer" "The lexer"
-"Two variables that encapsulate internal parser state:"
-{ $subsection file }
-{ $subsection lexer }
-"Creating a default lexer:"
-{ $subsection <lexer> }
-"A word to test of the end of input has been reached:"
-{ $subsection still-parsing? }
-"A word to advance the lexer to the next line:"
-{ $subsection next-line }
-"Two generic words to override the lexer's token boundary detection:"
-{ $subsection skip-blank }
-{ $subsection skip-word }
-"A utility used when parsing string literals:"
-{ $subsection parse-string }
-"The parser can be invoked with a custom lexer:"
-{ $subsection (parse-lines) }
-{ $subsection with-parser } ;
-
 ARTICLE: "parser-files" "Parsing source files"
 "The parser can run source files:"
 { $subsection run-file }
@@ -192,25 +173,6 @@ $nl
 
 ABOUT: "parser"
 
-: $parsing-note ( children -- )
-    drop
-    "This word should only be called from parsing words."
-    $notes ;
-
-HELP: lexer
-{ $var-description "Stores the current " { $link lexer } " instance." }
-{ $class-description "An object for tokenizing parser input. It has the following slots:"
-    { $list
-        { { $link lexer-text } " - the lines being parsed; an array of strings" }
-        { { $link lexer-line } " - the line number being parsed; unlike most indices this is 1-based for friendlier error reporting and integration with text editors" }
-        { { $link lexer-column } " - the current column position, zero-based" }
-    }
-"Custom lexing can be implemented by delegating a tuple to an instance of this class and implementing the " { $link skip-word } " and " { $link skip-blank } " generic words." } ;
-
-HELP: <lexer>
-{ $values { "text" "a sequence of strings" } { "lexer" lexer } }
-{ $description "Creates a new lexer for tokenizing the given sequence of lines." } ;
-
 HELP: location
 { $values { "loc" "a " { $snippet "{ path line# }" } " pair" } }
 { $description "Outputs the current parser location. This value can be passed to " { $link set-where } " or " { $link remember-definition } "." } ;
@@ -226,73 +188,9 @@ HELP: parser-notes?
 { $values { "?" "a boolean" } }
 { $description "Tests if the parser will print various notes and warnings. To disable parser notes, either set " { $link parser-notes } " to " { $link f } ", or pass the " { $snippet "-quiet" } " command line switch." } ;
 
-HELP: next-line
-{ $values { "lexer" lexer } }
-{ $description "Advances the lexer to the next input line, discarding the remainder of the current line." } ;
-
-HELP: parse-error
-{ $error-description "Thrown when the parser encounters invalid input. A parse error wraps an underlying error and holds the file being parsed, line number, and column number." } ;
-
-HELP: <parse-error>
-{ $values { "msg" "an error" } { "error" parse-error } }
-{ $description "Creates a new " { $link parse-error } ", filling in the location information from the current " { $link lexer } "." } ;
-
-HELP: skip
-{ $values { "i" "a starting index" } { "seq" sequence } { "?" "a boolean" } { "n" integer } }
-{ $description "Skips to the first space character (if " { $snippet "boolean" } " is " { $link f } ") or the first non-space character (otherwise)." } ;
-
-HELP: change-lexer-column
-{ $values { "lexer" lexer } { "quot" "a quotation with stack effect " { $snippet "( col line -- newcol )" } } }
-{ $description "Applies a quotation to the current column and line text to produce a new column, and moves the lexer position." } ;
-
-HELP: skip-blank
-{ $values { "lexer" lexer } }
-{ $contract "Skips whitespace characters." }
-{ $notes "Custom lexers can implement this generic word." } ;
-
-HELP: skip-word
-{ $values { "lexer" lexer } }
-{ $contract
-    "Skips until the end of the current token."
-    $nl
-    "The default implementation treats a single " { $snippet "\"" } " as a word by itself; otherwise it searches forward until a whitespace character or the end of the line."
-}
-{ $notes "Custom lexers can implement this generic word." } ;
-
-HELP: still-parsing-line?
-{ $values { "lexer" lexer } { "?" "a boolean" } }
-{ $description "Outputs " { $link f } " if the end of the current line has been reached, " { $link t } " otherwise." } ;
-
-HELP: parse-token
-{ $values { "lexer" lexer } { "str/f" "a " { $link string } " or " { $link f } } }
-{ $description "Reads the next token from the lexer. Tokens are delimited by whitespace, with the exception that " { $snippet "\"" } " is treated like a single token even when not followed by whitespace." } ;
-
-HELP: scan
-{ $values { "str/f" "a " { $link string } " or " { $link f } } }
-{ $description "Reads the next token from the lexer. See " { $link parse-token } " for details." }
-$parsing-note ;
-
-HELP: bad-escape
-{ $error-description "Indicates the parser encountered an invalid escape code following a backslash (" { $snippet "\\" } ") in a string literal. See " { $link "escape" } " for a list of valid escape codes." } ;
-
 HELP: bad-number
 { $error-description "Indicates the parser encountered an invalid numeric literal." } ;
 
-HELP: escape
-{ $values { "escape" "a single-character escape" } { "ch" "a character" } }
-{ $description "Converts from a single-character escape code and the corresponding character." }
-{ $examples { $example "USING: kernel parser prettyprint ;" "CHAR: n escape CHAR: \\n = ." "t" } } ;
-
-HELP: parse-string
-{ $values { "str" "a new " { $link string } } }
-{ $description "Parses the line until a quote (\"), interpreting escape codes along the way." }
-{ $errors "Throws an error if the string contains an invalid escape sequence." }
-$parsing-note ;
-
-HELP: still-parsing?
-{ $values { "lexer" lexer } { "?" "a boolean" } }
-{ $description "Outputs " { $link f } " if end of input has been reached, " { $link t } " otherwise." } ;
-
 HELP: use
 { $var-description "A variable holding the current vocabulary search path as a sequence of assocs." } ;
 
@@ -338,12 +236,6 @@ HELP: create-in
 { $description "Creates a word in the current vocabulary. Until re-defined, the word throws an error when invoked." }
 $parsing-note ;
 
-HELP: parse-tokens
-{ $values { "end" string } { "seq" "a new sequence of strings" } }
-{ $description "Reads a sequence of tokens until the first occurrence of " { $snippet "end" } ". The tokens remain as strings and are not processed in any way." }
-{ $examples "This word is used to implement " { $link POSTPONE: USING: } "." }
-$parsing-note ;
-
 HELP: CREATE
 { $values { "word" word } }
 { $description "Reads the next token from the line currently being parsed, and creates a word with that name in the current vocabulary." }
@@ -369,31 +261,6 @@ HELP: scan-word
 { $errors "Throws an error if the token does not name a word, and does not parse as a number." }
 $parsing-note ;
 
-HELP: invalid-slot-name
-{ $values { "name" string } }
-{ $description "Throws an " { $link invalid-slot-name } " error." }
-{ $error-description "Thrown by " { $link POSTPONE: TUPLE: } " and " { $link POSTPONE: ERROR: } " if a suspect token appears as a slot name." }
-{ $notes "The suspect tokens are chosen so that the following code raises this parse error, instead of silently greating a tuple with garbage slots:"
-    { $code
-        "TUPLE: my-mistaken-tuple slot-a slot-b"
-        ""
-        ": some-word ( a b c -- ) ... ;"
-    }
-} ;
-
-HELP: unexpected
-{ $values { "want" "a " { $link word } " or " { $link f } } { "got" word } }
-{ $description "Throws an " { $link unexpected } " error." }
-{ $error-description "Thrown by the parser if an unmatched closing delimiter is encountered." }
-{ $examples
-    "Parsing the following snippet will throw this error:"
-    { $code "[ 1 2 3 }" }
-} ;
-
-HELP: unexpected-eof
-{ $values { "word" "a " { $link word } } }
-{ $description "Throws an " { $link unexpected } " error indicating the parser was looking for an occurrence of " { $snippet "word" } " but encountered end of file." } ;
-
 HELP: parse-step
 { $values { "accum" vector } { "end" word } { "?" "a boolean" } }
 { $description "Parses a token. If the token is a number or an ordinary word, it is added to the accumulator. If it is a parsing word, calls the parsing word with the accumulator on the stack. Outputs " { $link f } " if " { $snippet "end" } " is encountered, " { $link t } " otherwise." }
@@ -417,28 +284,15 @@ HELP: parsed
 { $description "Convenience word for parsing words. It behaves exactly the same as " { $link push } ", except the accumulator remains on the stack." }
 $parsing-note ;
 
-HELP: with-parser
-{ $values { "lexer" lexer } { "quot" "a quotation with stack effect " { $snippet "( -- accum )" } } { "newquot" "a new " { $link quotation } } }
-{ $description "Sets up the parser and calls the quotation. The quotation can make use of parsing words such as " { $link scan } " and " { $link parse-until } ". It must yield a sequence, which is converted to a quotation and output. Any errors thrown by the quotation are wrapped in parse errors." } ;
-
 HELP: (parse-lines)
 { $values { "lexer" lexer } { "quot" "a new " { $link quotation } } }
 { $description "Parses Factor source code using a custom lexer. The vocabulary search path is taken from the current scope." }
-{ $errors "Throws a " { $link parse-error } " if the input is malformed." } ;
+{ $errors "Throws a " { $link lexer-error } " if the input is malformed." } ;
 
 HELP: parse-lines
 { $values { "lines" "a sequence of strings" } { "quot" "a new " { $link quotation } } }
 { $description "Parses Factor source code which has been tokenized into lines. The vocabulary search path is taken from the current scope." }
-{ $errors "Throws a " { $link parse-error } " if the input is malformed." } ;
-
-HELP: lexer-factory
-{ $var-description "A variable holding a quotation with stack effect " { $snippet "( lines -- lexer )" } ". This quotation is called by the parser to create " { $link lexer } " instances. This variable can be rebound to a quotation which outputs a custom tuple delegating to " { $link lexer } " to customize syntax." } ;
-
-HELP: parse-effect
-{ $values { "end" string } { "effect" "an instance of " { $link effect } } }
-{ $description "Parses a stack effect from the current input line." }
-{ $examples "This word is used by " { $link POSTPONE: ( } " and " { $link POSTPONE: (( } " to parse stack effect declarations." }
-$parsing-note ;
+{ $errors "Throws a " { $link lexer-error } " if the input is malformed." } ;
 
 HELP: parse-base
 { $values { "base" "an integer between 2 and 36" } { "parsed" integer } }
diff --git a/core/parser/parser-tests.factor b/core/parser/parser-tests.factor
index 555c6eb32c..eb37d556d0 100755
--- a/core/parser/parser-tests.factor
+++ b/core/parser/parser-tests.factor
@@ -485,3 +485,9 @@ must-fail-with
 [ t ] [ "staging-problem-test-2" "parser.tests" lookup >boolean ] unit-test
 
 [ "DEFER: blah" eval ] [ error>> no-current-vocab? ] must-fail-with
+
+[
+    "IN: parser.tests : blah ; parsing FORGET: blah" eval
+] [
+    error>> staging-violation?
+] must-fail-with
diff --git a/core/parser/parser.factor b/core/parser/parser.factor
index 129d5ef2ee..44708f11f3 100755
--- a/core/parser/parser.factor
+++ b/core/parser/parser.factor
@@ -4,38 +4,17 @@ USING: arrays definitions generic assocs kernel math namespaces
 prettyprint sequences strings vectors words quotations inspector
 io.styles io combinators sorting splitting math.parser effects
 continuations debugger io.files io.streams.string vocabs
-io.encodings.utf8 source-files classes classes.tuple hashtables
-compiler.errors compiler.units accessors sets ;
+io.encodings.utf8 source-files classes hashtables
+compiler.errors compiler.units accessors sets lexer ;
 IN: parser
 
-TUPLE: lexer text line line-text line-length column ;
-
-: next-line ( lexer -- )
-    dup [ line>> ] [ text>> ] bi ?nth >>line-text
-    dup line-text>> length >>line-length
-    [ 1+ ] change-line
-    0 >>column
-    drop ;
-
-: new-lexer ( text class -- lexer )
-    new
-        0 >>line
-        swap >>text
-    dup next-line ; inline
-
-: <lexer> ( text -- lexer )
-    lexer new-lexer ;
-
 : location ( -- loc )
-    file get lexer get lexer-line 2dup and
-    [ >r source-file-path r> 2array ] [ 2drop f ] if ;
+    file get lexer get line>> 2dup and
+    [ >r path>> r> 2array ] [ 2drop f ] if ;
 
 : save-location ( definition -- )
     location remember-definition ;
 
-: save-class-location ( class -- )
-    location remember-class ;
-
 SYMBOL: parser-notes
 
 t parser-notes set-global
@@ -43,13 +22,6 @@ t parser-notes set-global
 : parser-notes? ( -- ? )
     parser-notes get "quiet" get not and ;
 
-: file. ( file -- )
-    [
-        source-file-path <pathname> pprint
-    ] [
-        "<interactive>" write
-    ] if* ":" write ;
-
 : note. ( str -- )
     parser-notes? [
         file get file.
@@ -61,143 +33,9 @@ t parser-notes set-global
         "Note: " write dup print
     ] when drop ;
 
-: skip ( i seq ? -- n )
-    over >r
-    [ swap CHAR: \s eq? xor ] curry find-from drop
-    [ r> drop ] [ r> length ] if* ;
-
-: change-lexer-column ( lexer quot -- )
-    swap
-    [ dup lexer-column swap lexer-line-text rot call ] keep
-    set-lexer-column ; inline
-
-GENERIC: skip-blank ( lexer -- )
-
-M: lexer skip-blank ( lexer -- )
-    [ t skip ] change-lexer-column ;
-
-GENERIC: skip-word ( lexer -- )
-
-M: lexer skip-word ( lexer -- )
-    [
-        2dup nth CHAR: " eq? [ drop 1+ ] [ f skip ] if
-    ] change-lexer-column ;
-
-: still-parsing? ( lexer -- ? )
-    dup lexer-line swap lexer-text length <= ;
-
-: still-parsing-line? ( lexer -- ? )
-    dup lexer-column swap lexer-line-length < ;
-
-: (parse-token) ( lexer -- str )
-    [ lexer-column ] keep
-    [ skip-word ] keep
-    [ lexer-column ] keep
-    lexer-line-text subseq ;
-
-:  parse-token ( lexer -- str/f )
-    dup still-parsing? [
-        dup skip-blank
-        dup still-parsing-line?
-        [ (parse-token) ] [ dup next-line parse-token ] if
-    ] [ drop f ] if ;
-
-: scan ( -- str/f ) lexer get parse-token ;
-
-ERROR: bad-escape ;
-
-M: bad-escape summary drop "Bad escape code" ;
-
-: escape ( escape -- ch )
-    H{
-        { CHAR: a  CHAR: \a }
-        { CHAR: e  CHAR: \e }
-        { CHAR: n  CHAR: \n }
-        { CHAR: r  CHAR: \r }
-        { CHAR: t  CHAR: \t }
-        { CHAR: s  CHAR: \s }
-        { CHAR: \s CHAR: \s }
-        { CHAR: 0  CHAR: \0 }
-        { CHAR: \\ CHAR: \\ }
-        { CHAR: \" CHAR: \" }
-    } at [ bad-escape ] unless* ;
-
-SYMBOL: name>char-hook
-
-name>char-hook global [
-    [ "Unicode support not available" throw ] or
-] change-at
-
-: unicode-escape ( str -- ch str' )
-    "{" ?head-slice [
-        CHAR: } over index cut-slice
-        >r >string name>char-hook get call r>
-        rest-slice
-    ] [
-        6 cut-slice >r hex> r>
-    ] if ;
-
-: next-escape ( str -- ch str' )
-    "u" ?head-slice [
-        unicode-escape
-    ] [
-        unclip-slice escape swap
-    ] if ;
-
-: (parse-string) ( str -- m )
-    dup [ "\"\\" member? ] find dup [
-        >r cut-slice >r % r> rest-slice r>
-        dup CHAR: " = [
-            drop slice-from
-        ] [
-            drop next-escape >r , r> (parse-string)
-        ] if
-    ] [
-        "Unterminated string" throw
-    ] if ;
-
-: parse-string ( -- str )
-    lexer get [
-        [ swap tail-slice (parse-string) ] "" make swap
-    ] change-lexer-column ;
-
-TUPLE: parse-error file line column line-text error ;
-
-: <parse-error> ( msg -- error )
-    \ parse-error new
-        file get >>file
-        lexer get line>> >>line
-        lexer get column>> >>column
-        lexer get line-text>> >>line-text
-        swap >>error ;
-
-: parse-dump ( error -- )
-    {
-        [ file>> file. ]
-        [ line>> number>string print ]
-        [ line-text>> dup string? [ print ] [ drop ] if ]
-        [ column>> 0 or CHAR: \s <string> write ]
-    } cleave
-    "^" print ;
-
-M: parse-error error.
-    [ parse-dump ] [ error>> error. ] bi ;
-
-M: parse-error summary
-    error>> summary ;
-
-M: parse-error compute-restarts
-    error>> compute-restarts ;
-
-M: parse-error error-help
-    error>> error-help ;
-
 SYMBOL: use
 SYMBOL: in
 
-: word/vocab% ( word -- )
-    "(" % dup word-vocabulary % " " % word-name % ")" % ;
-
 : (use+) ( vocab -- )
     vocab-words use get push ;
 
@@ -216,25 +54,8 @@ SYMBOL: in
 : set-in ( name -- )
     check-vocab-string dup in set create-vocab (use+) ;
 
-ERROR: unexpected want got ;
-
-PREDICATE: unexpected-eof < unexpected
-    unexpected-got not ;
-
 M: parsing-word stack-effect drop (( parsed -- parsed )) ;
 
-: unexpected-eof ( word -- * ) f unexpected ;
-
-: (parse-tokens) ( accum end -- accum )
-    scan 2dup = [
-        2drop
-    ] [
-        [ pick push (parse-tokens) ] [ unexpected-eof ] if*
-    ] if ;
-
-: parse-tokens ( end -- seq )
-    100 <vector> swap (parse-tokens) >array ;
-
 ERROR: no-current-vocab ;
 
 M: no-current-vocab summary ( obj -- )
@@ -248,18 +69,8 @@ M: no-current-vocab summary ( obj -- )
 
 : CREATE ( -- word ) scan create-in ;
 
-: CREATE-GENERIC ( -- word ) CREATE dup reset-word ;
-
 : CREATE-WORD ( -- word ) CREATE dup reset-generic ;
 
-: create-class-in ( word -- word )
-    current-vocab create
-    dup save-class-location
-    dup predicate-word dup set-word save-location ;
-
-: CREATE-CLASS ( -- word )
-    scan create-class-in ;
-
 : word-restarts ( possibilities -- restarts )
     natural-sort [
         [ "Use the word " swap summary append ] keep
@@ -296,62 +107,6 @@ M: no-word-error summary
         ] ?if
     ] when ;
 
-: create-method-in ( class generic -- method )
-    create-method f set-word dup save-location ;
-
-: CREATE-METHOD ( -- method )
-    scan-word bootstrap-word scan-word create-method-in ;
-
-: shadowed-slots ( superclass slots -- shadowed )
-    >r all-slot-names r> intersect ;
-
-: check-slot-shadowing ( class superclass slots -- )
-    shadowed-slots [
-        [
-            "Definition of slot ``" %
-            %
-            "'' in class ``" %
-            word-name %
-            "'' shadows a superclass slot" %
-        ] "" make note.
-    ] with each ;
-
-ERROR: invalid-slot-name name ;
-
-M: invalid-slot-name summary
-    drop
-    "Invalid slot name" ;
-
-: (parse-tuple-slots) ( -- )
-    #! This isn't meant to enforce any kind of policy, just
-    #! to check for mistakes of this form:
-    #!
-    #! TUPLE: blahblah foo bing
-    #!
-    #! : ...
-    scan {
-        { [ dup not ] [ unexpected-eof ] }
-        { [ dup { ":" "(" "<" } member? ] [ invalid-slot-name ] }
-        { [ dup ";" = ] [ drop ] }
-        [ , (parse-tuple-slots) ]
-    } cond ;
-
-: parse-tuple-slots ( -- seq )
-    [ (parse-tuple-slots) ] { } make ;
-
-: parse-tuple-definition ( -- class superclass slots )
-    CREATE-CLASS
-    scan {
-        { ";" [ tuple f ] }
-        { "<" [ scan-word parse-tuple-slots ] }
-        [ >r tuple parse-tuple-slots r> prefix ]
-    } case 3dup check-slot-shadowing ;
-
-ERROR: not-in-a-method-error ;
-
-M: not-in-a-method-error summary
-    drop "call-next-method can only be called in a method definition" ;
-
 ERROR: staging-violation word ;
 
 M: staging-violation summary
@@ -362,6 +117,10 @@ M: staging-violation summary
     dup changed-definitions get key? [ staging-violation ] when
     execute ;
 
+: scan-object ( -- object )
+    scan-word dup parsing-word?
+    [ V{ } clone swap execute-parsing first ] when ;
+
 : parse-step ( accum end -- accum ? )
     scan-word {
         { [ 2dup eq? ] [ 2drop f ] }
@@ -379,37 +138,12 @@ M: staging-violation summary
 
 : parsed ( accum obj -- accum ) over push ;
 
-: with-parser ( lexer quot -- newquot )
-    swap lexer set
-    [ call >quotation ] [ <parse-error> rethrow ] recover ;
-
 : (parse-lines) ( lexer -- quot )
-    [ f parse-until ] with-parser ;
-
-SYMBOL: lexer-factory
-
-[ <lexer> ] lexer-factory set-global
+    [ f parse-until >quotation ] with-lexer ;
 
 : parse-lines ( lines -- quot )
     lexer-factory get call (parse-lines) ;
 
-! Parsing word utilities
-: parse-effect ( end -- effect )
-    parse-tokens dup { "(" "((" } intersect empty? [
-        { "--" } split1 dup [
-            <effect>
-        ] [
-            "Stack effect declaration must contain --" throw
-        ] if
-    ] [
-        "Stack effect declaration must not contain ( or ((" throw
-    ] if ;
-
-ERROR: bad-number ;
-
-: parse-base ( parsed base -- parsed )
-    scan swap base> [ bad-number ] unless* parsed ;
-
 : parse-literal ( accum end quot -- accum )
     >r parse-until r> call parsed ; inline
 
@@ -418,40 +152,14 @@ ERROR: bad-number ;
 
 : (:) ( -- word def ) CREATE-WORD parse-definition ;
 
-SYMBOL: current-class
-SYMBOL: current-generic
-
-: with-method-definition ( quot -- parsed )
-    [
-        >r
-        [ "method-class" word-prop current-class set ]
-        [ "method-generic" word-prop current-generic set ]
-        [ ] tri
-        r> call
-    ] with-scope ; inline
-
-: (M:) ( method def -- )
-    CREATE-METHOD [ parse-definition ] with-method-definition ;
-
-: scan-object ( -- object )
-    scan-word dup parsing-word?
-    [ V{ } clone swap execute first ] when ;
-
-GENERIC: expected>string ( obj -- str )
-
-M: f expected>string drop "end of input" ;
-M: word expected>string word-name ;
-M: string expected>string ;
-
-M: unexpected error.
-    "Expected " write
-    dup unexpected-want expected>string write
-    " but got " write
-    unexpected-got expected>string print ;
+ERROR: bad-number ;
 
 M: bad-number summary
     drop "Bad number literal" ;
 
+: parse-base ( parsed base -- parsed )
+    scan swap base> [ bad-number ] unless* parsed ;
+
 SYMBOL: bootstrap-syntax
 
 : with-file-vocabs ( quot -- )
diff --git a/core/source-files/source-files.factor b/core/source-files/source-files.factor
index 454f148974..0577dacc85 100755
--- a/core/source-files/source-files.factor
+++ b/core/source-files/source-files.factor
@@ -75,11 +75,36 @@ M: pathname forget*
 
 SYMBOL: file
 
+TUPLE: source-file-error file error ;
+
+: <source-file-error> ( msg -- error )
+    \ source-file-error new
+        file get >>file
+        swap >>error ;
+
+: file. ( file -- ) path>> <pathname> pprint ;
+
+M: source-file-error error.
+    "Error while parsing " write
+    [ file>> file. nl ] [ error>> error. ] bi ;
+
+M: source-file-error summary
+    error>> summary ;
+
+M: source-file-error compute-restarts
+    error>> compute-restarts ;
+
+M: source-file-error error-help
+    error>> error-help ;
+
 : with-source-file ( name quot -- )
     #! Should be called from inside with-compilation-unit.
     [
         swap source-file
         dup file set
         source-file-definitions old-definitions set
-        [ ] [ file get rollback-source-file ] cleanup
+        [
+            file get rollback-source-file
+            <source-file-error> rethrow
+        ] recover
     ] with-scope ; inline
diff --git a/core/strings/parser/parser-docs.factor b/core/strings/parser/parser-docs.factor
new file mode 100644
index 0000000000..0aa6d483ca
--- /dev/null
+++ b/core/strings/parser/parser-docs.factor
@@ -0,0 +1,16 @@
+USING: help.markup help.syntax strings lexer ;
+IN: strings.parser
+
+HELP: bad-escape
+{ $error-description "Indicates the parser encountered an invalid escape code following a backslash (" { $snippet "\\" } ") in a string literal. See " { $link "escape" } " for a list of valid escape codes." } ;
+
+HELP: escape
+{ $values { "escape" "a single-character escape" } { "ch" "a character" } }
+{ $description "Converts from a single-character escape code and the corresponding character." }
+{ $examples { $example "USING: kernel parser prettyprint ;" "CHAR: n escape CHAR: \\n = ." "t" } } ;
+
+HELP: parse-string
+{ $values { "str" "a new " { $link string } } }
+{ $description "Parses the line until a quote (\"), interpreting escape codes along the way." }
+{ $errors "Throws an error if the string contains an invalid escape sequence." }
+$parsing-note ;
diff --git a/core/strings/parser/parser.factor b/core/strings/parser/parser.factor
new file mode 100644
index 0000000000..08421b4a20
--- /dev/null
+++ b/core/strings/parser/parser.factor
@@ -0,0 +1,62 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel inspector assocs namespaces splitting sequences
+strings math.parser lexer ;
+IN: strings.parser
+
+ERROR: bad-escape ;
+
+M: bad-escape summary drop "Bad escape code" ;
+
+: escape ( escape -- ch )
+    H{
+        { CHAR: a  CHAR: \a }
+        { CHAR: e  CHAR: \e }
+        { CHAR: n  CHAR: \n }
+        { CHAR: r  CHAR: \r }
+        { CHAR: t  CHAR: \t }
+        { CHAR: s  CHAR: \s }
+        { CHAR: \s CHAR: \s }
+        { CHAR: 0  CHAR: \0 }
+        { CHAR: \\ CHAR: \\ }
+        { CHAR: \" CHAR: \" }
+    } at [ bad-escape ] unless* ;
+
+SYMBOL: name>char-hook
+
+name>char-hook global [
+    [ "Unicode support not available" throw ] or
+] change-at
+
+: unicode-escape ( str -- ch str' )
+    "{" ?head-slice [
+        CHAR: } over index cut-slice
+        >r >string name>char-hook get call r>
+        rest-slice
+    ] [
+        6 cut-slice >r hex> r>
+    ] if ;
+
+: next-escape ( str -- ch str' )
+    "u" ?head-slice [
+        unicode-escape
+    ] [
+        unclip-slice escape swap
+    ] if ;
+
+: (parse-string) ( str -- m )
+    dup [ "\"\\" member? ] find dup [
+        >r cut-slice >r % r> rest-slice r>
+        dup CHAR: " = [
+            drop slice-from
+        ] [
+            drop next-escape >r , r> (parse-string)
+        ] if
+    ] [
+        "Unterminated string" throw
+    ] if ;
+
+: parse-string ( -- str )
+    lexer get [
+        [ swap tail-slice (parse-string) ] "" make swap
+    ] change-lexer-column ;
diff --git a/core/syntax/syntax.factor b/core/syntax/syntax.factor
index 91a453408d..dfba35f71a 100755
--- a/core/syntax/syntax.factor
+++ b/core/syntax/syntax.factor
@@ -1,13 +1,14 @@
 ! Copyright (C) 2004, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien arrays bit-arrays byte-arrays byte-vectors
-definitions generic hashtables kernel math
-namespaces parser sequences strings sbufs vectors words
-quotations io assocs splitting classes.tuple generic.standard
-generic.math classes io.files vocabs float-arrays
-classes.union classes.intersection classes.mixin
-classes.predicate classes.singleton compiler.units
-combinators debugger ;
+definitions generic hashtables kernel math namespaces parser
+lexer sequences strings strings.parser sbufs vectors
+words quotations io assocs splitting classes.tuple
+generic.standard generic.math generic.parser classes io.files
+vocabs float-arrays classes.parser classes.union
+classes.intersection classes.mixin classes.predicate
+classes.singleton classes.tuple.parser compiler.units
+combinators debugger effects.parser ;
 IN: bootstrap.syntax
 
 ! These words are defined as a top-level form, instead of with
diff --git a/extra/bitfields/bitfields.factor b/extra/bitfields/bitfields.factor
index 7d3ef89759..c83d4b5152 100644
--- a/extra/bitfields/bitfields.factor
+++ b/extra/bitfields/bitfields.factor
@@ -1,4 +1,4 @@
-USING: parser kernel math sequences namespaces assocs inspector
+USING: parser lexer kernel math sequences namespaces assocs inspector
 words splitting math.parser arrays sequences.next mirrors
 shuffle compiler.units ;
 IN: bitfields
diff --git a/extra/bootstrap/unicode/unicode.factor b/extra/bootstrap/unicode/unicode.factor
index 0476cbf18b..b46e322d7b 100755
--- a/extra/bootstrap/unicode/unicode.factor
+++ b/extra/bootstrap/unicode/unicode.factor
@@ -1,4 +1,4 @@
-USING: parser kernel namespaces ;
+USING: strings.parser kernel namespaces ;
 
 USE: unicode.breaks
 USE: unicode.case
diff --git a/extra/cocoa/cocoa.factor b/extra/cocoa/cocoa.factor
index f4cfb20591..1dd1e0a264 100755
--- a/extra/cocoa/cocoa.factor
+++ b/extra/cocoa/cocoa.factor
@@ -2,7 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: compiler io kernel cocoa.runtime cocoa.subclassing
 cocoa.messages cocoa.types sequences words vocabs parser
-core-foundation namespaces assocs hashtables compiler.units ;
+core-foundation namespaces assocs hashtables compiler.units
+lexer ;
 IN: cocoa
 
 : (remember-send) ( selector variable -- )
diff --git a/extra/cpu/8080/emulator/emulator.factor b/extra/cpu/8080/emulator/emulator.factor
index b0ffb6ae54..aa8dc4f9cf 100755
--- a/extra/cpu/8080/emulator/emulator.factor
+++ b/extra/cpu/8080/emulator/emulator.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 !
 USING: kernel math sequences words arrays io io.files namespaces
-math.parser assocs quotations parser parser-combinators
+math.parser assocs quotations parser lexer parser-combinators
 tools.time io.encodings.binary sequences.deep symbols combinators ;
 IN: cpu.8080.emulator
 
diff --git a/extra/editors/editors-docs.factor b/extra/editors/editors-docs.factor
index 2b9e4cc021..0f50e40eb4 100644
--- a/extra/editors/editors-docs.factor
+++ b/extra/editors/editors-docs.factor
@@ -1,4 +1,4 @@
-USING: help.markup help.syntax parser vocabs.loader ;
+USING: help.markup help.syntax parser source-files vocabs.loader ;
 IN: editors
 
 ARTICLE: "editor" "Editor integration"
@@ -35,4 +35,4 @@ HELP: no-edit-hook
 { $error-description "Thrown when " { $link edit } " is called when the " { $link edit-hook } " variable is not set. See " { $link "editor" } "." } ;
 
 HELP: :edit
-{ $description "If the most recent error was a " { $link parse-error } " thrown while parsing a source file, opens the source file at the failing line in the default editor using the " { $link edit-hook } ". See " { $link "editor" } "." } ;
+{ $description "If the most recent error was a " { $link source-file-error } " thrown while parsing a source file, opens the source file at the failing line in the default editor using the " { $link edit-hook } ". See " { $link "editor" } "." } ;
diff --git a/extra/editors/editors.factor b/extra/editors/editors.factor
index ec8313363e..29cbbca90e 100755
--- a/extra/editors/editors.factor
+++ b/extra/editors/editors.factor
@@ -1,9 +1,9 @@
 ! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: parser kernel namespaces sequences definitions io.files
-inspector continuations tools.crossref tools.vocabs 
-io prettyprint source-files assocs vocabs vocabs.loader
-io.backend splitting accessors ;
+USING: parser lexer kernel namespaces sequences definitions
+io.files inspector continuations tools.crossref tools.vocabs io
+prettyprint source-files assocs vocabs vocabs.loader io.backend
+splitting accessors ;
 IN: editors
 
 TUPLE: no-edit-hook ;
@@ -35,21 +35,27 @@ SYMBOL: edit-hook
 : edit-vocab ( name -- )
     vocab-source-path 1 edit-location ;
 
-GENERIC: find-parse-error ( error -- error' )
+GENERIC: error-file ( error -- file )
 
-M: parse-error find-parse-error
-    dup error>> find-parse-error [ ] [ ] ?if ;
+GENERIC: error-line ( error -- line )
 
-M: condition find-parse-error
-    error>> find-parse-error ;
+M: lexer-error error-line line>> ;
 
-M: object find-parse-error
-    drop f ;
+M: source-file-error error-file file>> path>> ;
+
+M: source-file-error error-line error>> error-line ;
+
+M: condition error-file error>> error-file ;
+
+M: condition error-line error>> error-line ;
+
+M: object error-file drop f ;
+
+M: object error-line drop f ;
 
 : :edit ( -- )
-    error get find-parse-error [
-        [ file>> path>> ] [ line>> ] bi edit-location
-    ] when* ;
+    error get [ error-file ] [ error-line ] bi
+    2dup and [ edit-location ] [ 2drop ] if ;
 
 : edit-each ( seq -- )
     [
diff --git a/extra/gesture-logger/gesture-logger.factor b/extra/gesture-logger/gesture-logger.factor
index 76615a3de5..ba0ff5bedd 100644
--- a/extra/gesture-logger/gesture-logger.factor
+++ b/extra/gesture-logger/gesture-logger.factor
@@ -1,7 +1,8 @@
 ! Copyright (C) 2007 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: io kernel prettyprint ui ui.gadgets ui.gadgets.panes
-ui.gadgets.scrollers ui.gadgets.theme ui.gestures colors ;
+ui.gadgets.scrollers ui.gadgets.theme ui.gestures colors
+accessors ;
 IN: gesture-logger
 
 TUPLE: gesture-logger stream ;
diff --git a/extra/help/handbook/handbook.factor b/extra/help/handbook/handbook.factor
index dfbb7a12b8..246ad56e51 100755
--- a/extra/help/handbook/handbook.factor
+++ b/extra/help/handbook/handbook.factor
@@ -3,7 +3,7 @@ namespaces words sequences classes assocs vocabs kernel arrays
 prettyprint.backend kernel.private io generic math system
 strings sbufs vectors byte-arrays bit-arrays float-arrays
 quotations io.streams.byte-array io.encodings.string
-classes.builtin parser ;
+classes.builtin parser lexer ;
 IN: help.handbook
 
 ARTICLE: "conventions" "Conventions"
diff --git a/extra/html/templates/chloe/syntax/syntax.factor b/extra/html/templates/chloe/syntax/syntax.factor
index 7eeb756a39..cfa576d56f 100644
--- a/extra/html/templates/chloe/syntax/syntax.factor
+++ b/extra/html/templates/chloe/syntax/syntax.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 IN: html.templates.chloe.syntax
 USING: accessors kernel sequences combinators kernel namespaces
-classes.tuple assocs splitting words arrays memoize parser
+classes.tuple assocs splitting words arrays memoize parser lexer
 io io.files io.encodings.utf8 io.streams.string
 unicode.case tuple-syntax mirrors fry math urls
 multiline xml xml.data xml.writer xml.utilities
diff --git a/extra/html/templates/fhtml/fhtml.factor b/extra/html/templates/fhtml/fhtml.factor
index 74e5c37ef1..e435fdce5f 100755
--- a/extra/html/templates/fhtml/fhtml.factor
+++ b/extra/html/templates/fhtml/fhtml.factor
@@ -4,7 +4,7 @@
 USING: continuations sequences kernel namespaces debugger
 combinators math quotations generic strings splitting
 accessors assocs fry
-parser io io.files io.streams.string io.encodings.utf8
+parser lexer io io.files io.streams.string io.encodings.utf8
 html.elements
 html.templates ;
 IN: html.templates.fhtml
@@ -55,8 +55,8 @@ DEFER: <% delimiter
 
 : parse-template-lines ( lines -- quot )
     <template-lexer> [
-        V{ } clone lexer get parse-%> f (parse-until)
-    ] with-parser ;
+        V{ } clone lexer get parse-%> f (parse-until) >quotation
+    ] with-lexer ;
 
 : parse-template ( string -- quot )
     [
diff --git a/extra/http/http-tests.factor b/extra/http/http-tests.factor
index 522d0c1845..a920d4e67a 100755
--- a/extra/http/http-tests.factor
+++ b/extra/http/http-tests.factor
@@ -5,6 +5,12 @@ assocs io.sockets db db.sqlite continuations urls hashtables
 accessors ;
 IN: http.tests
 
+[ "text/plain" latin1 ] [ "text/plain" parse-content-type ] unit-test
+
+[ "text/html" utf8 ] [ "text/html;  charset=UTF-8" parse-content-type ] unit-test
+
+[ "application/octet-stream" binary ] [ "application/octet-stream" parse-content-type ] unit-test
+
 : lf>crlf "\n" split "\r\n" join ;
 
 STRING: read-request-test-1
diff --git a/extra/http/http.factor b/extra/http/http.factor
index 4001301cb1..d5712d5bab 100755
--- a/extra/http/http.factor
+++ b/extra/http/http.factor
@@ -211,7 +211,8 @@ TUPLE: post-data raw content content-type ;
     " " split harvest [ "=" split1 [ >lower ] dip ] { } map>assoc ;
 
 : parse-content-type ( content-type -- type encoding )
-    ";" split1 parse-content-type-attributes "charset" swap at ;
+    ";" split1 parse-content-type-attributes "charset" swap at
+    name>encoding over "text/" head? latin1 binary ? or ;
 
 : read-request ( -- request )
     <request>
@@ -310,7 +311,7 @@ M: response clone
     dup "content-type" header [
         parse-content-type
         [ >>content-type ]
-        [ name>encoding binary or >>content-charset ] bi*
+        [ >>content-charset ] bi*
     ] when* ;
 
 : read-response ( -- response )
diff --git a/extra/io/encodings/8-bit/8-bit-docs.factor b/extra/io/encodings/8-bit/8-bit-docs.factor
index 33d629b105..8f5e955998 100644
--- a/extra/io/encodings/8-bit/8-bit-docs.factor
+++ b/extra/io/encodings/8-bit/8-bit-docs.factor
@@ -24,20 +24,13 @@ ARTICLE: "io.encodings.8-bit" "8-bit encodings"
 { $subsection koi8-r }
 { $subsection windows-1252 }
 { $subsection ebcdic }
-{ $subsection mac-roman }
-"Words used in defining these"
-{ $subsection 8-bit }
-{ $subsection define-8-bit-encoding } ;
+{ $subsection mac-roman } ;
 
 ABOUT: "io.encodings.8-bit"
 
 HELP: 8-bit
 { $class-description "Describes an 8-bit encoding, including its name (a symbol) and a table used for encoding and decoding." } ;
 
-HELP: define-8-bit-encoding
-{ $values { "name" string } { "stream" "an input stream" } }
-{ $description "Creates a new encoding. The stream should be in a similar format to those at " { $url "ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/" } } ;
-
 HELP: latin1
 { $description "This is the ISO-8859-1 encoding, also called Latin-1: Western European. It is an 8-bit superset of ASCII which is the default for a mimetype starting with 'text' and provides the characters necessary for most western European languages." } 
 { $see-also "encodings-introduction" } ;
diff --git a/extra/locals/locals.factor b/extra/locals/locals.factor
index cc6a7d093e..49eec6d652 100755
--- a/extra/locals/locals.factor
+++ b/extra/locals/locals.factor
@@ -4,8 +4,8 @@ USING: kernel namespaces sequences sequences.private assocs math
 inference.transforms parser words quotations debugger macros
 arrays macros splitting combinators prettyprint.backend
 definitions prettyprint hashtables prettyprint.sections sets
-sequences.private effects generic compiler.units accessors
-locals.backend memoize ;
+sequences.private effects effects.parser generic generic.parser
+compiler.units accessors locals.backend memoize lexer ;
 IN: locals
 
 ! Inspired by
diff --git a/extra/match/match.factor b/extra/match/match.factor
index 8a174034ba..0ae285d20d 100755
--- a/extra/match/match.factor
+++ b/extra/match/match.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 !
 ! Based on pattern matching code from Paul Graham's book 'On Lisp'.
-USING: parser kernel words namespaces sequences classes.tuple
+USING: parser lexer kernel words namespaces sequences classes.tuple
 combinators macros assocs math effects ;
 IN: match
 
diff --git a/extra/money/money.factor b/extra/money/money.factor
index 54c53e9bec..ba7a0ae04f 100644
--- a/extra/money/money.factor
+++ b/extra/money/money.factor
@@ -1,4 +1,4 @@
-USING: io kernel math math.functions math.parser parser
+USING: io kernel math math.functions math.parser parser lexer
 namespaces sequences splitting grouping combinators
 continuations sequences.lib ;
 IN: money
diff --git a/extra/mortar/mortar.factor b/extra/mortar/mortar.factor
index 3a4dc6fefb..1b5b6f2393 100644
--- a/extra/mortar/mortar.factor
+++ b/extra/mortar/mortar.factor
@@ -1,5 +1,5 @@
 
-USING: kernel io parser words namespaces quotations arrays assocs sequences
+USING: kernel io parser lexer words namespaces quotations arrays assocs sequences
        splitting grouping math shuffle ;
 
 IN: mortar
diff --git a/extra/multiline/multiline.factor b/extra/multiline/multiline.factor
index ce79bdaf5f..cf671c5609 100755
--- a/extra/multiline/multiline.factor
+++ b/extra/multiline/multiline.factor
@@ -1,6 +1,6 @@
 ! Copyright (C) 2007 Daniel Ehrenberg
 ! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces parser kernel sequences words quotations math ;
+USING: namespaces parser lexer kernel sequences words quotations math ;
 IN: multiline
 
 : next-line-text ( -- str )
diff --git a/extra/opengl/gl/extensions/extensions.factor b/extra/opengl/gl/extensions/extensions.factor
index 8f2eee9459..fd547c8b5a 100644
--- a/extra/opengl/gl/extensions/extensions.factor
+++ b/extra/opengl/gl/extensions/extensions.factor
@@ -1,6 +1,6 @@
 USING: alien alien.syntax combinators kernel parser sequences
 system words namespaces hashtables init math arrays assocs
-continuations ;
+continuations lexer ;
 IN: opengl.gl.extensions
 
 ERROR: unknown-gl-platform ;
diff --git a/extra/openssl/libssl/libssl.factor b/extra/openssl/libssl/libssl.factor
index dced2e5c0c..e951ad8858 100755
--- a/extra/openssl/libssl/libssl.factor
+++ b/extra/openssl/libssl/libssl.factor
@@ -2,7 +2,7 @@
 ! Portions copyright (C) 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.syntax combinators kernel system namespaces
-assocs parser sequences words quotations math.bitfields ;
+assocs parser lexer sequences words quotations math.bitfields ;
 
 IN: openssl.libssl
 
diff --git a/extra/qualified/qualified.factor b/extra/qualified/qualified.factor
index 5810a03f80..d636cc0152 100644
--- a/extra/qualified/qualified.factor
+++ b/extra/qualified/qualified.factor
@@ -1,5 +1,7 @@
-USING: kernel sequences assocs hashtables parser vocabs words namespaces
-vocabs.loader debugger sets ;
+! Copyright (C) 2007, 2008 Daniel Ehrenberg.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel sequences assocs hashtables parser lexer
+vocabs words namespaces vocabs.loader debugger sets ;
 IN: qualified
 
 : define-qualified ( vocab-name prefix-name -- )
diff --git a/extra/regexp/regexp.factor b/extra/regexp/regexp.factor
index 99e6b887c8..8872338f5d 100755
--- a/extra/regexp/regexp.factor
+++ b/extra/regexp/regexp.factor
@@ -1,5 +1,5 @@
 USING: arrays combinators kernel lists math math.parser
-namespaces parser parser-combinators parser-combinators.simple
+namespaces parser lexer parser-combinators parser-combinators.simple
 promises quotations sequences combinators.lib strings math.order
 assocs prettyprint.backend memoize unicode.case unicode.categories ;
 USE: io
diff --git a/extra/semantic-db/semantic-db.factor b/extra/semantic-db/semantic-db.factor
index 7d50d384e2..27e8cf1d90 100755
--- a/extra/semantic-db/semantic-db.factor
+++ b/extra/semantic-db/semantic-db.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays combinators combinators.cleave combinators.lib
 continuations db db.tuples db.types db.sqlite kernel math
-math.parser namespaces parser sets sequences sequences.deep
+math.parser namespaces parser lexer sets sequences sequences.deep
 sequences.lib strings words destructors ;
 IN: semantic-db
 
diff --git a/extra/state-machine/state-machine.factor b/extra/state-machine/state-machine.factor
index 4c83c64641..b5e8c16b02 100755
--- a/extra/state-machine/state-machine.factor
+++ b/extra/state-machine/state-machine.factor
@@ -1,4 +1,4 @@
-USING: kernel parser strings math namespaces sequences words io
+USING: kernel parser lexer strings math namespaces sequences words io
 arrays quotations debugger kernel.private sequences.private ;
 IN: state-machine
 
diff --git a/extra/symbols/symbols.factor b/extra/symbols/symbols.factor
index 20cf16e640..6cf8eac6fb 100755
--- a/extra/symbols/symbols.factor
+++ b/extra/symbols/symbols.factor
@@ -1,6 +1,7 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: parser sequences words kernel classes.singleton ;
+USING: parser lexer sequences words kernel classes.singleton
+classes.parser ;
 IN: symbols
 
 : SYMBOLS:
diff --git a/extra/tools/deploy/shaker/shaker.factor b/extra/tools/deploy/shaker/shaker.factor
index 3df5485f4e..f9b56a1d8d 100755
--- a/extra/tools/deploy/shaker/shaker.factor
+++ b/extra/tools/deploy/shaker/shaker.factor
@@ -1,9 +1,9 @@
 ! Copyright (C) 2007, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: qualified io.streams.c init fry namespaces assocs kernel
-parser tools.deploy.config vocabs sequences words words.private
-memory kernel.private continuations io prettyprint
-vocabs.loader debugger system strings sets ;
+parser lexer strings.parser tools.deploy.config vocabs sequences
+words words.private memory kernel.private continuations io
+prettyprint vocabs.loader debugger system strings sets ;
 QUALIFIED: bootstrap.stage2
 QUALIFIED: classes
 QUALIFIED: command-line
diff --git a/extra/tuple-syntax/tuple-syntax.factor b/extra/tuple-syntax/tuple-syntax.factor
index cf439f6407..ce717f4211 100755
--- a/extra/tuple-syntax/tuple-syntax.factor
+++ b/extra/tuple-syntax/tuple-syntax.factor
@@ -1,4 +1,4 @@
-USING: kernel sequences slots parser words classes
+USING: kernel sequences slots parser lexer words classes
 slots.private mirrors ;
 IN: tuple-syntax
 
diff --git a/extra/ui/tools/interactor/interactor.factor b/extra/ui/tools/interactor/interactor.factor
index 72bd4e43a3..fcd3f9ab22 100755
--- a/extra/ui/tools/interactor/interactor.factor
+++ b/extra/ui/tools/interactor/interactor.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays assocs combinators continuations documents
 hashtables io io.styles kernel math math.order math.vectors
-models namespaces parser prettyprint quotations sequences
+models namespaces parser lexer prettyprint quotations sequences
 strings threads listener classes.tuple ui.commands ui.gadgets
 ui.gadgets.editors ui.gadgets.presentations ui.gadgets.worlds
 ui.gestures definitions calendar concurrency.flags
@@ -149,7 +149,7 @@ M: interactor dispose drop ;
     mark>caret ;
 
 : handle-parse-error ( interactor error -- )
-    dup parse-error? [ 2dup go-to-error error>> ] when
+    dup lexer-error? [ 2dup go-to-error error>> ] when
     swap find-workspace debugger-popup ;
 
 : try-parse ( lines interactor -- quot/error/f )
@@ -157,7 +157,7 @@ M: interactor dispose drop ;
         drop parse-lines-interactive
     ] [
         2nip
-        dup parse-error? [
+        dup lexer-error? [
             dup error>> unexpected-eof? [ drop f ] when
         ] when
     ] recover ;
diff --git a/extra/unicode/syntax/syntax.factor b/extra/unicode/syntax/syntax.factor
index b5ba25db4e..2410779804 100755
--- a/extra/unicode/syntax/syntax.factor
+++ b/extra/unicode/syntax/syntax.factor
@@ -1,4 +1,4 @@
-USING: unicode.data kernel math sequences parser bit-arrays
+USING: unicode.data kernel math sequences parser lexer bit-arrays
 namespaces sequences.private arrays quotations assocs
 classes.predicate math.order ;
 IN: unicode.syntax
diff --git a/extra/urls/urls.factor b/extra/urls/urls.factor
index 38511de8e8..de661bdd9d 100644
--- a/extra/urls/urls.factor
+++ b/extra/urls/urls.factor
@@ -1,9 +1,10 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel unicode.categories combinators sequences splitting
+USING: kernel unicode.categories combinators combinators.lib
+sequences splitting
 fry namespaces assocs arrays strings io.sockets
 io.sockets.secure io.encodings.string io.encodings.utf8
-math math.parser accessors mirrors parser
+math math.parser accessors mirrors parser strings.parser lexer
 prettyprint.backend hashtables present ;
 IN: urls
 
@@ -11,12 +12,11 @@ IN: urls
     #! In a URL, can this character be used without
     #! URL-encoding?
     {
-        { [ dup letter? ] [ t ] }
-        { [ dup LETTER? ] [ t ] }
-        { [ dup digit? ] [ t ] }
-        { [ dup "/_-." member? ] [ t ] }
-        [ f ]
-    } cond nip ; foldable
+        [ letter? ]
+        [ LETTER? ]
+        [ digit? ]
+        [ "/_-." member? ]
+    } 1|| ; foldable
 
 <PRIVATE
 
diff --git a/extra/vars/vars.factor b/extra/vars/vars.factor
index 5942215a69..e3e13be3a9 100644
--- a/extra/vars/vars.factor
+++ b/extra/vars/vars.factor
@@ -2,7 +2,7 @@
 
 ! Thanks to Mackenzie Straight for the idea
 
-USING: kernel parser words namespaces sequences quotations ;
+USING: kernel parser lexer words namespaces sequences quotations ;
 
 IN: vars
 
diff --git a/extra/xml/generator/generator.factor b/extra/xml/generator/generator.factor
index 44bd1934f8..bf4bd618b7 100644
--- a/extra/xml/generator/generator.factor
+++ b/extra/xml/generator/generator.factor
@@ -1,7 +1,7 @@
 ! Copyright (C) 2006, 2007 Daniel Ehrenberg
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces kernel xml.data xml.utilities assocs splitting
-sequences parser quotations sequences.lib xml.utilities ;
+sequences parser lexer quotations sequences.lib xml.utilities ;
 IN: xml.generator
 
 : comment, ( string -- ) <comment> , ;
@@ -36,7 +36,7 @@ IN: xml.generator
     [ \ contained*, parsed ] [
         scan-word \ [ =
         [ POSTPONE: [ \ tag*, parsed ]
-        [ "Expected [ missing" <parse-error> throw ] if
+        [ "Expected [ missing" throw ] if
     ] if ;
 
 DEFER: >>
diff --git a/extra/xml/utilities/utilities.factor b/extra/xml/utilities/utilities.factor
index 87a0242412..c53bbf3b0f 100755
--- a/extra/xml/utilities/utilities.factor
+++ b/extra/xml/utilities/utilities.factor
@@ -1,7 +1,7 @@
 ! Copyright (C) 2005, 2006 Daniel Ehrenberg
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel namespaces sequences words io assocs
-quotations strings parser arrays xml.data xml.writer debugger
+quotations strings parser lexer arrays xml.data xml.writer debugger
 splitting vectors sequences.deep ;
 IN: xml.utilities
 
diff --git a/extra/xmode/loader/syntax/syntax.factor b/extra/xmode/loader/syntax/syntax.factor
index b3adf5cb60..4c95a45832 100644
--- a/extra/xmode/loader/syntax/syntax.factor
+++ b/extra/xmode/loader/syntax/syntax.factor
@@ -1,6 +1,6 @@
 USING: xmode.tokens xmode.rules xmode.keyword-map xml.data
 xml.utilities xml assocs kernel combinators sequences
-math.parser namespaces parser xmode.utilities regexp io.files ;
+math.parser namespaces parser lexer xmode.utilities regexp io.files ;
 IN: xmode.loader.syntax
 
 SYMBOL: ignore-case?
diff --git a/extra/xmode/utilities/utilities.factor b/extra/xmode/utilities/utilities.factor
index 2e1d0a2872..d6f9c42799 100644
--- a/extra/xmode/utilities/utilities.factor
+++ b/extra/xmode/utilities/utilities.factor
@@ -1,5 +1,5 @@
 USING: sequences assocs kernel quotations namespaces xml.data
-xml.utilities combinators macros parser words ;
+xml.utilities combinators macros parser lexer words ;
 IN: xmode.utilities
 
 : implies >r not r> or ; inline

From b26e6b90f55f8a0d37f2b109d7813cdcfca45812 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 25 Jun 2008 03:33:58 -0500
Subject: [PATCH 67/85] Code cleanup

---
 extra/combinators/short-circuit/short-circuit.factor |  7 +------
 extra/io/servers/connection/connection.factor        |  2 +-
 extra/opengl/demo-support/demo-support.factor        |  2 +-
 extra/opengl/shaders/shaders.factor                  |  2 +-
 extra/regexp/regexp.factor                           |  5 +----
 extra/unicode/breaks/breaks.factor                   |  3 +--
 extra/unicode/collation/collation-tests.factor       |  2 +-
 extra/unicode/collation/collation.factor             | 10 +++++-----
 extra/unicode/data/data.factor                       | 10 +++++-----
 extra/unicode/normalize/normalize.factor             |  2 +-
 extra/urls/urls.factor                               | 12 ++++++------
 extra/webapps/wee-url/wee-url.factor                 |  2 +-
 12 files changed, 25 insertions(+), 34 deletions(-)

diff --git a/extra/combinators/short-circuit/short-circuit.factor b/extra/combinators/short-circuit/short-circuit.factor
index 1738e8ec38..3301633d7d 100644
--- a/extra/combinators/short-circuit/short-circuit.factor
+++ b/extra/combinators/short-circuit/short-circuit.factor
@@ -1,16 +1,11 @@
 
 USING: kernel combinators quotations arrays sequences assocs
-       locals shuffle macros fry newfx ;
+       locals shuffle macros fry ;
 
 IN: combinators.short-circuit
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: short-circuit ( quots quot default -- quot )
-    1quotation -rot { } map>assoc <reversed> alist>quot ;
-
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
 :: n&&-rewrite ( quots N -- quot )
    quots
      [ '[ drop N ndup @ dup not ] [ drop N ndrop f ] 2array ]
diff --git a/extra/io/servers/connection/connection.factor b/extra/io/servers/connection/connection.factor
index 0ff83261fb..cb26ed5722 100755
--- a/extra/io/servers/connection/connection.factor
+++ b/extra/io/servers/connection/connection.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: continuations destructors kernel math math.parser
 namespaces parser sequences strings prettyprint debugger
-quotations combinators combinators.lib logging calendar assocs
+quotations combinators logging calendar assocs
 fry accessors arrays io io.sockets io.encodings.ascii
 io.sockets.secure io.files io.streams.duplex io.timeouts
 io.encodings threads concurrency.combinators
diff --git a/extra/opengl/demo-support/demo-support.factor b/extra/opengl/demo-support/demo-support.factor
index 88531a70bc..6596948f45 100755
--- a/extra/opengl/demo-support/demo-support.factor
+++ b/extra/opengl/demo-support/demo-support.factor
@@ -1,4 +1,4 @@
-USING: arrays combinators.lib kernel math math.functions
+USING: arrays kernel math math.functions
 math.order math.vectors namespaces opengl opengl.gl sequences ui
 ui.gadgets ui.gestures ui.render accessors ;
 IN: opengl.demo-support
diff --git a/extra/opengl/shaders/shaders.factor b/extra/opengl/shaders/shaders.factor
index c05e180c11..7c18736bde 100755
--- a/extra/opengl/shaders/shaders.factor
+++ b/extra/opengl/shaders/shaders.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel opengl.gl alien.c-types continuations namespaces
 assocs alien alien.strings libc opengl math sequences combinators
-combinators.lib macros arrays io.encodings.ascii ;
+macros arrays io.encodings.ascii ;
 IN: opengl.shaders
 
 : with-gl-shader-source-ptr ( string quot -- )
diff --git a/extra/regexp/regexp.factor b/extra/regexp/regexp.factor
index 29f3c500c7..c329977875 100755
--- a/extra/regexp/regexp.factor
+++ b/extra/regexp/regexp.factor
@@ -21,9 +21,6 @@ SYMBOL: ignore-case?
     [ [ between? ] ]
     if 2curry ;
 
-: or-predicates ( quots -- quot )
-    [ \ dup prefix ] map [ [ t ] ] f short-circuit \ nip suffix ;
-
 : <@literal ( parser obj -- action ) [ nip ] curry <@ ;
 
 : <@delay ( parser quot -- action ) [ curry ] curry <@ ;
@@ -180,7 +177,7 @@ C: <group-result> group-result
 : 'positive-character-class' ( -- parser )
     "]" token [ CHAR: ] = ] <@literal 'character-class-term' <*> <&:>
     'character-class-term' <+> <|>
-    [ or-predicates ] <@ ;
+    [ [ 1|| ] curry ] <@ ;
 
 : 'negative-character-class' ( -- parser )
     "^" token 'positive-character-class' &>
diff --git a/extra/unicode/breaks/breaks.factor b/extra/unicode/breaks/breaks.factor
index 745fb83c3c..fe19685b53 100755
--- a/extra/unicode/breaks/breaks.factor
+++ b/extra/unicode/breaks/breaks.factor
@@ -1,8 +1,7 @@
 USING: combinators.short-circuit unicode.categories kernel math combinators splitting
 sequences math.parser io.files io assocs arrays namespaces
 math.ranges unicode.normalize values io.encodings.ascii
-unicode.syntax unicode.data compiler.units alien.syntax sets
-combinators.lib ;
+unicode.syntax unicode.data compiler.units alien.syntax sets ;
 IN: unicode.breaks
 
 C-ENUM: Any L V T Extend Control CR LF graphemes ;
diff --git a/extra/unicode/collation/collation-tests.factor b/extra/unicode/collation/collation-tests.factor
index 5de90d238d..5bc25de804 100755
--- a/extra/unicode/collation/collation-tests.factor
+++ b/extra/unicode/collation/collation-tests.factor
@@ -1,6 +1,6 @@
 USING: io io.files splitting grouping unicode.collation
 sequences kernel io.encodings.utf8 math.parser math.order
-tools.test assocs io.streams.null words combinators.lib ;
+tools.test assocs io.streams.null words ;
 IN: unicode.collation.tests
 
 : parse-test ( -- strings )
diff --git a/extra/unicode/collation/collation.factor b/extra/unicode/collation/collation.factor
index 8deed708e6..3e239430d4 100755
--- a/extra/unicode/collation/collation.factor
+++ b/extra/unicode/collation/collation.factor
@@ -1,7 +1,7 @@
-USING: combinators.short-circuit sequences io.files io.encodings.ascii kernel values
-splitting accessors math.parser ascii io assocs strings math
-namespaces sorting combinators math.order arrays
-unicode.normalize unicode.data combinators.lib locals
+USING: combinators.short-circuit sequences io.files
+io.encodings.ascii kernel values splitting accessors math.parser
+ascii io assocs strings math namespaces sorting combinators
+math.order arrays unicode.normalize unicode.data locals
 unicode.syntax macros sequences.deep words unicode.breaks
 quotations ;
 IN: unicode.collation
@@ -86,7 +86,7 @@ ducet insert-helpers
 : add ( char -- )
     dup blocked? [ 1string , ] [
         dup possible-bases dup length
-        [ ?combine ] 2with contains?
+        [ ?combine ] with with contains?
         [ drop ] [ 1string , ] if
     ] if ;
 
diff --git a/extra/unicode/data/data.factor b/extra/unicode/data/data.factor
index b6c6292e90..f74e2e0473 100755
--- a/extra/unicode/data/data.factor
+++ b/extra/unicode/data/data.factor
@@ -1,8 +1,8 @@
-USING: combinators.short-circuit assocs math kernel sequences io.files hashtables
-quotations splitting grouping arrays math.parser hash2 math.order
-byte-arrays words namespaces words compiler.units parser
-io.encodings.ascii values interval-maps ascii sets
-combinators.lib combinators locals math.ranges sorting ;
+USING: combinators.short-circuit assocs math kernel sequences
+io.files hashtables quotations splitting grouping arrays
+math.parser hash2 math.order byte-arrays words namespaces words
+compiler.units parser io.encodings.ascii values interval-maps
+ascii sets combinators locals math.ranges sorting ;
 IN: unicode.data
 
 VALUE: simple-lower
diff --git a/extra/unicode/normalize/normalize.factor b/extra/unicode/normalize/normalize.factor
index 3b64cf577f..124840a7fb 100755
--- a/extra/unicode/normalize/normalize.factor
+++ b/extra/unicode/normalize/normalize.factor
@@ -1,5 +1,5 @@
 USING: sequences namespaces unicode.data kernel math arrays
-locals combinators.lib sorting.insertion combinators.lib ;
+locals sorting.insertion ;
 IN: unicode.normalize
 
 ! Conjoining Jamo behavior
diff --git a/extra/urls/urls.factor b/extra/urls/urls.factor
index de661bdd9d..4c45164815 100644
--- a/extra/urls/urls.factor
+++ b/extra/urls/urls.factor
@@ -1,11 +1,11 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel unicode.categories combinators combinators.lib
-sequences splitting
-fry namespaces assocs arrays strings io.sockets
-io.sockets.secure io.encodings.string io.encodings.utf8
-math math.parser accessors mirrors parser strings.parser lexer
-prettyprint.backend hashtables present ;
+USING: kernel unicode.categories combinators
+combinators.short-circuit sequences splitting fry namespaces
+assocs arrays strings io.sockets io.sockets.secure
+io.encodings.string io.encodings.utf8 math math.parser accessors
+mirrors parser strings.parser lexer prettyprint.backend
+hashtables present ;
 IN: urls
 
 : url-quotable? ( ch -- ? )
diff --git a/extra/webapps/wee-url/wee-url.factor b/extra/webapps/wee-url/wee-url.factor
index 27187c4352..5f354b2a19 100644
--- a/extra/webapps/wee-url/wee-url.factor
+++ b/extra/webapps/wee-url/wee-url.factor
@@ -1,7 +1,7 @@
 ! Copyright (C) 2007 Doug Coleman.
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: math.ranges sequences random accessors combinators.lib
+USING: math.ranges sequences random accessors
 kernel namespaces fry db.types db.tuples urls validators
 html.components html.forms http http.server.dispatchers furnace
 furnace.actions furnace.boilerplate furnace.redirection ;

From cf345df3f561adfe207c84b1671cfbb9c1178ce7 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 25 Jun 2008 03:53:36 -0500
Subject: [PATCH 68/85] Bootstrap fix

---
 core/lexer/lexer-docs.factor    | 5 -----
 extra/help/markup/markup.factor | 5 +++++
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/core/lexer/lexer-docs.factor b/core/lexer/lexer-docs.factor
index b61fc82a25..a7dcb161e5 100644
--- a/core/lexer/lexer-docs.factor
+++ b/core/lexer/lexer-docs.factor
@@ -2,11 +2,6 @@ IN: lexer
 USING: help.markup help.syntax kernel math sequences strings
 words quotations ;
 
-: $parsing-note ( children -- )
-    drop
-    "This word should only be called from parsing words."
-    $notes ;
-
 HELP: lexer
 { $var-description "Stores the current " { $link lexer } " instance." }
 { $class-description "An object for tokenizing parser input. It has the following slots:"
diff --git a/extra/help/markup/markup.factor b/extra/help/markup/markup.factor
index 32e4084150..150a66ec92 100755
--- a/extra/help/markup/markup.factor
+++ b/extra/help/markup/markup.factor
@@ -290,6 +290,11 @@ M: string ($instance)
 : $values-x/y ( children -- )
     drop { { "x" number } { "y" number } } $values ;
 
+: $parsing-note ( children -- )
+    drop
+    "This word should only be called from parsing words."
+    $notes ;
+
 : $io-error ( children -- )
     drop
     "Throws an error if the I/O operation fails." $errors ;

From 666d4abaee5739c989eb870a8f99b14957766edc Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 25 Jun 2008 04:06:18 -0500
Subject: [PATCH 69/85] More fixes

---
 core/parser/parser-tests.factor                | 14 +++++++-------
 core/parser/parser.factor                      |  8 ++------
 core/prettyprint/prettyprint-tests.factor      |  6 ++++--
 core/source-files/source-files.factor          |  5 ++---
 core/vocabs/loader/loader-tests.factor         |  2 +-
 extra/http/http-tests.factor                   | 10 +++++-----
 extra/opengl/shaders/shaders.factor            |  2 +-
 extra/unicode/collation/collation-tests.factor |  2 +-
 extra/webapps/wee-url/wee-url.factor           |  2 +-
 9 files changed, 24 insertions(+), 27 deletions(-)

diff --git a/core/parser/parser-tests.factor b/core/parser/parser-tests.factor
index eb37d556d0..074b3738ac 100755
--- a/core/parser/parser-tests.factor
+++ b/core/parser/parser-tests.factor
@@ -198,7 +198,7 @@ IN: parser.tests
     [
         "IN: parser.tests : x ; : y 3 throw ; this is an error"
         <string-reader> "a" parse-stream
-    ] [ parse-error? ] must-fail-with
+    ] [ source-file-error? ] must-fail-with
 
     [ t ] [
         "y" "parser.tests" lookup >boolean
@@ -298,12 +298,12 @@ IN: parser.tests
     [
         "IN: parser.tests TUPLE: another-pred-test ; GENERIC: another-pred-test?"
         <string-reader> "removing-the-predicate" parse-stream
-    ] [ error>> error>> redefine-error? ] must-fail-with
+    ] [ error>> error>> error>> redefine-error? ] must-fail-with
 
     [
         "IN: parser.tests TUPLE: class-redef-test ; TUPLE: class-redef-test ;"
         <string-reader> "redefining-a-class-1" parse-stream
-    ] [ error>> error>> redefine-error? ] must-fail-with
+    ] [ error>> error>> error>> redefine-error? ] must-fail-with
 
     [ ] [
         "IN: parser.tests TUPLE: class-redef-test ; SYMBOL: class-redef-test"
@@ -313,7 +313,7 @@ IN: parser.tests
     [
         "IN: parser.tests TUPLE: class-redef-test ; SYMBOL: class-redef-test : class-redef-test ;"
         <string-reader> "redefining-a-class-3" parse-stream drop
-    ] [ error>> error>> redefine-error? ] must-fail-with
+    ] [ error>> error>> error>> redefine-error? ] must-fail-with
 
     [ ] [
         "IN: parser.tests TUPLE: class-fwd-test ;"
@@ -323,7 +323,7 @@ IN: parser.tests
     [
         "IN: parser.tests \\ class-fwd-test"
         <string-reader> "redefining-a-class-3" parse-stream drop
-    ] [ error>> error>> no-word-error? ] must-fail-with
+    ] [ error>> error>> error>> no-word-error? ] must-fail-with
 
     [ ] [
         "IN: parser.tests TUPLE: class-fwd-test ; SYMBOL: class-fwd-test"
@@ -333,12 +333,12 @@ IN: parser.tests
     [
         "IN: parser.tests \\ class-fwd-test"
         <string-reader> "redefining-a-class-3" parse-stream drop
-    ] [ error>> error>> no-word-error? ] must-fail-with
+    ] [ error>> error>> error>> no-word-error? ] must-fail-with
 
     [
         "IN: parser.tests : foo ; TUPLE: foo ;"
         <string-reader> "redefining-a-class-4" parse-stream drop
-    ] [ error>> error>> redefine-error? ] must-fail-with
+    ] [ error>> error>> error>> redefine-error? ] must-fail-with
 
     [ ] [
         "IN: parser.tests : foo ( x y -- z ) 1 2 ; : bar ( a -- b ) ;" eval
diff --git a/core/parser/parser.factor b/core/parser/parser.factor
index 44708f11f3..601245c463 100755
--- a/core/parser/parser.factor
+++ b/core/parser/parser.factor
@@ -24,12 +24,8 @@ t parser-notes set-global
 
 : note. ( str -- )
     parser-notes? [
-        file get file.
-        lexer get [
-            lexer-line number>string print
-        ] [
-            nl
-        ] if*
+        file get [ file. ] when*
+        lexer get line>> number>string write ": " write
         "Note: " write dup print
     ] when drop ;
 
diff --git a/core/prettyprint/prettyprint-tests.factor b/core/prettyprint/prettyprint-tests.factor
index d5f4dd5906..9e11611f5b 100755
--- a/core/prettyprint/prettyprint-tests.factor
+++ b/core/prettyprint/prettyprint-tests.factor
@@ -167,9 +167,11 @@ unit-test
     "another-retain-layout" another-retain-layout-test check-see
 ] unit-test
 
+DEFER: parse-error-file
+
 : another-soft-break-test
     {
-        "USING: namespaces parser sequences ;"
+        "USING: namespaces sequences ;"
         "IN: prettyprint.tests"
         ": another-soft-break-layout ( node -- quot )"
         "    parse-error-file"
@@ -183,7 +185,7 @@ unit-test
 
 : string-layout
     {
-        "USING: io kernel parser ;"
+        "USING: io kernel lexer ;"
         "IN: prettyprint.tests"
         ": string-layout-test ( error -- )"
         "    \"Expected \" write dup unexpected-want expected>string write"
diff --git a/core/source-files/source-files.factor b/core/source-files/source-files.factor
index 0577dacc85..2c5c19708e 100755
--- a/core/source-files/source-files.factor
+++ b/core/source-files/source-files.factor
@@ -82,11 +82,10 @@ TUPLE: source-file-error file error ;
         file get >>file
         swap >>error ;
 
-: file. ( file -- ) path>> <pathname> pprint ;
+: file. ( file -- ) path>> <pathname> . ;
 
 M: source-file-error error.
-    "Error while parsing " write
-    [ file>> file. nl ] [ error>> error. ] bi ;
+    [ file>> file. ] [ error>> error. ] bi ;
 
 M: source-file-error summary
     error>> summary ;
diff --git a/core/vocabs/loader/loader-tests.factor b/core/vocabs/loader/loader-tests.factor
index 45b0d6b019..5ed0b0a34c 100755
--- a/core/vocabs/loader/loader-tests.factor
+++ b/core/vocabs/loader/loader-tests.factor
@@ -68,7 +68,7 @@ IN: vocabs.loader.tests
     <string-reader>
     "resource:core/vocabs/loader/test/a/a.factor"
     parse-stream
-] [ error>> error>> no-word-error? ] must-fail-with
+] [ error>> error>> error>> no-word-error? ] must-fail-with
 
 0 "count-me" set-global
 
diff --git a/extra/http/http-tests.factor b/extra/http/http-tests.factor
index a920d4e67a..2a02d2cc20 100755
--- a/extra/http/http-tests.factor
+++ b/extra/http/http-tests.factor
@@ -1,8 +1,8 @@
-USING: http tools.test multiline tuple-syntax
-io.streams.string io.encodings.utf8 io.encodings.string
-kernel arrays splitting sequences
-assocs io.sockets db db.sqlite continuations urls hashtables
-accessors ;
+USING: http tools.test multiline tuple-syntax io.streams.string
+io.encodings.utf8 io.encodings.8-bit io.encodings.binary
+io.encodings.string kernel arrays splitting sequences assocs
+io.sockets db db.sqlite continuations urls hashtables accessors
+;
 IN: http.tests
 
 [ "text/plain" latin1 ] [ "text/plain" parse-content-type ] unit-test
diff --git a/extra/opengl/shaders/shaders.factor b/extra/opengl/shaders/shaders.factor
index 7c18736bde..c05e180c11 100755
--- a/extra/opengl/shaders/shaders.factor
+++ b/extra/opengl/shaders/shaders.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel opengl.gl alien.c-types continuations namespaces
 assocs alien alien.strings libc opengl math sequences combinators
-macros arrays io.encodings.ascii ;
+combinators.lib macros arrays io.encodings.ascii ;
 IN: opengl.shaders
 
 : with-gl-shader-source-ptr ( string quot -- )
diff --git a/extra/unicode/collation/collation-tests.factor b/extra/unicode/collation/collation-tests.factor
index 5bc25de804..d523a15ada 100755
--- a/extra/unicode/collation/collation-tests.factor
+++ b/extra/unicode/collation/collation-tests.factor
@@ -17,7 +17,7 @@ IN: unicode.collation.tests
 
 : test-equality
     { primary= secondary= tertiary= quaternary= }
-    [ execute ] 2with each ;
+    [ execute ] with with each ;
 
 [ f f f f ] [ "hello" "hi" test-equality ] unit-test
 [ t f f f ] [ "hello" "h\u0000e9llo" test-equality ] unit-test
diff --git a/extra/webapps/wee-url/wee-url.factor b/extra/webapps/wee-url/wee-url.factor
index 5f354b2a19..27187c4352 100644
--- a/extra/webapps/wee-url/wee-url.factor
+++ b/extra/webapps/wee-url/wee-url.factor
@@ -1,7 +1,7 @@
 ! Copyright (C) 2007 Doug Coleman.
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: math.ranges sequences random accessors
+USING: math.ranges sequences random accessors combinators.lib
 kernel namespaces fry db.types db.tuples urls validators
 html.components html.forms http http.server.dispatchers furnace
 furnace.actions furnace.boilerplate furnace.redirection ;

From c71d09ee30a8fe6682f6967371bdc30a2e371a18 Mon Sep 17 00:00:00 2001
From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info>
Date: Wed, 25 Jun 2008 04:52:52 -0500
Subject: [PATCH 70/85] combinators.lib: Remove old code

---
 extra/combinators/lib/lib.factor | 41 --------------------------------
 1 file changed, 41 deletions(-)

diff --git a/extra/combinators/lib/lib.factor b/extra/combinators/lib/lib.factor
index d9509b30f4..63e9750e8b 100755
--- a/extra/combinators/lib/lib.factor
+++ b/extra/combinators/lib/lib.factor
@@ -59,47 +59,6 @@ MACRO: napply ( n -- )
 : assoc-map-with ( obj assoc quot -- assoc )
     with* assoc-map ; inline
 
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! short circuiting words
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-! : short-circuit ( quots quot default -- quot )
-!     1quotation -rot { } map>assoc <reversed> alist>quot ;
-
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-! MACRO: 0&& ( quots -- quot )
-!   [ '[ drop @ dup not ] [ drop f ] 2array ] map
-!   { [ t ] [ ] }                       suffix
-!   '[ f , cond ] ;
-
-! MACRO: 1&& ( quots -- quot )
-!   [ '[ drop dup @ dup not ] [ drop drop f ] 2array ] map
-!   { [ t ] [ nip ] }                                  suffix
-!   '[ f , cond ] ;
-
-! MACRO: 2&& ( quots -- quot )
-!   [ '[ drop 2dup @ dup not ] [ drop 2drop f ] 2array ] map
-!   { [ t ] [ 2nip ] }                                   suffix
-!   '[ f , cond ] ;
-
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-! MACRO: 0|| ( quots -- quot )
-!   [ '[ drop @ dup ] [ ] 2array ] map
-!   { [ drop t ] [ f ] } suffix
-!   '[ f , cond ] ;
-
-! MACRO: 1|| ( quots -- quot )
-!   [ '[ drop dup @ dup ] [ nip ] 2array ] map
-!   { [ drop drop t ] [ f ] }              suffix
-!   '[ f , cond ] ;
-
-! MACRO: 2|| ( quots -- quot )
-!   [ '[ drop 2dup @ dup ] [ 2nip ] 2array ] map
-!   { [ drop 2drop t ] [ f ] }               suffix
-!   '[ f , cond ] ;
-
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 ! ifte
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

From d65a76d10f4810fecf3727356056ff8b7a828074 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 25 Jun 2008 15:35:14 -0500
Subject: [PATCH 71/85] Fixing builder failures

---
 extra/io/encodings/8-bit/8-bit.factor              | 2 +-
 extra/peg/ebnf/ebnf.factor                         | 3 ++-
 extra/persistent-vectors/persistent-vectors.factor | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/extra/io/encodings/8-bit/8-bit.factor b/extra/io/encodings/8-bit/8-bit.factor
index 30eb745314..16fe052867 100755
--- a/extra/io/encodings/8-bit/8-bit.factor
+++ b/extra/io/encodings/8-bit/8-bit.factor
@@ -81,7 +81,7 @@ PRIVATE>
         [ encoding-file parse-file 8-bit boa ]
         bi*
     ] assoc-map
+    [ keys [ define-symbol ] each ]
     [ 8-bit-encodings set-global ]
-    [ [ [ ] curry define ] assoc-each ]
     bi
 ] with-compilation-unit
diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 0bf07f2687..6812aefee0 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -4,7 +4,8 @@ USING: kernel compiler.units words arrays strings math.parser sequences
        quotations vectors namespaces math assocs continuations peg
        peg.parsers unicode.categories multiline combinators.lib 
        splitting accessors effects sequences.deep peg.search
-       combinators.short-circuit ;
+       combinators.short-circuit lexer io.streams.string inference io
+       prettyprint combinators parser ;
 IN: peg.ebnf
 
 : rule ( name word -- parser )
diff --git a/extra/persistent-vectors/persistent-vectors.factor b/extra/persistent-vectors/persistent-vectors.factor
index c80de3b0cd..691ebfcf4d 100644
--- a/extra/persistent-vectors/persistent-vectors.factor
+++ b/extra/persistent-vectors/persistent-vectors.factor
@@ -1,7 +1,7 @@
 ! Based on Clojure's PersistentVector by Rich Hickey.
 
 USING: math accessors kernel sequences.private sequences arrays
-combinators combinators.lib parser prettyprint.backend ;
+combinators combinators.short-circuit parser prettyprint.backend ;
 IN: persistent-vectors
 
 ERROR: empty-error pvec ;

From bc5c7840165cae1fb36d7276bc11706dd4d16654 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Wed, 25 Jun 2008 15:37:01 -0500
Subject: [PATCH 72/85] Help lint fix

---
 core/strings/parser/parser-docs.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/strings/parser/parser-docs.factor b/core/strings/parser/parser-docs.factor
index 0aa6d483ca..e1c53cd87a 100644
--- a/core/strings/parser/parser-docs.factor
+++ b/core/strings/parser/parser-docs.factor
@@ -7,7 +7,7 @@ HELP: bad-escape
 HELP: escape
 { $values { "escape" "a single-character escape" } { "ch" "a character" } }
 { $description "Converts from a single-character escape code and the corresponding character." }
-{ $examples { $example "USING: kernel parser prettyprint ;" "CHAR: n escape CHAR: \\n = ." "t" } } ;
+{ $examples { $example "USING: kernel prettyprint strings.parser ;" "CHAR: n escape CHAR: \\n = ." "t" } } ;
 
 HELP: parse-string
 { $values { "str" "a new " { $link string } } }

From 45bc2a0a023c2e363aa884ca4cb3a2dcacad43ad Mon Sep 17 00:00:00 2001
From: slava <slava@slava-laptop.(none)>
Date: Wed, 25 Jun 2008 16:58:19 -0500
Subject: [PATCH 73/85] More robust server tests

---
 .../distributed/distributed-tests.factor      |  4 ---
 .../distributed/distributed.factor            | 17 ++++++------
 extra/http/http-tests.factor                  | 23 ++++++++--------
 .../connection/connection-tests.factor        | 16 ++++++-----
 extra/io/servers/connection/connection.factor | 27 ++++++++++++++-----
 5 files changed, 49 insertions(+), 38 deletions(-)

diff --git a/extra/concurrency/distributed/distributed-tests.factor b/extra/concurrency/distributed/distributed-tests.factor
index dc20e7ad5c..528e1956b8 100755
--- a/extra/concurrency/distributed/distributed-tests.factor
+++ b/extra/concurrency/distributed/distributed-tests.factor
@@ -13,8 +13,6 @@ concurrency.messaging continuations accessors prettyprint ;
 
 [ ] [ test-node dup (start-node) ] unit-test
 
-[ ] [ 1000 sleep ] unit-test
-
 [ ] [
     [
         receive first2 >r 3 + r> send
@@ -30,6 +28,4 @@ concurrency.messaging continuations accessors prettyprint ;
     receive
 ] unit-test
 
-[ ] [ 1000 sleep ] unit-test
-
 [ ] [ test-node stop-node ] unit-test
diff --git a/extra/concurrency/distributed/distributed.factor b/extra/concurrency/distributed/distributed.factor
index 9ae2627505..4da079e812 100755
--- a/extra/concurrency/distributed/distributed.factor
+++ b/extra/concurrency/distributed/distributed.factor
@@ -12,16 +12,15 @@ SYMBOL: local-node
     deserialize
     [ first2 get-process send ] [ stop-server ] if* ;
 
+: <node-server> ( addrspec -- threaded-server )
+    <threaded-server>
+        swap >>insecure
+        binary >>encoding
+        "concurrency.distributed" >>name
+        [ handle-node-client ] >>handler ;
+
 : (start-node) ( addrspec addrspec -- )
-    local-node set-global
-    [
-        <threaded-server>
-            swap >>insecure
-            binary >>encoding
-            "concurrency.distributed" >>name
-            [ handle-node-client ] >>handler
-        start-server
-    ] curry "Distributed concurrency server" spawn drop ;
+    local-node set-global <node-server> start-server* ;
 
 : start-node ( port -- )
     host-name over <inet> (start-node) ;
diff --git a/extra/http/http-tests.factor b/extra/http/http-tests.factor
index 2a02d2cc20..9b95dc1408 100755
--- a/extra/http/http-tests.factor
+++ b/extra/http/http-tests.factor
@@ -190,6 +190,13 @@ test-db [
     init-furnace-tables
 ] with-db
 
+: test-httpd ( -- )
+    #! Return as soon as server is running.
+    <http-server>
+        1237 >>insecure
+        f >>secure
+    start-server* ;
+
 [ ] [
     [
         <dispatcher>
@@ -202,12 +209,10 @@ test-db [
             "redirect-loop" add-responder
         main-responder set
 
-        [ 1237 httpd ] "HTTPD test" spawn drop
+        test-httpd
     ] with-scope
 ] unit-test
 
-[ ] [ 100 sleep ] unit-test
-
 [ t ] [
     "resource:extra/http/test/foo.html" ascii file-contents
     "http://localhost:1237/nested/foo.html" http-get nip ascii decode =
@@ -235,12 +240,10 @@ test-db [
         test-db <db-persistence>
         main-responder set
 
-        [ 1237 httpd ] "HTTPD test" spawn drop
+        test-httpd
     ] with-scope
 ] unit-test
 
-[ ] [ 100 sleep ] unit-test
-
 : 404? [ download-failed? ] [ response>> code>> 404 = ] bi and ;
 
 ! This should give a 404 not an infinite redirect loop
@@ -262,12 +265,10 @@ test-db [
         test-db <db-persistence>
         main-responder set
 
-        [ 1237 httpd ] "HTTPD test" spawn drop
+        test-httpd
     ] with-scope
 ] unit-test
 
-[ ] [ 100 sleep ] unit-test
-
 [ "Hi" ] [ "http://localhost:1237/" http-get nip ] unit-test
 
 [ "Goodbye" ] [ "http://localhost:1237/quit" http-get nip ] unit-test
@@ -293,12 +294,10 @@ SYMBOL: a
         test-db <db-persistence>
         main-responder set
 
-        [ 1237 httpd ] "HTTPD test" spawn drop
+        test-httpd
     ] with-scope
 ] unit-test
 
-[ ] [ 100 sleep ] unit-test
-
 3 a set-global
 
 : test-a string>xml "input" tag-named "value" swap at ;
diff --git a/extra/io/servers/connection/connection-tests.factor b/extra/io/servers/connection/connection-tests.factor
index bb87d67917..84e0d684ac 100755
--- a/extra/io/servers/connection/connection-tests.factor
+++ b/extra/io/servers/connection/connection-tests.factor
@@ -29,18 +29,22 @@ concurrency.promises io.encodings.ascii io threads calendar ;
 
 [ ] [ <promise> "p" set ] unit-test
 
+[ ] [
+    <threaded-server>
+        5 >>max-connections
+        1237 >>insecure
+        [ "Hello world." write stop-server ] >>handler
+    "server" set
+] unit-test
+
 [ ] [
     [
-        <threaded-server>
-            5 >>max-connections
-            1237 >>insecure
-            [ "Hello world." write stop-server ] >>handler
-        start-server
+        "server" get start-server
         t "p" get fulfill
     ] in-thread
 ] unit-test
 
-[ ] [ 100 sleep ] unit-test
+[ ] [ "server" get wait-for-server ] unit-test
 
 [ "Hello world." ] [ "localhost" 1237 <inet> ascii <client> drop contents ] unit-test
 
diff --git a/extra/io/servers/connection/connection.factor b/extra/io/servers/connection/connection.factor
index cb26ed5722..fa0e2f515d 100755
--- a/extra/io/servers/connection/connection.factor
+++ b/extra/io/servers/connection/connection.factor
@@ -6,7 +6,8 @@ quotations combinators logging calendar assocs
 fry accessors arrays io io.sockets io.encodings.ascii
 io.sockets.secure io.files io.streams.duplex io.timeouts
 io.encodings threads concurrency.combinators
-concurrency.semaphores combinators.short-circuit ;
+concurrency.semaphores concurrency.flags
+combinators.short-circuit ;
 IN: io.servers.connection
 
 TUPLE: threaded-server
@@ -18,7 +19,8 @@ max-connections
 semaphore
 timeout
 encoding
-handler ;
+handler
+ready ;
 
 : local-server ( port -- addrspec ) "localhost" swap <inet> ;
 
@@ -31,7 +33,8 @@ handler ;
         1 minutes >>timeout
         V{ } clone >>sockets
         <secure-config> >>secure-config
-        [ "No handler quotation" throw ] >>handler ; inline
+        [ "No handler quotation" throw ] >>handler
+        <flag> >>ready ; inline
 
 : <threaded-server> ( -- threaded-server )
     threaded-server new-threaded-server ;
@@ -86,11 +89,13 @@ M: threaded-server handle-client* handler>> call ;
         if*
     ] [ accept-loop ] bi ; inline
 
-: start-accept-loop ( server -- )
+: started-accept-loop ( server -- )
+    threaded-server get
+    [ sockets>> push ] [ ready>> raise-flag ] bi ;
+
+: start-accept-loop ( addrspec -- )
     threaded-server get encoding>> <server>
-    [ threaded-server get sockets>> push ]
-    [ [ accept-loop ] with-disposal ]
-    bi ;
+    [ started-accept-loop ] [ [ accept-loop ] with-disposal ] bi ;
 
 \ start-accept-loop ERROR add-error-logging
 
@@ -115,6 +120,14 @@ PRIVATE>
         ] with-variable
     ] with-secure-context ;
 
+: wait-for-server ( threaded-server -- )
+    ready>> wait-for-flag ;
+
+: start-server* ( threaded-server -- )
+    [ [ start-server ] curry "Threaded server" spawn drop ]
+    [ wait-for-server ]
+    bi ;
+
 : stop-server ( -- )
     threaded-server get [ f ] change-sockets drop dispose-each ;
 

From 9d15cb9328cb1a2d046680bc9b835094a8bf00ec Mon Sep 17 00:00:00 2001
From: slava <slava@slava-laptop.(none)>
Date: Wed, 25 Jun 2008 20:46:52 -0500
Subject: [PATCH 74/85] Remove old debugging code

---
 core/compiler/compiler.factor | 1 -
 1 file changed, 1 deletion(-)

diff --git a/core/compiler/compiler.factor b/core/compiler/compiler.factor
index 4ee2fd5cdf..093b215013 100755
--- a/core/compiler/compiler.factor
+++ b/core/compiler/compiler.factor
@@ -46,7 +46,6 @@ SYMBOL: +failed+
     ] tri ;
 
 : (compile) ( word -- )
-    dup dup "compile-count" word-prop 0 or 1 + "compile-count" set-word-prop
     [
         H{ } clone dependencies set
 

From 68ddfc941042c85761647da8a2b726b57e4ee1c1 Mon Sep 17 00:00:00 2001
From: slava <slava@slava-laptop.(none)>
Date: Wed, 25 Jun 2008 20:47:07 -0500
Subject: [PATCH 75/85] Fixing deployment tests

---
 extra/bunny/deploy.factor               | 14 ++---
 extra/http/http-tests.factor            |  2 +-
 extra/tools/deploy/deploy-tests.factor  | 35 +++++++++++
 extra/tools/deploy/shaker/shaker.factor | 77 +++++++++++++++++++------
 extra/tools/deploy/test/4/deploy.factor | 12 ++--
 extra/tools/deploy/test/5/5.factor      |  7 +++
 extra/tools/deploy/test/5/deploy.factor | 15 +++++
 7 files changed, 131 insertions(+), 31 deletions(-)
 create mode 100644 extra/tools/deploy/test/5/5.factor
 create mode 100644 extra/tools/deploy/test/5/deploy.factor

diff --git a/extra/bunny/deploy.factor b/extra/bunny/deploy.factor
index 643737b23c..22e97b455e 100755
--- a/extra/bunny/deploy.factor
+++ b/extra/bunny/deploy.factor
@@ -1,15 +1,15 @@
 USING: tools.deploy.config ;
 H{
-    { deploy-word-defs? f }
+    { deploy-math? t }
+    { deploy-reflection 2 }
+    { deploy-io 3 }
+    { deploy-c-types? f }
     { deploy-random? f }
+    { deploy-ui? t }
     { deploy-name "Bunny" }
+    { deploy-word-defs? f }
+    { "stop-after-last-window?" t }
     { deploy-threads? t }
     { deploy-compiler? t }
-    { deploy-math? t }
-    { deploy-c-types? f }
-    { deploy-io 3 }
-    { deploy-reflection 1 }
-    { deploy-ui? t }
-    { "stop-after-last-window?" t }
     { deploy-word-props? f }
 }
diff --git a/extra/http/http-tests.factor b/extra/http/http-tests.factor
index 9b95dc1408..7ddf6cf3aa 100755
--- a/extra/http/http-tests.factor
+++ b/extra/http/http-tests.factor
@@ -215,7 +215,7 @@ test-db [
 
 [ t ] [
     "resource:extra/http/test/foo.html" ascii file-contents
-    "http://localhost:1237/nested/foo.html" http-get nip ascii decode =
+    "http://localhost:1237/nested/foo.html" http-get nip =
 ] unit-test
 
 [ "http://localhost:1237/redirect-loop" http-get nip ]
diff --git a/extra/tools/deploy/deploy-tests.factor b/extra/tools/deploy/deploy-tests.factor
index 5309784b7c..ed22902af2 100755
--- a/extra/tools/deploy/deploy-tests.factor
+++ b/extra/tools/deploy/deploy-tests.factor
@@ -62,3 +62,38 @@ namespaces continuations layouts accessors ;
         2array try-process
     ] curry unit-test
 ] each
+
+USING: http.client furnace.actions http.server http.server.dispatchers
+http.server.responses http.server.static io.servers.connection ;
+
+: add-quit-action
+    <action>
+        [ stop-server "Goodbye" "text/html" <content> ] >>display
+    "quit" add-responder ;
+
+: test-httpd ( -- )
+    #! Return as soon as server is running.
+    <http-server>
+        1237 >>insecure
+        f >>secure
+    start-server* ;
+
+[ ] [
+    [
+        <dispatcher>
+            add-quit-action
+            "resource:extra/http/test" <static> >>default
+        main-responder set
+
+        test-httpd
+    ] with-scope
+] unit-test
+
+[ ] [
+    "tools.deploy.test.5" shake-and-bake
+    vm
+    "-i=" "test.image" temp-file append
+    2array try-process
+] unit-test
+
+[ ] [ "http://localhost:1237/quit" http-get 2drop ] unit-test
diff --git a/extra/tools/deploy/shaker/shaker.factor b/extra/tools/deploy/shaker/shaker.factor
index f9b56a1d8d..5a20dd8911 100755
--- a/extra/tools/deploy/shaker/shaker.factor
+++ b/extra/tools/deploy/shaker/shaker.factor
@@ -69,26 +69,69 @@ IN: tools.deploy.shaker
     [ "no-def-strip" word-prop not ] filter
     [ [ ] swap set-word-def ] each ;
 
-: strip-word-props ( retain-props words -- )
+: strip-word-props ( stripped-props words -- )
     "Stripping word properties" show
     [
         [
             word-props swap
-            '[ , nip member? ] assoc-filter
+            '[ , nip member? not ] assoc-filter
             f assoc-like
         ] keep set-word-props
     ] with each ;
 
-: retained-props ( -- seq )
+: stripped-word-props ( -- seq )
     [
-        "class" ,
-        "metaclass" ,
-        "layout" ,
-        deploy-ui? get [
-            "gestures" ,
-            "commands" ,
-            { "+nullary+" "+listener+" "+description+" }
-            [ "ui.commands" lookup , ] each
+        strip-dictionary? [
+            {
+                "coercer"
+                "compiled-effect"
+                "compiled-uses"
+                "constraints"
+                "declared-effect"
+                "default-output-classes"
+                "identities"
+                "if-intrinsics"
+                "infer"
+                "inferred-effect"
+                "interval"
+                "intrinsics"
+                "loc"
+                "members"
+                "methods"
+                "combination"
+                "cannot-infer"
+                "default-method"
+                "optimizer-hooks"
+                "output-classes"
+                "participants"
+                "predicate"
+                "predicate-definition"
+                "predicating"
+                "slots"
+                "slot-names"
+                "specializer"
+                "step-into"
+                "step-into?"
+                "superclass"
+                "reading"
+                "writing"
+                "type"
+                "engines"
+            } %
+        ] when
+        
+        strip-prettyprint? [
+            {
+                "delimiter"
+                "flushable"
+                "foldable"
+                "inline"
+                "lambda"
+                "macro"
+                "memo-quot"
+                "parsing"
+                "word-style"
+            } %
         ] when
     ] { } make ;
 
@@ -134,11 +177,11 @@ IN: tools.deploy.shaker
 
         strip-io? [ io.backend:io-backend , ] when
 
-        [
-            io.backend:io-backend ,
-            "default-buffer-size" "io.ports" lookup ,
-        ] { } make
-        { "alarms" "io" "tools" } strip-vocab-globals %
+        { } {
+            "alarms"
+            "tools"
+            "io.launcher"
+        } strip-vocab-globals %
 
         strip-dictionary? [
             { } { "cpu" } strip-vocab-globals %
@@ -243,7 +286,7 @@ SYMBOL: deploy-vocab
     strip-recompile-hook
     strip-init-hooks
     deploy-vocab get vocab-main set-boot-quot*
-    retained-props >r
+    stripped-word-props >r
     stripped-globals strip-globals
     r> strip-words ;
 
diff --git a/extra/tools/deploy/test/4/deploy.factor b/extra/tools/deploy/test/4/deploy.factor
index 5250ad698a..894d6aa62e 100644
--- a/extra/tools/deploy/test/4/deploy.factor
+++ b/extra/tools/deploy/test/4/deploy.factor
@@ -1,15 +1,15 @@
 USING: tools.deploy.config ;
 H{
     { deploy-math? f }
-    { deploy-ui? f }
-    { deploy-compiler? t }
-    { deploy-word-props? f }
-    { deploy-word-defs? f }
+    { deploy-reflection 1 }
     { deploy-io 2 }
-    { deploy-name "tools.deploy.test.4" }
     { deploy-c-types? f }
     { deploy-random? f }
+    { deploy-ui? f }
+    { deploy-name "tools.deploy.test.4" }
+    { deploy-word-defs? f }
     { "stop-after-last-window?" t }
     { deploy-threads? t }
-    { deploy-reflection 1 }
+    { deploy-compiler? t }
+    { deploy-word-props? f }
 }
diff --git a/extra/tools/deploy/test/5/5.factor b/extra/tools/deploy/test/5/5.factor
new file mode 100644
index 0000000000..debc020d49
--- /dev/null
+++ b/extra/tools/deploy/test/5/5.factor
@@ -0,0 +1,7 @@
+IN: tools.deploy.test.5
+USING: http.client kernel ;
+
+: deploy-test-5 ( -- )
+    "http://localhost:1237/foo.html" http-get 2drop ;
+
+MAIN: deploy-test-5
diff --git a/extra/tools/deploy/test/5/deploy.factor b/extra/tools/deploy/test/5/deploy.factor
new file mode 100644
index 0000000000..87536457b0
--- /dev/null
+++ b/extra/tools/deploy/test/5/deploy.factor
@@ -0,0 +1,15 @@
+USING: tools.deploy.config ;
+H{
+    { deploy-math? t }
+    { deploy-reflection 2 }
+    { deploy-io 3 }
+    { deploy-c-types? f }
+    { deploy-random? t }
+    { deploy-ui? f }
+    { deploy-name "tools.deploy.test.5" }
+    { deploy-word-defs? f }
+    { "stop-after-last-window?" t }
+    { deploy-threads? t }
+    { deploy-compiler? t }
+    { deploy-word-props? f }
+}

From 536b849c29cfe2a5c4ac648f476fd80f55ad9ab0 Mon Sep 17 00:00:00 2001
From: slava <slava@slava-laptop.(none)>
Date: Wed, 25 Jun 2008 22:06:34 -0500
Subject: [PATCH 76/85] Tweak UI error handling for deployment

---
 extra/ui/gadgets/worlds/worlds.factor | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/extra/ui/gadgets/worlds/worlds.factor b/extra/ui/gadgets/worlds/worlds.factor
index 2895dd07cc..4d2f31cda5 100755
--- a/extra/ui/gadgets/worlds/worlds.factor
+++ b/extra/ui/gadgets/worlds/worlds.factor
@@ -1,8 +1,9 @@
-! Copyright (C) 2005, 2007 Slava Pestov.
+! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays assocs continuations kernel math models
 namespaces opengl sequences io combinators math.vectors
-ui.gadgets ui.gestures ui.render ui.backend inspector ;
+ui.gadgets ui.gestures ui.render ui.backend inspector
+debugger ;
 IN: ui.gadgets.worlds
 
 TUPLE: world < identity-tuple
@@ -78,7 +79,8 @@ TUPLE: world-error world ;
 
 SYMBOL: ui-error-hook
 
-: ui-error ( error -- ) ui-error-hook get call ;
+: ui-error ( error -- )
+    ui-error-hook get [ call ] [ print-error ] if* ;
 
 [ rethrow ] ui-error-hook set-global
 

From 92d5c683e63a1f3de9583892c879b283e0f17a68 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Thu, 26 Jun 2008 20:46:59 -0500
Subject: [PATCH 77/85] Fix :edit for nested parse errors

---
 extra/editors/editors.factor | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/extra/editors/editors.factor b/extra/editors/editors.factor
index 29cbbca90e..78f6caf965 100755
--- a/extra/editors/editors.factor
+++ b/extra/editors/editors.factor
@@ -39,19 +39,29 @@ GENERIC: error-file ( error -- file )
 
 GENERIC: error-line ( error -- line )
 
-M: lexer-error error-line line>> ;
+M: lexer-error error-file
+    error>> error-file ;
 
-M: source-file-error error-file file>> path>> ;
+M: lexer-error error-line
+    [ error>> error-line ] [ line>> ] bi or ;
 
-M: source-file-error error-line error>> error-line ;
+M: source-file-error error-file
+    [ error>> error-file ] [ file>> path>> ] bi or ;
 
-M: condition error-file error>> error-file ;
+M: source-file-error error-line
+    error>> error-line ;
 
-M: condition error-line error>> error-line ;
+M: condition error-file
+    error>> error-file ;
 
-M: object error-file drop f ;
+M: condition error-line
+    error>> error-line ;
 
-M: object error-line drop f ;
+M: object error-file
+    drop f ;
+
+M: object error-line
+    drop f ;
 
 : :edit ( -- )
     error get [ error-file ] [ error-line ] bi

From 3f520c3c791de021d00405569e12e01d86c84f28 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Thu, 26 Jun 2008 20:47:36 -0500
Subject: [PATCH 78/85] Better error messages for when new or boa are applied
 to the wrong type

---
 core/classes/tuple/tuple-tests.factor         | 13 ++++----
 core/classes/tuple/tuple.factor               | 30 +++++++++----------
 core/debugger/debugger.factor                 |  7 +++--
 core/effects/effects.factor                   |  4 +--
 core/inference/backend/backend.factor         |  2 +-
 .../transforms/transforms-tests.factor        |  8 ++++-
 core/inference/transforms/transforms.factor   | 26 ++++++++++------
 core/optimizer/math/partial/partial.factor    |  2 +-
 core/syntax/syntax.factor                     |  2 +-
 9 files changed, 57 insertions(+), 37 deletions(-)

diff --git a/core/classes/tuple/tuple-tests.factor b/core/classes/tuple/tuple-tests.factor
index 604914bd5c..c93bd11ffe 100755
--- a/core/classes/tuple/tuple-tests.factor
+++ b/core/classes/tuple/tuple-tests.factor
@@ -4,7 +4,7 @@ namespaces quotations sequences.private classes continuations
 generic.standard effects classes.tuple classes.tuple.private
 arrays vectors strings compiler.units accessors classes.algebra
 calendar prettyprint io.streams.string splitting inspector
-columns math.order classes.private ;
+columns math.order classes.private slots.private ;
 IN: classes.tuple.tests
 
 TUPLE: rect x y w h ;
@@ -94,7 +94,7 @@ TUPLE: size-test a b c d ;
 
 [ t ] [
     T{ size-test } tuple-size
-    size-test tuple-size =
+    size-test tuple-layout layout-size =
 ] unit-test
 
 GENERIC: <yo-momma>
@@ -220,7 +220,7 @@ C: <erg's-reshape-problem> erg's-reshape-problem
 
 [
     "IN: classes.tuple.tests SYMBOL: not-a-class C: <not-a-class> not-a-class" eval
-] [ error>> no-tuple-class? ] must-fail-with
+] [ error>> not-a-tuple-class? ] must-fail-with
 
 ! Inheritance
 TUPLE: computer cpu ram ;
@@ -252,7 +252,7 @@ C: <laptop> laptop
 test-laptop-slot-values
 
 [ laptop ] [
-    "laptop" get tuple-layout
+    "laptop" get 1 slot
     dup layout-echelon swap
     layout-superclasses nth
 ] unit-test
@@ -490,7 +490,7 @@ USE: vocabs
     ] with-compilation-unit
 ] unit-test
 
-[ "USE: words T{ word }" eval ] [ error>> no-method? ] must-fail-with
+[ "USE: words T{ word }" eval ] [ error>> not-a-tuple-class? ] must-fail-with
 
 ! Accessors not being forgotten...
 [ [ ] ] [
@@ -595,3 +595,6 @@ GENERIC: break-me ( obj -- )
 [ ] [ "IN: classes.tuple.tests USE: math USE: kernel M: integer break-me drop ;" eval ] unit-test
 
 [ f ] [ \ break-me "methods" word-prop assoc-empty? ] unit-test
+
+! Insufficient type checking
+[ \ vocab tuple>array drop ] must-fail
diff --git a/core/classes/tuple/tuple.factor b/core/classes/tuple/tuple.factor
index b4a2302a9e..df59f34ff4 100755
--- a/core/classes/tuple/tuple.factor
+++ b/core/classes/tuple/tuple.factor
@@ -9,32 +9,32 @@ IN: classes.tuple
 
 M: tuple class 1 slot 2 slot { word } declare ;
 
-ERROR: no-tuple-class class ;
+ERROR: not-a-tuple object ;
+
+: check-tuple ( object -- tuple )
+    dup tuple? [ not-a-tuple ] unless ; inline
+
+ERROR: not-a-tuple-class class ;
+
+: check-tuple-class ( class -- class )
+    dup tuple-class? [ not-a-tuple-class ] unless ; inline
 
 <PRIVATE
 
-GENERIC: tuple-layout ( object -- layout )
+: tuple-layout ( class -- layout )
+    check-tuple-class "layout" word-prop ;
 
-M: tuple-class tuple-layout "layout" word-prop ;
-
-M: tuple tuple-layout 1 slot ;
-
-M: tuple-layout tuple-layout ;
-
-: tuple-size tuple-layout layout-size ; inline
+: tuple-size ( tuple -- size )
+    1 slot layout-size ; inline
 
 : prepare-tuple>array ( tuple -- n tuple layout )
-    [ tuple-size ] [ ] [ tuple-layout ] tri ;
+    check-tuple [ tuple-size ] [ ] [ 1 slot ] tri ;
 
 : copy-tuple-slots ( n tuple -- array )
     [ array-nth ] curry map ;
 
 PRIVATE>
 
-: check-tuple ( class -- )
-    dup tuple-class?
-    [ drop ] [ no-tuple-class ] if ;
-
 : tuple>array ( tuple -- array )
     prepare-tuple>array
     >r copy-tuple-slots r>
@@ -63,7 +63,7 @@ ERROR: bad-superclass class ;
 <PRIVATE
 
 : tuple= ( tuple1 tuple2 -- ? )
-    2dup [ tuple-layout ] bi@ eq? [
+    2dup [ 1 slot ] bi@ eq? [
         [ drop tuple-size ]
         [ [ [ drop array-nth ] [ nip array-nth ] 3bi = ] 2curry ]
         2bi all-integers?
diff --git a/core/debugger/debugger.factor b/core/debugger/debugger.factor
index cfad144737..2ac903a39b 100755
--- a/core/debugger/debugger.factor
+++ b/core/debugger/debugger.factor
@@ -209,8 +209,11 @@ M: inconsistent-next-method summary
 M: check-method summary
     drop "Invalid parameters for create-method" ;
 
-M: no-tuple-class summary
-    drop "BOA constructors can only be defined for tuple classes" ;
+M: not-a-tuple summary
+    drop "Not a tuple" ;
+
+M: not-a-tuple-class summary
+    drop "Not a tuple class" ;
 
 M: bad-superclass summary
     drop "Tuple classes can only inherit from other tuple classes" ;
diff --git a/core/effects/effects.factor b/core/effects/effects.factor
index 099260f111..d7923ad595 100755
--- a/core/effects/effects.factor
+++ b/core/effects/effects.factor
@@ -42,14 +42,14 @@ M: integer (stack-picture) drop "object" ;
 
 GENERIC: stack-effect ( word -- effect/f )
 
-M: symbol stack-effect drop 0 1 <effect> ;
+M: symbol stack-effect drop (( -- symbol )) ;
 
 M: word stack-effect
     { "declared-effect" "inferred-effect" }
     swap word-props [ at ] curry map [ ] find nip ;
 
 M: effect clone
-    [ in>> clone ] keep effect-out clone <effect> ;
+    [ in>> clone ] [ out>> clone ] bi <effect> ;
 
 : split-shuffle ( stack shuffle -- stack1 stack2 )
     in>> length cut* ;
diff --git a/core/inference/backend/backend.factor b/core/inference/backend/backend.factor
index f8b071e803..59fbd289db 100755
--- a/core/inference/backend/backend.factor
+++ b/core/inference/backend/backend.factor
@@ -228,7 +228,7 @@ M: object constructor drop f ;
         1 infer->r
         peek-d reify-curry
         1 infer-r>
-        2 1 <effect> swap #call consume/produce
+        (( obj quot -- curry )) swap #call consume/produce
     ] when* ;
 
 : reify-curries ( n -- )
diff --git a/core/inference/transforms/transforms-tests.factor b/core/inference/transforms/transforms-tests.factor
index f90dd2350c..7f5f8035fb 100755
--- a/core/inference/transforms/transforms-tests.factor
+++ b/core/inference/transforms/transforms-tests.factor
@@ -1,7 +1,7 @@
 IN: inference.transforms.tests
 USING: sequences inference.transforms tools.test math kernel
 quotations inference accessors combinators words arrays
-classes ;
+classes classes.tuple ;
 
 : compose-n-quot ( word -- quot' ) <repetition> >quotation ;
 : compose-n ( quot -- ) compose-n-quot call ;
@@ -46,3 +46,9 @@ C: <color> color
 [ 16 -3 1/6 ] [ 4 3 6 \ spread-test word-def call ] unit-test
 
 [ fixnum instance? ] must-infer
+
+: bad-new-test ( -- obj ) V{ } new ;
+
+[ bad-new-test ] must-infer
+
+[ bad-new-test ] [ T{ not-a-tuple-class f V{ } } = ] must-fail-with
diff --git a/core/inference/transforms/transforms.factor b/core/inference/transforms/transforms.factor
index 5ca10c7545..8fc72b0f09 100755
--- a/core/inference/transforms/transforms.factor
+++ b/core/inference/transforms/transforms.factor
@@ -2,8 +2,9 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays kernel words sequences generic math namespaces
 quotations assocs combinators math.bitfields inference.backend
-inference.dataflow inference.state classes.tuple.private effects
-inspector hashtables classes generic sets definitions ;
+inference.dataflow inference.state classes.tuple
+classes.tuple.private effects inspector hashtables classes
+generic sets definitions ;
 IN: inference.transforms
 
 : pop-literals ( n -- rstate seq )
@@ -83,19 +84,26 @@ M: duplicated-slots-error summary
 ] 1 define-transform
 
 \ boa [
-    dup +inlined+ depends-on
-    tuple-layout [ <tuple-boa> ] curry
+    dup tuple-class? [
+        dup +inlined+ depends-on
+        tuple-layout [ <tuple-boa> ] curry
+    ] [
+        [ not-a-tuple-class ] curry time-bomb
+    ] if
 ] 1 define-transform
 
 \ new [
     1 ensure-values
     peek-d value? [
-        pop-literal
-        dup +inlined+ depends-on
-        tuple-layout [ <tuple> ] curry
-        swap infer-quot
+        pop-literal dup tuple-class? [
+            dup +inlined+ depends-on
+            tuple-layout [ <tuple> ] curry
+            swap infer-quot
+        ] [
+            \ not-a-tuple-class boa time-bomb drop
+        ] if
     ] [
-        \ new 1 1 <effect> make-call-node
+        \ new (( class -- tuple )) make-call-node
     ] if
 ] "infer" set-word-prop
 
diff --git a/core/optimizer/math/partial/partial.factor b/core/optimizer/math/partial/partial.factor
index 8b5e25deb1..30a726e022 100644
--- a/core/optimizer/math/partial/partial.factor
+++ b/core/optimizer/math/partial/partial.factor
@@ -59,7 +59,7 @@ PREDICATE: math-partial < word
 : define-integer-op-word ( word fix-word big-word -- )
     [
         [ integer-op-word ] [ integer-op-quot ] 3bi
-        2 1 <effect> define-declared
+        (( x y -- z )) define-declared
     ]
     [
         [ integer-op-word ] [ 2drop ] 3bi
diff --git a/core/syntax/syntax.factor b/core/syntax/syntax.factor
index dfba35f71a..4d4b81d00e 100755
--- a/core/syntax/syntax.factor
+++ b/core/syntax/syntax.factor
@@ -168,7 +168,7 @@ IN: bootstrap.syntax
 
     "C:" [
         CREATE-WORD
-        scan-word dup check-tuple
+        scan-word check-tuple-class
         [ boa ] curry define-inline
     ] define-syntax
 

From fd4542a41daa83099726f6b83ff6962f7840248f Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Thu, 26 Jun 2008 22:38:59 -0500
Subject: [PATCH 79/85] Fix windows bootstrap

---
 extra/windows/com/syntax/syntax.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extra/windows/com/syntax/syntax.factor b/extra/windows/com/syntax/syntax.factor
index 80a4a040c4..4ce0d3a89c 100755
--- a/extra/windows/com/syntax/syntax.factor
+++ b/extra/windows/com/syntax/syntax.factor
@@ -1,5 +1,5 @@
 USING: alien alien.c-types effects kernel windows.ole32 combinators.lib
-parser splitting grouping sequences.lib sequences namespaces
+parser lexer splitting grouping sequences.lib sequences namespaces
 assocs quotations shuffle accessors words macros alien.syntax
 fry arrays ;
 IN: windows.com.syntax

From a25b0a8cb15d60ff3c75de89fe4d0d98a3cc874a Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Fri, 27 Jun 2008 00:48:05 -0500
Subject: [PATCH 80/85] Fix &add, etc

---
 core/inspector/inspector-tests.factor | 26 ++++++++++++++++++++++++++
 core/inspector/inspector.factor       | 11 +++++++++--
 core/mirrors/mirrors.factor           |  9 ++-------
 3 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/core/inspector/inspector-tests.factor b/core/inspector/inspector-tests.factor
index 72c1a9a6bf..c230364342 100644
--- a/core/inspector/inspector-tests.factor
+++ b/core/inspector/inspector-tests.factor
@@ -9,3 +9,29 @@ H{ } describe
 H{ } describe
 
 [ "fixnum instance\n" ] [ [ 3 describe ] with-string-writer ] unit-test
+
+[ ] [ inspector-hook get-global inspector-hook set ] unit-test
+
+[ ] [ H{ } clone inspect ] unit-test
+
+[ ] [ "a" "b" &add ] unit-test
+
+[ H{ { "b" "a" } } ] [ me get ] unit-test
+
+[ ] [ "x" 0 &put ] unit-test
+
+[ H{ { "b" "x" } } ] [ me get ] unit-test
+
+[ ] [ 0 &at ] unit-test
+
+[ "x" ] [ me get ] unit-test
+
+[ ] [ &back ] unit-test
+
+[ ] [ "y" 0 &rename ] unit-test
+
+[ H{ { "y" "x" } } ] [ me get ] unit-test
+
+[ ] [ 0 &delete ] unit-test
+
+[ H{ } ] [ me get ] unit-test
diff --git a/core/inspector/inspector.factor b/core/inspector/inspector.factor
index fd4e11901a..d32f1c90cf 100755
--- a/core/inspector/inspector.factor
+++ b/core/inspector/inspector.factor
@@ -3,7 +3,7 @@
 USING: arrays generic hashtables io kernel assocs math
 namespaces prettyprint sequences strings io.styles vectors words
 quotations mirrors splitting math.parser classes vocabs refs
-sets ;
+sets sorting ;
 IN: inspector
 
 GENERIC: summary ( object -- string )
@@ -78,10 +78,17 @@ SYMBOL: +editable+
 
 : summary. ( obj -- ) [ summary ] keep write-object nl ;
 
+: sorted-keys ( assoc -- alist )
+    dup mirror? [ keys ] [
+        keys
+        [ [ unparse-short ] keep ] { } map>assoc
+        sort-keys values
+    ] if ;
+
 : describe* ( obj flags -- )
     clone [
         dup summary.
-        make-mirror dup keys dup empty? [
+        make-mirror dup sorted-keys dup empty? [
             2drop
         ] [
             dup enum? [ +sequence+ on ] when
diff --git a/core/mirrors/mirrors.factor b/core/mirrors/mirrors.factor
index 0a49163075..607ba1542f 100755
--- a/core/mirrors/mirrors.factor
+++ b/core/mirrors/mirrors.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: assocs hashtables kernel sequences generic words
 arrays classes slots slots.private classes.tuple math vectors
-quotations sorting prettyprint accessors ;
+quotations accessors ;
 IN: mirrors
 
 : all-slots ( class -- slots )
@@ -47,13 +47,8 @@ M: mirror assoc-size mirror-slots length ;
 
 INSTANCE: mirror assoc
 
-: sort-assoc ( assoc -- alist )
-    >alist
-    [ [ first unparse-short ] keep ] { } map>assoc
-    sort-keys values ;
-
 GENERIC: make-mirror ( obj -- assoc )
-M: hashtable make-mirror sort-assoc ;
+M: hashtable make-mirror ;
 M: integer make-mirror drop f ;
 M: array make-mirror <enum> ;
 M: vector make-mirror <enum> ;

From 334d6d86c39ecb4e159067d5195aef991ac6bbd6 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Fri, 27 Jun 2008 01:02:11 -0500
Subject: [PATCH 81/85] Fix 'exit after last window closed' setting for
 deployment

---
 extra/ui/cocoa/cocoa.factor | 1 -
 1 file changed, 1 deletion(-)

diff --git a/extra/ui/cocoa/cocoa.factor b/extra/ui/cocoa/cocoa.factor
index 0db38e5eca..b0653ffa39 100755
--- a/extra/ui/cocoa/cocoa.factor
+++ b/extra/ui/cocoa/cocoa.factor
@@ -110,7 +110,6 @@ M: cocoa-ui-backend ui
     "UI" assert.app [
         [
             init-clipboard
-            stop-after-last-window? off
             cocoa-init-hook get [ call ] when*
             start-ui
             finish-launching

From 38d5151322cd4434f378742f36bedfc27ffd4d73 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Fri, 27 Jun 2008 01:30:23 -0500
Subject: [PATCH 82/85] Fixing syndication to handle more RSS feeds seen in the
 wild

---
 extra/syndication/syndication.factor       |  2 +-
 extra/xml/utilities/utilities-tests.factor |  8 ++++++++
 extra/xml/utilities/utilities.factor       | 11 ++++++-----
 3 files changed, 15 insertions(+), 6 deletions(-)
 create mode 100644 extra/xml/utilities/utilities-tests.factor

diff --git a/extra/syndication/syndication.factor b/extra/syndication/syndication.factor
index 32b3c925f3..8d4c91177a 100644
--- a/extra/syndication/syndication.factor
+++ b/extra/syndication/syndication.factor
@@ -53,7 +53,7 @@ TUPLE: entry title url description date ;
     swap {
         [ "title" tag-named children>string >>title ]
         [ { "link" "guid" } any-tag-named children>string >url >>url ]
-        [ "description" tag-named children>string >>description ]
+        [ { "description" "encoded" } any-tag-named children>string >>description ]
         [
             { "date" "pubDate" } any-tag-named
             children>string try-parsing-timestamp >>date
diff --git a/extra/xml/utilities/utilities-tests.factor b/extra/xml/utilities/utilities-tests.factor
new file mode 100644
index 0000000000..c150c7133d
--- /dev/null
+++ b/extra/xml/utilities/utilities-tests.factor
@@ -0,0 +1,8 @@
+IN: xml.utilities.tests
+USING: xml xml.utilities tools.test ;
+
+[ "bar" ] [ "<foo>bar</foo>" string>xml children>string ] unit-test
+
+[ "" ] [ "<foo></foo>" string>xml children>string ] unit-test
+
+[ "" ] [ "<foo/>" string>xml children>string ] unit-test
diff --git a/extra/xml/utilities/utilities.factor b/extra/xml/utilities/utilities.factor
index c53bbf3b0f..e1875bd0c1 100755
--- a/extra/xml/utilities/utilities.factor
+++ b/extra/xml/utilities/utilities.factor
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel namespaces sequences words io assocs
 quotations strings parser lexer arrays xml.data xml.writer debugger
-splitting vectors sequences.deep ;
+splitting vectors sequences.deep combinators ;
 IN: xml.utilities
 
 ! * System for words specialized on tag names
@@ -48,10 +48,11 @@ M: process-missing error.
     standard-prolog { } rot { } <xml> ;
 
 : children>string ( tag -- string )
-    tag-children
-    dup [ string? ] all?
-    [ "XML tag unexpectedly contains non-text children" throw ] unless
-    concat ;
+    tag-children {
+        { [ dup empty? ] [ drop "" ] }
+        { [ dup [ string? not ] contains? ] [ "XML tag unexpectedly contains non-text children" throw ] }
+        [ concat ]
+    } cond ;
 
 : children-tags ( tag -- sequence )
     tag-children [ tag? ] filter ;

From 89301622513e13e458316bc838a9af2a5cc3b09f Mon Sep 17 00:00:00 2001
From: "U-SLAVA-DFB8FF805\\Slava" <Slava@slava-dfb8ff805.(none)>
Date: Fri, 27 Jun 2008 01:56:53 -0500
Subject: [PATCH 83/85] Fix Windows bootstrap

---
 extra/io/windows/nt/files/files.factor | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/extra/io/windows/nt/files/files.factor b/extra/io/windows/nt/files/files.factor
index e8bdd8e4ec..2a39cea479 100755
--- a/extra/io/windows/nt/files/files.factor
+++ b/extra/io/windows/nt/files/files.factor
@@ -3,7 +3,7 @@ io.timeouts io.ports io.windows io.windows.files
 io.windows.nt.backend windows windows.kernel32
 kernel libc math threads system
 alien.c-types alien.arrays alien.strings sequences combinators
-combinators.lib sequences.lib ascii splitting alien strings
+combinators.short-circuit ascii splitting alien strings
 assocs namespaces io.files.private accessors ;
 IN: io.windows.nt.files
 
@@ -22,21 +22,18 @@ M: winnt root-directory? ( path -- ? )
     {
         { [ dup empty? ] [ f ] }
         { [ dup [ path-separator? ] all? ] [ t ] }
-        { [ dup right-trim-separators
-          { [ dup length 2 = ] [ dup second CHAR: : = ] } 0&& nip ] [
-            t
-        ] }
+        { [ dup right-trim-separators { [ length 2 = ] [ second CHAR: : = ] } 1&& ] [ t ] }
         [ f ]
     } cond nip ;
 
 ERROR: not-absolute-path ;
 
 : root-directory ( string -- string' )
-    {
-        [ dup length 2 >= ]
-        [ dup second CHAR: : = ]
-        [ dup first Letter? ]
-    } 0&& [ 2 head ] [ not-absolute-path ] if ;
+    dup {
+        [ length 2 >= ]
+        [ second CHAR: : = ]
+        [ first Letter? ]
+    } 1&& [ 2 head ] [ not-absolute-path ] if ;
 
 : prepend-prefix ( string -- string' )
     dup unicode-prefix head? [

From 358c09d204cac20bfb1298e7f3c7611003c44751 Mon Sep 17 00:00:00 2001
From: "U-SLAVA-DFB8FF805\\Slava" <Slava@slava-dfb8ff805.(none)>
Date: Fri, 27 Jun 2008 02:17:19 -0500
Subject: [PATCH 84/85] combinators.lib 3apply is kernel's tri@; remove and
 update usages

---
 core/kernel/kernel-tests.factor            | 5 +++++
 extra/combinators/lib/lib-tests.factor     | 3 ---
 extra/combinators/lib/lib.factor           | 2 --
 extra/io/windows/files/files.factor        | 6 +++---
 extra/io/windows/nt/backend/backend.factor | 2 +-
 extra/project-euler/032/032.factor         | 6 +++---
 extra/project-euler/039/039.factor         | 2 +-
 extra/project-euler/075/075.factor         | 2 +-
 extra/reports/noise/noise.factor           | 1 -
 extra/semantic-db/semantic-db.factor       | 4 ++--
 extra/windows/com/syntax/syntax.factor     | 2 +-
 extra/windows/com/wrapper/wrapper.factor   | 6 +++---
 extra/windows/ole32/ole32.factor           | 4 ++--
 13 files changed, 22 insertions(+), 23 deletions(-)
 mode change 100644 => 100755 extra/project-euler/039/039.factor
 mode change 100644 => 100755 extra/project-euler/075/075.factor
 mode change 100644 => 100755 extra/windows/ole32/ole32.factor

diff --git a/core/kernel/kernel-tests.factor b/core/kernel/kernel-tests.factor
index 4b129ad59d..c5bd0615a7 100755
--- a/core/kernel/kernel-tests.factor
+++ b/core/kernel/kernel-tests.factor
@@ -117,3 +117,8 @@ IN: kernel.tests
 : total-failure-2 [ ] (call) unimplemented ;
 
 [ total-failure-2 ] must-fail
+
+! From combinators.lib
+[ 1 1 2 2 3 3 ] [ 1 2 3 [ dup ] tri@ ] unit-test
+[ 1 4 9 ] [ 1 2 3 [ sq ] tri@ ] unit-test
+[ [ sq ] tri@ ] must-infer
diff --git a/extra/combinators/lib/lib-tests.factor b/extra/combinators/lib/lib-tests.factor
index 680e3220b0..e511e88fcc 100755
--- a/extra/combinators/lib/lib-tests.factor
+++ b/extra/combinators/lib/lib-tests.factor
@@ -10,9 +10,6 @@ IN: combinators.lib.tests
 [ 1 2 3 4 5 [ drop drop drop drop drop 2 ] 5 nkeep ] must-infer
 { 2 1 2 3 4 5 } [ 1 2 3 4 5 [ drop drop drop drop drop 2 ] 5 nkeep ] unit-test
 [ [ 1 2 3 + ] ] [ 1 2 3 [ + ] 3 ncurry ] unit-test
-[ 1 1 2 2 3 3 ] [ 1 2 3 [ dup ] 3apply ] unit-test
-[ 1 4 9 ] [ 1 2 3 [ sq ] 3apply ] unit-test
-[ [ sq ] 3apply ] must-infer
 [ { 1 2 } { 2 4 } { 3 8 } { 4 16 } { 5 32 } ] [ 1 2 3 4 5 [ dup 2^ 2array ] 5 napply ] unit-test
 [ [ dup 2^ 2array ] 5 napply ] must-infer
 
diff --git a/extra/combinators/lib/lib.factor b/extra/combinators/lib/lib.factor
index 63e9750e8b..3fab4f62ae 100755
--- a/extra/combinators/lib/lib.factor
+++ b/extra/combinators/lib/lib.factor
@@ -36,8 +36,6 @@ MACRO: napply ( n -- )
     '[ , ntuck , nslip ] ]
   map concat >quotation [ call ] append ;
 
-: 3apply ( obj obj obj quot -- ) 3 napply ; inline
-
 : 2with ( param1 param2 obj quot -- obj curry )
     with with ; inline
 
diff --git a/extra/io/windows/files/files.factor b/extra/io/windows/files/files.factor
index 6787936f96..a4aae1a005 100755
--- a/extra/io/windows/files/files.factor
+++ b/extra/io/windows/files/files.factor
@@ -4,7 +4,7 @@ USING: alien.c-types io.binary io.backend io.files io.buffers
 io.windows kernel math splitting
 windows windows.kernel32 windows.time calendar combinators
 math.functions sequences namespaces words symbols system
-combinators.lib io.ports destructors accessors
+io.ports destructors accessors
 math.bitfields math.bitfields.lib ;
 IN: io.windows.files
 
@@ -216,11 +216,11 @@ M: winnt link-info ( path -- info )
         "FILETIME" <c-object>
         "FILETIME" <c-object>
         [ GetFileTime win32-error=0/f ] 3keep
-        [ FILETIME>timestamp >local-time ] 3apply
+        [ FILETIME>timestamp >local-time ] tri@
     ] with-destructors ;
 
 : (set-file-times) ( handle timestamp/f timestamp/f timestamp/f -- )
-    [ timestamp>FILETIME ] 3apply
+    [ timestamp>FILETIME ] tri@
     SetFileTime win32-error=0/f ;
 
 : set-file-times ( path timestamp/f timestamp/f timestamp/f -- )
diff --git a/extra/io/windows/nt/backend/backend.factor b/extra/io/windows/nt/backend/backend.factor
index 1a7462f304..786275c736 100755
--- a/extra/io/windows/nt/backend/backend.factor
+++ b/extra/io/windows/nt/backend/backend.factor
@@ -3,7 +3,7 @@ continuations destructors io io.backend io.ports io.timeouts
 io.windows io.windows.files libc kernel math namespaces
 sequences threads classes.tuple.lib windows windows.errors
 windows.kernel32 strings splitting io.files
-io.buffers qualified ascii combinators.lib system
+io.buffers qualified ascii system
 accessors locals ;
 QUALIFIED: windows.winsock
 IN: io.windows.nt.backend
diff --git a/extra/project-euler/032/032.factor b/extra/project-euler/032/032.factor
index 68b42ca442..8a54c595a9 100755
--- a/extra/project-euler/032/032.factor
+++ b/extra/project-euler/032/032.factor
@@ -31,11 +31,11 @@ IN: project-euler.032
 
 : 1and4 ( n -- ? )
     number>string 1 cut-slice 4 cut-slice
-    [ string>number ] 3apply [ * ] dip = ;
+    [ string>number ] tri@ [ * ] dip = ;
 
 : 2and3 ( n -- ? )
     number>string 2 cut-slice 3 cut-slice
-    [ string>number ] 3apply [ * ] dip = ;
+    [ string>number ] tri@ [ * ] dip = ;
 
 : valid? ( n -- ? )
     dup 1and4 swap 2and3 or ;
@@ -65,7 +65,7 @@ PRIVATE>
 
 ! multiplicand/multiplier/product
 : mmp ( pair -- n )
-    first2 2dup * [ number>string ] 3apply 3append string>number ;
+    first2 2dup * [ number>string ] tri@ 3append string>number ;
 
 PRIVATE>
 
diff --git a/extra/project-euler/039/039.factor b/extra/project-euler/039/039.factor
old mode 100644
new mode 100755
index 9075b19324..7a9f51f1d3
--- a/extra/project-euler/039/039.factor
+++ b/extra/project-euler/039/039.factor
@@ -44,7 +44,7 @@ SYMBOL: p-count
     dup sum max-p < [
         dup sum adjust-p-count
         [ u-transform ] [ a-transform ] [ d-transform ] tri
-        [ (count-perimeters) ] 3apply
+        [ (count-perimeters) ] tri@
     ] [
         drop
     ] if ;
diff --git a/extra/project-euler/075/075.factor b/extra/project-euler/075/075.factor
old mode 100644
new mode 100755
index 453ebfa129..8e5b849de5
--- a/extra/project-euler/075/075.factor
+++ b/extra/project-euler/075/075.factor
@@ -57,7 +57,7 @@ SYMBOL: p-count
     dup sum max-p < [
         dup sum adjust-p-count
         [ u-transform ] [ a-transform ] [ d-transform ] tri
-        [ (count-perimeters) ] 3apply
+        [ (count-perimeters) ] tri@
     ] [
         drop
     ] if ;
diff --git a/extra/reports/noise/noise.factor b/extra/reports/noise/noise.factor
index 3537d2e719..fc8ba9821c 100755
--- a/extra/reports/noise/noise.factor
+++ b/extra/reports/noise/noise.factor
@@ -20,7 +20,6 @@ IN: reports.noise
         { 2swap 3 }
         { 2with 2 }
         { 2with* 3 }
-        { 3apply 1/2 }
         { 3curry 2 }
         { 3drop 1 }
         { 3dup 2 }
diff --git a/extra/semantic-db/semantic-db.factor b/extra/semantic-db/semantic-db.factor
index 27e8cf1d90..89ad6fe2d0 100755
--- a/extra/semantic-db/semantic-db.factor
+++ b/extra/semantic-db/semantic-db.factor
@@ -36,10 +36,10 @@ TUPLE: arc id subject object relation ;
 : delete-arc ( arc -- ) delete-tuples ;
 
 : create-arc ( subject object relation -- )
-    [ id>> ] 3apply <arc> insert-tuple ;
+    [ id>> ] tri@ <arc> insert-tuple ;
 
 : nodes>arc ( subject object relation -- arc )
-    [ [ id>> ] [ f ] if* ] 3apply <arc> ;
+    [ [ id>> ] [ f ] if* ] tri@ <arc> ;
 
 : select-arcs ( subject object relation -- arcs )
     nodes>arc select-tuples ;
diff --git a/extra/windows/com/syntax/syntax.factor b/extra/windows/com/syntax/syntax.factor
index 4ce0d3a89c..e0ea65e8be 100755
--- a/extra/windows/com/syntax/syntax.factor
+++ b/extra/windows/com/syntax/syntax.factor
@@ -1,4 +1,4 @@
-USING: alien alien.c-types effects kernel windows.ole32 combinators.lib
+USING: alien alien.c-types effects kernel windows.ole32
 parser lexer splitting grouping sequences.lib sequences namespaces
 assocs quotations shuffle accessors words macros alien.syntax
 fry arrays ;
diff --git a/extra/windows/com/wrapper/wrapper.factor b/extra/windows/com/wrapper/wrapper.factor
index 6d6aa078e8..266439ad79 100755
--- a/extra/windows/com/wrapper/wrapper.factor
+++ b/extra/windows/com/wrapper/wrapper.factor
@@ -2,8 +2,8 @@ USING: alien alien.c-types windows.com.syntax
 windows.com.syntax.private windows.com continuations kernel
 sequences.lib namespaces windows.ole32 libc vocabs
 assocs accessors arrays sequences quotations combinators
-math combinators.lib words compiler.units destructors fry
-math.parser ;
+math words compiler.units destructors fry
+math.parser combinators.lib ;
 IN: windows.com.wrapper
 
 TUPLE: com-wrapper vtbls disposed ;
@@ -84,7 +84,7 @@ unless
     swap append ;
 
 : compile-alien-callback ( word return parameters abi quot -- alien )
-    [ alien-callback ] 4 ncurry
+    '[ , , , , alien-callback ]
     [ [ (( -- alien )) define-declared ] pick slip ]
     with-compilation-unit
     execute ;
diff --git a/extra/windows/ole32/ole32.factor b/extra/windows/ole32/ole32.factor
old mode 100644
new mode 100755
index a71a569f16..7daba37063
--- a/extra/windows/ole32/ole32.factor
+++ b/extra/windows/ole32/ole32.factor
@@ -1,5 +1,5 @@
 USING: alien alien.syntax alien.c-types alien.strings math
-kernel sequences windows windows.types combinators.lib
+kernel sequences windows windows.types
 math.order ;
 IN: windows.ole32
 
@@ -132,5 +132,5 @@ FUNCTION: void ReleaseStgMedium ( LPSTGMEDIUM pmedium ) ;
     utf16n string>alien "GUID" <c-object> [ CLSIDFromString ole32-error ] keep ;
 : guid>string ( guid -- string )
     GUID-STRING-LENGTH 1+ [ "ushort" <c-array> ] keep
-    [ StringFromGUID2 drop ] { 2 } multikeep utf16n alien>string ;
+    [ StringFromGUID2 drop ] 2keep drop utf16n alien>string ;
 

From 9d6f21d83c1a860301f73a7d1211ece86e51a262 Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Fri, 27 Jun 2008 03:03:31 -0500
Subject: [PATCH 85/85] Fix bug exposed by new/boa change

---
 extra/peg/ebnf/ebnf.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index 6812aefee0..3d48665c8c 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -23,7 +23,7 @@ TUPLE: tokenizer any one many ;
 
 : parser-tokenizer ( parser -- tokenizer )
   [ 1quotation ] keep
-  [ swap [ = ] curry semantic ] curry dup tokenizer boa ;
+  [ swap [ = ] curry semantic ] curry dup \ tokenizer boa ;
 
 : rule-tokenizer ( name word -- tokenizer )
   rule parser-tokenizer ;