diff graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/HashNodes.java @ 13529:856c2c294f84

Merge.
author Christian Humer <christian.humer@gmail.com>
date Tue, 07 Jan 2014 18:53:04 +0100
parents 0fbee3eb71f0
children f70c894ae874
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/HashNodes.java	Tue Jan 07 18:53:04 2014 +0100
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.core;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.core.*;
+import com.oracle.truffle.ruby.runtime.core.array.*;
+
+@CoreClass(name = "Hash")
+public abstract class HashNodes {
+
+    @CoreMethod(names = "[]", isModuleMethod = true, needsSelf = false, isSplatted = true)
+    public abstract static class ConstructNode extends CoreMethodNode {
+
+        public ConstructNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ConstructNode(ConstructNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyHash construct(Object[] args) {
+            final RubyHash hash = new RubyHash(getContext().getCoreLibrary().getHashClass());
+
+            if (args.length == 1) {
+                final RubyArray array = (RubyArray) args[0];
+
+                for (int n = 0; n < array.size(); n++) {
+                    final RubyArray keyValue = (RubyArray) array.get(n);
+                    hash.put(keyValue.get(0), keyValue.get(1));
+                }
+            } else {
+                assert args.length % 2 == 0;
+
+                for (int n = 0; n < args.length; n += 2) {
+                    hash.put(args[n], args[n + 1]);
+                }
+            }
+
+            return hash;
+        }
+
+    }
+
+    @CoreMethod(names = "[]", minArgs = 1, maxArgs = 1)
+    public abstract static class GetIndexNode extends CoreMethodNode {
+
+        public GetIndexNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public GetIndexNode(GetIndexNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public Object construct(VirtualFrame frame, RubyHash hash, Object index) {
+            final Object value = hash.get(index);
+
+            if (value == null) {
+                if (hash.defaultBlock == null) {
+                    return NilPlaceholder.INSTANCE;
+                } else {
+                    return hash.defaultBlock.call(frame.pack(), hash, index);
+                }
+            } else {
+                return value;
+            }
+        }
+
+    }
+
+    @CoreMethod(names = "[]=", minArgs = 2, maxArgs = 2)
+    public abstract static class SetIndexNode extends CoreMethodNode {
+
+        public SetIndexNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public SetIndexNode(SetIndexNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public Object construct(RubyHash hash, Object index, Object value) {
+            hash.put(index, value);
+            return value;
+        }
+
+    }
+
+    @CoreMethod(names = "delete", minArgs = 1, maxArgs = 1)
+    public abstract static class DeleteNode extends CoreMethodNode {
+
+        public DeleteNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public DeleteNode(DeleteNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public Object delete(RubyHash hash, Object index) {
+            hash.checkFrozen();
+
+            final Object value = hash.getMap().remove(index);
+
+            if (value == null) {
+                return NilPlaceholder.INSTANCE;
+            } else {
+                return value;
+            }
+        }
+
+    }
+
+    @CoreMethod(names = "each", needsBlock = true, maxArgs = 0)
+    public abstract static class EachNode extends YieldingCoreMethodNode {
+
+        public EachNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public EachNode(EachNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public NilPlaceholder each(VirtualFrame frame, RubyHash hash, RubyProc block) {
+            for (Map.Entry<Object, Object> entry : hash.storage.entrySet()) {
+                yield(frame, block, entry.getKey(), entry.getValue());
+            }
+
+            return NilPlaceholder.INSTANCE;
+        }
+
+    }
+
+    @CoreMethod(names = "empty?", maxArgs = 0)
+    public abstract static class EmptyNode extends CoreMethodNode {
+
+        public EmptyNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public EmptyNode(EmptyNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public boolean empty(RubyHash hash) {
+            return hash.storage.isEmpty();
+        }
+
+    }
+
+    @CoreMethod(names = "initialize", needsBlock = true, maxArgs = 0)
+    public abstract static class InitializeNode extends CoreMethodNode {
+
+        public InitializeNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public InitializeNode(InitializeNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public NilPlaceholder initialize(RubyHash hash, @SuppressWarnings("unused") UndefinedPlaceholder block) {
+            hash.initialize(null);
+            return NilPlaceholder.INSTANCE;
+        }
+
+        @Specialization
+        public NilPlaceholder initialize(RubyHash hash, RubyProc block) {
+            hash.initialize(block);
+            return NilPlaceholder.INSTANCE;
+        }
+
+    }
+
+    @CoreMethod(names = {"map", "collect"}, needsBlock = true, maxArgs = 0)
+    public abstract static class MapNode extends YieldingCoreMethodNode {
+
+        public MapNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public MapNode(MapNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyArray map(VirtualFrame frame, RubyHash hash, RubyProc block) {
+            final RubyArray result = new RubyArray(getContext().getCoreLibrary().getArrayClass());
+
+            for (Map.Entry<Object, Object> entry : hash.storage.entrySet()) {
+                result.push(yield(frame, block, entry.getKey(), entry.getValue()));
+            }
+
+            return result;
+        }
+
+    }
+
+    @CoreMethod(names = "key?", minArgs = 1, maxArgs = 1)
+    public abstract static class KeyNode extends CoreMethodNode {
+
+        public KeyNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public KeyNode(KeyNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public boolean key(RubyHash hash, Object key) {
+            return hash.storage.containsKey(key);
+        }
+
+    }
+
+    @CoreMethod(names = "keys", maxArgs = 0)
+    public abstract static class KeysNode extends CoreMethodNode {
+
+        public KeysNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public KeysNode(KeysNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyArray keys(RubyHash hash) {
+            final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass());
+
+            for (Object key : hash.storage.keySet()) {
+                array.push(key);
+            }
+
+            return array;
+        }
+
+    }
+
+    @CoreMethod(names = "size", maxArgs = 0)
+    public abstract static class SizeNode extends CoreMethodNode {
+
+        public SizeNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public SizeNode(SizeNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public int size(RubyHash hash) {
+            return hash.storage.size();
+        }
+
+    }
+
+    @CoreMethod(names = "values", maxArgs = 0)
+    public abstract static class ValuesNode extends CoreMethodNode {
+
+        public ValuesNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ValuesNode(ValuesNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyArray values(RubyHash hash) {
+            final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass());
+
+            for (Object value : hash.storage.values()) {
+                array.push(value);
+            }
+
+            return array;
+        }
+
+    }
+
+}