diff --git a/src/main/java/carpet/script/Context.java b/src/main/java/carpet/script/Context.java index 6d39a603..5aaa1399 100644 --- a/src/main/java/carpet/script/Context.java +++ b/src/main/java/carpet/script/Context.java @@ -16,6 +16,7 @@ public class Context static final int ITERATOR = 6; static final int SIGNATURE = 7; static final int LOCALIZATION = 8; + static final int LVALUE = 9; private Map variables = new HashMap<>(); diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 7ffaabe8..6b037022 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -16,6 +16,7 @@ import carpet.script.value.AbstractListValue; import carpet.script.value.ContainerValueInterface; import carpet.script.value.FunctionSignatureValue; import carpet.script.value.GlobalValue; +import carpet.script.value.LContainerValue; import carpet.script.value.LazyListValue; import carpet.script.value.ListValue; import carpet.script.value.MapValue; @@ -1242,11 +1243,18 @@ public class Expression implements Cloneable */ public void Operators() { - addBinaryOperator(".", precedence.get("attribute~."),true, (container, key) -> + addLazyBinaryOperator(".", precedence.get("attribute~."),true, (c, t, container_lv, key_lv) -> { - if (container instanceof ContainerValueInterface) - return ((ContainerValueInterface) container).get(key); - throw new InternalExpressionException("Cannot access elements of a non-container"); + Value container = container_lv.evalValue(c); + if (!(container instanceof ContainerValueInterface)) + throw new InternalExpressionException("Cannot access elements of a non-container"); + Value address = key_lv.evalValue(c); + if (t != Context.LVALUE) + { + Value retVal = ((ContainerValueInterface) container).get(address); + return (cc, ct) -> retVal; + } + return (cc, ct) -> new LContainerValue((ContainerValueInterface) container, address); }); addBinaryOperator("+", precedence.get("addition+-"), true, Value::add); addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract); @@ -1290,7 +1298,7 @@ public class Expression implements Cloneable addLazyBinaryOperator("=", precedence.get("assign=<>"), false, (c, t, lv1, lv2) -> { - Value v1 = lv1.evalValue(c); + Value v1 = lv1.evalValue(c, Context.LVALUE); Value v2 = lv2.evalValue(c); if (v1 instanceof ListValue.ListConstructorValue && v2 instanceof ListValue) { @@ -1309,6 +1317,11 @@ public class Expression implements Cloneable } return (cc, tt) -> Value.TRUE; } + if (v1 instanceof LContainerValue) + { + Value ret = ((LContainerValue) v1).getContainer().put(((LContainerValue) v1).getAddress(), v2); + return (cc, tt) -> ret; + } v1.assertAssignable(); String varname = v1.getVariable(); Value copy = v2.reboundedTo(varname); diff --git a/src/main/java/carpet/script/value/FrameworkValue.java b/src/main/java/carpet/script/value/FrameworkValue.java new file mode 100644 index 00000000..cae758ab --- /dev/null +++ b/src/main/java/carpet/script/value/FrameworkValue.java @@ -0,0 +1,30 @@ +package carpet.script.value; + +import carpet.script.exception.ExpressionException; + +public abstract class FrameworkValue extends Value +{ + @Override + public String getString() + { + throw new ExpressionException("Scarpet language component cannot be used"); + } + + @Override + public boolean getBoolean() + { + throw new ExpressionException("Scarpet language component cannot be used"); + } + + @Override + public Value clone() + { + throw new ExpressionException("Scarpet language component cannot be used"); + } + + @Override + public int hashCode() + { + throw new UnsupportedOperationException("Scarpet language component cannot be used as map key"); + } +} diff --git a/src/main/java/carpet/script/value/FunctionSignatureValue.java b/src/main/java/carpet/script/value/FunctionSignatureValue.java index 48596a49..49903a00 100644 --- a/src/main/java/carpet/script/value/FunctionSignatureValue.java +++ b/src/main/java/carpet/script/value/FunctionSignatureValue.java @@ -4,29 +4,13 @@ import carpet.script.exception.ExpressionException; import java.util.List; -public class FunctionSignatureValue extends Value +public class FunctionSignatureValue extends FrameworkValue { private String identifier; private List arguments; private List globals; - @Override - public String getString() - { - throw new ExpressionException("Function "+identifier+" is not defined yet"); - } - @Override - public boolean getBoolean() - { - throw new ExpressionException("Function "+identifier+" is not defined yet"); - } - - @Override - public Value clone() - { - throw new ExpressionException("Function "+identifier+" is not defined yet"); - } public FunctionSignatureValue(String name, List args, List globals) { this.identifier = name; @@ -43,11 +27,7 @@ public class FunctionSignatureValue extends Value } public List getGlobals() {return globals;} - @Override - public int hashCode() - { - throw new UnsupportedOperationException("function signature value cannot be used as map key"); - } + } diff --git a/src/main/java/carpet/script/value/LContainerValue.java b/src/main/java/carpet/script/value/LContainerValue.java new file mode 100644 index 00000000..b95ae723 --- /dev/null +++ b/src/main/java/carpet/script/value/LContainerValue.java @@ -0,0 +1,16 @@ +package carpet.script.value; + +public class LContainerValue extends FrameworkValue +{ + private ContainerValueInterface container; + private Value address; + + public LContainerValue(ContainerValueInterface c, Value v) + { + container = c; + address = v; + } + + public ContainerValueInterface getContainer() {return container; } + public Value getAddress() {return address; } +}