Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions de.peeeq.wurstscript/parserspec/jass_im.parseq
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ ImConst =
| ImBoolVal(boolean valB)
| ImFuncRef(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImFunction func)
| ImNull(ref ImType type)
| ImTypeRef(@ignoreForEquality de.peeeq.wurstscript.ast.Element trace, ref ImClassType clazz)

ImTypeArguments * ImTypeArgument

Expand Down
1 change: 1 addition & 0 deletions de.peeeq.wurstscript/parserspec/wurstscript.parseq
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ Expr =
| ExprDestroy(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, Expr destroyedObj)
| ExprIfElse(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, Expr cond, Expr ifTrue, Expr ifFalse)
| ExprArrayLength(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, Expr array)
| ExprTypeRef(@ignoreForEquality de.peeeq.wurstscript.parser.WPos source, TypeExpr typ)

ExprMember =
ExprMemberVar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@ indexes:
'[' expr ']'
;

exprTypeRef
: typeName=ID typeArgsNonEmpty
;

expr:
exprPrimary
Expand All @@ -368,12 +371,14 @@ expr:
;



exprPrimary:
exprFunctionCall
| exprNewObject
| exprClosure
| exprStatementsBlock
| exprDestroy
| exprTypeRef
| varname=ID indexes?
| atom=(INT
| REAL
Expand Down Expand Up @@ -438,6 +443,9 @@ stmtBreak:'break';
stmtSkip:'skip';


typeArgsNonEmpty
: '<' (args+=typeExpr (',' args+=typeExpr)*)? '>'
;

typeArgs: ('<' (args+=typeExpr (',' args+=typeExpr)*)? '>')?;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public IlConstHandle BlzCreateFrameByType(ILconstString typeName, ILconstString
return new IlConstHandle("framehandle", new FrameHandle());
}

public IlConstHandle BlzGetFrameByName(ILconstString name, ILconstInt createContext) {
return new IlConstHandle("framehandle", new FrameHandle());
}

public void BlzFrameSetSize(IlConstHandle frame, ILconstReal width, ILconstReal height) {
}

Expand All @@ -35,4 +39,6 @@ public IlConstHandle ConvertOriginFrameType(ILconstInt i) {
return new IlConstHandle("frameType", i.getVal());
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,11 @@ public List<Either<String, MarkedString>> case_VisibilityPublic(VisibilityPublic
return string("This element can be used everywhere");
}

@Override
public List<Either<String, MarkedString>> case_ExprTypeRef(ExprTypeRef exprTypeRef) {
return List.of();
}

@Override
public List<Either<String, MarkedString>> case_TopLevelDeclarations(TopLevelDeclarations topLevelDeclarations) {
return string("A list of declarations.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,30 @@
import de.peeeq.wurstscript.ast.ExprMemberMethod;
import de.peeeq.wurstscript.ast.ExprNewObject;
import de.peeeq.wurstscript.types.CallSignature;
import de.peeeq.wurstscript.types.WurstType;

public class AttrCallSignature {

public static CallSignature calculate(ExprFunctionCall c) {
Expr receiver = null;
if (c.attrImplicitParameter() instanceof Expr) {
receiver = (Expr) c.attrImplicitParameter();
}
return new CallSignature(receiver, c.getArgs());
Expr receiver = (c.attrImplicitParameter() instanceof Expr) ? (Expr) c.attrImplicitParameter() : null;
WurstType hint = receiver != null ? receiver.attrTyp() : null;
return new CallSignature(receiver, hint, c.getArgs());
}

public static CallSignature calculate(ExprMemberMethod c) {
return new CallSignature(c.attrImplicitParameter(), c.getArgs());
// Always keep the instantiated left type as hint (e.g. OtherBox<int>)
WurstType hint = c.getLeft().attrTyp();

if (c.getLeft().attrTyp().isStaticRef()) {
// static ref like OtherBox<int>.staticItr()
return new CallSignature(null, hint, c.getArgs());
}

// instance call: keep real receiver expression AND hint
return new CallSignature(c.attrImplicitParameter(), hint, c.getArgs());
}

public static CallSignature calculate(ExprNewObject c) {
return new CallSignature(null, c.getArgs());
return new CallSignature((Expr) null, null, c.getArgs());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -591,4 +591,8 @@ public static WurstType calculate(ExprArrayLength exprArrayLength) {
exprArrayLength.addError(".length is only valid on arrays.");
return de.peeeq.wurstscript.types.WurstTypeUnknown.instance();
}

public static WurstType calculate(ExprTypeRef e) {
return e.getTyp().attrTyp();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
public class AttrImplicitParameter {

public static OptExpr getImplicitParameter(ExprMemberVar e) {
Expr result = getImplicitParameterUsingLeft(e);
Expr result = getImplicitParameterUsingLeft(e, true); // keep static refs
if (result == null) {
return getImplicitParamterCaseNormalVar(e);
} else {
Expand All @@ -18,7 +18,7 @@ public static OptExpr getImplicitParameter(ExprMemberVar e) {
}

public static OptExpr getImplicitParameter(ExprMemberArrayVar e) {
Expr result = getImplicitParameterUsingLeft(e);
Expr result = getImplicitParameterUsingLeft(e, true); // keep static refs
if (result == null) {
return getImplicitParamterCaseNormalVar(e);
} else {
Expand All @@ -40,7 +40,7 @@ public static OptExpr getImplicitParameter(ExprFunctionCall e) {
}

public static OptExpr getImplicitParameter(ExprMemberMethod e) {
Expr result = getImplicitParameterUsingLeft(e);
Expr result = getImplicitParameterUsingLeft(e, false);
if (result == null) {
return getImplicitParameterCaseNormalFunctionCall(e);
} else {
Expand All @@ -55,14 +55,19 @@ public static OptExpr getImplicitParameter(ExprMemberMethod e) {
}
}

private static @Nullable Expr getImplicitParameterUsingLeft(HasReceiver e) {
if (e.getLeft().attrTyp().isStaticRef()) {
// we have a static ref like Math.sqrt()
// this will be handled like if we just have sqrt()
// if we have an implicit parameter depends on whether sqrt is static or not
private static @Nullable Expr getImplicitParameterUsingLeft(HasReceiver e, boolean keepStaticRef) {
Expr left = e.getLeft();

if (left.attrTyp().isStaticRef()) {
// Only keep typed refs like Box<int> so we can specialize generics.
// Plain identifiers like BoxInt must NOT become runtime receivers.
if (keepStaticRef && left instanceof ExprTypeRef) {
return left;
}
return null;
}
return e.getLeft();

return left;
}

private static OptExpr getImplicitParameterCaseNormalFunctionCall(FunctionCall e) {
Expand All @@ -71,12 +76,19 @@ private static OptExpr getImplicitParameterCaseNormalFunctionCall(FunctionCall e
}

static OptExpr getFunctionCallImplicitParameter(FunctionCall e, FuncLink calledFunc, boolean showError) {
if (e instanceof HasReceiver) {
HasReceiver hasReceiver = (HasReceiver) e;
Expr res = getImplicitParameterUsingLeft(hasReceiver);
if (res != null) {
return res;
if (e instanceof HasReceiver hasReceiver) {
Expr left = hasReceiver.getLeft();

if (left.attrTyp().isStaticRef()) {
// Keep ONLY typed static refs to propagate type args (Box<int>.foo()).
if (left instanceof ExprTypeRef) {
return left; // type-only receiver
}
return Ast.NoExpr(); // plain BoxInt.foo() has no receiver
}

// normal dynamic receiver
return left;
}
if (calledFunc == null) {
return Ast.NoExpr();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -425,4 +425,8 @@ public static String description(NoTypeParamConstraints noTypeParamConstraints)
public static String description(ExprArrayLength exprArrayLength) {
return "Get the length of an array.";
}

public static String description(ExprTypeRef exprTypeRef) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,8 @@ public static ImmutableList<NameDef> calculate(ExprIfElse e) {
public static ImmutableList<NameDef> calculate(ExprArrayLength exprArrayLength) {
return ImmutableList.emptyList();
}

public static ImmutableList<NameDef> calculate(ExprTypeRef exprTypeRef) {
return ImmutableList.emptyList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private static <T extends NameLink> ImmutableCollection<T> removeDuplicates(List

public static ImmutableCollection<FuncLink> lookupMemberFuncs(Element node, WurstType receiverType, String name, boolean showErrors) {
if (!showErrors) {
GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType, GlobalCaches.LookupType.MEMBER_FUNC);
GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType.getFullName(), GlobalCaches.LookupType.MEMBER_FUNC);
@SuppressWarnings("unchecked")
ImmutableCollection<FuncLink> cached = (ImmutableCollection<FuncLink>) GlobalCaches.lookupCache.get(key);
if (cached != null) {
Expand Down Expand Up @@ -155,7 +155,7 @@ public static ImmutableCollection<FuncLink> lookupMemberFuncs(Element node, Wurs
ImmutableCollection<FuncLink> immutableResult = removeDuplicates(result);

if (!showErrors) {
GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType, GlobalCaches.LookupType.MEMBER_FUNC);
GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType.getFullName(), GlobalCaches.LookupType.MEMBER_FUNC);
GlobalCaches.lookupCache.put(key, immutableResult);
}

Expand Down Expand Up @@ -252,7 +252,7 @@ public static NameLink lookupVarNoConfig(Element node, String name, boolean show

public static NameLink lookupMemberVar(Element node, WurstType receiverType, String name, boolean showErrors) {
if (!showErrors) {
GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType, GlobalCaches.LookupType.MEMBER_VAR);
GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType.getFullName(), GlobalCaches.LookupType.MEMBER_VAR);
NameLink cached = (NameLink) GlobalCaches.lookupCache.get(key);
if (cached != null) {
return cached;
Expand Down Expand Up @@ -286,7 +286,7 @@ public static NameLink lookupMemberVar(Element node, WurstType receiverType, Str

if (bestMatch != null) {
if (!showErrors) {
GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType, GlobalCaches.LookupType.MEMBER_VAR);
GlobalCaches.CacheKey key = new GlobalCaches.CacheKey(node, name + "@" + receiverType.getFullName(), GlobalCaches.LookupType.MEMBER_VAR);
GlobalCaches.lookupCache.put(key, bestMatch.link);
}
return bestMatch.link;
Expand Down Expand Up @@ -413,13 +413,30 @@ private DefLinkMatch(DefLink link, int distance) {

public static DefLink matchDefLinkReceiver(DefLink n, WurstType receiverType, Element node, boolean showErrors) {
WurstType n_receiverType = n.getReceiverType();
if (n_receiverType == null) {
return null;
}
VariableBinding mapping = receiverType.matchAgainstSupertype(n_receiverType, node, VariableBinding.emptyMapping().withTypeVariables(n.getTypeParams()), VariablePosition.RIGHT);
if (mapping == null) {
return null;
if (n_receiverType == null) return null;

VariableBinding vb = VariableBinding.emptyMapping();

// 1) include type params from the receiver type (class/interface/module instantiation)
if (n_receiverType instanceof WurstTypeClassOrInterface wtc) {
if (wtc.getDef() instanceof AstElementWithTypeParameters tpOwner) {
vb = vb.withTypeVariables(tpOwner.getTypeParameters());
}
} else if (n_receiverType instanceof WurstTypeModuleInstanciation mins) {
ClassDef cd = mins.getDef().attrNearestClassDef();
if (cd != null) {
vb = vb.withTypeVariables(cd.getTypeParameters());
}
}

// 2) include function/extension type params as before
vb = vb.withTypeVariables(n.getTypeParams());

VariableBinding mapping =
receiverType.matchAgainstSupertype(n_receiverType, node, vb, VariablePosition.RIGHT);

if (mapping == null) return null;

if (showErrors) {
if (n.getVisibility() == Visibility.PRIVATE_OTHER) {
node.addError(Utils.printElement(n.getDef()) + " is private and cannot be used here.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1432,4 +1432,8 @@ public static void prettyPrint(ExprArrayLength exprArrayLength, Spacer spacer, S
exprArrayLength.getArray().prettyPrint(spacer, sb, indent);
sb.append(".length");
}

public static void prettyPrint(ExprTypeRef exprTypeRef, Spacer spacer, StringBuilder sb, int indent) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package de.peeeq.wurstscript.intermediatelang;

import de.peeeq.wurstscript.jassIm.ImClassType;

public final class ILconstTypeRef implements ILconst {
private final ImClassType type; // usually

public ILconstTypeRef(ImClassType type) {
this.type = type;
}

public ImClassType getType() {
return type;
}

@Override
public String print() {
return "";
}

@Override
public boolean isEqualTo(ILconst other) {
return false;
Comment on lines +16 to +23

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Implement equality/print for type reference constants

The new ILconstTypeRef always returns an empty string from print() and false from isEqualTo(...) (lines 16‑23), so any compile‑time evaluation that produces an ImTypeRef will yield a constant that can never compare equal even when the underlying class types match. This breaks basic semantics for expressions that compare or store type references (e.g. type‑keyed maps or equality checks in compile‑time functions) and will cause all such comparisons to return false. It should compare the wrapped ImClassType and render a meaningful value instead of hard‑coding failure.

Useful? React with 👍 / 👎.

}

@Override public String toString() {
return "type(" + type + ")";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -490,4 +490,10 @@ public static ILconst eval(ImCast imCast, ProgramState globalState, LocalState l
}
return res;
}

public static ILconst eval(ImTypeRef imTypeRef, ProgramState globalState, LocalState localState) {
// Resolve any type vars based on current substitutions:
ImType resolved = globalState.resolveType(imTypeRef.attrTyp());
return new ILconstTypeRef((ImClassType) resolved);
}
}
Loading
Loading