Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
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 @@ -25,7 +25,7 @@ jassGlobalsBlock:
;

jassGlobalDecl:
constant='constant'? typeExpr name=ID ('=' initial=expr)? NL
constant='constant'? typeExpr name=(ID|CONTINUE|SKIP_|BREAK) ('=' initial=expr)? NL
;

jassFuncDef:
Expand All @@ -35,7 +35,7 @@ jassFuncDef:
'endfunction' NL
;

jassLocal: 'local' typeExpr name=ID ('=' initial=expr)? NL;
jassLocal: 'local' typeExpr name=(ID|CONTINUE|SKIP_|BREAK) ('=' initial=expr)? NL;

jassStatements: stmts+=jassStatement*;

Expand Down Expand Up @@ -224,7 +224,7 @@ funcSignature:
formalParameters: '(' (params+=formalParameter (',' params+=formalParameter)*)? ')';

formalParameter:
vararg=VARARG? typeExpr name=ID
vararg=VARARG? typeExpr name=(ID|CONTINUE|SKIP_|BREAK)
;

typeExpr:
Expand All @@ -238,7 +238,7 @@ typeExpr:
varDef:
modifiersWithDoc
('var'|constant='constant' varType=typeExpr?|constant='let'|varType=typeExpr)
name=ID ('=' variableInit)? NL
name=(ID|CONTINUE|SKIP_|BREAK) ('=' variableInit)? NL
;

variableInit: (arrayInit | initial=expr);
Expand Down Expand Up @@ -312,12 +312,12 @@ stmtWhile:

localVarDef:
(var='var'|let='let'|type=typeExpr)
name=ID ('=' variableInit)?
name=(ID|CONTINUE|SKIP_|BREAK) ('=' variableInit)?
;


localVarDefInline:
typeExpr? name=ID
typeExpr? name=(ID|CONTINUE|SKIP_|BREAK)
;

stmtSet:
Expand All @@ -335,12 +335,12 @@ exprAssignable:
;

exprMemberVar:
expr dots=('.'|'..') varname=ID? indexes?
expr dots=('.'|'..') varname=(ID|CONTINUE|SKIP_|BREAK)? indexes?
;


exprVarAccess:
varname=(ID|IT) indexes?
varname=(ID|CONTINUE|SKIP_|BREAK|IT) indexes?
;


Expand All @@ -354,7 +354,7 @@ expr:
| left=expr 'castTo' castToType=typeExpr
| left=expr 'instanceof' instaneofType=typeExpr
| receiver=expr dotsCall=('.'|'..') funcName=ID? typeArgs argumentList
| receiver=expr dotsVar=('.'|'..') varName=ID? indexes?
| receiver=expr dotsVar=('.'|'..') varName=(ID|CONTINUE|SKIP_|BREAK)? indexes?
| left=expr op=('*'|'/'|'%'|'div'|'mod') right=expr
| op='-' right=expr // TODO move unary minus one up to be compatible with Java etc.
// currently it is here to be backwards compatible with the old wurst parser
Expand All @@ -375,7 +375,7 @@ exprPrimary:
| exprClosure
| exprStatementsBlock
| exprDestroy
| varname=(ID|IT) indexes?
| varname=(ID|CONTINUE|SKIP_|BREAK|IT) indexes?
| atom=(INT
| REAL
| STRING
Expand Down Expand Up @@ -412,7 +412,7 @@ shortFormalParameters:
| /* empty */
;

shortFormalParameter: typeExpr? name=ID;
shortFormalParameter: typeExpr? name=(ID|CONTINUE|SKIP_|BREAK);

typeParams: ('<' (params+=typeParam (',' params+=typeParam)*)? '>')?;

Expand Down Expand Up @@ -447,6 +447,7 @@ exprList : exprs+=expr (',' exprs+=expr)*;




nativeType: 'nativetype' name=ID ('extends' extended=ID)? NL;
initBlock: 'init' NL statementsBlock;
nativeDef: modifiersWithDoc 'native' funcSignature NL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
import de.peeeq.wurstio.languageserver.WFile;
import de.peeeq.wurstscript.WLogger;
import de.peeeq.wurstscript.ast.*;
import de.peeeq.wurstscript.attributes.AttrFuncDef;
import de.peeeq.wurstscript.attributes.CofigOverridePackages;
import de.peeeq.wurstscript.attributes.names.FuncLink;
import de.peeeq.wurstscript.attributes.names.NameLink;
import de.peeeq.wurstscript.parser.WPos;
import de.peeeq.wurstscript.types.WurstTypeArray;
import de.peeeq.wurstscript.types.WurstType;
import de.peeeq.wurstscript.types.WurstTypeNamedScope;
import de.peeeq.wurstscript.utils.Utils;
Expand Down Expand Up @@ -77,6 +80,10 @@ private List<? extends Location> execute2(ModelManager modelManager) {
return linkTo(originalDecl);
}
}
FunctionDefinition indexOpDecl = getIndexOperatorDeclarationAtPos(e);
if (indexOpDecl != null) {
return linkTo(indexOpDecl);
}
if (e instanceof FuncRef) {
FuncRef funcRef = (FuncRef) e;
FunctionDefinition decl = funcRef.attrFuncDef();
Expand Down Expand Up @@ -117,6 +124,37 @@ private List<? extends Location> execute2(ModelManager modelManager) {
return Collections.emptyList();
}

private FunctionDefinition getIndexOperatorDeclarationAtPos(Element e) {
Element target = e;
if (target instanceof Indexes && target.getParent() instanceof NameRef) {
target = target.getParent();
}
if (!(target instanceof NameRef) || !(target instanceof AstElementWithIndexes)) {
return null;
}

NameRef nr = (NameRef) target;
AstElementWithIndexes withIndexes = (AstElementWithIndexes) target;
if (withIndexes.getIndexes().size() != 1) {
return null;
}
NameLink link = nr.attrNameLink();
if (link == null || link.getTyp() instanceof WurstTypeArray) {
return null;
}

WurstType receiverType = link.getTyp();
WurstType indexType = withIndexes.getIndexes().get(0).attrTyp();
if (nr.getParent() instanceof StmtSet && ((StmtSet) nr.getParent()).getUpdatedExpr() == nr) {
StmtSet set = (StmtSet) nr.getParent();
FuncLink f = AttrFuncDef.getIndexSetOperator(nr, receiverType, indexType, set.getRight().attrTyp());
return f == null ? null : f.getDef();
}

FuncLink f = AttrFuncDef.getIndexGetOperator(nr, receiverType, indexType);
return f == null ? null : f.getDef();
}

private List<? extends Location> typeDefinitionFor(Element e) {
if (e instanceof TypeExpr) {
TypeExpr typeExpr = (TypeExpr) e;
Expand Down
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,41 @@ 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) {
List<WurstType> argTypes = Collections.singletonList(indexType);
FuncLink candidate = searchMemberFunc(node, receiverType, overloadingIndexGet, argTypes);
if (candidate == null || !matchesArguments(node, candidate, argTypes)) {
return null;
}
return candidate;
}

public static @Nullable FuncLink getIndexSetOperator(Expr node, WurstType receiverType, WurstType indexType, WurstType valueType) {
List<WurstType> argTypes = Lists.newArrayList(indexType, valueType);
FuncLink candidate = searchMemberFunc(node, receiverType, overloadingIndexSet, argTypes);
if (candidate == null || !matchesArguments(node, candidate, argTypes)) {
return null;
}
return candidate;
}

private static boolean matchesArguments(Element node, FuncLink f, List<WurstType> argumentTypes) {
if (f.getParameterTypes().size() != argumentTypes.size()) {
return false;
}
VariableBinding mapping = f.getVariableBinding();
for (int i = 0; i < argumentTypes.size(); i++) {
WurstType at = argumentTypes.get(i);
WurstType pt = f.getParameterType(i);
VariableBinding m2 = at.matchAgainstSupertype(pt, node, mapping, VariablePosition.RIGHT);
if (m2 == null) {
return false;
}
mapping = m2;
}
return true;
}


/**
* 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 @@ -88,16 +88,27 @@ private void createReflectionFunctions() {
"instanceCount",
TypesHelper.imInt(),
JassIm.ImIntVal(0),
c ->
JassIm.ImOperatorCall(WurstOperator.MINUS,
c -> {
ClassManagementVars m = translator.getClassManagementVarsFor(c);
if (m == null) {
return JassIm.ImIntVal(0);
}
return JassIm.ImOperatorCall(WurstOperator.MINUS,
JassIm.ImExprs(
JassIm.ImVarAccess(translator.getClassManagementVarsFor(c).maxIndex),
JassIm.ImVarAccess(translator.getClassManagementVarsFor(c).freeCount))));
JassIm.ImVarAccess(m.maxIndex),
JassIm.ImVarAccess(m.freeCount)));
});
maxInstanceCountFunc = accessClassManagementVar(
"maxInstanceCount",
TypesHelper.imInt(),
JassIm.ImIntVal(0),
c -> JassIm.ImVarAccess(translator.getClassManagementVarsFor(c).maxIndex));
c -> {
ClassManagementVars m = translator.getClassManagementVarsFor(c);
if (m == null) {
return JassIm.ImIntVal(0);
}
return JassIm.ImVarAccess(m.maxIndex);
});
maxTypeIdFunc = maxTypeIdFunc();
}

Expand All @@ -111,9 +122,13 @@ private ImFunction maxTypeIdFunc() {
}

public static int calculateMaxTypeId(ImProg prog) {
return calculateMaxTypeId(TypeId.calculate(prog));
}

private static int calculateMaxTypeId(Map<ImClass, Integer> classId) {
boolean seen = false;
int best = 0;
for (Integer x : prog.attrTypeId().values()) {
for (Integer x : classId.values()) {
int i = x;
if (!seen || i > best) {
seen = true;
Expand All @@ -129,8 +144,9 @@ private ImFunction accessClassManagementVar(String funcName, ImType returnType,
ImVar typeId = JassIm.ImVar(trace, TypesHelper.imInt(), "typeId", false);
ImVars parameters = JassIm.ImVars(typeId);
ImVars locals = JassIm.ImVars();
Map<ImClass, Integer> classId = prog.attrTypeId();
int maxTypeId = calculateMaxTypeId(prog);
// Use fresh IDs from current classes to avoid stale attrTypeId cache inconsistencies.
Map<ImClass, Integer> classId = TypeId.calculate(prog);
int maxTypeId = calculateMaxTypeId(classId);
Comment thread
Frotty marked this conversation as resolved.
Outdated
ImClass[] typeIdToClass = new ImClass[maxTypeId + 1];
for (Map.Entry<ImClass, Integer> e : classId.entrySet()) {
typeIdToClass[e.getValue()] = e.getKey();
Expand All @@ -149,7 +165,11 @@ private ImStmts generateBinarySearch(int lower, int upper, ImVar typeId, ImClass
if (lower > upper) {
return JassIm.ImStmts();
} else if (lower == upper) {
return JassIm.ImStmts(JassIm.ImReturn(prog.getTrace(), makeAccess.apply(typeIdToClass[lower])));
ImClass c = typeIdToClass[lower];
if (c == null) {
return JassIm.ImStmts();
}
return JassIm.ImStmts(JassIm.ImReturn(prog.getTrace(), makeAccess.apply(c)));
} else {
int mid = lower + (upper - lower) / 2;
return
Expand Down
Loading
Loading