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

Verify ascribed types of parameters really exist #6584

Merged
merged 25 commits into from
May 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1cdb009
Verify ascribed types of parameters really exist
JaroslavTulach May 5, 2023
e4a3cd4
Ascriptions in type constructors shall be checked as well
JaroslavTulach May 5, 2023
cb6215c
No need to store result in arr variable
JaroslavTulach May 9, 2023
e378be5
Verify ascribed arguments of atom constructors
JaroslavTulach May 9, 2023
ebb52ce
Have to disable verifyAscribedArgument on the Type here
JaroslavTulach May 9, 2023
0711186
map the copy of the Type members
JaroslavTulach May 9, 2023
6345ee0
Adding missing imports
JaroslavTulach May 10, 2023
5522b68
Allow type parameters as ascribed types
JaroslavTulach May 10, 2023
17d7453
More of _ per Hubert's advice
JaroslavTulach May 10, 2023
6e2ce12
Less of currly braces
JaroslavTulach May 10, 2023
e385838
Case with _
JaroslavTulach May 10, 2023
648546e
buildEngineDistribution succeeds to generate its indicies with these …
JaroslavTulach May 10, 2023
b540a09
Modify UID version of the caches to avoid clashes of different IRs
JaroslavTulach May 10, 2023
0a378eb
Merging with origin/develop
JaroslavTulach May 10, 2023
91fba7e
Forcibly drop BindingsMap caches
JaroslavTulach May 10, 2023
0f82e6a
Extend cached BindingsMap, when it exists
JaroslavTulach May 10, 2023
67cf459
Force loading from cache before asking ensureParsed
JaroslavTulach May 11, 2023
7f6c0d8
Use bindings associated with module
JaroslavTulach May 11, 2023
61fbbda
scalafmtAll
JaroslavTulach May 11, 2023
569989b
Merge remote-tracking branch 'origin/develop' into wip/jtulach/CheckA…
JaroslavTulach May 11, 2023
478c2be
Call to mapImports is causing StackOverflow
JaroslavTulach May 11, 2023
f2df70c
Cleaning up bindings when re-assigning new source to a module
JaroslavTulach May 12, 2023
50e1da7
Merging with Dmitry's #6655
JaroslavTulach May 14, 2023
e9a42f2
Less changes against develop branch
JaroslavTulach May 14, 2023
2d21386
Make SignatureTest.ascribedWithAParameter pass
JaroslavTulach May 14, 2023
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 @@ -4,6 +4,7 @@ import project.Data.Numbers.Integer
import project.Data.Range.Extensions
import project.Data.Range.Range
import project.Data.Text.Regex.No_Such_Group
import project.Data.Text.Regex.Pattern.Pattern
import project.Data.Text.Span.Span
import project.Data.Text.Span.Utf_16_Span
import project.Data.Text.Text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Standard.Table.Internal.Widget_Helpers
from Standard.Table import Sort_Column, Data_Formatter, Value_Type, Auto
from Standard.Table.Errors import Floating_Point_Equality, Inexact_Type_Coercion, Invalid_Value_Type, Lossy_Conversion

import project.Connection.Connection.Connection
import project.Data.SQL_Statement.SQL_Statement
import project.Data.SQL_Type.SQL_Type
import project.Internal.Helpers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,7 @@ yield switch (op.codeRepr()) {
}
case Tree.Ident id when insideTypeAscription -> {
try {
yield buildQualifiedName(id, getIdentifiedLocation(id), false);
yield buildNameOrQualifiedName(id, getIdentifiedLocation(id));
} catch (SyntaxException ex) {
yield ex.toError();
}
Expand Down Expand Up @@ -1412,11 +1412,14 @@ private List<IR.Pattern> translatePatternFields(java.util.List<Tree> tail) throw
return new IR$Name$Qualified(qualifiedNameSegments(t, generateId), loc, meta(), diag());
}
private IR.Name buildNameOrQualifiedName(Tree t) throws SyntaxException {
return buildNameOrQualifiedName(t, Option.empty());
}
private IR.Name buildNameOrQualifiedName(Tree t, Option<IdentifiedLocation> loc) throws SyntaxException {
var segments = qualifiedNameSegments(t, false);
if (segments.length() == 1) {
return segments.head();
} else {
return new IR$Name$Qualified(segments, Option.empty(), meta(), diag());
return new IR$Name$Qualified(segments, loc, meta(), diag());
}
}
private java.util.List<Tree> unrollOprRhs(Tree list, String operator) throws SyntaxException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import scala.annotation.unused
*/

@SerialVersionUID(
5569L // removes special handling of `enso_project` method
6584L // verify ascribed types
)
case class BindingsMap(
definedEntities: List[DefinedEntity],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ case object GlobalNames extends IRPass {
"No fresh name supply passed to UppercaseNames resolver."
)
)
processExpression(ir, scopeMap, freshNameSupply, None)
processExpression(ir, scopeMap, List(), freshNameSupply, None)
}

/** @inheritdoc */
Expand All @@ -110,7 +110,7 @@ case object GlobalNames extends IRPass {
_.getMetadata(MethodDefinitions)
)
method.mapExpressions(
processExpression(_, bindings, freshNameSupply, resolution)
processExpression(_, bindings, List(), freshNameSupply, resolution)
)
case tp: IR.Module.Scope.Definition.Type =>
tp.copy(members =
Expand All @@ -119,6 +119,7 @@ case object GlobalNames extends IRPass {
processExpression(
_,
bindings,
tp.params,
freshNameSupply,
bindings.resolveName(tp.name.name).toOption.map(Resolution)
)
Expand All @@ -127,13 +128,16 @@ case object GlobalNames extends IRPass {
)

case a =>
a.mapExpressions(processExpression(_, bindings, freshNameSupply, None))
a.mapExpressions(
processExpression(_, bindings, List(), freshNameSupply, None)
)
}
}

private def processExpression(
ir: IR.Expression,
bindings: BindingsMap,
params: List[IR.DefinitionArgument],
freshNameSupply: FreshNameSupply,
selfTypeResolution: Option[Resolution],
isInsideApplication: Boolean = false
Expand All @@ -149,62 +153,66 @@ case object GlobalNames extends IRPass {
)
)
case lit: IR.Name.Literal =>
lit.getMetadata(FullyQualifiedNames) match {
case Some(
FullyQualifiedNames.FQNResolution(
FullyQualifiedNames.ResolvedModule(modRef)
)
) =>
lit.updateMetadata(this -->> Resolution(ResolvedModule(modRef)))
case _ =>
if (!lit.isMethod && !isLocalVar(lit)) {
val resolution = bindings.resolveName(lit.name)
resolution match {
case Left(error) =>
IR.Error.Resolution(
lit,
IR.Error.Resolution.ResolverError(error)
if (params.exists(p => p.name.name == lit.name)) {
lit
} else {
lit.getMetadata(FullyQualifiedNames) match {
case Some(
FullyQualifiedNames.FQNResolution(
FullyQualifiedNames.ResolvedModule(modRef)
)
case Right(r @ BindingsMap.ResolvedMethod(mod, method)) =>
if (isInsideApplication) {
lit.updateMetadata(this -->> BindingsMap.Resolution(r))
} else {
val self = freshNameSupply
.newName()
.updateMetadata(
this -->> BindingsMap.Resolution(
BindingsMap.ResolvedModule(mod)
)
)
// The synthetic applications gets the location so that instrumentation
// identifies the node correctly
val fun = lit.copy(
name = method.name,
location = None
)
val app = IR.Application.Prefix(
fun,
List(IR.CallArgument.Specified(None, self, None)),
hasDefaultsSuspended = false,
lit.location
) =>
lit.updateMetadata(this -->> Resolution(ResolvedModule(modRef)))
case _ =>
if (!lit.isMethod && !isLocalVar(lit)) {
val resolution = bindings.resolveName(lit.name)
resolution match {
case Left(error) =>
IR.Error.Resolution(
lit,
IR.Error.Resolution.ResolverError(error)
)
fun
.getMetadata(ExpressionAnnotations)
.foreach(annotationsMeta =>
app.updateMetadata(
ExpressionAnnotations -->> annotationsMeta
case Right(r @ BindingsMap.ResolvedMethod(mod, method)) =>
if (isInsideApplication) {
lit.updateMetadata(this -->> BindingsMap.Resolution(r))
} else {
val self = freshNameSupply
.newName()
.updateMetadata(
this -->> BindingsMap.Resolution(
BindingsMap.ResolvedModule(mod)
)
)
// The synthetic applications gets the location so that instrumentation
// identifies the node correctly
val fun = lit.copy(
name = method.name,
location = None
)
fun.passData.remove(ExpressionAnnotations)
app
}
case Right(value) =>
lit.updateMetadata(this -->> BindingsMap.Resolution(value))
}
val app = IR.Application.Prefix(
fun,
List(IR.CallArgument.Specified(None, self, None)),
hasDefaultsSuspended = false,
lit.location
)
fun
.getMetadata(ExpressionAnnotations)
.foreach(annotationsMeta =>
app.updateMetadata(
ExpressionAnnotations -->> annotationsMeta
)
)
fun.passData.remove(ExpressionAnnotations)
app
}
case Right(value) =>
lit.updateMetadata(this -->> BindingsMap.Resolution(value))
}

} else {
lit
}
} else {
lit
}
}
}
case app: IR.Application.Prefix =>
app.function match {
Expand All @@ -214,13 +222,15 @@ case object GlobalNames extends IRPass {
app,
lit,
bindings,
params,
freshNameSupply,
selfTypeResolution
)
else
resolveLocalApplication(
app,
bindings,
params,
freshNameSupply,
selfTypeResolution
)
Expand All @@ -229,6 +239,7 @@ case object GlobalNames extends IRPass {
processExpression(
_,
bindings,
params,
freshNameSupply,
selfTypeResolution
)
Expand All @@ -243,19 +254,27 @@ case object GlobalNames extends IRPass {
app: IR.Application.Prefix,
fun: IR.Name.Literal,
bindingsMap: BindingsMap,
params: List[IR.DefinitionArgument],
freshNameSupply: FreshNameSupply,
selfTypeResolution: Option[Resolution]
): IR.Expression = {
val processedFun = processExpression(
app.function,
bindingsMap,
params,
freshNameSupply,
selfTypeResolution,
isInsideApplication = true
)
val processedArgs = app.arguments.map(
_.mapExpressions(
processExpression(_, bindingsMap, freshNameSupply, selfTypeResolution)
processExpression(
_,
bindingsMap,
params,
freshNameSupply,
selfTypeResolution
)
)
)
processedFun.getMetadata(this) match {
Expand All @@ -278,20 +297,28 @@ case object GlobalNames extends IRPass {
private def resolveLocalApplication(
app: IR.Application.Prefix,
bindings: BindingsMap,
params: List[IR.DefinitionArgument],
freshNameSupply: FreshNameSupply,
selfTypeResolution: Option[Resolution]
): IR.Expression = {
val processedFun =
processExpression(
app.function,
bindings,
params,
freshNameSupply,
selfTypeResolution
)
val processedArgs =
app.arguments.map(
_.mapExpressions(
processExpression(_, bindings, freshNameSupply, selfTypeResolution)
processExpression(
_,
bindings,
params,
freshNameSupply,
selfTypeResolution
)
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.graalvm.polyglot.PolyglotException;
import org.graalvm.polyglot.Source;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.BeforeClass;
Expand Down Expand Up @@ -42,4 +43,59 @@ public void wrongFunctionSignature() throws Exception {
assertTrue("It is a syntax error exception", e.isSyntaxError());
}
}

@Test
public void wrongAscribedTypeSignature() throws Exception {
final URI uri = new URI("memory://neg.enso");
final Source src = Source.newBuilder("enso", """
neg (a : Xyz) = 0 - a
""", uri.getHost())
.uri(uri)
.buildLiteral();

try {
var module = ctx.eval(src);
var neg = module.invokeMember("eval_expression", "neg");
fail("Expecting an exception from compilation, not: " + neg);
} catch (PolyglotException e) {
assertTrue("It is a syntax error exception", e.isSyntaxError());
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
}
}

@Test
public void wrongAscribedInConstructor() throws Exception {
final URI uri = new URI("memory://constructor.enso");
final Source src = Source.newBuilder("enso", """
type Neg
Val (a : Xyz)

neg = Neg.Val 10
""", uri.getHost())
.uri(uri)
.buildLiteral();

try {
var module = ctx.eval(src);
var neg = module.invokeMember("eval_expression", "neg");
fail("Expecting an exception from compilation, not: " + neg);
} catch (PolyglotException e) {
assertTrue("It is a syntax error exception", e.isSyntaxError());
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
}
}

@Test
public void ascribedWithAParameter() throws Exception {
final URI uri = new URI("memory://constructor.enso");
final Source src = Source.newBuilder("enso", """
type Maybe a
Nothing
Some unwrap:a
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
""", uri.getHost())
.uri(uri)
.buildLiteral();

var module = ctx.eval(src);
var some = module.invokeMember("eval_expression", "Maybe.Some 10");
assertEquals("Can read ten", 10, some.getMember("unwrap").asInt());
}
}