Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a698e782b375
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1a43d1836db9
Choose a head ref
  • 10 commits
  • 20 files changed
  • 1 contributor

Commits on Dec 24, 2016

  1. Copy the full SHA
    8a10fc4 View commit details
  2. Copy the full SHA
    b2e5106 View commit details
  3. Copy the full SHA
    27da7b1 View commit details
  4. Copy the full SHA
    15e535c View commit details
  5. 2
    Copy the full SHA
    40f44c6 View commit details
  6. Copy the full SHA
    9fdc073 View commit details
  7. Copy the full SHA
    98d3f94 View commit details
  8. 2
    Copy the full SHA
    ce49572 View commit details
  9. Copy the full SHA
    6cba7f5 View commit details
  10. Copy the full SHA
    1a43d18 View commit details
Showing with 271 additions and 2,063 deletions.
  1. +86 −12 truffle/src/main/java/org/jruby/truffle/parser/TranslatorDriver.java
  2. +0 −64 truffle/src/main/java/org/jruby/truffle/parser/lexer/ByteListLexerSource.java
  3. +0 −82 truffle/src/main/java/org/jruby/truffle/parser/lexer/GetsLexerSource.java
  4. +0 −232 truffle/src/main/java/org/jruby/truffle/parser/lexer/KeywordMatch.java
  5. +44 −17 truffle/src/main/java/org/jruby/truffle/parser/lexer/LexerSource.java
  6. +0 −12 truffle/src/main/java/org/jruby/truffle/parser/lexer/LexingCommon.java
  7. +1 −2 truffle/src/main/java/org/jruby/truffle/parser/lexer/SyntaxException.java
  8. +0 −151 truffle/src/main/java/org/jruby/truffle/parser/parser/Parser.java
  9. +2 −10 truffle/src/main/java/org/jruby/truffle/parser/parser/ParserConfiguration.java
  10. +2 −3 truffle/src/main/java/org/jruby/truffle/parser/parser/ParserSupport.java
  11. +0 −62 truffle/src/main/java/org/jruby/truffle/parser/scope/DummyDynamicScope.java
  12. +134 −200 truffle/src/main/java/org/jruby/truffle/parser/scope/DynamicScope.java
  13. +0 −182 truffle/src/main/java/org/jruby/truffle/parser/scope/FourVarDynamicScope.java
  14. +0 −299 truffle/src/main/java/org/jruby/truffle/parser/scope/ManyVarsDynamicScope.java
  15. +0 −151 truffle/src/main/java/org/jruby/truffle/parser/scope/NoVarsDynamicScope.java
  16. +0 −132 truffle/src/main/java/org/jruby/truffle/parser/scope/OneVarDynamicScope.java
  17. +2 −68 truffle/src/main/java/org/jruby/truffle/parser/scope/StaticScope.java
  18. +0 −59 truffle/src/main/java/org/jruby/truffle/parser/scope/StaticScopeFactory.java
  19. +0 −173 truffle/src/main/java/org/jruby/truffle/parser/scope/ThreeVarDynamicScope.java
  20. +0 −152 truffle/src/main/java/org/jruby/truffle/parser/scope/TwoVarDynamicScope.java
Original file line number Diff line number Diff line change
@@ -6,6 +6,33 @@
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
* Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
* Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
* Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
*/
package org.jruby.truffle.parser;

@@ -22,6 +49,7 @@
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.LoadRequiredLibrariesNode;
import org.jruby.truffle.core.SetTopLevelBindingNode;
import org.jruby.truffle.core.string.ByteList;
import org.jruby.truffle.language.DataNode;
import org.jruby.truffle.language.LexicalScope;
import org.jruby.truffle.language.RubyNode;
@@ -30,6 +58,7 @@
import org.jruby.truffle.language.arguments.ProfileArgumentNode;
import org.jruby.truffle.language.arguments.ReadPreArgumentNode;
import org.jruby.truffle.language.arguments.RubyArguments;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.exceptions.TopLevelRaiseHandler;
import org.jruby.truffle.language.locals.WriteLocalVariableNode;
import org.jruby.truffle.language.methods.Arity;
@@ -41,32 +70,32 @@
import org.jruby.truffle.language.methods.SharedMethodInfo;
import org.jruby.truffle.language.methods.UnsupportedOperationBehavior;
import org.jruby.truffle.parser.ast.RootParseNode;
import org.jruby.truffle.parser.lexer.LexerSource;
import org.jruby.truffle.parser.lexer.SyntaxException;
import org.jruby.truffle.parser.parser.ParserConfiguration;
import org.jruby.truffle.parser.parser.RubyParser;
import org.jruby.truffle.parser.parser.RubyParserResult;
import org.jruby.truffle.parser.scope.DynamicScope;
import org.jruby.truffle.parser.scope.ManyVarsDynamicScope;
import org.jruby.truffle.parser.scope.StaticScope;
import org.jruby.truffle.parser.scope.StaticScopeFactory;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class TranslatorDriver {

private final RubyContext context;
private final ParseEnvironment parseEnvironment;

public TranslatorDriver(RubyContext context) {
this.context = context;
parseEnvironment = new ParseEnvironment(context);
}

public RubyRootNode parse(RubyContext context, Source source, Encoding defaultEncoding, ParserContext parserContext, String[] argumentNames, FrameDescriptor frameDescriptor, MaterializedFrame parentFrame, boolean ownScopeForAssignments, Node currentNode) {
// Set up the JRuby parser

final org.jruby.truffle.parser.parser.Parser parser = new org.jruby.truffle.parser.parser.Parser(context);

final StaticScopeFactory staticScopeFactory = new StaticScopeFactory();
final StaticScope staticScope = staticScopeFactory.newLocalScope(null);
final StaticScope staticScope = new StaticScope(StaticScope.Type.LOCAL, null);

/*
* Note that jruby-parser will be mistaken about how deep the existing variables are,
@@ -110,7 +139,7 @@ public RubyRootNode parse(RubyContext context, Source source, Encoding defaultEn
}
}

final DynamicScope dynamicScope = new ManyVarsDynamicScope(staticScope);
final DynamicScope ManyVarsDynamicScope = new DynamicScope(staticScope);

boolean isInlineSource = parserContext == ParserContext.SHELL;
boolean isEvalParse = parserContext == ParserContext.EVAL || parserContext == ParserContext.INLINE || parserContext == ParserContext.MODULE;
@@ -124,9 +153,7 @@ public RubyRootNode parse(RubyContext context, Source source, Encoding defaultEn

// Parse to the JRuby AST

RootParseNode node;

node = (RootParseNode) parser.parse(source.getName(), source.getCode().getBytes(StandardCharsets.UTF_8), dynamicScope, parserConfiguration);
RootParseNode node = parse(source.getName(), source.getCode().getBytes(StandardCharsets.UTF_8), ManyVarsDynamicScope, parserConfiguration);

final SourceSection sourceSection = source.createSection(0, source.getCode().length());
final TempSourceSection tempSourceSection = new TempSourceSection(sourceSection);
@@ -234,6 +261,53 @@ public RubyRootNode parse(RubyContext context, Source source, Encoding defaultEn
return new RubyRootNode(context, truffleNode.getRubySourceSection().toSourceSection(source), environment.getFrameDescriptor(), sharedMethodInfo, truffleNode, environment.needsDeclarationFrame());
}

public RootParseNode parse(String file, byte[] content, DynamicScope blockScope,
ParserConfiguration configuration) {
List<ByteList> list = null;
ByteList in = new ByteList(content, configuration.getDefaultEncoding());
LexerSource ByteListLexerSource = new LexerSource(file, configuration.getLineNumber(), in, list);
// We only need to pass in current scope if we are evaluating as a block (which
// is only done for evals). We need to pass this in so that we can appropriately scope
// down to captured scopes when we are parsing.
if (blockScope != null) {
configuration.parseAsBlock(blockScope);
}

RubyParser parser = new RubyParser(context, ByteListLexerSource, new RubyWarnings(configuration.getContext()));
RubyParserResult result;
try {
result = parser.parse(configuration);
} catch (IOException e) {
// Enebo: We may want to change this error to be more specific,
// but I am not sure which conditions leads to this...so lame message.
throw new RaiseException(context.getCoreExceptions().syntaxError("Problem reading source: " + e, null));
} catch (SyntaxException e) {
switch (e.getPid()) {
case UNKNOWN_ENCODING:
case NOT_ASCII_COMPATIBLE:
throw new RaiseException(context.getCoreExceptions().argumentError(e.getMessage(), null));
default:
StringBuilder buffer = new StringBuilder(100);
buffer.append(e.getFile()).append(':');
buffer.append(e.getLine() + 1).append(": ");
buffer.append(e.getMessage());

throw new RaiseException(context.getCoreExceptions().syntaxError(buffer.toString(), null));
}
}

// If variables were added then we may need to grow the dynamic scope to match the static
// one.
// FIXME: Make this so we only need to check this for blockScope != null. We cannot
// currently since we create the ManyVarsDynamicScope for a LocalStaticScope before parse begins.
// Refactoring should make this fixable.
if (result.getScope() != null) {
result.getScope().growIfNeeded();
}

return (RootParseNode) result.getAST();
}

private TranslatorEnvironment environmentForFrameDescriptor(RubyContext context, FrameDescriptor frameDescriptor) {
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(
context.getCoreLibrary().getSourceSection(),

This file was deleted.

This file was deleted.

232 changes: 0 additions & 232 deletions truffle/src/main/java/org/jruby/truffle/parser/lexer/KeywordMatch.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -37,9 +37,9 @@
import java.util.List;

/**
* Simple source capable of providing the next line in Ruby source file being lex'd.
* Lexer source for ripper when we have all bytes available to us.
*/
public abstract class LexerSource {
public class LexerSource {
// The name of this source (e.g. a filename: foo.rb)
private final String name; // mri: parser_ruby_sourcefile

@@ -48,16 +48,50 @@ public abstract class LexerSource {

protected List<ByteList> scriptLines;

public LexerSource(String sourceName, int lineOffset, List<ByteList> scriptLines) {
this.name = sourceName;
this.lineOffset = lineOffset;
this.scriptLines = scriptLines;
}
private ByteList completeSource; // The entire source of the file
private int offset = 0; // Offset into source overall (mri: lex_gets_ptr)

/**
* What file are we lexing?
* @return the files name
* Create our food-source for the lexer.
*
* @param sourceName is the file we are reading
* @param line starting line number for source (used by eval)
* @param in the ByteList backing the source we want to lex
*/
public LexerSource(String sourceName, int line, ByteList in, List<ByteList> list) {
this.name = sourceName;
this.lineOffset = line;
this.scriptLines = list;
this.completeSource = in;
}

public Encoding getEncoding() {
return completeSource.getEncoding();
}

public void setEncoding(Encoding encoding) {
completeSource.setEncoding(encoding);
encodeExistingScriptLines(encoding);
}

public ByteList gets() {
int length = completeSource.length();
if (offset >= length) return null; // At end of source/eof

int end = completeSource.indexOf('\n', offset) + 1;
if (end == 0) end = length;

ByteList line = completeSource.makeShared(offset, end - offset);
offset = end;

if (scriptLines != null) scriptLines.add(line);

return line;
}

public int getOffset() {
return offset;
}
public String getFilename() {
return name;
}
@@ -77,11 +111,4 @@ public void encodeExistingScriptLines(Encoding encoding) {
}
}

public abstract Encoding getEncoding();

public abstract void setEncoding(Encoding encoding);

public abstract ByteList gets();

public abstract int getOffset();
}
}
Original file line number Diff line number Diff line change
@@ -265,10 +265,6 @@ public void lex_goto_eol() {
lex_p = lex_pend;
}

public int lineno() {
return ruby_sourceline + src.getLineOffset();
}

protected void magicCommentEncoding(ByteList encoding) {
if (!comment_at_top()) return;

@@ -362,14 +358,6 @@ public int precise_mbclen() {
return current_enc.length(data, begin + lex_p - 1, begin + lex_pend);
}

public void printState() {
if (lex_state == 0) {
System.out.println("NULL");
} else {
System.out.println(lex_state);
}
}

public void pushback(int c) {
if (c == -1) return;

Original file line number Diff line number Diff line change
@@ -81,9 +81,8 @@ public String getID() {
private int line;
private PID pid;

public SyntaxException(PID pid, String file, int line, String lastLine, String message, Object... data) {
public SyntaxException(PID pid, String file, int line, String lastLine, String message) {
super(prepareMessage(message, lastLine));

this.pid = pid;
this.file = file;
this.line = line;
151 changes: 0 additions & 151 deletions truffle/src/main/java/org/jruby/truffle/parser/parser/Parser.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -34,8 +34,7 @@
import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.parser.scope.DynamicScope;
import org.jruby.truffle.parser.scope.ManyVarsDynamicScope;
import org.jruby.truffle.parser.scope.StaticScopeFactory;
import org.jruby.truffle.parser.scope.StaticScope;

public class ParserConfiguration {
private DynamicScope existingScope = null;
@@ -56,15 +55,12 @@ public class ParserConfiguration {
private Encoding defaultEncoding;
private RubyContext context;

private final StaticScopeFactory staticScopeFactory;

public ParserConfiguration(RubyContext context, int lineNumber, boolean inlineSource, boolean isFileParse, boolean saveData) {
this.context = context;
this.inlineSource = inlineSource;
this.lineNumber = lineNumber;
this.isEvalParse = !isFileParse;
this.saveData = saveData;
staticScopeFactory = new StaticScopeFactory();
}

public void setFrozenStringLiteral(boolean frozenStringLiteral) {
@@ -133,7 +129,7 @@ public DynamicScope getScope(String file) {
// will always happen because of $~ and $_).
// FIXME: Because we end up adjusting this after-the-fact, we can't use
// any of the specific-size scopes.
return new ManyVarsDynamicScope(staticScopeFactory.newLocalScope(null, file), existingScope);
return new DynamicScope(new StaticScope(StaticScope.Type.LOCAL, (StaticScope) null, file), existingScope);
}

public boolean isCoverageEnabled() {
@@ -155,8 +151,4 @@ public boolean isSaveData() {
public boolean isInlineSource() {
return inlineSource;
}

public StaticScopeFactory getStaticScopeFactory() {
return staticScopeFactory;
}
}
Original file line number Diff line number Diff line change
@@ -40,7 +40,6 @@
import org.jruby.truffle.core.regexp.ClassicRegexp;
import org.jruby.truffle.core.regexp.RegexpOptions;
import org.jruby.truffle.core.rope.CodeRange;
import org.jruby.truffle.core.rope.RopeOperations;
import org.jruby.truffle.core.string.ByteList;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.core.string.StringSupport;
@@ -197,11 +196,11 @@ public void popCurrentScope() {
}

public void pushBlockScope() {
currentScope = configuration.getStaticScopeFactory().newBlockScope(currentScope, lexer.getFile());
currentScope = new StaticScope(StaticScope.Type.BLOCK, currentScope, lexer.getFile());
}

public void pushLocalScope() {
currentScope = configuration.getStaticScopeFactory().newLocalScope(currentScope, lexer.getFile());
currentScope = new StaticScope(StaticScope.Type.LOCAL, currentScope, lexer.getFile());
currentScope.setCommandArgumentStack(lexer.getCmdArgumentState().getStack());
lexer.getCmdArgumentState().reset(0);
}

This file was deleted.

334 changes: 134 additions & 200 deletions truffle/src/main/java/org/jruby/truffle/parser/scope/DynamicScope.java
Original file line number Diff line number Diff line change
@@ -24,10 +24,25 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/

package org.jruby.truffle.parser.scope;

public abstract class DynamicScope {
/**
* Represents the the dynamic portion of scoping information. The variableValues are the
* values of assigned local or block variables. The staticScope identifies which sort of
* scope this is (block or local).
*
* Properties of Dynamic Scopes:
* 1. static and dynamic scopes have the same number of names to values
* 2. size of variables (and thus names) is determined during parsing. So those structured do
* not need to change
*
* FIXME: When creating dynamic scopes we sometimes accidentally pass in extra parents. This
* is harmless (other than wasting memory), but we should not do that. We can fix this in two
* ways:
* 1. Fix all callers
* 2. Check parent that is passed in and make if new instance is local, then its parent is not local
*/
public class DynamicScope {
// Static scoping information for this scope
protected final StaticScope staticScope;

@@ -36,30 +51,19 @@ public abstract class DynamicScope {

private boolean lambda;

protected DynamicScope(StaticScope staticScope, DynamicScope parent) {
// Our values holder (name of variables are kept in staticScope)
private Object[] variableValues;

public DynamicScope(StaticScope staticScope, DynamicScope parent) {
this.staticScope = staticScope;
this.parent = parent;
allocate();
}

protected DynamicScope(StaticScope staticScope) {
this(staticScope, null);
}

public static DynamicScope newDynamicScope(StaticScope staticScope, DynamicScope parent) {
switch (staticScope.getNumberOfVariables()) {
case 0:
return new NoVarsDynamicScope(staticScope, parent);
case 1:
return new OneVarDynamicScope(staticScope, parent);
case 2:
return new TwoVarDynamicScope(staticScope, parent);
case 3:
return new ThreeVarDynamicScope(staticScope, parent);
case 4:
return new FourVarDynamicScope(staticScope, parent);
default:
return new ManyVarsDynamicScope(staticScope, parent);
}
public DynamicScope(StaticScope staticScope) {
this.staticScope = staticScope;
this.parent = null;
allocate();
}

/**
@@ -77,113 +81,14 @@ public DynamicScope getNextCapturedScope() { // Used by ruby-debug-ide
}

/**
* Returns the n-th parent scope of this scope.
* May return <code>null</code>.
* @param n - number of levels above to look.
* @return The n-th parent scope or <code>null</code>.
*/
public DynamicScope getNthParentScope(int n) {
DynamicScope scope = this;
for (int i = 0; i < n; i++) {
if (scope == null) break;
scope = scope.getParentScope();
}
return scope;
}

public static DynamicScope newDynamicScope(StaticScope staticScope) {
return newDynamicScope(staticScope, null);
}

/**
* Find the scope to use for flip-flops. Flip-flops live either in the
* topmost "method scope" or in their nearest containing "eval scope".
*
* @return The scope to use for flip-flops
*/
public DynamicScope getFlipScope() {
if (staticScope.getLocalScope() == staticScope) {
return this;
} else {
return parent.getFlipScope();
}
}

/**
* Get the static scope associated with this DynamicScope.
* Get the static scope associated with this ManyVarsDynamicScope.
*
* @return static complement to this scope
*/
public final StaticScope getStaticScope() {
return staticScope;
}

/**
* Get all variable names captured (visible) by this scope (sans $~ and $_).
*
* @return a list of variable names
*/
public final String[] getAllNamesInScope() {
return staticScope.getAllNamesInScope();
}

public abstract void growIfNeeded();

public abstract DynamicScope cloneScope();

public abstract Object[] getValues();

/**
* Get value from current scope or one of its captured scopes.
*
* FIXME: block variables are not getting primed to nil so we need to null check those
* until we prime them properly. Also add assert back in.
*
* @param offset zero-indexed value that represents where variable lives
* @param depth how many captured scopes down this variable should be set
* @return the value here
*/
public abstract Object getValue(int offset, int depth);

/**
* Variation of getValue that checks for nulls, returning and setting the given value (presumably nil)
*/
public abstract Object getValueOrNil(int offset, int depth, Object nil);

/**
* getValueOrNil for depth 0
*/
public abstract Object getValueDepthZeroOrNil(int offset, Object nil);

/**
* getValueOrNil for index 0, depth 0
*/
public abstract Object getValueZeroDepthZeroOrNil(Object nil);

/**
* getValueOrNil for index 1, depth 0
*/
public abstract Object getValueOneDepthZeroOrNil(Object nil);

/**
* getValueOrNil for index 2, depth 0
*/
public abstract Object getValueTwoDepthZeroOrNil(Object nil);

/**
* getValueOrNil for index 3, depth 0
*/
public abstract Object getValueThreeDepthZeroOrNil(Object nil);

/**
* Set value in current dynamic scope or one of its captured scopes.
*
* @param offset zero-indexed value that represents where variable lives
* @param value to set
* @param depth how many captured scopes down this variable should be set
*/
public abstract Object setValue(int offset, Object value, int depth);

/**
* Set value in current dynamic scope or one of its captured scopes.
*
@@ -195,83 +100,6 @@ public Object setValue(Object value, int offset, int depth) {
return setValue(offset, value, depth);
}

/**
* Set value in current dynamic scope or one of its captured scopes.
*
* @param offset zero-indexed value that represents where variable lives
* @param value to set
* @param depth how many captured scopes down this variable should be set
*/
public void setValueVoid(Object value, int offset, int depth) {
setValue(offset, value, depth);
}

/**
* setValue for depth zero
*
* @param value to set
* @param offset zero-indexed value that represents where variable lives
*/
public abstract Object setValueDepthZero(Object value, int offset);

/**
* setValue for depth zero
*
* @param value to set
* @param offset zero-indexed value that represents where variable lives
*/
public void setValueDepthZeroVoid(Object value, int offset) {
setValueDepthZero(value, offset);
}

/**
* Set value zero in this scope;
*/
public abstract Object setValueZeroDepthZero(Object value);

/**
* Set value zero in this scope;
*/
public void setValueZeroDepthZeroVoid(Object value) {
setValueZeroDepthZero(value);
}

/**
* Set value one in this scope.
*/
public abstract Object setValueOneDepthZero(Object value);

/**
* Set value one in this scope.
*/
public void setValueOneDepthZeroVoid(Object value) {
setValueOneDepthZero(value);
}

/**
* Set value two in this scope.
*/
public abstract Object setValueTwoDepthZero(Object value);

/**
* Set value two in this scope.
*/
public void setValueTwoDepthZeroVoid(Object value) {
setValueTwoDepthZero(value);
}

/**
* Set value three in this scope.
*/
public abstract Object setValueThreeDepthZero(Object value);

/**
* Set value three in this scope.
*/
public void setValueThreeDepthZeroVoid(Object value) {
setValueThreeDepthZero(value);
}

@Override
public String toString() {
return toString(new StringBuffer(), "");
@@ -300,7 +128,7 @@ public String toString(StringBuffer buf, String indent) {
buf.append(names[size-1]).append("=");

assert variableValues.length == names.length : "V: " + variableValues.length +
" != N: " + names.length + " for " + buf;
" != N: " + names.length + " for " + buf;

if (variableValues[size-1] == null) {
buf.append("null");
@@ -326,4 +154,110 @@ public void setLambda(boolean lambda) {
public boolean isLambda() {
return lambda;
}

private void allocate() {
if(variableValues == null) {
int size = staticScope.getNumberOfVariables();
variableValues = new Object[size];
}
}

public Object[] getValues() {
return variableValues;
}

/**
* Get value from current scope or one of its captured scopes.
*
* FIXME: block variables are not getting primed to nil so we need to null check those
* until we prime them properly. Also add assert back in.
*
* @param offset zero-indexed value that represents where variable lives
* @param depth how many captured scopes down this variable should be set
* @return the value here
*/
public Object getValue(int offset, int depth) {
if (depth > 0) {
return parent.getValue(offset, depth - 1);
}
assertGetValue(offset, depth);
// &foo are not getting set from somewhere...I want the following assert to be true though
//assert variableValues[offset] != null : "Getting unassigned: " + staticScope.getVariables()[offset];
return variableValues[offset];
}

/**
* Set value in current dynamic scope or one of its captured scopes.
*
* @param offset zero-indexed value that represents where variable lives
* @param value to set
* @param depth how many captured scopes down this variable should be set
*/
public Object setValue(int offset, Object value, int depth) {
if (depth > 0) {
assertParent();

return parent.setValue(offset, value, depth - 1);
} else {
assertSetValue(offset, value);

return setValueDepthZero(value, offset);
}
}

public Object setValueDepthZero(Object value, int offset) {
assertSetValueDepthZero(offset, value);

return variableValues[offset] = value;
}

/**
*
* Make a larger dynamic scope if the static scope grew.
*
* Eval's with bindings require us to possibly change the size of the dynamic scope if
* things like 'eval "b = 2", binding' happens.
*
*/
public void growIfNeeded() {
int dynamicSize = variableValues == null ? 0: variableValues.length;

if (staticScope.getNumberOfVariables() > dynamicSize) {
Object values[] = new Object[staticScope.getNumberOfVariables()];

if (dynamicSize > 0) {
copy(variableValues, 0, values, 0, dynamicSize);
}

variableValues = values;
}
}

public static void copy(Object[] src, int srcOff, Object[] dst, int dstOff, final int length) {
switch (length) {
case 0: return;
case 1: dst[dstOff] = src[srcOff]; return;
case 2: dst[dstOff] = src[srcOff]; dst[++dstOff] = src[srcOff + 1]; return;
case 3: dst[dstOff] = src[srcOff]; dst[++dstOff] = src[srcOff + 1]; dst[++dstOff] = src[srcOff + 2]; return;
}
System.arraycopy(src, srcOff, dst, dstOff, length);
}

private void assertGetValue(int offset, int depth) {
Object[] values = variableValues;
assert values != null && offset < values.length : "No variables or index to big for getValue off: " + offset + ", Dep: " + depth + ", O: " + this;
}

private void assertParent() {
assert parent != null : "If depth > 0, then parent should not ever be null";
}

private void assertSetValue(int offset, Object value) {
assert offset < variableValues.length : "Setting " + offset + " to " + value + ", O: " + this;
}

private void assertSetValueDepthZero(int offset, Object value) {
assert offset < variableValues.length : "Setting " + offset + " to " + value + ", O: " + this;
}

}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -52,19 +52,12 @@
* will point to the previous scope of the enclosing module/class (cref).
*
*/
public class StaticScope implements Serializable {
private static final long serialVersionUID = 3423852552352498148L;
public class StaticScope {

// Next immediate scope. Variable and constant scoping rules make use of this variable
// in different ways.
final protected StaticScope enclosingScope;

// Live reference to module
private transient Object cref = null;

// Next CRef down the lexical structure
private StaticScope previousCRefScope = null;

// Our name holder (offsets are assigned as variables are added)
private String[] variableNames;

@@ -91,7 +84,7 @@ public enum Type {
/**
*
*/
protected StaticScope(Type type, StaticScope enclosingScope, String file) {
public StaticScope(Type type, StaticScope enclosingScope, String file) {
this(type, enclosingScope, NO_NAMES);

this.file = file;
@@ -216,45 +209,6 @@ public void setVariables(String[] names) {
System.arraycopy(names, 0, variableNames, 0, names.length);
}

/**
* Gets a constant back from lexical search from the cref in this scope.
* As it is for defined? we will not forced resolution of autoloads nor
* call const_defined
*/
public Object getConstantDefined(String internedName) {
/*Object result = cref.fetchConstant(internedName);
if (result != null) return result;
return previousCRefScope == null ? null : previousCRefScope.getConstantDefinedNoObject(internedName);*/
throw new UnsupportedOperationException();
}

public Object getConstantDefinedNoObject(String internedName) {
if (previousCRefScope == null) return null;

return getConstantDefined(internedName);
}

public Object getConstant(String internedName) {
/*Object result = getConstantInner(internedName);
// If we could not find the constant from cref..then try getting from inheritence hierarchy
return result == null ? cref.getConstantNoConstMissing(internedName) : result;*/
throw new UnsupportedOperationException();
}

public Object getConstantInner(String internedName) {
/*Object result = cref.fetchConstant(internedName);
if (result != null) {
return result == RubyObject.UNDEF ? cref.resolveUndefConstant(internedName) : result;
}
return previousCRefScope == null ? null : previousCRefScope.getConstantInnerNoObject(internedName);*/
throw new UnsupportedOperationException();
}

/**
* Next outer most scope in list of scopes. An enclosing scope may have no direct scoping
* relationship to its child. If I am in a localScope and then I enter something which
@@ -400,26 +354,6 @@ public StaticScope getLocalScope() {
return (type != Type.BLOCK) ? this : enclosingScope.getLocalScope();
}

/**
* Update current scoping structure to populate with proper cref scoping values. This should
* be called at any point when you reference a scope for the first time. For the interpreter
* this is done in a small number of places (defnNode, defsNode, and getBlock). The compiler
* does this in the same places.
*
* @return the current cref, though this is largely an implementation detail
*/
public Object determineModule() {
if (cref == null) {
cref = getEnclosingScope().determineModule();

assert cref != null : "CRef is always created before determine happens";

previousCRefScope = getEnclosingScope().previousCRefScope;
}

return cref;
}

public boolean isBlockScope() {
return isBlockOrEval;
}

This file was deleted.

This file was deleted.

This file was deleted.