Commits

Taku Miyakawa committed 3625a5b

Renames public modules for the new Nomenclature

  • Participants
  • Parent commits 1e94094

Comments (0)

Files changed (212)

File src/build/deleteassertion.kn

 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # THE SOFTWARE.
 
-use('Java.null')
+use('JAVA.null')
 use('org.objectweb.asm.ClassReader')
 use('org.objectweb.asm.ClassWriter')
 use('org.objectweb.asm.ClassVisitor')

File src/doc/characteristics.rst

 
 ::
 
-    use('Set')
-    :Yokozuna_ = Set.set('Takanohana' 'Asashoryu' 'Hakuho')
+    use('SET')
+    :Yokozuna_ = SET.set('Takanohana' 'Asashoryu' 'Hakuho')
     printline(Yokozuna_) # => set('Asashoryu' 'Takanohana' 'Hakuho')
 
 In this example, you have to put the second argument ``-10`` in parentheses

File src/doc/language/core.rst

 
 ::
 
-    use('Map')
+    use('MAP')
 
     :Value_ = value
-    Value_.:Alternatives_ = Map.map('Num_' 42)
+    Value_.:Alternatives_ = MAP.map('Num_' 42)
     Value_.:extend_base_varmissing = { > :Me_ (:Symbol_)
         Me_.Alternatives_.haskey?(Symbol_).then {
             [Me_.Alternatives_.get(Symbol_)]

File src/main/java/org/kink_lang/kink/internal/Envs.java

 
     /** Returns a new environment. */
     public static Value env() {
-        return Modules.find( "Core" ).child();
+        return Modules.find( "CORE" ).child();
     }
 
 

File src/main/java/org/kink_lang/kink/internal/box/InputStreamEnhancer.java

                     }
                 }
             };
-            return Modules.find( "Seq" ).tailCall( ONESHOTSEQ , Value.value( fun ) );
+            return Modules.find( "SEQ" ).tailCall( ONESHOTSEQ , Value.value( fun ) );
         }
 
 

File src/main/java/org/kink_lang/kink/internal/box/RandomEnhancer.java

                     return Value.value( new ValueList( numVal ) );
                 }
             };
-            return Modules.find( "Seq" ).tailCall( ONESHOTSEQ , Value.value( fun ) );
+            return Modules.find( "SEQ" ).tailCall( ONESHOTSEQ , Value.value( fun ) );
         }
 
 

File src/main/java/org/kink_lang/kink/internal/eval/MultiSetEvaluator.java

 import java.util.Collections;
 
 /**
- * Short-cut evaluator for Core.values, VALUE.child, VALUE.setvars.
+ * Short-cut evaluator for CORE.values, VALUE.child, VALUE.setvars.
  */
 public abstract class MultiSetEvaluator extends Evaluator {
 

File src/main/java/org/kink_lang/kink/internal/eval/ValueFuncEvaluator.java

 import java.util.List;
 
 /**
- * Short-cut evaluator for Core.value.
+ * Short-cut evaluator for CORE.value.
  */
 public class ValueFuncEvaluator extends MultiSetEvaluator {
 
 
-    /** {@code Core.value}. */
+    /** {@code CORE.value}. */
     private static volatile Value valueFunc;
 
 
 
 
     /**
-     * Sets the value of {@code Core.value}.
+     * Sets the value of {@code CORE.value}.
      *
      * @param funcValue
-     *     Value of {@code Core.value}.
+     *     Value of {@code CORE.value}.
      */
     static void initializeValueFunc( Value funcValue ) {
         ValueFuncEvaluator.valueFunc = funcValue;
 
 
     /**
-     * Listener to listen the state of Core.value.
+     * Listener to listen the state of CORE.value.
      */
     public static class CoreModuleListener implements ModuleListener {
         @Override public void notifyModuleRegistered( String moduleName , Value module ) {
-            if ( moduleName.equals( "Core" ) ) {
+            if ( moduleName.equals( "CORE" ) ) {
                 initializeValueFunc( module.get( new GetSite( "value" ) ) );
             }
         }

File src/main/java/org/kink_lang/kink/internal/expression/CallExpression.java

     }
 
 
-    /** Tests that the expression can be regarded as invocation of {@code Core.value}. */
+    /** Tests that the expression can be regarded as invocation of {@code CORE.value}. */
     boolean isValueFunction() {
         return isValueFunctionReceiver()
             && getSymbol().equals( "value" )
 
     /**
      * Tests that the receiver of the expression can be regarded
-     * as the receiver of {@code Core.value}.
+     * as the receiver of {@code CORE.value}.
      */
     private boolean isValueFunctionReceiver() {
         if ( getReceiver() instanceof EnvExpression ) {
         } else if ( getReceiver() instanceof VarDereferenceExpression ) {
             VarDereferenceExpression varDereferenceReceiver
                 = (VarDereferenceExpression) getReceiver();
-            return varDereferenceReceiver.getSymbol().equals( "Core" );
+            return varDereferenceReceiver.getSymbol().equals( "CORE" );
         } else {
             return false;
         }
     }
 
 
-    /** Returns an evaluator of {@code Core.value}. */
+    /** Returns an evaluator of {@code CORE.value}. */
     private Evaluator valueFunctionEvaluator() {
         assert isValueFunction();
         return new ValueFuncEvaluator(

File src/main/java/org/kink_lang/kink/internal/jsr223/KinkEngineFactory.java

 
     @Override
     public String getLanguageVersion() {
-        Value versionModule = Modules.find( "KinkVersion" );
+        Value versionModule = Modules.find( "KINK_VERSION" );
         Value version = versionModule.call( VERSION );
         return version.toString();
     }

File src/main/java/org/kink_lang/kink/internal/module/Core.java

 import java.util.Random;
 import java.math.BigInteger;
 
-/** Core module. */
+/** CORE module. */
 public final class Core extends ModuleFactory {
 
 
 
     @Override
     public String getName() {
-        return "Core";
+        return "CORE";
     }
 
 
 
 
         private static final class CoreHolder {
-            static final Value CORE = Modules.find( "Core" );
+            static final Value CORE = Modules.find( "CORE" );
 
             private CoreHolder() {
                 throw new UnsupportedOperationException( "Should not be instantiated" );
 
         @Define
         public Value show( @Receiver Value envOrCore ) {
-            return Value.value( envOrCore == CoreHolder.CORE ? "Core" : "<env>" );
+            return Value.value( envOrCore == CoreHolder.CORE ? "CORE" : "<env>" );
         }
 
 

File src/main/java/org/kink_lang/kink/internal/module/Meta.java

 import org.kink_lang.kink.ModuleFactory;
 import org.kink_lang.kink.Define;
 
-/** Factory of Meta module. */
+/** Factory of META module. */
 public final class Meta extends ModuleFactory {
 
 
+    @Override
+    public String getName() {
+        return "META";
+    }
+
+
     /**
      * Returns a meta value.
      *

File src/main/java/org/kink_lang/kink/internal/module/Using.java

 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/** Factory mof Using module. */
+/** Factory mof USING module. */
 public final class Using extends ModuleFactory {
 
 
     private static final GetSite CLOSE = new GetSite( "close" );
 
 
+    @Override
+    public String getName() {
+        return "USING";
+    }
+
+
     /**
      * Calls {@code fun} with {@code closeable}, and then calls "call" method of {@code closeable}.
      *

File src/main/kink/COMMAND.kn

+#!/usr/bin/env kink
+# vim: et sw=4 sts=4
+
+# Copyright (c) 2013 Miyakawa Taku
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+use('USING.using')
+use('java.lang.Thread')
+use('java.lang.ProcessBuilder')
+use('java.lang.ProcessBuilder$Redirect')
+use('java.nio.charset.Charset')
+use('java.lang.String')
+
+:command = { (* :Args_)
+    :Process_builder = ProcessBuilder.new(Args_)
+    Process_builder.inheritIO
+    _command_from_pb(Process_builder)
+}
+
+:_command_from_pb = { (:Process_builder)
+    Command_proto.child('Process_builder' Process_builder)
+}
+
+:Command_trait = [
+    'directory' { > :Command_ (:Dir_)
+        Command_.Process_builder.directory(path(Dir_.toString))
+    }
+    'join' { > :Command_ ()
+        :Process_ = Command_.Process_builder.start
+        Command_._spawn_in(Process_)
+        Command_._spawn_out(Process_)
+        Command_._spawn_err(Process_)
+        Command_._join_in
+        Command_._join_out
+        Command_._join_err
+        :Status_ = Process_.waitFor
+        Command_.:join = constfun(Status_)
+        Status_
+    }
+    'text' { > :Command_ (:Coding_ = Charset.defaultCharset)
+        :Text_ = ()
+        Command_.handle_out { (:Stream_)
+            :Text_.solid = Stream_.text(Coding_)
+        }
+        Command_.join
+        Text_
+    }
+    'bytes' { > :Command_ ()
+        :Bytes_ = ()
+        Command_.handle_out { (:Stream_) :Bytes_.solid = Stream_.bytes }
+        Command_.join
+        Bytes_
+    }
+    'give_text' { > :Command_ (:Text_)
+        Command_.handle_in { (:Stream_) Stream_.print(Text_) }
+    }
+    'give_bytes' { > :Command_ (:Bytes_)
+        Command_.handle_in { (:Stream_) Stream_.write(Bytes_) }
+    }
+    'merge_error' { > :Command_ ()
+        Command_.Process_builder.redirectErrorStream(true)
+    }
+    'handle_in' { > :Command_ (:_block)
+        Command_.Process_builder.redirectInput(Redirect.PIPE)
+        Command_.:_spawn_in = { (:Process_)
+            :Thread_ = Thread.new {
+                using(Process_.getOutputStream $_block)
+            }
+            Command_.:_join_in = { Thread_.join }
+            Thread_.start
+        }
+    }
+    'handle_out' { > :Command_ (:_block)
+        Command_.Process_builder.redirectOutput(Redirect.PIPE)
+        Command_.:_spawn_out = { (:Process_)
+            :Thread_ = Thread.new {
+                using(Process_.getInputStream $_block)
+            }
+            Command_.:_join_out = { Thread_.join }
+            Thread_.start
+        }
+    }
+    'handle_error' { > :Command_ (:_block)
+        Command_.Process_builder.redirectError(Redirect.PIPE)
+        Command_.:_spawn_err = { (:Process_)
+            :Thread_ = Thread.new {
+                using(Process_.getErrorStream $_block)
+            }
+            Command_.:_join_err = { Thread_.join }
+            Thread_.start
+        }
+    }
+    '_spawn_in' {}
+    '_spawn_out' {}
+    '_spawn_err' {}
+    '_join_in' {}
+    '_join_out' {}
+    '_join_err' {}
+    'command??' { > :Command_
+        Command_.:Process_builder.exists?
+    }
+]
+
+:Command_proto = value(*** Command_trait)

File src/main/kink/COMMON_PATTERN.kn

+#!/usr/bin/env kink
+# vim: et sw=4 sts=4
+
+# Copyright (c) 2013 Miyakawa Taku
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+## Complement of Pattern_
+:not = { (:Pattern_)
+    value(
+        'op_match' { (:Case_) ! (Case_ =~ Pattern_) }
+        'show' { expand('not(#{Pattern_.show})') }
+    )
+}
+
+## Union of the patterns
+:or = { (* :Patterns_)
+    value(
+        'op_match' { (:Case_) Patterns_.any? { Case_ =~ \0 } }
+        'show' {
+            :Contents_ = Patterns_.map { ' ' + \0.show + ' ' } .join
+            expand('or(#Contents_)')
+        }
+    )
+}
+
+## Intersection of the patterns
+:and = { (* :Patterns_)
+    value(
+        'op_match' { (:Case_) Patterns_.all? { Case_ =~ \0 } }
+        'show' {
+            :Contents_ = Patterns_.map { ' ' + \0.show + ' ' } .join
+            expand('and(#Contents_)')
+        }
+    )
+}
+
+## Pattern that tests equality to the expected value
+:eq = { (:Expected_)
+    value(
+        'op_match' { (:Case_) Case_ == Expected_ }
+        'show' { () expand('eq(#{Expected_.show})') }
+    )
+}
+
+## Pattern that checks non-equality to the not-expected value
+:ne = { (:Not_expected)
+    value(
+        'op_match' { (:Case_) Case_ != Not_expected }
+        'show' { () expand('ne(#{Not_expected.show})') }
+    )
+}
+
+## Pattern that checks the argument is less than the above value
+:lt = { (:Above_)
+    value(
+        'op_match' { (:Arg_) Arg_ < Above_ }
+        'show' { () expand('lt(#{Above_.show})') }
+    )
+}
+
+## Pattern that checks the argument is less than or equal to the max value
+:le = { (:Max_)
+    value(
+        'op_match' { (:Arg_) Arg_ <= Max_ }
+        'show' { () expand('le(#{Max_.show})') }
+    )
+}
+
+## Pattern that checks the argument is greater than to the below value
+:gt = { (:Below_)
+    value(
+        'op_match' { (:Arg_) Arg_ > Below_ }
+        'show' { () expand('gt(#{Below_.show})') }
+    )
+}
+
+## Pattern that checks the argument is greater than to the below value
+:ge = { (:Min_)
+    value(
+        'op_match' { (:Arg_) Arg_ >= Min_ }
+        'show' { () expand('ge(#{Min_.show})') }
+    )
+}
+
+## Pattern that the argument is an instance of the class (default:java.lang.Object)
+:object = { (:Class_)
+    :Class_.exists?.then {
+        value(
+            'op_match' { (:Arg_) Arg_.instanceof?(Class_) }
+            'show' { () expand('object(class(#{Class_.getName.show}))') }
+        )
+    } {
+        value(
+            'op_match' { (:Arg_) Arg_.object?? }
+            'show' { () 'object' }
+        )
+    }
+}
+
+## Pattern that the argument is identical to the expected value
+:identical = { (:Expected_)
+    value(
+        'op_match' { (:Arg_) Arg_.identity == Expected_.identity }
+        'show' { () expand('identical(#{Expected_.show})') }
+    )
+}
+
+## Pattern that the argument is sub of the argument value
+:sub = { (:Target_)
+    value(
+        'op_match' { (:Arg_) Arg_.sub?(Target_) }
+        'show' { () expand('sub(#{Target_.show})') }
+    )
+}
+
+:sameobject = { (:Expected_)
+    value(
+        'op_match' { (:Arg_) Arg_.sameinstance?(Expected_) }
+        'show' { () expand('sameobject(#{Expected_.show})') }
+    )
+}

File src/main/kink/COMPARE.kn

+#!/usr/bin/env kink
+# vim: et sw=4 sts=4
+
+# Copyright (c) 2013 Miyakawa Taku
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# Returns a trait to compare the receiver and an argument.
+# The trait produces methods 'compare', 'op_lt', 'op_le', 'op_gt' and 'op_ge'.
+#
+# _compare:
+#   Takes two arguments and returns
+#   0 if \0 == \1,
+#   a negative number if \0 < \1,
+#   a positive number if \0 > \1.
+:comparetrait = { (:_compare)
+    [
+        'op_cmp' { > :One_ (:Another_) _compare(One_ Another_) }
+        'op_lt' { > :One_ (:Another_) _compare(One_ Another_) < 0 }
+        'op_le' { > :One_ (:Another_) _compare(One_ Another_) <= 0 }
+        'op_gt' { > :One_ (:Another_) _compare(One_ Another_) > 0 }
+        'op_ge' { > :One_ (:Another_) _compare(One_ Another_) >= 0 }
+    ]
+}
+
+# Returns a function that compares two values by sort keys extracted by '_sortkey'.
+#
+# _sortkey:
+#   Takes an argument and returns a sort key of the argument.
+#
+# Usage:
+#   use('COMPARE')
+#   :List_ = [20 42 95 26 27]
+#   :Sorted_ = List_.sort(COMPARE.by { \0 % 10 })
+#   printline(Sorted_) # => [20 42 95 26 27]
+:by = { (:_sortkey)
+    { _sortkey(\0) <=> _sortkey(\1) }
+}
+
+# Returns a function that compares two values in a reverse order from '_compare'.
+#
+# _compare = { \0 <=> \1 }:
+#   Takes two arguments and returns an original order.
+#
+# Usage:
+#   use('COMPARE')
+#   :List_ = [20 42 95 26 27]
+#   :Sorted_ = List_.sort(COMPARE.reverse)
+#   printline(Sorted_) # => [95 42 27 26 20]
+#
+# Usage:
+#   use('COMPARE')
+#   :List_ = [20 42 95 26 27]
+#   :Sorted_ = List_.sort(COMPARE.reverse(COMPARE.by { \0 % 10 }))
+#   printline(Sorted_) # => [27 26 95 42 20]
+:reverse = { (:_compare)
+    :_compare.exists?.then {
+        { _compare(\1 \0) }
+    } {
+        { \1 <=> \0 }
+    }
+}

File src/main/kink/Command.kn

-#!/usr/bin/env kink
-# vim: et sw=4 sts=4
-
-# Copyright (c) 2013 Miyakawa Taku
-# 
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-use('Using.using')
-use('java.lang.Thread')
-use('java.lang.ProcessBuilder')
-use('java.lang.ProcessBuilder$Redirect')
-use('java.nio.charset.Charset')
-use('java.lang.String')
-
-:command = { (* :Args_)
-    :Process_builder = ProcessBuilder.new(Args_)
-    Process_builder.inheritIO
-    _command_from_pb(Process_builder)
-}
-
-:_command_from_pb = { (:Process_builder)
-    Command_proto.child('Process_builder' Process_builder)
-}
-
-:Command_trait = [
-    'directory' { > :Command_ (:Dir_)
-        Command_.Process_builder.directory(path(Dir_.toString))
-    }
-    'join' { > :Command_ ()
-        :Process_ = Command_.Process_builder.start
-        Command_._spawn_in(Process_)
-        Command_._spawn_out(Process_)
-        Command_._spawn_err(Process_)
-        Command_._join_in
-        Command_._join_out
-        Command_._join_err
-        :Status_ = Process_.waitFor
-        Command_.:join = constfun(Status_)
-        Status_
-    }
-    'text' { > :Command_ (:Coding_ = Charset.defaultCharset)
-        :Text_ = ()
-        Command_.handle_out { (:Stream_)
-            :Text_.solid = Stream_.text(Coding_)
-        }
-        Command_.join
-        Text_
-    }
-    'bytes' { > :Command_ ()
-        :Bytes_ = ()
-        Command_.handle_out { (:Stream_) :Bytes_.solid = Stream_.bytes }
-        Command_.join
-        Bytes_
-    }
-    'give_text' { > :Command_ (:Text_)
-        Command_.handle_in { (:Stream_) Stream_.print(Text_) }
-    }
-    'give_bytes' { > :Command_ (:Bytes_)
-        Command_.handle_in { (:Stream_) Stream_.write(Bytes_) }
-    }
-    'merge_error' { > :Command_ ()
-        Command_.Process_builder.redirectErrorStream(true)
-    }
-    'handle_in' { > :Command_ (:_block)
-        Command_.Process_builder.redirectInput(Redirect.PIPE)
-        Command_.:_spawn_in = { (:Process_)
-            :Thread_ = Thread.new {
-                using(Process_.getOutputStream $_block)
-            }
-            Command_.:_join_in = { Thread_.join }
-            Thread_.start
-        }
-    }
-    'handle_out' { > :Command_ (:_block)
-        Command_.Process_builder.redirectOutput(Redirect.PIPE)
-        Command_.:_spawn_out = { (:Process_)
-            :Thread_ = Thread.new {
-                using(Process_.getInputStream $_block)
-            }
-            Command_.:_join_out = { Thread_.join }
-            Thread_.start
-        }
-    }
-    'handle_error' { > :Command_ (:_block)
-        Command_.Process_builder.redirectError(Redirect.PIPE)
-        Command_.:_spawn_err = { (:Process_)
-            :Thread_ = Thread.new {
-                using(Process_.getErrorStream $_block)
-            }
-            Command_.:_join_err = { Thread_.join }
-            Thread_.start
-        }
-    }
-    '_spawn_in' {}
-    '_spawn_out' {}
-    '_spawn_err' {}
-    '_join_in' {}
-    '_join_out' {}
-    '_join_err' {}
-    'command??' { > :Command_
-        Command_.:Process_builder.exists?
-    }
-]
-
-:Command_proto = value(*** Command_trait)

File src/main/kink/CommonPattern.kn

-#!/usr/bin/env kink
-# vim: et sw=4 sts=4
-
-# Copyright (c) 2013 Miyakawa Taku
-# 
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-## Complement of Pattern_
-:not = { (:Pattern_)
-    value(
-        'op_match' { (:Case_) ! (Case_ =~ Pattern_) }
-        'show' { expand('not(#{Pattern_.show})') }
-    )
-}
-
-## Union of the patterns
-:or = { (* :Patterns_)
-    value(
-        'op_match' { (:Case_) Patterns_.any? { Case_ =~ \0 } }
-        'show' {
-            :Contents_ = Patterns_.map { ' ' + \0.show + ' ' } .join
-            expand('or(#Contents_)')
-        }
-    )
-}
-
-## Intersection of the patterns
-:and = { (* :Patterns_)
-    value(
-        'op_match' { (:Case_) Patterns_.all? { Case_ =~ \0 } }
-        'show' {
-            :Contents_ = Patterns_.map { ' ' + \0.show + ' ' } .join
-            expand('and(#Contents_)')
-        }
-    )
-}
-
-## Pattern that tests equality to the expected value
-:eq = { (:Expected_)
-    value(
-        'op_match' { (:Case_) Case_ == Expected_ }
-        'show' { () expand('eq(#{Expected_.show})') }
-    )
-}
-
-## Pattern that checks non-equality to the not-expected value
-:ne = { (:Not_expected)
-    value(
-        'op_match' { (:Case_) Case_ != Not_expected }
-        'show' { () expand('ne(#{Not_expected.show})') }
-    )
-}
-
-## Pattern that checks the argument is less than the above value
-:lt = { (:Above_)
-    value(
-        'op_match' { (:Arg_) Arg_ < Above_ }
-        'show' { () expand('lt(#{Above_.show})') }
-    )
-}
-
-## Pattern that checks the argument is less than or equal to the max value
-:le = { (:Max_)
-    value(
-        'op_match' { (:Arg_) Arg_ <= Max_ }
-        'show' { () expand('le(#{Max_.show})') }
-    )
-}
-
-## Pattern that checks the argument is greater than to the below value
-:gt = { (:Below_)
-    value(
-        'op_match' { (:Arg_) Arg_ > Below_ }
-        'show' { () expand('gt(#{Below_.show})') }
-    )
-}
-
-## Pattern that checks the argument is greater than to the below value
-:ge = { (:Min_)
-    value(
-        'op_match' { (:Arg_) Arg_ >= Min_ }
-        'show' { () expand('ge(#{Min_.show})') }
-    )
-}
-
-## Pattern that the argument is an instance of the class (default:java.lang.Object)
-:object = { (:Class_)
-    :Class_.exists?.then {
-        value(
-            'op_match' { (:Arg_) Arg_.instanceof?(Class_) }
-            'show' { () expand('object(class(#{Class_.getName.show}))') }
-        )
-    } {
-        value(
-            'op_match' { (:Arg_) Arg_.object?? }
-            'show' { () 'object' }
-        )
-    }
-}
-
-## Pattern that the argument is identical to the expected value
-:identical = { (:Expected_)
-    value(
-        'op_match' { (:Arg_) Arg_.identity == Expected_.identity }
-        'show' { () expand('identical(#{Expected_.show})') }
-    )
-}
-
-## Pattern that the argument is sub of the argument value
-:sub = { (:Target_)
-    value(
-        'op_match' { (:Arg_) Arg_.sub?(Target_) }
-        'show' { () expand('sub(#{Target_.show})') }
-    )
-}
-
-:sameobject = { (:Expected_)
-    value(
-        'op_match' { (:Arg_) Arg_.sameinstance?(Expected_) }
-        'show' { () expand('sameobject(#{Expected_.show})') }
-    )
-}

File src/main/kink/Compare.kn

-#!/usr/bin/env kink
-# vim: et sw=4 sts=4
-
-# Copyright (c) 2013 Miyakawa Taku
-# 
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-# Returns a trait to compare the receiver and an argument.
-# The trait produces methods 'compare', 'op_lt', 'op_le', 'op_gt' and 'op_ge'.
-#
-# _compare:
-#   Takes two arguments and returns
-#   0 if \0 == \1,
-#   a negative number if \0 < \1,
-#   a positive number if \0 > \1.
-:comparetrait = { (:_compare)
-    [
-        'op_cmp' { > :One_ (:Another_) _compare(One_ Another_) }
-        'op_lt' { > :One_ (:Another_) _compare(One_ Another_) < 0 }
-        'op_le' { > :One_ (:Another_) _compare(One_ Another_) <= 0 }
-        'op_gt' { > :One_ (:Another_) _compare(One_ Another_) > 0 }
-        'op_ge' { > :One_ (:Another_) _compare(One_ Another_) >= 0 }
-    ]
-}
-
-# Returns a function that compares two values by sort keys extracted by '_sortkey'.
-#
-# _sortkey:
-#   Takes an argument and returns a sort key of the argument.
-#
-# Usage:
-#   use('Compare')
-#   :List_ = [20 42 95 26 27]
-#   :Sorted_ = List_.sort(Compare.by { \0 % 10 })
-#   printline(Sorted_) # => [20 42 95 26 27]
-:by = { (:_sortkey)
-    { _sortkey(\0) <=> _sortkey(\1) }
-}
-
-# Returns a function that compares two values in a reverse order from '_compare'.
-#
-# _compare = { \0 <=> \1 }:
-#   Takes two arguments and returns an original order.
-#
-# Usage:
-#   use('Compare')
-#   :List_ = [20 42 95 26 27]
-#   :Sorted_ = List_.sort(Compare.reverse)
-#   printline(Sorted_) # => [95 42 27 26 20]
-#
-# Usage:
-#   use('Compare')
-#   :List_ = [20 42 95 26 27]
-#   :Sorted_ = List_.sort(Compare.reverse(Compare.by { \0 % 10 }))
-#   printline(Sorted_) # => [27 26 95 42 20]
-:reverse = { (:_compare)
-    :_compare.exists?.then {
-        { _compare(\1 \0) }
-    } {
-        { \1 <=> \0 }
-    }
-}

File src/main/kink/JAVA.kn

+#! kink
+# vim: et sw=4 sts=4
+
+# Copyright (c) 2013 Miyakawa Taku
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+:void = constfun(class('java.lang.Void').TYPE)
+
+:boolean = constfun(class('java.lang.Boolean').TYPE)
+
+:char = constfun(class('java.lang.Character').TYPE)
+
+:byte = constfun(class('java.lang.Byte').TYPE)
+
+:short = constfun(class('java.lang.Short').TYPE)
+
+:int = constfun(class('java.lang.Integer').TYPE)
+
+:long = constfun(class('java.lang.Long').TYPE)
+
+:float = constfun(class('java.lang.Float').TYPE)
+
+:double = constfun(class('java.lang.Double').TYPE)
+
+:null = constfun(int.getSuperclass)

File src/main/kink/Java.kn

-#! kink
-# vim: et sw=4 sts=4
-
-# Copyright (c) 2013 Miyakawa Taku
-# 
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-:void = constfun(class('java.lang.Void').TYPE)
-
-:boolean = constfun(class('java.lang.Boolean').TYPE)
-
-:char = constfun(class('java.lang.Character').TYPE)
-
-:byte = constfun(class('java.lang.Byte').TYPE)
-
-:short = constfun(class('java.lang.Short').TYPE)
-
-:int = constfun(class('java.lang.Integer').TYPE)
-
-:long = constfun(class('java.lang.Long').TYPE)
-
-:float = constfun(class('java.lang.Float').TYPE)
-
-:double = constfun(class('java.lang.Double').TYPE)
-
-:null = constfun(int.getSuperclass)

File src/main/kink/KINK_VERSION.kn

+#!/usr/bin/env kink
+# vim: et sw=4 sts=4
+
+# Copyright (c) 2013 Miyakawa Taku
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+:_read_version = {
+    use('USING.using')
+    use('org.kink_lang.kink.Value')
+    :String_ = using(Value.getClassLoader.getResourceAsStream('org/kink_lang/kink/version.txt')) {
+        \0.text.trim
+    }
+    :Numbers_ = (String_ / '.').map { \0.int }
+    [String_ Numbers_]
+}
+
+[:String_ :Numbers_] = _read_version
+
+# Version string of the interpreter.
+:version = constfun(String_)
+
+# Version numbers of the interpreter.
+:numbers = constfun(Numbers_)

File src/main/kink/KinkVersion.kn

-#!/usr/bin/env kink
-# vim: et sw=4 sts=4
-
-# Copyright (c) 2013 Miyakawa Taku
-# 
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-:_read_version = {
-    use('Using.using')
-    use('org.kink_lang.kink.Value')
-    :String_ = using(Value.getClassLoader.getResourceAsStream('org/kink_lang/kink/version.txt')) {
-        \0.text.trim
-    }
-    :Numbers_ = (String_ / '.').map { \0.int }
-    [String_ Numbers_]
-}
-
-[:String_ :Numbers_] = _read_version
-
-# Version string of the interpreter.
-:version = constfun(String_)
-
-# Version numbers of the interpreter.
-:numbers = constfun(Numbers_)

File src/main/kink/LIST.kn

+#! kink
+# vim: et sw=4 sts=4
+
+# Copyright (c) 2013 Miyakawa Taku
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+## Zips lists
+:zip = { (* :Lists_)
+    Lists_.any?.then {
+        _min_count(Lists_).times.list.map { (:Index_) Lists_.map { \0.get(Index_) } }
+    } {
+        []
+    }
+}
+
+# Minimum count of lists
+:_min_count = { (:Lists_)
+    Lists_.map { \0.count } .min
+}
+
+## Unfold a list
+:unfold = { (:Init_ :Continue_pattern :_transform :_next)
+    :Result_ = []
+    :_loop.do(Init_) { (:Accum_)
+        (Accum_ =~ Continue_pattern).then {
+            Result_.push(_transform(Accum_))
+            _loop(_next(Accum_))
+        }
+    }
+    Result_
+}
+
+## Expand a list
+:extend = { (:_try_pop)
+    :List_ = []
+    :_loop.do {
+        _try_pop.switch(
+            [] {}
+            [:Elem_] {
+                List_.push(Elem_)
+                _loop
+            }
+        )
+    }
+    List_
+}

File src/main/kink/List.kn

-#! kink
-# vim: et sw=4 sts=4
-
-# Copyright (c) 2013 Miyakawa Taku
-# 
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-## Zips lists
-:zip = { (* :Lists_)
-    Lists_.any?.then {
-        _min_count(Lists_).times.list.map { (:Index_) Lists_.map { \0.get(Index_) } }
-    } {
-        []
-    }
-}
-
-# Minimum count of lists
-:_min_count = { (:Lists_)
-    Lists_.map { \0.count } .min
-}
-
-## Unfold a list
-:unfold = { (:Init_ :Continue_pattern :_transform :_next)
-    :Result_ = []
-    :_loop.do(Init_) { (:Accum_)
-        (Accum_ =~ Continue_pattern).then {
-            Result_.push(_transform(Accum_))
-            _loop(_next(Accum_))
-        }
-    }
-    Result_
-}
-
-## Expand a list
-:extend = { (:_try_pop)
-    :List_ = []
-    :_loop.do {
-        _try_pop.switch(
-            [] {}
-            [:Elem_] {
-                List_.push(Elem_)
-                _loop
-            }
-        )
-    }
-    List_
-}

File src/main/kink/MAP.kn

+#!/usr/bin/env kink
+# vim: et sw=4 sts=4
+
+# Copyright (c) 2013 Miyakawa Taku
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+use('java.util.concurrent.ConcurrentHashMap')
+use('java.lang.ThreadLocal')
+use('SCOPE_GUARD.scopeguarding')
+use('JAVA.null')
+use('META.meta')
+
+:map = { (* :Args_)
+    :Java_map = ConcurrentHashMap.new
+    Args_.unconcat(2).loop { ([:Key_ :Value_])
+        Java_map.put(meta(Key_) meta(Value_))
+    }
+    Map_proto.child(
+        'Java_map' Java_map
+        'Tl_showing' ThreadLocal.new
+    )
+}
+
+:_key_not_found = { (:Key_)
+    throw(expand('Key not found: #{Key_.show}'))
+}
+
+:Map_proto = value(
+    'Java_map' ConcurrentHashMap.new
+    'Tl_showing' ThreadLocal.new
+    'any?' { > :Map_ ()
+        !Map_.Java_map.isEmpty
+    }
+    'empty?' { > :Map_ ()
+        Map_.Java_map.isEmpty
+    }
+    'count' { > :Map_ () Map_.Java_map.size }
+    'get' { > :Map_ (:Key_ :_no_element = {_key_not_found(Key_)}  :_element_found = {\0} )
+        Map_.Java_map.get(meta(Key_)).switch(
+            (null) { _no_element }
+            :Value_ { _element_found( Value_.unmeta ) }
+        )
+    }
+    'haskey?' { > :Map_ (:Key_)
+        Map_.Java_map.containsKey(meta(Key_))
+    }
+    'has?' { > :Map_ (:Value_)
+        Map_.Java_map.values.contains(meta(Value_))
+    }
+    'set' { > :Map_ (:Key_ :Value_)
+        Map_.Java_map.put(meta(Key_) meta(Value_))
+        Map_
+    }
+    'setifabsent' { > :Map_ (:Key_ :Value_ :_not_set = {Map_} :_set = {Map_})
+        Map_.Java_map.putIfAbsent(meta(Key_) meta(Value_)).switch(
+            (null) { _set }
+            :Old_ { _not_set(Old_.unmeta) }
+        )
+    }
+    'setifpresent' { > :Map_ (:Key_ :Value_ :_not_set = {Map_} :_set = {Map_})
+        Map_.Java_map.replace(meta(Key_) meta(Value_)).switch(
+            (null) { _not_set }
+            :Old_ { _set(Old_.unmeta) }
+        )
+    }
+    'setifequal' { > :Map_ (:Key_ :Old_ :New_ :_not_set = {Map_} :_set = {Map_})
+        Map_.Java_map.replace(meta(Key_) meta(Old_) meta(New_)).then($_set $_not_set)
+    }
+    'pop' { > :Map_ (:Key_ :_not_popped = {_key_not_found(Key_)}  :_popped = {\0})
+        Map_.Java_map.remove(meta(Key_)).switch(
+            (null) { _not_popped }
+            :Value_ { _popped(Value_.unmeta) }
+        )
+    }
+    'append' { > :Map_ (:Another_ :_select = {\2})
+        Another_.pairs.loop { ([:Key_ :Value_])
+            :Put_ = Map_.Java_map.containsKey(meta(Key_)).then {
+                _select(Key_ Map_.Java_map.get(meta(Key_)).unmeta Value_)
+            } {
+                Value_
+            }
+            Map_.Java_map.put(meta(Key_) meta(Put_))
+        }
+        Map_
+    }
+    'op_add' { > :Map_ (:Another_)
+        Map_.clone.tee {
+            \0.append(Another_)
+        }
+    }
+    'clear' { > :Map_ ()
+        Map_.Java_map.clear
+        Map_
+    }
+    'clone' { > :Map_ ()
+        :Newmap_ = map
+        Map_.pairs.loop { ([:Key_ :Value_])
+            Newmap_.set(Key_ Value_)
+        }
+        Newmap_
+    }
+    'keyseq' { > :Map_ ()
+        Map_.Java_map.keySet.seq.map { \0.unmeta }
+    }
+    'keys' { > :Map_ ()
+        Map_.keyseq.list
+    }
+    'seq' { > :Map_ ()
+        Map_.Java_map.values.seq.map { \0.unmeta }
+    }
+    'list' { > :Map_ ()
+        Map_.seq.list
+    }
+    'pairseq' { > :Map_ ()
+        Map_.Java_map.entrySet.seq.map { [\0.getKey.unmeta \0.getValue.unmeta] }
+    }
+    'pairs' { > :Map_ ()
+        Map_.Java_map.entrySet.seq.map { [\0.getKey.unmeta \0.getValue.unmeta] } .list
+    }
+    'hash' { > :Map_ ()
+        Map_.pairs.fold(0) { \0 + \1.hash }
+    }
+    'op_eq' { > :Map_ (:Another_)
+        Another_.map??
+        && Map_.count == Another_.count
+        && Another_.pairs.all? { ([:Key_ :Value_])
+            Map_.haskey?(Key_) && Map_.get(Key_) == Value_
+        }
+    }
+    'show' { > :Map_ ()
+        Map_.Tl_showing.get.switch(
+            (null) {
+                scopeguarding { (:Scope_)
+                    Map_.Tl_showing.set(true)
+                    Scope_.onexit { Map_.Tl_showing.remove }
+                    :Contents_ = Map_.pairs.map { ([:Key_ :Value_])
+                        expand('#{Key_.show} #{Value_.show}')
+                    } .join('  ')
+                    expand('map(#Contents_)')
+                }
+            }
+            (any) {
+                'map(...)'
+            }
+        )
+    }
+    'map??' { true }
+)

File src/main/kink/Map.kn

-#!/usr/bin/env kink
-# vim: et sw=4 sts=4
-
-# Copyright (c) 2013 Miyakawa Taku
-# 
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-use('java.util.concurrent.ConcurrentHashMap')
-use('java.lang.ThreadLocal')
-use('ScopeGuard.scopeguarding')
-use('Java.null')
-use('Meta.meta')
-
-:map = { (* :Args_)
-    :Java_map = ConcurrentHashMap.new
-    Args_.unconcat(2).loop { ([:Key_ :Value_])
-        Java_map.put(meta(Key_) meta(Value_))
-    }
-    Map_proto.child(
-        'Java_map' Java_map
-        'Tl_showing' ThreadLocal.new
-    )
-}
-
-:_key_not_found = { (:Key_)
-    throw(expand('Key not found: #{Key_.show}'))
-}
-
-:Map_proto = value(
-    'Java_map' ConcurrentHashMap.new
-    'Tl_showing' ThreadLocal.new
-    'any?' { > :Map_ ()
-        !Map_.Java_map.isEmpty
-    }
-    'empty?' { > :Map_ ()
-        Map_.Java_map.isEmpty
-    }
-    'count' { > :Map_ () Map_.Java_map.size }
-    'get' { > :Map_ (:Key_ :_no_element = {_key_not_found(Key_)}  :_element_found = {\0} )
-        Map_.Java_map.get(meta(Key_)).switch(
-            (null) { _no_element }
-            :Value_ { _element_found( Value_.unmeta ) }
-        )
-    }
-    'haskey?' { > :Map_ (:Key_)
-        Map_.Java_map.containsKey(meta(Key_))
-    }
-    'has?' { > :Map_ (:Value_)
-        Map_.Java_map.values.contains(meta(Value_))
-    }
-    'set' { > :Map_ (:Key_ :Value_)
-        Map_.Java_map.put(meta(Key_) meta(Value_))
-        Map_
-    }
-    'setifabsent' { > :Map_ (:Key_ :Value_ :_not_set = {Map_} :_set = {Map_})
-        Map_.Java_map.putIfAbsent(meta(Key_) meta(Value_)).switch(
-            (null) { _set }
-            :Old_ { _not_set(Old_.unmeta) }
-        )
-    }
-    'setifpresent' { > :Map_ (:Key_ :Value_ :_not_set = {Map_} :_set = {Map_})
-        Map_.Java_map.replace(meta(Key_) meta(Value_)).switch(
-            (null) { _not_set }
-            :Old_ { _set(Old_.unmeta) }
-        )
-    }
-    'setifequal' { > :Map_ (:Key_ :Old_ :New_ :_not_set = {Map_} :_set = {Map_})
-        Map_.Java_map.replace(meta(Key_) meta(Old_) meta(New_)).then($_set $_not_set)
-    }
-    'pop' { > :Map_ (:Key_ :_not_popped = {_key_not_found(Key_)}  :_popped = {\0})
-        Map_.Java_map.remove(meta(Key_)).switch(
-            (null) { _not_popped }
-            :Value_ { _popped(Value_.unmeta) }
-        )
-    }
-    'append' { > :Map_ (:Another_ :_select = {\2})
-        Another_.pairs.loop { ([:Key_ :Value_])
-            :Put_ = Map_.Java_map.containsKey(meta(Key_)).then {
-                _select(Key_ Map_.Java_map.get(meta(Key_)).unmeta Value_)
-            } {
-                Value_
-            }
-            Map_.Java_map.put(meta(Key_) meta(Put_))
-        }
-        Map_
-    }
-    'op_add' { > :Map_ (:Another_)
-        Map_.clone.tee {
-            \0.append(Another_)
-        }
-    }
-    'clear' { > :Map_ ()
-        Map_.Java_map.clear
-        Map_
-    }
-    'clone' { > :Map_ ()
-        :Newmap_ = map
-        Map_.pairs.loop { ([:Key_ :Value_])
-            Newmap_.set(Key_ Value_)
-        }
-        Newmap_
-    }
-    'keyseq' { > :Map_ ()
-        Map_.Java_map.keySet.seq.map { \0.unmeta }
-    }
-    'keys' { > :Map_ ()
-        Map_.keyseq.list
-    }
-    'seq' { > :Map_ ()
-        Map_.Java_map.values.seq.map { \0.unmeta }
-    }
-    'list' { > :Map_ ()
-        Map_.seq.list
-    }
-    'pairseq' { > :Map_ ()
-        Map_.Java_map.entrySet.seq.map { [\0.getKey.unmeta \0.getValue.unmeta] }
-    }
-    'pairs' { > :Map_ ()
-        Map_.Java_map.entrySet.seq.map { [\0.getKey.unmeta \0.getValue.unmeta] } .list
-    }
-    'hash' { > :Map_ ()
-        Map_.pairs.fold(0) { \0 + \1.hash }
-    }
-    'op_eq' { > :Map_ (:Another_)
-        Another_.map??
-        && Map_.count == Another_.count
-        && Another_.pairs.all? { ([:Key_ :Value_])
-            Map_.haskey?(Key_) && Map_.get(Key_) == Value_
-        }
-    }
-    'show' { > :Map_ ()
-        Map_.Tl_showing.get.switch(
-            (null) {
-                scopeguarding { (:Scope_)
-                    Map_.Tl_showing.set(true)
-                    Scope_.onexit { Map_.Tl_showing.remove }
-                    :Contents_ = Map_.pairs.map { ([:Key_ :Value_])
-                        expand('#{Key_.show} #{Value_.show}')
-                    } .join('  ')
-                    expand('map(#Contents_)')
-                }
-            }
-            (any) {
-                'map(...)'
-            }
-        )
-    }
-    'map??' { true }
-)

File src/main/kink/PARSE_COMMAND.kn

+#!/usr/bin/env kink
+# vim: et sw=4 sts=4
+
+# Copyright (c) 2013 Miyakawa Taku
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# New parser
+:parser = { ()
+    Parser_proto.child(
+        '_strictorder?' constfun(false)
+        '_options' constfun([])
+        '_handleerror' {}
+    )
+}
+
+# No-argument option
+:_noarg = { (:handle)
+    value(
+        'handle_long_with_eq' { (:Parser_ :Name_ :Arg_)
+            Parser_._raise(expand('#Name_ takes no arguments'))
+        }
+        'handle_long_without_eq' { > :Option_ (:Parser_ :First_ :Command_)
+            handle
+        }
+        'handle_short' { > :Option_ (:Parser_ :Name_ :Chars_ :Command_)
+            handle
+        }
+    )
+}
+
+# Require-argument option
+:_reqarg = { (:handle)
+    value(
+        'handle_long_with_eq' { > :Option_ (:Parser_ :Name_ :Arg_)
+            handle(Arg_)
+        }
+        'handle_long_without_eq' { > :Option_ (:Parser_ :Name_ :Command_)
+            (! Command_.any?).then {
+                Parser_._raise(expand('#Name_ takes an argument'))
+            }
+            :Arg_ = Command_.pop(0)
+            handle(Arg_)
+        }
+        'handle_short' { > :Option_ (:Parser_ :Name_ :Chars_ :Command_)
+            switch(
+                { Chars_.any? } { handle(Chars_.join) }
+                { Command_.any? } { handle(Command_.pop(0)) }
+                (any) { Parser_._raise(expand('#Name_ takes an argument')) }
+            )
+            Chars_.clear
+        }
+    )
+}
+
+# Optional-argument option
+:_optarg = { (:handle)
+    value(
+        'handle_long_with_eq' { > :Option_ (:Parser_ :Name_ :Arg_)
+            handle(Arg_)
+        }
+        'handle_long_without_eq' { > :Option_ (:Parser_ :Name_ :Command_)
+            handle
+        }
+        'handle_short' { > :Option_ (:Parser_ :Name_ :Chars_ :Command_)
+            handle(*** Chars_.any?.then { [Chars_.join] } { [] })
+            Chars_.clear
+        }
+    )
+}
+
+# Returns a pattern which matches to the pair whoes name is exactly Name_
+:_exact_name = { (:Name_)
+    { ([:N_ any]) N_ == Name_ }
+}
+
+# Returns a pattern which matches to the pair whoes name starts with Start_
+:_part_name = { (:Start_)
+    { ([:N_ any]) N_.startswith?(Start_) }
+}
+
+# Prototype of parsers
+:Parser_proto = value(
+    'strictorder' { > :Parser_ ()
+        Parser_.:_strictorder? = constfun(true)
+        Parser_
+    }
+    'onerror' { > :Parser_ (:_handleerror)
+        Parser_.:_handleerror = $_handleerror
+        Parser_
+    }
+    'noarg' { > :Parser_ (* :Args_)
+        Parser_._addoption(Args_ $_noarg)
+        Parser_
+    }
+    'reqarg' { > :Parser_ (* :Args_)
+        Parser_._addoption(Args_ $_reqarg)
+        Parser_
+    }
+    'optarg' { > :Parser_ (* :Args_)
+        Parser_._addoption(Args_ $_optarg)
+        Parser_
+    }
+
+    # Handles an error message
+    '_handleerror' {}
+
+    # Raises error
+    '_raise' { > :Parser_ (:Message_)
+        Parser_._handleerror(Message_)
+        throw(Message_)
+    }
+
+    # True if the parse is strictorder
+    '_strictorder?' constfun(false)
+
+    # Options
+    '_options' constfun([])
+
+    # Adds an option to the configuration
+    '_addoption' { > :Parser_ (:Args_ :newoption)
+        :handle = Args_.last
+        :Option_ = newoption($handle)
+        Args_.droptail(1).loop { (:Name_)
+            Parser_._options.push([Name_ Option_])
+        }
+    }
+
+    # Parses the command line list with the configuration
+    'parse' { > :Parser_ (:Command_)
+        :Command_clone = Command_.clone
+        :Result_ = []
+        { Command_clone.any? }.loop {
+            Parser_._process_first(Command_clone Result_)
+        }
+        Result_
+    }
+
+    # Processes the first chunk of the command line list
+    '_process_first' { > :Parser_ (:Command_ :Result_)
+        :First_ = Command_.pop(0)
+        First_.switch(
+            '--' {
+                Result_.append(Command_)
+                Command_.clear
+            }
+            { First_.startswith?('--') && First_.any?('=') } {
+                :Eq_index = First_.index('=')
+                :Name_ = First_.head(Eq_index)
+                :Arg_ = First_.drophead(Eq_index + 1)
+                :Option_ = Parser_._find_long(Name_)
+                Option_.handle_long_with_eq(Parser_ Name_ Arg_)
+            }
+            { First_.startswith?('--') } {
+                :Option_ = Parser_._find_long(First_)
+                Option_.handle_long_without_eq(Parser_ First_ Command_)
+            }
+            { First_.startswith?('-') && First_ != '-' } {
+                Parser_._parse_short(First_.drophead(1).list Command_)