Large diffs are not rendered by default.

@@ -14,7 +14,6 @@ public class ParserHelper {
"record",
"function",
"end",
"def",
"if",
"then",
"else",

Large diffs are not rendered by default.

@@ -19,7 +19,7 @@ public class Parser {
// 構造キーワード
%token<Token> OBJECT, RECORD, FUNCTION
// 制御構造キーワード
%token<Token> DEF, IF, THEN, ELSE, FOR, WHILE, DO, TRY, CATCH, FINALLY, SWITCH, CASE, ASSERT, USING, LOCK, END
%token<Token> IF, THEN, ELSE, FOR, WHILE, DO, TRY, CATCH, FINALLY, SWITCH, CASE, ASSERT, USING, LOCK, END
// 制御構文キーワード
%token<Token> BREAK, CONTINUE, THROW, RETURN, ATMARK
// 演算子
@@ -93,8 +93,6 @@ stmt:
{ $$ = new ForStatement($4, $6, $1, EmptyStatement.INSTANCE).setPos($3.getPos()); }
| cmdStmt ATMARK WHILE expr SEMICOLON
{ $$ = new WhileStatement($4, $1, EmptyStatement.INSTANCE).setPos($3.getPos()); }
| DEF leftvalue ASSIGN expr SEMICOLON
{ $$ = new ExpressionStatement(newNewSlotCall($2, $4, true)).setPos($1.getPos()); }
| labelOpt IF expr THEN stmtList elseStmtOpt END
{ $$ = new IfStatement($1, $3, $5, $6).setPos($2.getPos()); }
| labelOpt FOR id COLON expr DO stmtListOpt elseStmtOpt END
@@ -96,7 +96,6 @@ WSP = [\ \t]
"record" { return tk(Parser.RECORD); }
"function" { return tk(Parser.FUNCTION); }
"end" { return tk(Parser.END); }
"def" { return tk(Parser.DEF); }
"if" { return tk(Parser.IF); }
"then" { return tk(Parser.THEN); }
"else" { return tk(Parser.ELSE); }
@@ -27,7 +27,7 @@ public String debugString() {
}

public ABuiltinFunction register(AnubisObject owner, String name) {
owner.setSlot(name, this, true);
owner.setSlot(name, this);
return this;
}

@@ -118,11 +118,6 @@ public void setSlot(String name, AnubisObject value) {
;
}

@Override
public void setSlot(String name, AnubisObject value, boolean readonly) {
;
}

@Override
public String toString() {
return debugString();
@@ -20,19 +20,12 @@ public AnubisObject get() {
public void set(AnubisObject value) {
; // nop
}

@Override
public void set(AnubisObject value, boolean readonly) {
; // nop
}
}

public abstract class Field {
public abstract AnubisObject get();

public abstract void set(AnubisObject value);

public abstract void set(AnubisObject value, boolean readonly);
}

public class NestedField extends Field {
@@ -48,13 +41,6 @@ public void set(AnubisObject value) {
// TODO Auto-generated method stub

}

@Override
public void set(AnubisObject value, boolean readonly) {
// TODO Auto-generated method stub

}

}

public class VariableField extends Field {
@@ -74,10 +60,5 @@ public AnubisObject get() {
public void set(AnubisObject value) {
ARecord.this.setSlot(name, value);
}

@Override
public void set(AnubisObject value, boolean readonly) {
ARecord.this.setSlot(name, value, readonly);
}
}
}
@@ -4,7 +4,7 @@
import anubis.SlotRef;
import anubis.SpecialSlot;
import anubis.except.ExceptionProvider;
import anubis.except.SlotReadonlyException;
import anubis.except.ObjectFreezeException;

public abstract class AbstractAObject implements AnubisObject {
protected final SlotTable slots;
@@ -78,7 +78,7 @@ public void setSlot(SpecialSlot type, AnubisObject value) {
this._outer = value;
break;
case THIS:
throw ExceptionProvider.newSlotReadonly(this, "this");
throw ExceptionProvider.newObjectFreeze(this, "this");
default:
throw ExceptionProvider.newSlotNotFound(this, type.toString());
}
@@ -87,21 +87,10 @@ public void setSlot(SpecialSlot type, AnubisObject value) {
@Override
public void setSlot(String name, AnubisObject value) {
try {
slots.put(name, value, false);
slots.put(name, value);
}
catch (SlotReadonlyException ex) {
throw ExceptionProvider.newSlotReadonly(ex, this, name);
catch (ObjectFreezeException ex) {
throw ExceptionProvider.newObjectFreeze(ex, this, name);
}
}

@Override
public void setSlot(String name, AnubisObject value, boolean readonly) {
try {
slots.put(name, value, readonly);
}
catch (SlotReadonlyException ex) {
throw ExceptionProvider.newSlotReadonly(ex, this, name);
}
}

}
@@ -1,61 +1,20 @@
package anubis.runtime;

import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import anubis.AnubisObject;
import anubis.except.ExceptionProvider;

/**
* @author SiroKuro
*/
public abstract class AbstractSlotTable implements SlotTable {
private Set<String> readonly = null;
private volatile boolean immutable = false;

public void freeze() {
this.immutable = true;
}

@Override
public synchronized SnapShot getSnap() {
final Map<String, AnubisObject> slots = getSlotSnaps();
final Set<String> readonlys = getReadonlySnaps();
return new SnapShot() {
@Override
public Set<String> getReadonlySlots() {
return readonlys;
}

@Override
public Map<String, AnubisObject> getSlots() {
return slots;
}
};
}

protected synchronized void assertNotReadonly(String name, boolean setReadonly) {
if (immutable || (readonly != null && readonly.contains(name))) {
throw ExceptionProvider.newSlotReadonly(name);
}
if (setReadonly) {
prepareReadonlySet().add(name);
}
}

protected Set<String> getReadonlySnaps() {
if (readonly == null)
return Collections.emptySet();
return Collections.unmodifiableSet(new HashSet<String>(readonly));
}

protected abstract Map<String, AnubisObject> getSlotSnaps();

private Set<String> prepareReadonlySet() {
if (this.readonly == null) {
this.readonly = new HashSet<String>();
protected synchronized void assertNotFreeze() {
if (immutable) {
throw ExceptionProvider.newObjectFreeze();
}
return this.readonly;
}
}
@@ -68,7 +68,7 @@ protected static SlotTable newClassTable(Class<?> cls) {
// traits へ変換
SlotTable result = new SimpleSlotTable();
for (Entry<String, FunctionAccessor> ent: accessors.entrySet()) {
result.put(ent.getKey(), AObjects.attachTraits(JFunction.valueOf(ent.getValue())), true);
result.put(ent.getKey(), AObjects.attachTraits(JFunction.valueOf(ent.getValue())));
}
return result;
}
@@ -11,28 +11,30 @@
public class SimpleSlotTable extends AbstractSlotTable {
private volatile Map<String, AnubisObject> internal = null;

@Override
public AnubisObject get(String name) {
if (internal != null) {
return internal.get(name);
}
return null;
}

public synchronized void put(String name, AnubisObject value, boolean setReadonly) {
assertNotReadonly(name, setReadonly);
if (value == null)
prepareInternal().remove(name);
else
prepareInternal().put(name, value);
}

@Override
protected Map<String, AnubisObject> getSlotSnaps() {
public Map<String, AnubisObject> getSnap() {
if (internal == null)
return Collections.emptyMap();
return Collections.unmodifiableMap(new HashMap<String, AnubisObject>(internal));
}

@Override
public synchronized void put(String name, AnubisObject value) {
assertNotFreeze();
if (value == null)
prepareInternal().remove(name);
else
prepareInternal().put(name, value);
}

private Map<String, AnubisObject> prepareInternal() {
if (this.internal == null) {
this.internal = new HashMap<String, AnubisObject>();
@@ -1,7 +1,6 @@
package anubis.runtime;

import java.util.Map;
import java.util.Set;
import anubis.AnubisObject;

/**
@@ -13,13 +12,7 @@ public interface SlotTable {

public AnubisObject get(String name);

public SnapShot getSnap();
public Map<String, AnubisObject> getSnap();

public void put(String name, AnubisObject value, boolean setReadonly);

public interface SnapShot {
public Set<String> getReadonlySlots();

public Map<String, AnubisObject> getSlots();
}
public void put(String name, AnubisObject value);
}
@@ -4,14 +4,14 @@
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import anubis.AnubisObject;
import anubis.SpecialSlot;
import anubis.except.ExceptionProvider;
import anubis.parser.ParserHelper;
import anubis.runtime.SlotTable.SnapShot;

/**
* @author SiroKuro
@@ -60,9 +60,9 @@ public static int asIntArgs(AnubisObject obj, int _default) {
return num.getNumber().intValue();
}

public static String formatDumpString(AObject object, SnapShot snapShot) {
public static String formatDumpString(AObject object, Map<String, AnubisObject> snaps) {
int max_length = 5;
for (String key: snapShot.getSlots().keySet()) {
for (String key: snaps.keySet()) {
key = ParserHelper.quoteIdentifier(key);
if (max_length < key.length()) {
max_length = key.length();
@@ -73,7 +73,7 @@ public static String formatDumpString(AObject object, SnapShot snapShot) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
{
pw.println(object.debugString());
pw.println(object.debugString() + " {");
// 特殊スロットのダンプ
AnubisObject _this = object.getSlot(SpecialSlot.THIS);
AnubisObject _super = object.getSlot(SpecialSlot.SUPER);
@@ -85,15 +85,9 @@ public static String formatDumpString(AObject object, SnapShot snapShot) {
if (_outer != null)
pw.println(padding(max_length, " outer") + " = " + Operator.toDebugString(_outer));
// 一般スロットのダンプ
for (Entry<String, AnubisObject> elm: snapShot.getSlots().entrySet()) {
if (snapShot.getReadonlySlots().contains(elm.getKey())) {
pw.println(padding(max_length, "R " + ParserHelper.quoteIdentifier(elm.getKey())) + " = "
+ Operator.toDebugString(elm.getValue()));
}
else {
pw.println(padding(max_length, " " + ParserHelper.quoteIdentifier(elm.getKey())) + " = "
+ Operator.toDebugString(elm.getValue()));
}
for (Entry<String, AnubisObject> elm: snaps.entrySet()) {
pw.println(padding(max_length, " " + ParserHelper.quoteIdentifier(elm.getKey())) + " = "
+ Operator.toDebugString(elm.getValue()));
}
pw.println("}");
}
@@ -1,20 +1,19 @@
package anubis.runtime.builtin;

import anubis.AnubisObject;
import anubis.runtime.ABuiltinFunction._3;
import anubis.runtime.ABuiltinFunction._2;
import anubis.runtime.AString;
import anubis.runtime.Operator;
import anubis.runtime.Utils;

public class ARootNewSlot extends _3 {
public class ARootNewSlot extends _2 {
public ARootNewSlot(AnubisObject owner, String name) {
super(owner, name);
}

@Override
protected AnubisObject exec(AnubisObject _this, AnubisObject name, AnubisObject value, AnubisObject readonly) {
protected AnubisObject exec(AnubisObject _this, AnubisObject name, AnubisObject value) {
AString text = Utils.as(AString.class, name);
_this.setSlot(text.getValue(), value, Operator.isTrue(readonly));
_this.setSlot(text.getValue(), value);
return value;
}
}
@@ -31,18 +31,7 @@ public AnubisObject get(String key) {
}

@Override
public void put(String name, AnubisObject value, boolean setReadonly) {
synchronized (bindings) {
assertNotReadonly(name, setReadonly);
if (value == null)
bindings.remove(name);
else
bindings.put(name, JCaster.cast(value));
}
}

@Override
protected Map<String, AnubisObject> getSlotSnaps() {
public Map<String, AnubisObject> getSnap() {
synchronized (bindings) {
Map<String, AnubisObject> result = new TreeMap<String, AnubisObject>();
for (Entry<String, Object> elm: bindings.entrySet()) {
@@ -51,4 +40,15 @@ protected Map<String, AnubisObject> getSlotSnaps() {
return Collections.unmodifiableMap(result);
}
}

@Override
public void put(String name, AnubisObject value) {
synchronized (bindings) {
assertNotFreeze();
if (value == null)
bindings.remove(name);
else
bindings.put(name, JCaster.cast(value));
}
}
}
@@ -56,33 +56,33 @@ public AnubisObject get(String name) {
}

@Override
public void put(String name, AnubisObject value, boolean setReadonly) {
assertNotReadonly(name, setReadonly);
Field ff = fields.get(name);
if (ff != null && Modifier.isFinal(ff.getModifiers()) == false) {
public Map<String, AnubisObject> getSnap() {
Map<String, AnubisObject> result = new TreeMap<String, AnubisObject>();
for (Field ff: fields.values()) {
try {
ff.set(object, JCaster.cast(ff.getType(), value));
result.put(ff.getName(), AObjects.getObject(ff.get(object)));
}
catch (IllegalAccessException ex) {
throw ExceptionProvider.wrapRuntimeException(ex);
}
}
else {
throw ExceptionProvider.newSlotReadonly(name);
}
return Collections.unmodifiableMap(result);
}

@Override
protected Map<String, AnubisObject> getSlotSnaps() {
Map<String, AnubisObject> result = new TreeMap<String, AnubisObject>();
for (Field ff: fields.values()) {
public void put(String name, AnubisObject value) {
assertNotFreeze();
Field ff = fields.get(name);
if (ff != null && Modifier.isFinal(ff.getModifiers()) == false) {
try {
result.put(ff.getName(), AObjects.getObject(ff.get(object)));
ff.set(object, JCaster.cast(ff.getType(), value));
}
catch (IllegalAccessException ex) {
throw ExceptionProvider.wrapRuntimeException(ex);
}
}
return Collections.unmodifiableMap(result);
else {
throw ExceptionProvider.newObjectFreeze(name);
}
}
}
@@ -31,18 +31,7 @@ public AnubisObject get(String name) {
}

@Override
public void put(String name, AnubisObject value, boolean setReadonly) {
synchronized (context) {
assertNotReadonly(name, setReadonly);
if (value == null)
context.removeAttribute(name, ScriptContext.ENGINE_SCOPE);
else
context.setAttribute(name, JCaster.cast(value), ScriptContext.ENGINE_SCOPE);
}
}

@Override
protected Map<String, AnubisObject> getSlotSnaps() {
public Map<String, AnubisObject> getSnap() {
synchronized (context) {
Map<String, AnubisObject> result = new TreeMap<String, AnubisObject>();
List<Integer> scopes = new ArrayList<Integer>(context.getScopes());
@@ -56,4 +45,15 @@ protected Map<String, AnubisObject> getSlotSnaps() {
return Collections.unmodifiableMap(result);
}
}

@Override
public void put(String name, AnubisObject value) {
synchronized (context) {
assertNotFreeze();
if (value == null)
context.removeAttribute(name, ScriptContext.ENGINE_SCOPE);
else
context.setAttribute(name, JCaster.cast(value), ScriptContext.ENGINE_SCOPE);
}
}
}
@@ -28,8 +28,6 @@ public void testEval() throws Exception {
assertEquals("abc", engine.eval("x"));
assertEquals("abcdef", engine.eval("x += 'def'"));
assertEquals("abcdef", engine.eval("x"));
assertEquals("ABC", engine.eval("def text = 'ABC'; return text;"));
assertEquals("ABC", engine.eval("text"));
}

/**
@@ -109,32 +109,32 @@ public void testNewSlotNotFound() {
}

/**
* {@link anubis.except.ExceptionProvider#newSlotReadonly(java.lang.String)} のためのテスト・メソッド。
* {@link anubis.except.ExceptionProvider#newObjectFreeze(java.lang.String)} のためのテスト・メソッド。
*/
@Test
public void testNewSlotReadonly1() {
SlotReadonlyException result = ExceptionProvider.newSlotReadonly("abc");
ObjectFreezeException result = ExceptionProvider.newObjectFreeze("abc");
assertNotNull(result);
System.out.println(result.getMessage());
}

/**
* {@link anubis.except.ExceptionProvider#newSlotReadonly(anubis.AnubisObject, java.lang.String)} のためのテスト・メソッド。
* {@link anubis.except.ExceptionProvider#newObjectFreeze(anubis.AnubisObject, java.lang.String)} のためのテスト・メソッド。
*/
@Test
public void testNewSlotReadonly2() {
SlotReadonlyException result = ExceptionProvider.newSlotReadonly(object, "abc");
ObjectFreezeException result = ExceptionProvider.newObjectFreeze(object, "abc");
assertNotNull(result);
System.out.println(result.getMessage());
}

/**
* {@link anubis.except.ExceptionProvider#newSlotReadonly(java.lang.Throwable, anubis.AnubisObject, java.lang.String)} のためのテスト・メソッド。
* {@link anubis.except.ExceptionProvider#newObjectFreeze(java.lang.Throwable, anubis.AnubisObject, java.lang.String)} のためのテスト・メソッド。
*/
@Test
public void testNewSlotReadonly3() {
Exception cause = new Exception("sample exception");
SlotReadonlyException result = ExceptionProvider.newSlotReadonly(cause, object, "abc");
ObjectFreezeException result = ExceptionProvider.newObjectFreeze(cause, object, "abc");
assertNotNull(result);
assertEquals(cause, result.getCause());
System.out.println(result.getMessage());
@@ -130,7 +130,6 @@ public void testParseStatement() throws Exception {
parse("continue;");
parse("continue LABEL;");
parse("throw null;");
parse("def x = 123;");
parse("assert x == 0;");
parse("x = 1 + 2 + 3 @if x == 1;");
parse("return 123 @if x == 1;");
@@ -6,7 +6,6 @@
import static org.junit.Assert.assertSame;
import org.junit.Test;
import anubis.AnubisObject;
import anubis.except.SlotReadonlyException;

/**
* @author SiroKuro
@@ -205,23 +204,4 @@ public void testGetSpecialSlot() {
assertNull(obj.getSlot(SUPER));
assertNull(obj.getSlot(OUTER));
}

/**
* 読み取り専用スロットの確認
*/
@Test
public void testSetSlotReadonly() {
obj.setSlot("a", obj2, true);
assertSame(obj2, obj.getSlot("a"));
}

/**
* 読み取り専用スロットに再設定した時の確認
*/
@Test(expected = SlotReadonlyException.class)
public void testSetSlotReadonly02() {
obj.setSlot("a", obj2, true);
assertSame(obj2, obj.getSlot("a"));
obj.setSlot("a", obj3);
}
}
@@ -6,7 +6,7 @@
import anubis.AbstractTest;
import anubis.AnubisObject;
import anubis.SpecialSlot;
import anubis.except.SlotReadonlyException;
import anubis.except.ObjectFreezeException;
import anubis.runtime.java.JCaster;

/**
@@ -27,7 +27,7 @@ public void testFieldAccess01() throws Exception {
assertAEquals(4, exec("obj.getY()"));
}

@Test(expected = SlotReadonlyException.class)
@Test(expected = ObjectFreezeException.class)
public void testFieldAccess02() throws Exception {
local.setSlot("cls", AObjects.getObject(Sample.class));