Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -43,6 +43,7 @@ public class EliminateClasses {
INSTANCE_COUNT,
MAX_INSTANCE_COUNT
);
private final Map<ImClass, Integer> classIds;
private ImFunction typeIdToTypeNameFunc;
private ImFunction maxTypeIdFunc;
private ImFunction instanceCountFunc;
Expand All @@ -52,6 +53,7 @@ public EliminateClasses(ImTranslator tr, ImProg prog, boolean checkedDispatch) {
translator = tr;
this.prog = prog;
this.checkedDispatch = checkedDispatch;
this.classIds = TypeId.calculate(prog);
}

public void eliminateClasses() {
Expand Down Expand Up @@ -88,32 +90,47 @@ 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();
}

@NotNull
private ImFunction maxTypeIdFunc() {
ImVars parameters = JassIm.ImVars();
int maxTypeId = calculateMaxTypeId(prog);
int maxTypeId = calculateMaxTypeId(classIds);
ImFunction f = JassIm.ImFunction(prog.getTrace(), "maxTypeId", JassIm.ImTypeVars(), parameters, imInt(), JassIm.ImVars(), JassIm.ImStmts(JassIm.ImReturn(prog.getTrace(), JassIm.ImIntVal(maxTypeId))), Collections.emptyList());
prog.getFunctions().add(f);
return f;
}

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,10 +146,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);
int maxTypeId = calculateMaxTypeId(classIds);
ImClass[] typeIdToClass = new ImClass[maxTypeId + 1];
for (Map.Entry<ImClass, Integer> e : classId.entrySet()) {
for (Map.Entry<ImClass, Integer> e : classIds.entrySet()) {
typeIdToClass[e.getValue()] = e.getKey();
}
ImStmts body = generateBinarySearch(1, maxTypeId, typeId, typeIdToClass, makeAccess);
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 Expand Up @@ -541,7 +561,7 @@ private void calculateTypeIdToMethodHelper(ImClass c,
}
}
if (current != null) {
typeIdToMethod.put(c.attrTypeId(), current);
typeIdToMethod.put(typeIdOf(c), current);
}
// process subclasses:
for (ImClass sc : c.attrSubclasses()) {
Expand Down Expand Up @@ -667,16 +687,15 @@ private void replaceTypeIdOfObj(ImTypeIdOfObj e) {
}

private void replaceTypeIdOfClass(ImTypeIdOfClass e) {
e.replaceBy(JassIm.ImIntVal(e.getClazz().getClassDef().attrTypeId()));
e.replaceBy(JassIm.ImIntVal(typeIdOf(e.getClazz().getClassDef())));
}

private void replaceInstanceof(ImInstanceof e) {
ImFunction f = e.getNearestFunc();
List<ImClass> allSubClasses = getAllSubclasses(e.getClazz().getClassDef());
List<Integer> subClassIds = new ArrayList<>();
for (ImClass allSubClass : allSubClasses) {
Integer attrTypeId = allSubClass.attrTypeId();
subClassIds.add(attrTypeId);
subClassIds.add(typeIdOf(allSubClass));
}
List<IntRange> idRanges = IntRange.createFromIntList(subClassIds);
ImExpr obj = e.getObj();
Expand Down Expand Up @@ -736,6 +755,18 @@ private void getAllSubclassesH(List<ImClass> result, ImClass clazz) {
}
}

private int typeIdOf(ImClass c) {
Integer id = classIds.get(c);
if (id != null) {
return id;
}
Integer fallback = TypeId.calculate(prog).get(c);
if (fallback != null) {
return fallback;
}
throw new CompileError(c, "Could not resolve type id for class " + c.getName() + ".");
}

private void replaceDealloc(ImDealloc e) {
ImFunction deallocFunc = translator.deallocFunc.getFor(e.getClazz().getClassDef());
ImExpr obj = e.getObj();
Expand Down
Loading
Loading