Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,15 @@ public static WurstType calculate(ExprVarArrayAccess term) {
WurstType varDefType = varDef.getTyp();
if (varDefType instanceof WurstTypeArray) {
return ((WurstTypeArray) varDefType).getBaseType();
} else {
term.addError("Variable " + varDef.getName() + " is of type " + varDefType + ", should be an array variable.");
}
if (term.getIndexes().size() == 1) {
FuncLink overload = AttrFuncDef.getIndexGetOperator(term, varDefType, term.getIndexes().get(0).attrTyp());
if (overload != null) {
return overload.getReturnType();
Comment thread
Frotty marked this conversation as resolved.
Outdated
}
Comment thread
Frotty marked this conversation as resolved.
}
term.addError("Variable " + varDef.getName() + " is of type " + varDefType +
", should be an array variable or define operator overloading function " + AttrFuncDef.overloadingIndexGet + ".");
return WurstTypeUnknown.instance();
}

Expand Down Expand Up @@ -412,7 +418,13 @@ public static WurstType calculate(ExprMemberArrayVarDot term) {
WurstTypeArray ar = (WurstTypeArray) typ;
return ar.getBaseType();
}
term.addError("Variable " + term.getVarName() + " is not an array.");
if (term.getIndexes().size() == 1) {
FuncLink overload = AttrFuncDef.getIndexGetOperator(term, typ, term.getIndexes().get(0).attrTyp());
if (overload != null) {
return overload.getReturnType();
}
}
term.addError("Variable " + term.getVarName() + " is not an array and has no " + AttrFuncDef.overloadingIndexGet + " overload.");
return typ;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public class AttrFuncDef {
public final static String overloadingMinus = "op_minus";
public final static String overloadingMult = "op_mult";
public final static String overloadingDiv = "op_divReal";
public final static String overloadingIndexGet = "op_index";
public final static String overloadingIndexSet = "op_indexAssign";

public static FuncLink calculate(final ExprFuncRef node) {

Expand Down Expand Up @@ -206,6 +208,14 @@ private static boolean isConstructorThisCall(ExprFunctionCall node) {
return searchMemberFunc(left, left.attrTyp(), funcName, Collections.singletonList(right.attrTyp()));
}

public static @Nullable FuncLink getIndexGetOperator(Expr node, WurstType receiverType, WurstType indexType) {
return searchMemberFunc(node, receiverType, overloadingIndexGet, Collections.singletonList(indexType));
}

public static @Nullable FuncLink getIndexSetOperator(Expr node, WurstType receiverType, WurstType indexType, WurstType valueType) {
return searchMemberFunc(node, receiverType, overloadingIndexSet, Lists.newArrayList(indexType, valueType));
}


/**
* checks if operator is a native operator like for 1+2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import de.peeeq.wurstscript.WurstOperator;
import de.peeeq.wurstscript.ast.*;
import de.peeeq.wurstscript.ast.Element;
import de.peeeq.wurstscript.attributes.AttrFuncDef;
import de.peeeq.wurstscript.attributes.CompileError;
import de.peeeq.wurstscript.attributes.names.FuncLink;
import de.peeeq.wurstscript.attributes.names.NameLink;
import de.peeeq.wurstscript.attributes.names.OtherLink;
import de.peeeq.wurstscript.jassIm.*;
Expand Down Expand Up @@ -262,6 +264,7 @@ private static ImExpr translateNameDef(NameRef e, ImTranslator t, ImFunction f)
VarDef varDef = (VarDef) decl;

ImVar v = t.getVarFor(varDef);
@Nullable FuncLink indexGetOverload = getIndexGetOverload(e, link);

if (e.attrImplicitParameter() instanceof Expr) {
// we have implicit parameter
Expand All @@ -279,6 +282,13 @@ private static ImExpr translateNameDef(NameRef e, ImTranslator t, ImFunction f)
}

if (e instanceof AstElementWithIndexes) {
if (indexGetOverload != null) {
AstElementWithIndexes withIndexes = (AstElementWithIndexes) e;
ImExpr receiver = JassIm.ImMemberAccess(e, implicitParam.imTranslateExpr(t, f), JassIm.ImTypeArguments(), v, JassIm.ImExprs());
ImExpr index = withIndexes.getIndexes().get(0).imTranslateExpr(t, f);
ImFunction calledFunc = t.getFuncFor(indexGetOverload.getDef());
return ImFunctionCall(e, calledFunc, ImTypeArguments(), ImExprs(receiver, index), false, CallType.NORMAL);
}
ImExpr index1 = implicitParam.imTranslateExpr(t, f);
ImExpr index2 = ((AstElementWithIndexes) e).getIndexes().get(0).imTranslateExpr(t, f);
return JassIm.ImMemberAccess(e, index1, JassIm.ImTypeArguments(), v, JassIm.ImExprs(index2));
Expand All @@ -289,6 +299,13 @@ private static ImExpr translateNameDef(NameRef e, ImTranslator t, ImFunction f)
} else {
// direct var access
if (e instanceof AstElementWithIndexes) {
if (indexGetOverload != null) {
AstElementWithIndexes withIndexes = (AstElementWithIndexes) e;
ImExpr receiver = ImVarAccess(v);
ImExpr index = withIndexes.getIndexes().get(0).imTranslateExpr(t, f);
ImFunction calledFunc = t.getFuncFor(indexGetOverload.getDef());
return ImFunctionCall(e, calledFunc, ImTypeArguments(), ImExprs(receiver, index), false, CallType.NORMAL);
}
// direct access array var
AstElementWithIndexes withIndexes = (AstElementWithIndexes) e;
if (withIndexes.getIndexes().size() > 1) {
Expand Down Expand Up @@ -752,6 +769,10 @@ public static ImLExpr translateLvalue(LExpr e, ImTranslator t, ImFunction f) {
VarDef varDef = (VarDef) decl;

ImVar v = t.getVarFor(varDef);
NameLink link = e.attrNameLink();
@Nullable FuncLink indexGetOverload = (link == null || !(e instanceof NameRef))
? null
: getIndexGetOverload((NameRef) e, link);

if (e.attrImplicitParameter() instanceof Expr) {
// we have implicit parameter
Expand All @@ -771,6 +792,9 @@ public static ImLExpr translateLvalue(LExpr e, ImTranslator t, ImFunction f) {
}

if (e instanceof AstElementWithIndexes) {
if (indexGetOverload != null) {
throw new CompileError(e.getSource(), "Cannot assign to overloaded [] access without " + AttrFuncDef.overloadingIndexSet + ".");
}
ImExpr index1 = implicitParam.imTranslateExpr(t, f);
ImExpr index2 = ((AstElementWithIndexes) e).getIndexes().get(0).imTranslateExpr(t, f);
return JassIm.ImMemberAccess(e, index1, JassIm.ImTypeArguments(), v, JassIm.ImExprs(index2));
Expand All @@ -782,6 +806,9 @@ public static ImLExpr translateLvalue(LExpr e, ImTranslator t, ImFunction f) {
} else {
// direct var access
if (e instanceof AstElementWithIndexes) {
if (indexGetOverload != null) {
throw new CompileError(e.getSource(), "Cannot assign to overloaded [] access without " + AttrFuncDef.overloadingIndexSet + ".");
}
// direct access array var
AstElementWithIndexes withIndexes = (AstElementWithIndexes) e;
if (withIndexes.getIndexes().size() > 1) {
Expand Down Expand Up @@ -810,4 +837,19 @@ public static ImExpr translate(ExprArrayLength exprArrayLength, ImTranslator tra
return JassIm.ImIntVal(0);
}

private static @Nullable FuncLink getIndexGetOverload(NameRef e, NameLink link) {
if (!(e instanceof AstElementWithIndexes)) {
return null;
}
AstElementWithIndexes withIndexes = (AstElementWithIndexes) e;
if (withIndexes.getIndexes().size() != 1) {
return null;
}
WurstType receiverType = link.getTyp();
if (receiverType instanceof WurstTypeArray) {
return null;
}
return AttrFuncDef.getIndexGetOperator(e, receiverType, withIndexes.getIndexes().get(0).attrTyp());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
import de.peeeq.wurstscript.WurstOperator;
import de.peeeq.wurstscript.ast.*;
import de.peeeq.wurstscript.ast.Element;
import de.peeeq.wurstscript.attributes.AttrFuncDef;
import de.peeeq.wurstscript.attributes.CompileError;
import de.peeeq.wurstscript.attributes.names.FuncLink;
import de.peeeq.wurstscript.attributes.names.NameLink;
import de.peeeq.wurstscript.attributes.names.OtherLink;
import de.peeeq.wurstscript.jassIm.*;
import de.peeeq.wurstscript.types.TypesHelper;
import de.peeeq.wurstscript.types.WurstType;
import de.peeeq.wurstscript.types.WurstTypeArray;
import de.peeeq.wurstscript.types.WurstTypeVararg;
import org.eclipse.jdt.annotation.Nullable;

import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -330,11 +335,54 @@ public static ImStmt translate(StmtReturn s, ImTranslator t, ImFunction f) {


public static ImStmt translate(StmtSet s, ImTranslator t, ImFunction f) {
ImStmt overloadedIndexSet = translateOverloadedIndexSet(s, t, f);
if (overloadedIndexSet != null) {
return overloadedIndexSet;
}
ImLExpr updated = s.getUpdatedExpr().imTranslateExprLvalue(t, f);
ImExpr right = s.getRight().imTranslateExpr(t, f);
return ImSet(s, updated, right);
}

private static @Nullable ImStmt translateOverloadedIndexSet(StmtSet s, ImTranslator t, ImFunction f) {
if (!(s.getUpdatedExpr() instanceof NameRef) || !(s.getUpdatedExpr() instanceof AstElementWithIndexes)) {
return null;
}
NameRef left = (NameRef) s.getUpdatedExpr();
AstElementWithIndexes withIndexes = (AstElementWithIndexes) s.getUpdatedExpr();
if (withIndexes.getIndexes().size() != 1) {
return null;
}
NameLink link = left.attrNameLink();
if (link == null || link.getTyp() instanceof WurstTypeArray) {
return null;
}
FuncLink setOverload = AttrFuncDef.getIndexSetOperator(
left,
link.getTyp(),
withIndexes.getIndexes().get(0).attrTyp(),
s.getRight().attrTyp());
if (setOverload == null) {
return null;
}
if (link instanceof OtherLink || !(link.getDef() instanceof VarDef)) {
throw new CompileError(s.getSource(), "Could not resolve assignment receiver for overloaded [] assignment.");
}
VarDef varDef = (VarDef) link.getDef();
ImVar receiverVar = t.getVarFor(varDef);
ImExpr receiver;
if (left.attrImplicitParameter() instanceof Expr) {
Expr implicit = (Expr) left.attrImplicitParameter();
receiver = JassIm.ImMemberAccess(left, implicit.imTranslateExpr(t, f), JassIm.ImTypeArguments(), receiverVar, JassIm.ImExprs());
} else {
receiver = ImVarAccess(receiverVar);
}
ImExpr index = withIndexes.getIndexes().get(0).imTranslateExpr(t, f);
ImExpr value = s.getRight().imTranslateExpr(t, f);
ImFunction calledFunc = t.getFuncFor(setOverload.getDef());
return ImFunctionCall(s, calledFunc, ImTypeArguments(), ImExprs(receiver, index, value), false, CallType.NORMAL);
}


public static ImStmt translate(StmtWhile s, ImTranslator t, ImFunction f) {
List<ImStmt> body = Lists.newArrayList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import de.peeeq.wurstscript.attributes.CompileError;
import de.peeeq.wurstscript.attributes.ImplicitFuncs;
import de.peeeq.wurstscript.attributes.OverloadingResolver;
import de.peeeq.wurstscript.attributes.AttrFuncDef;
import de.peeeq.wurstscript.attributes.names.DefLink;
import de.peeeq.wurstscript.attributes.names.FuncLink;
import de.peeeq.wurstscript.attributes.names.NameLink;
Expand Down Expand Up @@ -1198,10 +1199,33 @@ private void checkStmtSet(StmtSet s) {
.addError("Invalid assignment. This is not a variable, this is a " + nameLink);
return;
}

WurstType leftType = s.getUpdatedExpr().attrTyp();
WurstType rightType = s.getRight().attrTyp();

if (s.getUpdatedExpr() instanceof NameRef && s.getUpdatedExpr() instanceof AstElementWithIndexes) {
NameRef left = (NameRef) s.getUpdatedExpr();
AstElementWithIndexes leftWithIndex = (AstElementWithIndexes) s.getUpdatedExpr();
WurstType targetType = nameLink.getTyp();
if (!(targetType instanceof WurstTypeArray)) {
if (leftWithIndex.getIndexes().size() != 1) {
s.addError("Only one index is supported for overloaded [] assignment.");
return;
}
FuncLink setOverload = AttrFuncDef.getIndexSetOperator(
left,
targetType,
leftWithIndex.getIndexes().get(0).attrTyp(),
rightType);
if (setOverload == null) {
s.addError("No operator overloading function for [] assignment was found for receiver type "
+ targetType + ". The overloading function has to be named: " + AttrFuncDef.overloadingIndexSet);
return;
}
checkAssignment(Utils.isJassCode(s), s, setOverload.getParameterType(1), rightType);
Comment thread
Frotty marked this conversation as resolved.
checkIfAssigningToConstant(s.getUpdatedExpr());
checkIfNoEffectAssignment(s);
return;
}
}
WurstType leftType = s.getUpdatedExpr().attrTyp();
checkAssignment(Utils.isJassCode(s), s, leftType, rightType);

checkIfAssigningToConstant(s.getUpdatedExpr());
Expand Down Expand Up @@ -2644,9 +2668,12 @@ private void checkConstructor(ConstructorDef d) {

private void checkArrayAccess(ExprVarArrayAccess ea) {
checkNameRefDeprecated(ea, ea.tryGetNameDef());
for (Expr index : ea.getIndexes()) {
if (!(index.attrTyp().isSubtypeOf(WurstTypeInt.instance(), ea))) {
index.addError("Arrayindices have to be of type int");
NameLink nameLink = ea.attrNameLink();
if (nameLink != null && nameLink.getTyp() instanceof WurstTypeArray) {
for (Expr index : ea.getIndexes()) {
if (!(index.attrTyp().isSubtypeOf(WurstTypeInt.instance(), ea))) {
index.addError("Arrayindices have to be of type int");
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,64 @@ public void testOverloading_shortForm2() {
"endpackage");
}

@Test
public void testOverloading_indexRead() {
testAssertOkLines(true,
"package test",
" native testSuccess()",
" class ListLike",
" function op_index(int i) returns int",
" return i + 5",
" init",
" ListLike l = new ListLike()",
" int x = l[3]",
" if x == 8",
" testSuccess()",
"endpackage");
}

@Test
public void testOverloading_indexReadMissing() {
testAssertErrorsLines(true, "op_index",
"package test",
" class ListLike",
" init",
" ListLike l = new ListLike()",
" int x = l[3]",
"endpackage");
}

@Test
public void testOverloading_indexWrite() {
testAssertOkLines(true,
"package test",
" native testSuccess()",
" class ListLike",
" int x = 0",
" function op_index(int i) returns int",
" return x + i",
" function op_indexAssign(int i, int v)",
" x = v + i",
" init",
" ListLike l = new ListLike()",
" l[1] = 2",
" if l[1] == 4",
" testSuccess()",
"endpackage");
}

@Test
public void testOverloading_indexWriteMissingSetter() {
testAssertErrorsLines(true, "op_indexAssign",
"package test",
" class ListLike",
" function op_index(int i) returns int",
" return i",
" init",
" ListLike l = new ListLike()",
" l[1] = 2",
"endpackage");
}


}
Loading