mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 22:10:15 +03:00
Report failed name resolutions in type signatures (#4030)
Compiler performed name resolution of literals in type signatures but would silently fail to report any problems. This meant that wrong names or forgotten imports would sneak in to stdlib. This change introduces 2 main changes: 1) failed name resolutions are appended in `TypeNames` pass 2) `GatherDiagnostics` pass also collects and reports failures from type signatures IR Updated stdlib so that it passes given the correct gatekeepers in place.
This commit is contained in:
parent
0465aa3080
commit
3379ce51f2
@ -498,6 +498,7 @@
|
||||
- [IGV can jump to JMH sources & more][4008]
|
||||
- [Basic support of VSCode integration][4014]
|
||||
- [Sync language server with file system after VCS restore][4020]
|
||||
- [Report failures in name resolution in type signatures][4030]
|
||||
|
||||
[3227]: https://github.com/enso-org/enso/pull/3227
|
||||
[3248]: https://github.com/enso-org/enso/pull/3248
|
||||
@ -579,6 +580,7 @@
|
||||
[4008]: https://github.com/enso-org/enso/pull/4008
|
||||
[4014]: https://github.com/enso-org/enso/pull/4014
|
||||
[4020]: https://github.com/enso-org/enso/pull/4020
|
||||
[4030]: https://github.com/enso-org/enso/pull/4030
|
||||
|
||||
# Enso 2.0.0-alpha.18 (2021-10-12)
|
||||
|
||||
|
@ -7,6 +7,7 @@ import project.Error.Common.Type_Error
|
||||
import project.Error.Error
|
||||
import project.Error.File_Error.File_Error
|
||||
import project.Error.Problem_Behavior.Problem_Behavior
|
||||
import project.Network.URI.URI
|
||||
import project.Network.HTTP.Header.Header
|
||||
import project.Network.HTTP.HTTP
|
||||
import project.Network.HTTP.HTTP_Method.HTTP_Method
|
||||
|
@ -577,7 +577,7 @@ type Decimal
|
||||
## ALIAS From Text
|
||||
|
||||
Parses a textual representation of a decimal into a decimal number, returning
|
||||
a `Parse_Error` if the text does not represent a valid decimal.
|
||||
a `Number_Parse_Error` if the text does not represent a valid decimal.
|
||||
|
||||
Arguments:
|
||||
- text: The text to parse into a decimal.
|
||||
@ -587,7 +587,7 @@ type Decimal
|
||||
Parse the text "7.6" into a decimal number.
|
||||
|
||||
Decimal.parse "7.6"
|
||||
parse : Text -> Locale | Nothing -> Decimal ! Parse_Error
|
||||
parse : Text -> Locale | Nothing -> Decimal ! Number_Parse_Error
|
||||
parse text locale=Nothing = case locale of
|
||||
Nothing -> Panic.catch NumberFormatException (Double.parseDouble text) _->
|
||||
Error.throw (Number_Parse_Error.Error text)
|
||||
@ -945,7 +945,7 @@ type Integer
|
||||
## ALIAS From Text
|
||||
|
||||
Parses a textual representation of an integer into an integer number, returning
|
||||
a `Parse_Error` if the text does not represent a valid integer.
|
||||
a `Number_Parse_Error` if the text does not represent a valid integer.
|
||||
|
||||
Arguments:
|
||||
- text: The text to parse into a integer.
|
||||
|
@ -19,6 +19,7 @@ import project.Data.Text.Span.Utf_16_Span
|
||||
import project.Data.Text.Text
|
||||
import project.Data.Text.Text_Matcher.Text_Matcher
|
||||
import project.Data.Text.Text_Sub_Range.Codepoint_Ranges
|
||||
import project.Data.Text.Text_Sub_Range.Text_Sub_Range
|
||||
import project.Data.Vector.Vector
|
||||
import project.Error.Common.Compile_Error
|
||||
import project.Error.Common.Index_Out_Of_Bounds
|
||||
@ -30,6 +31,7 @@ import project.Meta
|
||||
import project.Nothing.Nothing
|
||||
|
||||
from project.Data.Boolean import Boolean, True, False
|
||||
from project.Data.Text.Text_Sub_Range import Codepoint_Ranges, Text_Sub_Range
|
||||
|
||||
import project.Data.Index_Sub_Range as Index_Sub_Range_Module
|
||||
|
||||
@ -523,7 +525,7 @@ Text.is_whitespace self =
|
||||
Get the ASCII bytes of the text "Hello".
|
||||
|
||||
"Hello".bytes (Encoding.ascii)
|
||||
Text.bytes : Encoding -> Problem_Behavior -> Vector Byte
|
||||
Text.bytes : Encoding -> Problem_Behavior -> Vector Integer
|
||||
Text.bytes self encoding on_problems=Problem_Behavior.Report_Warning =
|
||||
result = Encoding_Utils.get_bytes self (encoding . to_java_charset)
|
||||
vector = Vector.from_polyglot_array result.result
|
||||
@ -546,7 +548,7 @@ Text.bytes self encoding on_problems=Problem_Behavior.Report_Warning =
|
||||
Get the ASCII bytes of the text "Hello".
|
||||
|
||||
"Hello".bytes (Encoding.ascii)
|
||||
Text.from_bytes : Vector Byte -> Encoding -> Problem_Behavior -> Text
|
||||
Text.from_bytes : Vector Integer -> Encoding -> Problem_Behavior -> Text
|
||||
Text.from_bytes bytes encoding on_problems=Problem_Behavior.Report_Warning =
|
||||
result = Encoding_Utils.from_bytes bytes.to_array (encoding . to_java_charset)
|
||||
if result.warnings.is_nothing then result.result else
|
||||
@ -569,7 +571,7 @@ Text.from_bytes bytes encoding on_problems=Problem_Behavior.Report_Warning =
|
||||
Get the UTF-8 bytes of the text "Hello".
|
||||
|
||||
"Hello".utf_8
|
||||
Text.utf_8 : Problem_Behavior -> Vector Byte
|
||||
Text.utf_8 : Problem_Behavior -> Vector Integer
|
||||
Text.utf_8 self on_problems=Problem_Behavior.Report_Warning =
|
||||
self.bytes Encoding.utf_8 on_problems
|
||||
|
||||
@ -590,7 +592,7 @@ Text.utf_8 self on_problems=Problem_Behavior.Report_Warning =
|
||||
Decoding the bytes to get a text.
|
||||
|
||||
Text.from_utf_8 [-32, -92, -107, -32, -91, -115, -32, -92, -73, -32, -92, -65]
|
||||
Text.from_utf_8 : Vector Byte -> Problem_Behavior -> Text
|
||||
Text.from_utf_8 : Vector Integer -> Problem_Behavior -> Text
|
||||
Text.from_utf_8 bytes on_problems=Problem_Behavior.Report_Warning =
|
||||
Text.from_bytes bytes Encoding.utf_8 on_problems
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
import project.Data.Text.Text
|
||||
import project.Data.Text.Regex.Regex_Option.Regex_Option
|
||||
import project.Data.Text.Regex.Invalid_Option
|
||||
import project.Data.Text.Regex.Pattern.Pattern
|
||||
import project.Data.Vector.Vector
|
||||
import project.Error.Common.Compile_Error
|
||||
import project.Error.Unimplemented.Unimplemented
|
||||
|
@ -1,6 +1,7 @@
|
||||
import project.Data.Boolean.Boolean
|
||||
import project.Data.Numbers.Integer
|
||||
import project.Data.Text.Matching_Mode
|
||||
import project.Data.Text.Regex.Match.Match
|
||||
import project.Data.Text.Regex.Regex_Mode.Regex_Mode
|
||||
import project.Data.Text.Text
|
||||
import project.Data.Vector.Vector
|
||||
|
@ -1,5 +1,6 @@
|
||||
import project.Any.Any
|
||||
import project.Data.Json.JS_Object
|
||||
import project.Data.Numbers.Decimal
|
||||
import project.Data.Numbers.Integer
|
||||
import project.Data.Ordering.Ordering
|
||||
import project.Data.Pair.Pair
|
||||
|
@ -1,5 +1,6 @@
|
||||
import project.Any.Any
|
||||
import project.Data.Text.Text
|
||||
import project.Data.Vector.Vector
|
||||
import project.Meta
|
||||
import project.Panic.Panic
|
||||
import project.Runtime.Stack_Trace_Element
|
||||
|
@ -97,6 +97,13 @@ type Stack_Trace_Element
|
||||
## PRIVATE
|
||||
Value name source_location
|
||||
|
||||
## ADVANCED
|
||||
|
||||
Types indicating allowed IO operations
|
||||
type IO_Permissions
|
||||
Input
|
||||
Output
|
||||
|
||||
## ADVANCED
|
||||
UNSTABLE
|
||||
|
||||
|
@ -26,6 +26,8 @@ import project.System.File.File_Permissions.File_Permissions
|
||||
from project.Data.Boolean import Boolean, True, False
|
||||
|
||||
polyglot java import org.enso.base.Encoding_Utils
|
||||
polyglot java import org.enso.base.encoding.ReportingStreamDecoder
|
||||
polyglot java import org.enso.base.encoding.ReportingStreamEncoder
|
||||
polyglot java import java.io.InputStream as Java_Input_Stream
|
||||
polyglot java import java.io.OutputStream as Java_Output_Stream
|
||||
polyglot java import java.nio.file.FileSystems
|
||||
|
@ -1,6 +1,6 @@
|
||||
from Standard.Base import all
|
||||
|
||||
import project.Connection.Connection_Options
|
||||
import project.Connection.Connection_Options.Connection_Options
|
||||
import project.Internal.SQLite.SQLite_Connection
|
||||
|
||||
type SQLite_Options
|
||||
|
@ -7,8 +7,10 @@ import project.Connection.Connection.Connection
|
||||
import project.Data.SQL_Statement.SQL_Statement
|
||||
import project.Data.SQL_Type.SQL_Type
|
||||
import project.Data.Table.Table
|
||||
import project.Internal.IR.From_Spec.From_Spec
|
||||
import project.Internal.IR.Internal_Column.Internal_Column
|
||||
import project.Internal.IR.Order_Descriptor.Order_Descriptor
|
||||
import project.Internal.IR.Query.Query
|
||||
import project.Internal.Postgres.Postgres_Dialect
|
||||
import project.Internal.Redshift.Redshift_Dialect
|
||||
import project.Internal.SQLite.SQLite_Dialect
|
||||
|
@ -8,10 +8,12 @@ import Standard.Base.Error.Incomparable_Values.Incomparable_Values
|
||||
import Standard.Base.Error.Unimplemented.Unimplemented
|
||||
|
||||
from Standard.Table import Auto_Detect, Aggregate_Column, Data_Formatter, Column_Name_Mapping, Column_Selector, Sort_Column_Selector, Sort_Column, Match_Columns, Position
|
||||
import Standard.Table.Data.Column_Type_Selection.Column_Type_Selection
|
||||
import Standard.Table.Data.Expression.Expression
|
||||
import Standard.Table.Data.Expression.Expression_Error
|
||||
import Standard.Table.Data.Join_Condition.Join_Condition
|
||||
import Standard.Table.Data.Join_Kind.Join_Kind
|
||||
import Standard.Table.Data.Row.Row
|
||||
import Standard.Table.Data.Table.Table as Materialized_Table
|
||||
import Standard.Table.Internal.Java_Exports
|
||||
import Standard.Table.Internal.Table_Helpers
|
||||
@ -21,7 +23,7 @@ import Standard.Table.Internal.Aggregate_Column_Helper
|
||||
from Standard.Table.Data.Column import get_item_string
|
||||
from Standard.Table.Data.Table import print_table
|
||||
from Standard.Table.Internal.Filter_Condition_Helpers import make_filter_column
|
||||
from Standard.Table.Errors import No_Index_Set_Error, No_Such_Column
|
||||
from Standard.Table.Errors import Column_Count_Mismatch, No_Index_Set_Error, No_Such_Column
|
||||
|
||||
import project.Data.Column.Column
|
||||
import project.Data.SQL_Statement.SQL_Statement
|
||||
@ -1065,7 +1067,7 @@ type Table
|
||||
invalid, a `File_Error.Not_Found` is raised.
|
||||
- If another IO error occurs, such as access denied, an
|
||||
`File_Error.IO_Error` is raised.
|
||||
- If appending and the columns do not match, a `Column_Mismatch` is
|
||||
- If appending and the columns do not match, a `Column_Count_Mismatch` is
|
||||
raised.
|
||||
- Other specific errors or warnings that can be raised depend on the
|
||||
format argument.
|
||||
@ -1091,7 +1093,7 @@ type Table
|
||||
connection = Database.connect (SQLite (File.new "db.sqlite"))
|
||||
table = connection.query (SQL_Query.Table_Name "Table")
|
||||
table.write (enso_project.data / "example_csv_output.csv")
|
||||
write : File|Text -> File_Format -> Existing_File_Behavior -> Match_Columns -> Problem_Behavior -> Nothing ! Column_Mismatch | Illegal_Argument | File_Error
|
||||
write : File|Text -> File_Format -> Existing_File_Behavior -> Match_Columns -> Problem_Behavior -> Nothing ! Column_Count_Mismatch | Illegal_Argument | File_Error
|
||||
write self path format=Auto_Detect on_existing_file=Existing_File_Behavior.Backup match_columns=Match_Columns.By_Name on_problems=Report_Warning =
|
||||
# TODO This should ideally be done in a streaming manner, or at least respect the row limits.
|
||||
self.read.write path format on_existing_file match_columns on_problems
|
||||
|
@ -2,6 +2,7 @@ from Standard.Base import all
|
||||
|
||||
import project.Data.Table.Table
|
||||
import project.Data.Column.Column
|
||||
import project.Internal.IR.Internal_Column.Internal_Column
|
||||
|
||||
from project.Errors import Unsupported_Name, Unsupported_Database_Operation
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
from Standard.Base import all
|
||||
import Standard.Base.Error.File_Error.File_Error
|
||||
|
||||
import project.Read_Flag.Read_Flag
|
||||
import project.Write_Flag.Write_Flag
|
||||
import project.Data.Histogram.Histogram
|
||||
import project.Data.Matrix.Matrix
|
||||
import project.Data.Matrix_Error.Matrix_Error
|
||||
|
@ -1,3 +1,5 @@
|
||||
import Standard.Base.Data.Vector.Vector
|
||||
|
||||
## Represents different types of underlying storage for Columns.
|
||||
type Storage
|
||||
## A column storing text data.
|
||||
|
@ -18,6 +18,7 @@ import project.Data.Join_Condition.Join_Condition
|
||||
import project.Data.Join_Kind.Join_Kind
|
||||
import project.Data.Match_Columns.Match_Columns
|
||||
import project.Data.Position.Position
|
||||
import project.Data.Row.Row
|
||||
import project.Data.Storage.Storage
|
||||
import project.Data.Value_Type.Value_Type
|
||||
import project.Data.Sort_Column_Selector.Sort_Column_Selector
|
||||
@ -38,7 +39,7 @@ import project.Delimited.Delimited_Format.Delimited_Format
|
||||
|
||||
from project.Data.Column_Type_Selection import Column_Type_Selection, Auto
|
||||
from project.Internal.Rows_View import Rows_View
|
||||
from project.Errors import Missing_Input_Columns, Column_Indexes_Out_Of_Range, Duplicate_Type_Selector, No_Index_Set_Error, No_Such_Column, No_Input_Columns_Selected, No_Output_Columns, Invalid_Value_Type
|
||||
from project.Errors import Column_Count_Mismatch, Missing_Input_Columns, Column_Indexes_Out_Of_Range, Duplicate_Type_Selector, No_Index_Set_Error, No_Such_Column, No_Input_Columns_Selected, No_Output_Columns, Invalid_Value_Type
|
||||
|
||||
from project.Data.Column import get_item_string
|
||||
from project.Internal.Filter_Condition_Helpers import make_filter_column
|
||||
@ -1373,7 +1374,7 @@ type Table
|
||||
from Standard.Table import Excel
|
||||
|
||||
example_to_xlsx = Examples.inventory_table.write (enso_project.data / "example_xlsx_output.xlsx") Excel
|
||||
write : File|Text -> File_Format -> Existing_File_Behavior -> Match_Columns -> Problem_Behavior -> Nothing ! Column_Mismatch | Illegal_Argument | File_Error
|
||||
write : File|Text -> File_Format -> Existing_File_Behavior -> Match_Columns -> Problem_Behavior -> Nothing ! Column_Count_Mismatch | Illegal_Argument | File_Error
|
||||
write self path format=Auto_Detect on_existing_file=Existing_File_Behavior.Backup match_columns=Match_Columns.By_Name on_problems=Report_Warning =
|
||||
file = File.new path
|
||||
case format of
|
||||
|
@ -1,5 +1,6 @@
|
||||
from Standard.Base import all
|
||||
import Standard.Base.Error.File_Error.File_Error
|
||||
import Standard.Base.System.File.Input_Stream
|
||||
|
||||
import project.Data.Table.Table
|
||||
import project.Excel.Excel_Range.Excel_Range
|
||||
|
@ -2,7 +2,7 @@ from Standard.Base import all
|
||||
import Standard.Base.Error.Illegal_Argument.Illegal_Argument
|
||||
import Standard.Base.Error.Illegal_State.Illegal_State
|
||||
|
||||
import project.Data.Table
|
||||
import project.Data.Table.Table
|
||||
import project.Data.Match_Columns.Match_Columns
|
||||
import project.Excel.Excel_Range.Excel_Range
|
||||
import project.Excel.Excel_Section.Excel_Section
|
||||
|
@ -4,6 +4,7 @@ import Standard.Base.Data.Ordering.Vector_Lexicographic_Order
|
||||
import Standard.Base.Error.Illegal_Argument.Illegal_Argument
|
||||
import Standard.Base.Error.Illegal_State.Illegal_State
|
||||
|
||||
import project.Data.Column.Column
|
||||
import project.Data.Column_Name_Mapping.Column_Name_Mapping
|
||||
import project.Data.Column_Selector.Column_Selector
|
||||
import project.Data.Position.Position
|
||||
@ -192,7 +193,7 @@ type Table_Column_Helper
|
||||
A helper function which selects a single column from the table. It is aligned
|
||||
with the `select_columns_helper`, apart from Blank_Columns selector which is
|
||||
only handled by the other method but not this one.
|
||||
resolve_column_helper : (Integer | Text | Column) -> Problem_Builder -> a | Nothing
|
||||
resolve_column_helper : (Integer | Text | Column) -> Problem_Builder -> Any | Nothing
|
||||
resolve_column_helper self selector problem_builder = case selector of
|
||||
_ : Text ->
|
||||
matched_columns = self.internal_columns.filter column->(column.name==selector)
|
||||
|
@ -1,5 +1,6 @@
|
||||
from Standard.Base import all
|
||||
import Standard.Base.Runtime.Source_Location.Source_Location
|
||||
import Standard.Base.Runtime.Stack_Trace_Element
|
||||
|
||||
polyglot java import java.lang.NullPointerException
|
||||
|
||||
|
@ -174,14 +174,14 @@ limit_data limit data = case limit of
|
||||
extreme + data.take (Index_Sub_Range.Sample (limit - extreme.length))
|
||||
|
||||
## PRIVATE
|
||||
json_from_table : Table -> [Int]|Nothing -> Int|Nothing -> Text
|
||||
json_from_table : Table -> [Integer]|Nothing -> Integer|Nothing -> Text
|
||||
json_from_table table bounds limit =
|
||||
data = table.point_data |> bound_data bounds |> limit_data limit
|
||||
axes = table.axes
|
||||
JS_Object.from_pairs [[data_field, data], [axis_field, axes]] . to_json
|
||||
|
||||
## PRIVATE
|
||||
json_from_vector : Vector Any -> [Int]|Nothing -> Int|Nothing -> Text
|
||||
json_from_vector : Vector Any -> [Integer]|Nothing -> Integer|Nothing -> Text
|
||||
json_from_vector vec bounds limit =
|
||||
data = vec.point_data |> bound_data bounds |> limit_data limit
|
||||
JS_Object.from_pairs [[data_field, data], [axis_field, Nothing]] . to_json
|
||||
|
@ -69,7 +69,7 @@ prepare_visualization x max_rows=1000 = Helpers.recover_errors <| case x of
|
||||
`dataframe`.
|
||||
- all_rows_count: the number of all rows in the underlying data, useful if
|
||||
only a fragment is displayed.
|
||||
make_json : (Dataframe_Table | Database_Table) -> Vector Column -> Integer -> Text
|
||||
make_json : (Dataframe_Table | Database_Table) -> Vector Dataframe_Column -> Integer -> Text
|
||||
make_json dataframe indices all_rows_count =
|
||||
columns = dataframe.columns
|
||||
header = ["header", columns.map .name]
|
||||
|
@ -5,6 +5,7 @@ import org.enso.compiler.context.{InlineContext, ModuleContext}
|
||||
import org.enso.compiler.core.IR
|
||||
import org.enso.compiler.core.ir.MetadataStorage._
|
||||
import org.enso.compiler.pass.IRPass
|
||||
import org.enso.compiler.pass.resolve.TypeSignatures
|
||||
|
||||
import scala.annotation.unused
|
||||
|
||||
@ -19,7 +20,7 @@ case object GatherDiagnostics extends IRPass {
|
||||
override type Metadata = DiagnosticsMeta
|
||||
override type Config = IRPass.Configuration.Default
|
||||
|
||||
override val precursorPasses: Seq[IRPass] = List()
|
||||
override val precursorPasses: Seq[IRPass] = List(TypeSignatures)
|
||||
override val invalidatedPasses: Seq[IRPass] = List()
|
||||
|
||||
/** Executes the pass on the provided `ir`, and attaches all the encountered
|
||||
@ -63,8 +64,17 @@ case object GatherDiagnostics extends IRPass {
|
||||
*/
|
||||
private def gatherMetadata(ir: IR): DiagnosticsMeta = {
|
||||
val diagnostics = ir.preorder.collect {
|
||||
case err: IR.Diagnostic => List(err)
|
||||
case x => x.diagnostics.toList
|
||||
case err: IR.Diagnostic =>
|
||||
List(err)
|
||||
case x: IR.Module.Scope.Definition.Method =>
|
||||
val typeSignatureDiagnostics =
|
||||
x.getMetadata(TypeSignatures)
|
||||
.map(_.signature.preorder.collect { case err: IR.Diagnostic =>
|
||||
err
|
||||
})
|
||||
.getOrElse(Nil)
|
||||
typeSignatureDiagnostics ++ x.diagnostics.toList
|
||||
case x => x.diagnostics.toList
|
||||
}.flatten
|
||||
DiagnosticsMeta(
|
||||
diagnostics.distinctBy(d => new DiagnosticKeys(d))
|
||||
|
@ -4,7 +4,7 @@ import org.enso.compiler.context.{InlineContext, ModuleContext}
|
||||
import org.enso.compiler.core.IR
|
||||
import org.enso.compiler.core.ir.MetadataStorage.ToPair
|
||||
import org.enso.compiler.data.BindingsMap
|
||||
import org.enso.compiler.data.BindingsMap.Resolution
|
||||
import org.enso.compiler.data.BindingsMap.{Resolution, ResolvedModule}
|
||||
import org.enso.compiler.pass.IRPass
|
||||
import org.enso.compiler.pass.analyse.BindingAnalysis
|
||||
|
||||
@ -74,11 +74,25 @@ case object TypeNames extends IRPass {
|
||||
bindingsMap: BindingsMap,
|
||||
expression: IR.Expression
|
||||
): IR.Expression =
|
||||
expression.transformExpressions { case n: IR.Name.Literal =>
|
||||
bindingsMap
|
||||
.resolveName(n.name)
|
||||
.map(res => n.updateMetadata(this -->> Resolution(res)))
|
||||
.getOrElse(n)
|
||||
expression.transformExpressions {
|
||||
case expr if SuspendedArguments.representsSuspended(expr) => expr
|
||||
case n: IR.Name.Literal =>
|
||||
bindingsMap
|
||||
.resolveName(n.name)
|
||||
.map(res => n.updateMetadata(this -->> Resolution(res)))
|
||||
.fold(
|
||||
error =>
|
||||
IR.Error.Resolution(n, IR.Error.Resolution.ResolverError(error)),
|
||||
n =>
|
||||
n.getMetadata(this).get.target match {
|
||||
case _: ResolvedModule =>
|
||||
IR.Error.Resolution(
|
||||
n,
|
||||
IR.Error.Resolution.UnexpectedModule("type signature")
|
||||
)
|
||||
case _ => n
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/** Executes the pass on the provided `ir`, and returns a possibly transformed
|
||||
|
@ -83,11 +83,7 @@ case object TypeSignatures extends IRPass {
|
||||
|
||||
val newBindings: List[IR.Module.Scope.Definition] = mod.bindings.flatMap {
|
||||
case sig: IR.Type.Ascription =>
|
||||
val res = lastSignature match {
|
||||
case Some(oldSig) => Some(IR.Error.Unexpected.TypeSignature(oldSig))
|
||||
case None => None
|
||||
}
|
||||
|
||||
val res = lastSignature.map(IR.Error.Unexpected.TypeSignature(_))
|
||||
lastSignature = Some(sig)
|
||||
res
|
||||
case meth: IR.Module.Scope.Definition.Method =>
|
||||
|
@ -0,0 +1,174 @@
|
||||
package org.enso.compiler.test.pass.resolve
|
||||
|
||||
import org.enso.compiler.Passes
|
||||
import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext}
|
||||
import org.enso.compiler.core.IR
|
||||
import org.enso.compiler.data.BindingsMap.ResolutionNotFound
|
||||
import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager}
|
||||
import org.enso.compiler.pass.resolve.{TypeNames, TypeSignatures}
|
||||
import org.enso.compiler.test.CompilerTest
|
||||
|
||||
class TypeNamesTest extends CompilerTest {
|
||||
|
||||
// === Test Setup ===========================================================
|
||||
|
||||
val passes = new Passes(defaultConfig)
|
||||
|
||||
val precursorPasses: PassGroup = passes.getPrecursors(TypeNames).get
|
||||
|
||||
val passConfiguration: PassConfiguration = PassConfiguration()
|
||||
|
||||
implicit val passManager: PassManager =
|
||||
new PassManager(List(precursorPasses), passConfiguration)
|
||||
|
||||
/** Adds an extension method to a module for performing type signature
|
||||
* resolution.
|
||||
*
|
||||
* @param ir the IR to add the extension method to
|
||||
*/
|
||||
implicit class ResolveModule(ir: IR.Module) {
|
||||
|
||||
/** Resolves type signatures in [[ir]].
|
||||
*
|
||||
* @param moduleContext the context in which resolution is taking place
|
||||
* @return [[ir]], with all type signatures resolved
|
||||
*/
|
||||
def resolve(implicit moduleContext: ModuleContext): IR.Module = {
|
||||
TypeNames.runModule(ir, moduleContext)
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds an extension method to an expression for performing type signature
|
||||
* resolution.
|
||||
*
|
||||
* @param ir the expression to add the extension method to
|
||||
*/
|
||||
implicit class ResolveExpression(ir: IR.Expression) {
|
||||
|
||||
/** Resolves type signatures in [[ir]].
|
||||
*
|
||||
* @param inlineContext the context in which resolution is taking place
|
||||
* @return [[ir]], with all type signatures resolved
|
||||
*/
|
||||
def resolve(implicit inlineContext: InlineContext): IR.Expression = {
|
||||
TypeNames.runExpression(ir, inlineContext)
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a defaulted module context.
|
||||
*
|
||||
* @return a defaulted module context
|
||||
*/
|
||||
def mkModuleContext: ModuleContext = {
|
||||
buildModuleContext(freshNameSupply = Some(new FreshNameSupply))
|
||||
}
|
||||
|
||||
/** Creates a defaulted inline context.
|
||||
*
|
||||
* @return a defaulted inline context
|
||||
*/
|
||||
def mkInlineContext: InlineContext = {
|
||||
buildInlineContext(freshNameSupply = Some(new FreshNameSupply))
|
||||
}
|
||||
|
||||
// === The Tests ============================================================
|
||||
|
||||
"Resolution of type names in modules" should {
|
||||
implicit val ctx: ModuleContext = mkModuleContext
|
||||
|
||||
"should correctly resolve local type names" in {
|
||||
val ir =
|
||||
"""
|
||||
|type A
|
||||
|type B
|
||||
|type C
|
||||
|
|
||||
|foo : A -> B -> C
|
||||
|foo a b = a + b
|
||||
|""".stripMargin.preprocessModule.resolve
|
||||
|
||||
ir.bindings.length shouldEqual 4
|
||||
val meta = ir.bindings.last.getMetadata(TypeSignatures)
|
||||
meta shouldBe defined
|
||||
val diagnostics = meta.get.signature.preorder
|
||||
.collect({ case err: IR.Diagnostic =>
|
||||
err
|
||||
})
|
||||
|
||||
diagnostics shouldBe Nil
|
||||
}
|
||||
|
||||
"should report failures when type name is unknown" in {
|
||||
val ir =
|
||||
"""
|
||||
|type A
|
||||
|type B
|
||||
|
|
||||
|foo : A -> B -> C
|
||||
|foo a b = a + b
|
||||
|""".stripMargin.preprocessModule.resolve
|
||||
|
||||
ir.bindings.length shouldEqual 3
|
||||
val meta = ir.bindings.last.getMetadata(TypeSignatures)
|
||||
meta shouldBe defined
|
||||
val diagnostics = meta.get.signature.preorder
|
||||
.collect({ case err: IR.Diagnostic =>
|
||||
err
|
||||
})
|
||||
|
||||
diagnostics.length shouldEqual 1
|
||||
val resolutionFailure = diagnostics.head.asInstanceOf[IR.Error.Resolution]
|
||||
resolutionFailure.name shouldBe "C"
|
||||
resolutionFailure.reason shouldBe IR.Error.Resolution.ResolverError(
|
||||
ResolutionNotFound
|
||||
)
|
||||
}
|
||||
|
||||
"should report every failed name resolution" in {
|
||||
val ir =
|
||||
"""
|
||||
|foo : Integer -> Integer -> Integer
|
||||
|foo a b = a + b
|
||||
|""".stripMargin.preprocessModule.resolve
|
||||
|
||||
ir.bindings.length shouldEqual 1
|
||||
val meta = ir.bindings.last.getMetadata(TypeSignatures)
|
||||
meta shouldBe defined
|
||||
val diagnostics = meta.get.signature.preorder
|
||||
.collect({ case err: IR.Diagnostic =>
|
||||
err
|
||||
})
|
||||
|
||||
diagnostics.length shouldEqual 3
|
||||
diagnostics.foreach {
|
||||
case d: IR.Error.Resolution =>
|
||||
d.name shouldBe "Integer"
|
||||
d.reason shouldBe IR.Error.Resolution.ResolverError(
|
||||
ResolutionNotFound
|
||||
)
|
||||
case _ =>
|
||||
fail()
|
||||
}
|
||||
}
|
||||
|
||||
"should treat Suspended type specially" in {
|
||||
val ir =
|
||||
"""
|
||||
|type A
|
||||
|
|
||||
|foo : A -> Suspended -> A
|
||||
|foo a b = a + b
|
||||
|""".stripMargin.preprocessModule.resolve
|
||||
|
||||
ir.bindings.length shouldEqual 2
|
||||
val meta = ir.bindings.last.getMetadata(TypeSignatures)
|
||||
meta shouldBe defined
|
||||
val diagnostics = meta.get.signature.preorder
|
||||
.collect({ case err: IR.Diagnostic =>
|
||||
err
|
||||
})
|
||||
|
||||
diagnostics.length shouldEqual 0
|
||||
}
|
||||
}
|
||||
}
|
@ -155,7 +155,7 @@ class TypeSignaturesTest extends CompilerTest {
|
||||
| MyAtom
|
||||
|
|
||||
| ## is atom
|
||||
| is_atom : this -> Boolean
|
||||
| is_atom : Boolean
|
||||
| is_atom = true
|
||||
|
|
||||
| error_signature : Int
|
||||
|
@ -174,6 +174,9 @@ class TypeSignaturesTest
|
||||
"be parsed in a simple scenario" in {
|
||||
val code =
|
||||
"""
|
||||
|type Text
|
||||
|type Number
|
||||
|
|
||||
|foo : Text -> Number
|
||||
|foo a = 42""".stripMargin
|
||||
val module = code.preprocessModule
|
||||
@ -244,6 +247,11 @@ class TypeSignaturesTest
|
||||
"resolve execution contexts" in {
|
||||
val code =
|
||||
"""
|
||||
|type A
|
||||
|type B
|
||||
|type C
|
||||
|type Input
|
||||
|
|
||||
|foo : A -> B -> C in Input
|
||||
|foo a b = c
|
||||
|""".stripMargin
|
||||
|
@ -18,6 +18,7 @@ class DevelopmentContextTest extends InterpreterTest {
|
||||
"error on Input actions" in {
|
||||
val code =
|
||||
"""from Standard.Base import all
|
||||
|from Standard.Base.Runtime.IO_Permissions import Input
|
||||
|
|
||||
|input_action : Integer -> Integer in Input
|
||||
|input_action i = i
|
||||
@ -30,6 +31,7 @@ class DevelopmentContextTest extends InterpreterTest {
|
||||
"error on Output actions" in {
|
||||
val code =
|
||||
"""from Standard.Base import all
|
||||
|from Standard.Base.Runtime.IO_Permissions import Output
|
||||
|
|
||||
|output_action : Integer -> Nothing in Output
|
||||
|output_action i = i
|
||||
@ -42,6 +44,7 @@ class DevelopmentContextTest extends InterpreterTest {
|
||||
"allow locally running IO" in {
|
||||
val code =
|
||||
"""from Standard.Base import all
|
||||
|from Standard.Base.Runtime.IO_Permissions import Input, Output
|
||||
|
|
||||
|output_action : Integer -> Integer in Output
|
||||
|output_action i = i + 1
|
||||
@ -69,6 +72,7 @@ class ProductionContextTest extends InterpreterTest {
|
||||
"allow all IO" in {
|
||||
val code =
|
||||
"""from Standard.Base import all
|
||||
|from Standard.Base.Runtime.IO_Permissions import Input, Output
|
||||
|
|
||||
|output_action : Integer -> Integer in Output
|
||||
|output_action i = i + 1
|
||||
|
@ -4,6 +4,7 @@ from Standard.Test import Test, Test_Suite
|
||||
import Standard.Test.Extensions
|
||||
|
||||
polyglot java import java.util.HashMap
|
||||
polyglot java import java.util.Random as Java_Random
|
||||
|
||||
type CustomEqType
|
||||
C1 f1
|
||||
|
@ -1,12 +1,15 @@
|
||||
import Standard.Base.Runtime
|
||||
import Standard.Base.Data.Numbers.Integer
|
||||
|
||||
from Standard.Base.Runtime.IO_Permissions import Input, Output
|
||||
|
||||
from Standard.Test import Test
|
||||
import Standard.Test.Extensions
|
||||
|
||||
in_fn : Int -> Int in Input
|
||||
in_fn : Integer -> Integer in Input
|
||||
in_fn a = a * 2
|
||||
|
||||
out_fn : Int -> Int in Output
|
||||
out_fn : Integer -> Integer in Output
|
||||
out_fn a = a + 1
|
||||
|
||||
spec =
|
||||
|
@ -1,3 +1,7 @@
|
||||
type IO_Permissions
|
||||
Input
|
||||
Output
|
||||
|
||||
primitive_get_stack_trace = @Builtin_Method "Runtime.primitive_get_stack_trace"
|
||||
allow_input_in env = @Builtin_Method "Runtime.allow_input_in"
|
||||
allow_output_in env = @Builtin_Method "Runtime.allow_output_in"
|
||||
|
Loading…
Reference in New Issue
Block a user