Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/refactor fix more tests #173

Merged
merged 14 commits into from
Oct 4, 2024

Conversation

kindlich
Copy link
Member

@kindlich kindlich commented Sep 6, 2024

No description provided.

@kindlich kindlich changed the base branch from development to feature/refactor September 6, 2024 21:35
@@ -469,4 +470,8 @@ public int hashCode() {
result = 31 * result + (hasUnknowns ? 1 : 0);
return result;
}

public boolean hasInvalidTypes() {
return Stream.of(parameters).anyMatch(p -> p.type.isInvalid());
Copy link
Member Author

Choose a reason for hiding this comment

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

💭 Thought: While writing this I found out we have BasicTypeID.INVALID and InvalidTypeID.
Do we need to change some calls that only compare for == BasicTypeID.INVALID to check for isInvalid() instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, we should change that.

@@ -27,13 +28,19 @@ public interface ResolvedType {
default Optional<Expression> tryCastExplicit(TypeID target, ExpressionCompiler compiler, CodePosition position, Expression value, boolean optional) {
return findCaster(target)
.filter(caster -> !caster.getModifiers().isImplicit())
.map(caster -> caster.call(compiler.at(position), value, CallArguments.EMPTY));
.flatMap(caster -> MatchedCallArguments.match(compiler, position, Collections.singletonList(caster), target, TypeID.NONE)
Copy link
Member Author

Choose a reason for hiding this comment

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

These changes were done since we need the ExpansionTypeParameters even for a caster.
Is there a better way than matching the method like this or is this fine?

Optional<IGlobal> global = context.findGlobal(name.name);
if (global.isPresent())
return global.map(g -> g.getExpression(position, name.arguments).compile(this));
// Resolve a local type first so that functions can shadow Globals
Copy link
Member Author

Choose a reason for hiding this comment

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

Does this have any side-effects that could cause us trouble?

@@ -74,6 +75,10 @@ public Statement transform(ExpressionTransformer transformer, ConcatMap<LoopStat

@Override
public Optional<TypeID> getReturnType() {
if(statements.length == 0) {
Copy link
Member Author

Choose a reason for hiding this comment

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

I wasn't sure if this check should be a special-case check here or further below if the collect List is empty?


int i = 1;
int i = 0;
Copy link
Member Author

Choose a reason for hiding this comment

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

💭 Thought: We probably need to do similar changes to the other methods in this class, but so far only this one caused Tests to fail 🤷🏽‍♂️

return resolvedType.findImplicitConstructor()
.map(constructor -> constructor.casted(compiler, position, cast, null, this))
.orElseGet(() -> cast.invalid(CompileErrors.invalidArrayType(cast.type)));
Optional<CastedExpression> implicitConstructor = resolvedType.findImplicitConstructor()
Copy link
Member Author

Choose a reason for hiding this comment

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

In theory this and check and the cast.of(eval()) branch cause implicit ctors to be checked twice.
But if we remove this here, some matching didn't work so I left it in

compiled.setBody(body.compile(compiler.forMethod(compiled.header.withReturnType(BasicTypeID.VOID))));

// Implicit .ctors return the created object, but "normal" ones don't, so for non-implict .ctors we change the header to return VOID
FunctionHeader compilingHeader = modifiers.isImplicit() ? compiled.header : compiled.header.withReturnType(BasicTypeID.VOID);
Copy link
Member Author

Choose a reason for hiding this comment

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

❓ Question: Is this the proper place for that check?

@kindlich kindlich force-pushed the feature/refactor-fix-more-tests branch from 78dc709 to 55af6be Compare September 14, 2024 13:01
@@ -559,4 +567,12 @@ public static CompileError invalidPropertySetter(TypeID type, String name) {
public static CompileError invalidPropertyPair(TypeID type, String name) {
return new CompileError(CompileExceptionCode.INVALID_PROPERTY_PAIR, "Setter and getter of property " + name + " in type " + type + " have different types");
}

public static CompileError invalidLambdaHeader(FunctionHeader header) {
Copy link
Member Author

Choose a reason for hiding this comment

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

🏷️ Naming: We probably need a better name here

@@ -1,4 +1,5 @@
#error: 4:TYPE_NOT_INFERRED
#error: 5:TYPE_NOT_INFERRED
#error: 5:MISSING_RETURN
Copy link
Member Author

Choose a reason for hiding this comment

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

❓ Question: Should this report both errors?

* @param statement the statement to validate
* @param validator the validator used to log errors
*/
public static void validate(TypeID returnType, Statement statement, Validator validator) {
Copy link
Member Author

Choose a reason for hiding this comment

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

❓ Are all members checked by now?

  • FunctionalMembers (methods, operators, ...)
  • Getters
  • Implicit constructors (only implicit)
  • FunctionsDefinition

Copy link
Contributor

Choose a reason for hiding this comment

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

setters also, with return type void

* @param validator the validator used to log errors
*/
public static void validate(TypeID returnType, Statement statement, Validator validator) {
if (returnType == BasicTypeID.VOID) {
Copy link
Member Author

Choose a reason for hiding this comment

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

💭 Discussion: We could move the returnType check outside this function and only ever call this function if we know the type is not void. Which approach do we like more?

.map(it -> it.content.accept(this))
.reduce(ReturnKind::branches)
.orElse(ReturnKind.NEVER_RETURNS);
ReturnKind finallyClause = statement.finallyClause == null ? ReturnKind.NEVER_RETURNS : statement.finallyClause.accept(this);
Copy link
Member Author

Choose a reason for hiding this comment

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

❓ Question: Do we actually allow return statements inside finally blocks?

for (Statement statement : statements) {
if (result == ReturnKind.ALWAYS_RETURNS) {
validator.logError(statement.position, CompileErrors.unreachableStatement());
break;
Copy link
Member Author

Choose a reason for hiding this comment

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

❓ Question: Should we log this for all following statements or is the first one fine?

Comment on lines +174 to +182
public static ReturnKind branches(ReturnKind a, ReturnKind b) {
if (a == NEVER_RETURNS && b == NEVER_RETURNS) {
return NEVER_RETURNS;
}
if (a == ALWAYS_RETURNS && b == ALWAYS_RETURNS) {
return ALWAYS_RETURNS;
}
return RETURNS_IN_SOME_CASES;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

💭 Discussion: The same functionality would be achieved by the code block below.
I find the explicit if/else structure more readable, what do you think?

Suggested change
public static ReturnKind branches(ReturnKind a, ReturnKind b) {
if (a == NEVER_RETURNS && b == NEVER_RETURNS) {
return NEVER_RETURNS;
}
if (a == ALWAYS_RETURNS && b == ALWAYS_RETURNS) {
return ALWAYS_RETURNS;
}
return RETURNS_IN_SOME_CASES;
}
public static ReturnKind branches(ReturnKind a, ReturnKind b) {
return a == b ? a : RETURNS_IN_SOME_CASES;
}

@kindlich kindlich marked this pull request as ready for review October 3, 2024 14:56
@@ -469,4 +470,8 @@ public int hashCode() {
result = 31 * result + (hasUnknowns ? 1 : 0);
return result;
}

public boolean hasInvalidTypes() {
return Stream.of(parameters).anyMatch(p -> p.type.isInvalid());
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, we should change that.


@Override
public ReturnKind visitForeach(ForeachStatement statement) {
return statement.getContent().accept(this);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not correct if there are zero elements

* @param statement the statement to validate
* @param validator the validator used to log errors
*/
public static void validate(TypeID returnType, Statement statement, Validator validator) {
Copy link
Contributor

Choose a reason for hiding this comment

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

setters also, with return type void

@stanhebben stanhebben merged commit 75ba801 into feature/refactor Oct 4, 2024
0 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants