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:
Hubert Plociniczak 2023-01-09 11:35:36 +01:00 committed by GitHub
parent 0465aa3080
commit 3379ce51f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 280 additions and 35 deletions

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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))

View File

@ -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

View File

@ -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 =>

View File

@ -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
}
}
}

View File

@ -155,7 +155,7 @@ class TypeSignaturesTest extends CompilerTest {
| MyAtom
|
| ## is atom
| is_atom : this -> Boolean
| is_atom : Boolean
| is_atom = true
|
| error_signature : Int

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 =

View File

@ -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"