mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 22:10:15 +03:00
Support mixed constructors/bindings in types (#3870)
Libraries: Revert changes that were necessitated by a new rule we have decided not to introduce. Parser: - Support mixed constructors/bindings in types. - Disallow zero-length hex sequences in character escapes: `\x`, `\u`, `\u{}`, `\U`, `\U{}` are no longer legal synonyms for `\0` (matches old parser behavior).
This commit is contained in:
parent
85d4337f26
commit
a1db36b57c
@ -19,6 +19,18 @@ from project.Data.Statistics.Statistic import all
|
||||
from project.Data.Statistics.Statistic export all
|
||||
|
||||
type Statistic
|
||||
## PRIVATE
|
||||
Convert the Enso Statistic into Java equivalent.
|
||||
to_moment_statistic : SingleValue
|
||||
to_moment_statistic self = case self of
|
||||
Sum -> Moments.SUM
|
||||
Mean -> Moments.MEAN
|
||||
Variance p -> if p then Moments.VARIANCE_POPULATION else Moments.VARIANCE
|
||||
Standard_Deviation p -> if p then Moments.STANDARD_DEVIATION_POPULATION else Moments.STANDARD_DEVIATION
|
||||
Skew p -> if p then Moments.SKEW_POPULATION else Moments.SKEW
|
||||
Kurtosis -> Moments.KURTOSIS
|
||||
_ -> Nothing
|
||||
|
||||
## Count the number of non-Nothing and non-NaN values.
|
||||
Count
|
||||
|
||||
@ -77,18 +89,6 @@ type Statistic
|
||||
- predicted: the series to compute the r_squared with.
|
||||
R_Squared (predicted:Vector)
|
||||
|
||||
## PRIVATE
|
||||
Convert the Enso Statistic into Java equivalent.
|
||||
to_moment_statistic : SingleValue
|
||||
to_moment_statistic self = case self of
|
||||
Sum -> Moments.SUM
|
||||
Mean -> Moments.MEAN
|
||||
Variance p -> if p then Moments.VARIANCE_POPULATION else Moments.VARIANCE
|
||||
Standard_Deviation p -> if p then Moments.STANDARD_DEVIATION_POPULATION else Moments.STANDARD_DEVIATION
|
||||
Skew p -> if p then Moments.SKEW_POPULATION else Moments.SKEW
|
||||
Kurtosis -> Moments.KURTOSIS
|
||||
_ -> Nothing
|
||||
|
||||
|
||||
## Compute a single statistic on a vector like object.
|
||||
|
||||
|
@ -9,30 +9,6 @@ import project.Internal.IR.Order_Descriptor.Order_Descriptor
|
||||
|
||||
A context associated with an SQL query.
|
||||
type Context
|
||||
## PRIVATE
|
||||
|
||||
A context associated with an SQL query.
|
||||
|
||||
The expressions can only be computed in a context which specifies from where
|
||||
their columns come and set filters and other settings for processing the
|
||||
query.
|
||||
|
||||
Arguments:
|
||||
- from_spec: the sources for the query, see `From_Spec` for more
|
||||
details.
|
||||
- where_filters: a list of expressions for filtering - only the rows
|
||||
for which these expressions evaluate to true are included in the
|
||||
result.
|
||||
- orders: a list of ordering expressions, for each entry an ORDER BY
|
||||
clause is added.
|
||||
- groups: a list of grouping expressions, for each entry a GROUP BY is
|
||||
added, the resulting query can then directly include only the
|
||||
grouped-by columns or aggregate expressions.
|
||||
- meta_index: a list of internal columns to use for joining or grouping.
|
||||
- limit: an optional maximum number of elements that the equery should
|
||||
return.
|
||||
Value (from_spec : From_Spec) (where_filters : Vector SQL_Expression) (orders : Vector Order_Descriptor) (groups : Vector SQL_Expression) (meta_index : Vector Internal_Column) (limit : Nothing | Integer)
|
||||
|
||||
## PRIVATE
|
||||
|
||||
Creates a query context that just fetches data from a table, without any
|
||||
@ -66,6 +42,30 @@ type Context
|
||||
for_subquery subquery =
|
||||
Context.Value subquery [] [] [] [] Nothing
|
||||
|
||||
## PRIVATE
|
||||
|
||||
A context associated with an SQL query.
|
||||
|
||||
The expressions can only be computed in a context which specifies from where
|
||||
their columns come and set filters and other settings for processing the
|
||||
query.
|
||||
|
||||
Arguments:
|
||||
- from_spec: the sources for the query, see `From_Spec` for more
|
||||
details.
|
||||
- where_filters: a list of expressions for filtering - only the rows
|
||||
for which these expressions evaluate to true are included in the
|
||||
result.
|
||||
- orders: a list of ordering expressions, for each entry an ORDER BY
|
||||
clause is added.
|
||||
- groups: a list of grouping expressions, for each entry a GROUP BY is
|
||||
added, the resulting query can then directly include only the
|
||||
grouped-by columns or aggregate expressions.
|
||||
- meta_index: a list of internal columns to use for joining or grouping.
|
||||
- limit: an optional maximum number of elements that the equery should
|
||||
return.
|
||||
Value (from_spec : From_Spec) (where_filters : Vector SQL_Expression) (orders : Vector Order_Descriptor) (groups : Vector SQL_Expression) (meta_index : Vector Internal_Column) (limit : Nothing | Integer)
|
||||
|
||||
## PRIVATE
|
||||
|
||||
Returns a copy of the context with changed `meta_index`.
|
||||
|
@ -13,18 +13,6 @@ polyglot java import org.opencv.core.Scalar
|
||||
|
||||
## UNSTABLE
|
||||
type Image
|
||||
## UNSTABLE
|
||||
|
||||
The image data type.
|
||||
|
||||
Arguments:
|
||||
- opencv_mat: The underlying matrix that stores the image data.
|
||||
|
||||
The image is represented with a matrix of rows x columns. Each
|
||||
pixel is represented with a vector of 1 to 4 values (channels).
|
||||
Pixel values are normalized in a range [0.0 .. 1.0].
|
||||
Value opencv_mat
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
Create an image from the array of values.
|
||||
@ -114,6 +102,18 @@ type Image
|
||||
Panic.catch_java Any (Java_Codecs.write path self.opencv_mat int_flags) _->
|
||||
Error.throw (File.IO_Error (File.new path) 'Failed to write to the file')
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
The image data type.
|
||||
|
||||
Arguments:
|
||||
- opencv_mat: The underlying matrix that stores the image data.
|
||||
|
||||
The image is represented with a matrix of rows x columns. Each
|
||||
pixel is represented with a vector of 1 to 4 values (channels).
|
||||
Pixel values are normalized in a range [0.0 .. 1.0].
|
||||
Value opencv_mat
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
Return the number of image rows.
|
||||
|
@ -15,14 +15,6 @@ polyglot java import org.enso.table.operations.OrderBuilder
|
||||
from project.Data.Column.Column import Column_Data
|
||||
|
||||
type Column
|
||||
## PRIVATE
|
||||
|
||||
A representation of a column in a Table.
|
||||
|
||||
Arguments:
|
||||
- java_column: The internal representation of the column.
|
||||
Column_Data java_column
|
||||
|
||||
## Creates a new column given a name and a vector of elements.
|
||||
|
||||
Arguments:
|
||||
@ -39,6 +31,14 @@ type Column
|
||||
from_vector : Text -> Vector -> Column
|
||||
from_vector name items = Column_Data (Java_Column.fromItems name items.to_array)
|
||||
|
||||
## PRIVATE
|
||||
|
||||
A representation of a column in a Table.
|
||||
|
||||
Arguments:
|
||||
- java_column: The internal representation of the column.
|
||||
Column_Data java_column
|
||||
|
||||
## Returns a text containing an ASCII-art table displaying this data.
|
||||
|
||||
Arguments:
|
||||
|
@ -44,14 +44,6 @@ polyglot java import java.util.UUID
|
||||
|
||||
## Represents a column-oriented table data structure.
|
||||
type Table
|
||||
## PRIVATE
|
||||
|
||||
A table.
|
||||
|
||||
Arguments:
|
||||
- java_table: The internal java representation of the table.
|
||||
Table_Data java_table
|
||||
|
||||
## Creates a new table from a vector of `[name, items]` pairs.
|
||||
|
||||
Arguments:
|
||||
@ -99,6 +91,14 @@ type Table
|
||||
columns = header.map_with_index i-> name-> [name, rows.map (_.at i)]
|
||||
Table.new columns
|
||||
|
||||
## PRIVATE
|
||||
|
||||
A table.
|
||||
|
||||
Arguments:
|
||||
- java_table: The internal java representation of the table.
|
||||
Table_Data java_table
|
||||
|
||||
## Returns a text containing an ASCII-art table displaying this data.
|
||||
|
||||
Arguments:
|
||||
|
@ -5,8 +5,6 @@ polyglot java import org.enso.base.Text_Utils
|
||||
|
||||
## Object to generate (deterministic) random value for testing
|
||||
type Faker
|
||||
Value generator
|
||||
|
||||
upper_case_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".char_vector
|
||||
|
||||
lower_case_letters = "abcdefghijklmnopqrstuvwxyz".char_vector
|
||||
@ -22,6 +20,8 @@ type Faker
|
||||
generator = if seed == 0 then Random.new else Random.new seed
|
||||
Faker.Value generator
|
||||
|
||||
Value generator
|
||||
|
||||
## Creates a random Text based on a template of character sets.
|
||||
|
||||
Arguments:
|
||||
|
@ -29,9 +29,6 @@ find_caller_script stack =
|
||||
|
||||
## Holds configuration for a Test_Suite
|
||||
type Suite_Config
|
||||
## PRIVATE - construct a configuration
|
||||
Value only_group_regexp print_only_failures output_path
|
||||
|
||||
## Creates an Suite_Config based off environment and caller location
|
||||
from_environment : Suite_Config
|
||||
from_environment =
|
||||
@ -50,6 +47,9 @@ type Suite_Config
|
||||
|
||||
Suite_Config.Value only_group_regexp print_only_failures results_path
|
||||
|
||||
## PRIVATE - construct a configuration
|
||||
Value only_group_regexp print_only_failures output_path
|
||||
|
||||
should_run_group self name =
|
||||
regexp = self.only_group_regexp
|
||||
case regexp of
|
||||
|
@ -66,6 +66,7 @@ import org.enso.syntax2.Line;
|
||||
import org.enso.syntax2.TextElement;
|
||||
import org.enso.syntax2.Token;
|
||||
import org.enso.syntax2.Tree;
|
||||
import org.enso.syntax2.TypeDefStatement;
|
||||
|
||||
import scala.Option;
|
||||
import scala.collection.immutable.LinearSeq;
|
||||
@ -131,28 +132,31 @@ final class TreeToIr {
|
||||
return switch (inputAst) {
|
||||
case null -> appendTo;
|
||||
case Tree.TypeDef def -> {
|
||||
List<IR> irBody = nil();
|
||||
var typeName = buildName(def.getName(), true);
|
||||
var translatedBody = translateTypeBody(def.getBlock());
|
||||
var irConstructors = new java.util.ArrayList<IR>();
|
||||
for (var constructorLine : def.getConstructors()) {
|
||||
var definition = constructorLine.getExpression();
|
||||
if (definition == null) {
|
||||
continue;
|
||||
for (var line : def.getBody()) {
|
||||
var definition = line.getStatement();
|
||||
switch (definition) {
|
||||
case null -> {}
|
||||
case TypeDefStatement.Binding bind -> irBody = translateTypeBodyExpression(bind.getStatement(), irBody);
|
||||
case TypeDefStatement.TypeConstructorDef cons -> {
|
||||
if (cons.getDocumentation() != null) {
|
||||
irBody = cons(translateComment(def, cons.getDocumentation()), irBody);
|
||||
}
|
||||
var constructorName = buildName(inputAst, cons.getConstructor());
|
||||
List<IR.DefinitionArgument> args = translateArgumentsDefinition(cons.getArguments());
|
||||
var cAt = getIdentifiedLocation(inputAst);
|
||||
var ir = new IR$Module$Scope$Definition$Data(constructorName, args, cAt, meta(), diag());
|
||||
irBody = cons(ir, irBody);
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
if (definition.getDocumentation() != null) {
|
||||
irConstructors.add(translateComment(def, definition.getDocumentation()));
|
||||
}
|
||||
var constructorName = buildName(inputAst, definition.getConstructor());
|
||||
List<IR.DefinitionArgument> args = translateArgumentsDefinition(definition.getArguments());
|
||||
var cAt = getIdentifiedLocation(inputAst);
|
||||
irConstructors.add(new IR$Module$Scope$Definition$Data(constructorName, args, cAt, meta(), diag()));
|
||||
}
|
||||
var translatedConstructors = CollectionConverters.asScala(irConstructors.iterator()).toList();
|
||||
List<IR.DefinitionArgument> args = translateArgumentsDefinition(def.getParams());
|
||||
var type = new IR$Module$Scope$Definition$SugaredType(
|
||||
typeName,
|
||||
args,
|
||||
translatedConstructors.appendedAll(translatedBody),
|
||||
irBody.reverse(),
|
||||
getIdentifiedLocation(inputAst),
|
||||
meta(), diag()
|
||||
);
|
||||
@ -237,19 +241,6 @@ final class TreeToIr {
|
||||
return CollectionConverters.asScala(args.stream().map(p -> translateArgumentDefinition(p)).iterator()).toList();
|
||||
}
|
||||
|
||||
/** Translates the body of a type expression.
|
||||
*
|
||||
* @param body the body to be translated
|
||||
* @return the [[IR]] representation of `body`
|
||||
*/
|
||||
private List<IR> translateTypeBody(java.util.List<Line> block) {
|
||||
List<IR> res = nil();
|
||||
for (var line : block) {
|
||||
res = translateTypeBodyExpression(line.getExpression(), res);
|
||||
}
|
||||
return res.reverse();
|
||||
}
|
||||
|
||||
/** Translates any expression that can be found in the body of a type
|
||||
* declaration from [[AST]] into [[IR]].
|
||||
*
|
||||
|
@ -192,7 +192,13 @@ impl<'g> ToSExpr<'g> {
|
||||
match primitive {
|
||||
Primitive::U32 => Value::Number(read_u32(data).into()),
|
||||
Primitive::I32 => Value::Number((read_u32(data) as i32).into()),
|
||||
Primitive::Char => Value::Char(char::try_from(read_u32(data)).unwrap()),
|
||||
Primitive::Char => {
|
||||
let n = read_u32(data);
|
||||
match char::try_from(n) {
|
||||
Ok(c) => Value::Char(c),
|
||||
Err(_) => Value::Null,
|
||||
}
|
||||
}
|
||||
Primitive::U64 => Value::Number(read_u64(data).into()),
|
||||
Primitive::I64 => Value::Number((read_u64(data) as i64).into()),
|
||||
Primitive::Bool => {
|
||||
|
@ -144,17 +144,14 @@ fn doc_comments() {
|
||||
|
||||
#[test]
|
||||
fn type_definition_no_body() {
|
||||
test("type Bool", block![(TypeDef type Bool #() #() #())]);
|
||||
test("type Option a", block![(TypeDef type Option #((() (Ident a) () ())) #() #())]);
|
||||
test("type Option (a)", block![
|
||||
(TypeDef type Option #((() (Ident a) () ())) #() #())]);
|
||||
test("type Foo (a : Int)", block![
|
||||
(TypeDef type Foo #((() (Ident a) (":" (Ident Int)) ())) #() #())]);
|
||||
test("type A a=0", block![
|
||||
(TypeDef type A #((() (Ident a) () ("=" (Number () "0" ())))) #() #())]);
|
||||
test("type Existing_Headers (column_names : Vector Text)", block![
|
||||
test!("type Bool", (TypeDef type Bool #() #()));
|
||||
test!("type Option a", (TypeDef type Option #((() (Ident a) () ())) #()));
|
||||
test!("type Option (a)", (TypeDef type Option #((() (Ident a) () ())) #()));
|
||||
test!("type Foo (a : Int)", (TypeDef type Foo #((() (Ident a) (":" (Ident Int)) ())) #()));
|
||||
test!("type A a=0", (TypeDef type A #((() (Ident a) () ("=" (Number () "0" ())))) #()));
|
||||
test!("type Existing_Headers (column_names : Vector Text)",
|
||||
(TypeDef type Existing_Headers #(
|
||||
(() (Ident column_names) (":" (App (Ident Vector) (Ident Text))) ())) #() #())]);
|
||||
(() (Ident column_names) (":" (App (Ident Vector) (Ident Text))) ())) #()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -170,26 +167,29 @@ fn type_constructors() {
|
||||
#[rustfmt::skip]
|
||||
let expected = block![
|
||||
(TypeDef type Geo #()
|
||||
#(((() Circle #() #(((() (Ident radius) () ())) ((() (Ident x) () ())))))
|
||||
((() Rectangle #((() (Ident width) () ()) (() (Ident height) () ())) #()))
|
||||
((() Point #() #())))
|
||||
#())
|
||||
];
|
||||
#(((TypeConstructorDef
|
||||
() Circle #() #(((() (Ident radius) () ())) ((() (Ident x) () ())))))
|
||||
((TypeConstructorDef
|
||||
() Rectangle #((() (Ident width) () ()) (() (Ident height) () ())) #()))
|
||||
((TypeConstructorDef () Point #() #()))))];
|
||||
test(&code.join("\n"), expected);
|
||||
let code = "type Foo\n Bar (a : B = C.D)";
|
||||
#[rustfmt::skip]
|
||||
let expected = block![
|
||||
(TypeDef type Foo #()
|
||||
#(((() Bar #((() (Ident a) (":" (Ident B)) ("=" (OprApp (Ident C) (Ok ".") (Ident D))))) #())))
|
||||
#())];
|
||||
(TypeDef type Foo #() #(((TypeConstructorDef
|
||||
()
|
||||
Bar
|
||||
#((() (Ident a) (":" (Ident B)) ("=" (OprApp (Ident C) (Ok ".") (Ident D)))))
|
||||
#()))))];
|
||||
test(code, expected);
|
||||
let code = "type Foo\n ## Bar\n Baz";
|
||||
let expected =
|
||||
block![(TypeDef type Foo #() #((((#((Section " Bar")) #(())) Baz #() #()))) #())];
|
||||
let expected = block![(TypeDef type Foo #() #((
|
||||
(TypeConstructorDef (#((Section " Bar")) #(())) Baz #() #()))))];
|
||||
test(code, expected);
|
||||
let code = ["type A", " Foo (a : Integer, b : Integer)"];
|
||||
#[rustfmt::skip]
|
||||
let expected = block![(TypeDef type A #() #(((() Foo #((() (Invalid) () ())) #()))) #())];
|
||||
let expected = block![(TypeDef type A #() #((
|
||||
(TypeConstructorDef () Foo #((() (Invalid) () ())) #()))))];
|
||||
test(&code.join("\n"), expected);
|
||||
}
|
||||
|
||||
@ -198,11 +198,10 @@ fn type_methods() {
|
||||
let code = ["type Geo", " number =", " x", " area self = x + x"];
|
||||
#[rustfmt::skip]
|
||||
let expected = block![
|
||||
(TypeDef type Geo #() #()
|
||||
#((Function (Ident number) #() "=" (BodyBlock #((Ident x))))
|
||||
(Function (Ident area) #((() (Ident self) () ())) "="
|
||||
(OprApp (Ident x) (Ok "+") (Ident x)))))
|
||||
];
|
||||
(TypeDef type Geo #()
|
||||
#(((Binding (Function (Ident number) #() "=" (BodyBlock #((Ident x))))))
|
||||
((Binding (Function (Ident area) #((() (Ident self) () ())) "="
|
||||
(OprApp (Ident x) (Ok "+") (Ident x)))))))];
|
||||
test(&code.join("\n"), expected);
|
||||
}
|
||||
|
||||
@ -218,13 +217,14 @@ fn type_operator_methods() {
|
||||
];
|
||||
#[rustfmt::skip]
|
||||
let expected = block![
|
||||
(TypeDef type Foo #() #()
|
||||
#((TypeSignature (Ident #"+") ":"
|
||||
(OprApp (Ident Foo) (Ok "->") (OprApp (Ident Foo) (Ok "->") (Ident Foo))))
|
||||
(Function (Ident #"+") #((() (Ident self) () ()) (() (Ident b) () ())) "=" (Ident b))
|
||||
(TypeSignature (OprApp (Ident Foo) (Ok ".") (Ident #"+")) ":" (Ident Foo))
|
||||
(Function (OprApp (Ident Foo) (Ok ".") (Ident #"+"))
|
||||
#((() (Ident self) () ()) (() (Ident b) () ())) "=" (Ident b))))];
|
||||
(TypeDef type Foo #()
|
||||
#(((Binding (TypeSignature (Ident #"+") ":"
|
||||
(OprApp (Ident Foo) (Ok "->") (OprApp (Ident Foo) (Ok "->") (Ident Foo))))))
|
||||
((Binding
|
||||
(Function (Ident #"+") #((() (Ident self) () ()) (() (Ident b) () ())) "=" (Ident b))))
|
||||
((Binding (TypeSignature (OprApp (Ident Foo) (Ok ".") (Ident #"+")) ":" (Ident Foo))))
|
||||
((Binding (Function (OprApp (Ident Foo) (Ok ".") (Ident #"+"))
|
||||
#((() (Ident self) () ()) (() (Ident b) () ())) "=" (Ident b))))))];
|
||||
test(&code.join("\n"), expected);
|
||||
}
|
||||
|
||||
@ -245,15 +245,16 @@ fn type_def_full() {
|
||||
#[rustfmt::skip]
|
||||
let expected = block![
|
||||
(TypeDef type Geo #()
|
||||
#(((() Circle #() #(
|
||||
#(((TypeConstructorDef () Circle #() #(
|
||||
((() (Ident radius) (":" (Ident float)) ()))
|
||||
((() (Ident x) () ())))))
|
||||
((() Rectangle #((() (Ident width) () ()) (() (Ident height) () ())) #()))
|
||||
((() Point #() #()))
|
||||
(()))
|
||||
#((Function (Ident number) #() "=" (BodyBlock #((Ident x))))
|
||||
(Function (Ident area) #((() (Ident self) () ())) "=" (OprApp (Ident x) (Ok "+") (Ident x)))))
|
||||
];
|
||||
((TypeConstructorDef
|
||||
() Rectangle #((() (Ident width) () ()) (() (Ident height) () ())) #()))
|
||||
((TypeConstructorDef () Point #() #()))
|
||||
(())
|
||||
((Binding (Function (Ident number) #() "=" (BodyBlock #((Ident x))))))
|
||||
((Binding (Function (Ident area) #((() (Ident self) () ())) "="
|
||||
(OprApp (Ident x) (Ok "+") (Ident x)))))))];
|
||||
test(&code.join("\n"), expected);
|
||||
}
|
||||
|
||||
@ -264,9 +265,8 @@ fn type_def_defaults() {
|
||||
let expected = block![
|
||||
(TypeDef type Result #((() (Ident error) () ())
|
||||
(() (Ident ok) () ("=" (Ident Nothing))))
|
||||
#(((() Ok #((() (Ident value) (":" (Ident ok)) ("=" (Ident Nothing)))) #())))
|
||||
#())
|
||||
];
|
||||
#(((TypeConstructorDef () Ok
|
||||
#((() (Ident value) (":" (Ident ok)) ("=" (Ident Nothing)))) #()))))];
|
||||
test(&code.join("\n"), expected);
|
||||
}
|
||||
|
||||
@ -280,9 +280,9 @@ fn type_def_nested() {
|
||||
];
|
||||
#[rustfmt::skip]
|
||||
let expected = block![
|
||||
(TypeDef type Foo #() #()
|
||||
#((TypeDef type Bar #() #() #())
|
||||
(TypeDef type Baz #() #() #())))
|
||||
(TypeDef type Foo #()
|
||||
#(((Binding (TypeDef type Bar #() #())))
|
||||
((Binding (TypeDef type Baz #() #())))))
|
||||
];
|
||||
test(&code.join("\n"), expected);
|
||||
}
|
||||
@ -883,29 +883,24 @@ fn type_annotations() {
|
||||
|
||||
#[test]
|
||||
fn inline_text_literals() {
|
||||
#[rustfmt::skip]
|
||||
let cases = [
|
||||
(r#""I'm an inline raw text!""#, block![
|
||||
(TextLiteral #((Section "I'm an inline raw text!")))]),
|
||||
(r#"zero_length = """#, block![
|
||||
(Assignment (Ident zero_length) "=" (TextLiteral #()))]),
|
||||
(r#""type""#, block![(TextLiteral #((Section "type")))]),
|
||||
(r#"unclosed = ""#, block![(Assignment (Ident unclosed) "=" (TextLiteral #()))]),
|
||||
(r#"unclosed = "a"#, block![
|
||||
(Assignment (Ident unclosed) "=" (TextLiteral #((Section "a"))))]),
|
||||
(r#"'Other quote type'"#, block![(TextLiteral #((Section "Other quote type")))]),
|
||||
(r#""Non-escape: \n""#, block![(TextLiteral #((Section "Non-escape: \\n")))]),
|
||||
(r#""Non-escape: \""#, block![(TextLiteral #((Section "Non-escape: \\")))]),
|
||||
(r#"'String with \' escape'"#, block![
|
||||
(TextLiteral
|
||||
#((Section "String with ") (Escape '\'') (Section " escape")))]),
|
||||
(r#"'\u0915\u094D\u0937\u093F'"#, block![(TextLiteral #(
|
||||
(Escape '\u{0915}') (Escape '\u{094D}') (Escape '\u{0937}') (Escape '\u{093F}')))]),
|
||||
(r#"('\n')"#, block![(Group (TextLiteral #((Escape '\n'))))]),
|
||||
(r#"`"#, block![(Invalid)]),
|
||||
(r#"(")")"#, block![(Group (TextLiteral #((Section ")"))))]),
|
||||
];
|
||||
cases.into_iter().for_each(|(code, expected)| test(code, expected));
|
||||
test!(r#""I'm an inline raw text!""#, (TextLiteral #((Section "I'm an inline raw text!"))));
|
||||
test!(r#"zero_length = """#, (Assignment (Ident zero_length) "=" (TextLiteral #())));
|
||||
test!(r#""type""#, (TextLiteral #((Section "type"))));
|
||||
test!(r#"unclosed = ""#, (Assignment (Ident unclosed) "=" (TextLiteral #())));
|
||||
test!(r#"unclosed = "a"#, (Assignment (Ident unclosed) "=" (TextLiteral #((Section "a")))));
|
||||
test!(r#"'Other quote type'"#, (TextLiteral #((Section "Other quote type"))));
|
||||
test!(r#""Non-escape: \n""#, (TextLiteral #((Section "Non-escape: \\n"))));
|
||||
test!(r#""Non-escape: \""#, (TextLiteral #((Section "Non-escape: \\"))));
|
||||
test!(r#"'String with \' escape'"#,
|
||||
(TextLiteral #((Section "String with ") (Escape '\'') (Section " escape"))));
|
||||
test!(r#"'\u0915\u094D\u0937\u093F'"#, (TextLiteral
|
||||
#((Escape '\u{0915}') (Escape '\u{094D}') (Escape '\u{0937}') (Escape '\u{093F}'))));
|
||||
test!(r#"('\n')"#, (Group (TextLiteral #((Escape '\n')))));
|
||||
test!(r#"`"#, (Invalid));
|
||||
test!(r#"(")")"#, (Group (TextLiteral #((Section ")")))));
|
||||
test!(r#"'\x'"#, (TextLiteral #((Escape ()))));
|
||||
test!(r#"'\u'"#, (TextLiteral #((Escape ()))));
|
||||
test!(r#"'\U'"#, (TextLiteral #((Escape ()))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1238,12 +1233,8 @@ fn inline_annotations() {
|
||||
|
||||
#[test]
|
||||
fn multiline_annotations() {
|
||||
#[rustfmt::skip]
|
||||
let cases = [
|
||||
("@Builtin_Type\ntype Date", block![
|
||||
(Annotated "@" Builtin_Type #(()) (TypeDef type Date #() #() #()))]),
|
||||
];
|
||||
cases.into_iter().for_each(|(code, expected)| test(code, expected));
|
||||
test!("@Builtin_Type\ntype Date",
|
||||
(Annotated "@" Builtin_Type #(()) (TypeDef type Date #() #())));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1091,16 +1091,15 @@ impl<'s> Lexer<'s> {
|
||||
self.take_next();
|
||||
expect_len = 6;
|
||||
}
|
||||
let mut value: u32 = 0;
|
||||
let mut value: Option<u32> = None;
|
||||
for _ in 0..expect_len {
|
||||
if let Some(c) = self.current_char && let Some(x) = decode_hexadecimal_digit(c) {
|
||||
value = 16 * value + x as u32;
|
||||
value = Some(16 * value.unwrap_or_default() + x as u32);
|
||||
self.take_next();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let value = char::from_u32(value);
|
||||
if delimited && self.current_char == Some('}') {
|
||||
self.take_next();
|
||||
}
|
||||
@ -1108,7 +1107,7 @@ impl<'s> Lexer<'s> {
|
||||
let token = self.make_token(
|
||||
backslash_start,
|
||||
sequence_end.clone(),
|
||||
token::Variant::text_escape(value),
|
||||
token::Variant::text_escape(value.and_then(char::from_u32)),
|
||||
);
|
||||
self.output.push(token);
|
||||
sequence_end
|
||||
|
@ -313,14 +313,13 @@ fn type_def_body(matched_segments: NonEmptyVec<MatchedSegment>) -> syntax::Tree
|
||||
for block::Line { newline, expression } in block::lines(block) {
|
||||
builder.line(newline, expression);
|
||||
}
|
||||
let (constructors, body) = builder.finish();
|
||||
Tree::type_def(header, name, params, constructors, body)
|
||||
let body = builder.finish();
|
||||
Tree::type_def(header, name, params, body)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TypeDefBodyBuilder<'s> {
|
||||
constructors: Vec<syntax::tree::TypeConstructorLine<'s>>,
|
||||
body: Vec<syntax::tree::block::Line<'s>>,
|
||||
body: Vec<syntax::tree::TypeDefLine<'s>>,
|
||||
documentation: Option<(syntax::token::Newline<'s>, syntax::tree::DocComment<'s>)>,
|
||||
}
|
||||
|
||||
@ -342,58 +341,42 @@ impl<'s> TypeDefBodyBuilder<'s> {
|
||||
doc.newlines.push(newline);
|
||||
return;
|
||||
}
|
||||
if self.body.is_empty() {
|
||||
if let Some(expression) = expression {
|
||||
match Self::to_constructor_line(expression) {
|
||||
Ok(mut expression) => {
|
||||
if let Some((nl, mut doc)) = self.documentation.take() {
|
||||
let nl = mem::replace(&mut newline, nl);
|
||||
doc.newlines.push(nl);
|
||||
expression.documentation = doc.into();
|
||||
}
|
||||
let expression = Some(expression);
|
||||
let line = syntax::tree::TypeConstructorLine { newline, expression };
|
||||
self.constructors.push(line);
|
||||
let statement = expression.map(|expression| {
|
||||
let mut statement = Self::to_body_statement(expression);
|
||||
match &mut statement {
|
||||
syntax::tree::TypeDefStatement::Constructor { constructor } => {
|
||||
if let Some((nl, mut doc)) = self.documentation.take() {
|
||||
let nl = mem::replace(&mut newline, nl);
|
||||
doc.newlines.push(nl);
|
||||
constructor.documentation = doc.into();
|
||||
}
|
||||
}
|
||||
syntax::tree::TypeDefStatement::Binding { statement } => {
|
||||
if let Some((nl, mut doc)) = self.documentation.take() {
|
||||
let nl = mem::replace(&mut newline, nl);
|
||||
doc.newlines.push(nl);
|
||||
*statement = syntax::Tree::documented(doc, statement.clone().into());
|
||||
}
|
||||
Err(expression) => self.push_body(newline, expression.into()),
|
||||
}
|
||||
} else {
|
||||
self.constructors.push(newline.into());
|
||||
}
|
||||
} else {
|
||||
self.push_body(newline, expression);
|
||||
}
|
||||
statement
|
||||
});
|
||||
let line = syntax::tree::TypeDefLine { newline, statement };
|
||||
self.body.push(line);
|
||||
}
|
||||
|
||||
fn push_body(
|
||||
&mut self,
|
||||
mut newline: syntax::token::Newline<'s>,
|
||||
expression: Option<syntax::Tree<'s>>,
|
||||
) {
|
||||
let mut expression = expression.map(crate::expression_to_statement);
|
||||
if let Some((nl, mut doc)) = self.documentation.take() {
|
||||
let nl = mem::replace(&mut newline, nl);
|
||||
doc.newlines.push(nl);
|
||||
expression = syntax::Tree::documented(doc, expression.take()).into();
|
||||
}
|
||||
self.body.push(syntax::tree::block::Line { newline, expression });
|
||||
}
|
||||
|
||||
/// Return the constructor/body sequences.
|
||||
pub fn finish(
|
||||
mut self,
|
||||
) -> (Vec<syntax::tree::TypeConstructorLine<'s>>, Vec<syntax::tree::block::Line<'s>>) {
|
||||
/// Return the type body statements.
|
||||
pub fn finish(self) -> Vec<syntax::tree::TypeDefLine<'s>> {
|
||||
let mut body = self.body;
|
||||
if let Some((newline, doc)) = self.documentation {
|
||||
let expression = syntax::Tree::documented(doc, default()).into();
|
||||
self.body.push(syntax::tree::block::Line { newline, expression });
|
||||
let statement = syntax::Tree::documented(doc, default());
|
||||
let statement = Some(syntax::tree::TypeDefStatement::Binding { statement });
|
||||
body.push(syntax::tree::TypeDefLine { newline, statement });
|
||||
}
|
||||
(self.constructors, self.body)
|
||||
body
|
||||
}
|
||||
|
||||
/// Interpret the given expression as a `TypeConstructorDef`, if its syntax is compatible.
|
||||
fn to_constructor_line(
|
||||
expression: syntax::Tree<'_>,
|
||||
) -> Result<syntax::tree::TypeConstructorDef<'_>, syntax::Tree<'_>> {
|
||||
fn to_body_statement(expression: syntax::Tree<'_>) -> syntax::tree::TypeDefStatement<'_> {
|
||||
use syntax::tree::*;
|
||||
let mut last_argument_default = default();
|
||||
let mut left_offset = crate::source::Offset::default();
|
||||
@ -428,7 +411,9 @@ impl<'s> TypeDefBodyBuilder<'s> {
|
||||
})
|
||||
.collect();
|
||||
let arguments = default();
|
||||
return Ok(TypeConstructorDef { documentation, constructor, arguments, block });
|
||||
let constructor =
|
||||
TypeConstructorDef { documentation, constructor, arguments, block };
|
||||
return TypeDefStatement::Constructor { constructor };
|
||||
}
|
||||
_ => &expression,
|
||||
};
|
||||
@ -443,9 +428,12 @@ impl<'s> TypeDefBodyBuilder<'s> {
|
||||
*default = Some(ArgumentDefault { equals, expression });
|
||||
}
|
||||
let block = default();
|
||||
return Ok(TypeConstructorDef{ documentation, constructor, arguments, block });
|
||||
let constructor =
|
||||
TypeConstructorDef { documentation, constructor, arguments, block };
|
||||
return TypeDefStatement::Constructor { constructor };
|
||||
}
|
||||
Err(expression)
|
||||
let statement = crate::expression_to_statement(expression);
|
||||
TypeDefStatement::Binding { statement }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,14 +201,13 @@ macro_rules! with_ast_definition { ($f:ident ($($args:tt)*)) => { $f! { $($args)
|
||||
/// A type definition; introduced by a line consisting of the keyword `type`, an identifier
|
||||
/// to be used as the name of the type, and zero or more specifications of type parameters.
|
||||
/// The following indented block contains two types of lines:
|
||||
/// - First zero or more type constructors, and their subordinate blocks.
|
||||
/// - Then a block of statements, which may define methods or type methods.
|
||||
/// - Type constructors definitions.
|
||||
/// - Bindings, defining either methods or type methods.
|
||||
TypeDef {
|
||||
pub keyword: token::Ident<'s>,
|
||||
pub name: token::Ident<'s>,
|
||||
pub params: Vec<ArgumentDefinition<'s>>,
|
||||
pub constructors: Vec<TypeConstructorLine<'s>>,
|
||||
pub block: Vec<block::Line<'s>>,
|
||||
pub keyword: token::Ident<'s>,
|
||||
pub name: token::Ident<'s>,
|
||||
pub params: Vec<ArgumentDefinition<'s>>,
|
||||
pub body: Vec<TypeDefLine<'s>>,
|
||||
},
|
||||
/// A variable assignment, like `foo = bar 23`.
|
||||
Assignment {
|
||||
@ -403,24 +402,49 @@ impl<'s> span::Builder<'s> for Error {
|
||||
|
||||
// === Type Definitions ===
|
||||
|
||||
/// A line within a type definition, containing a type constructor definition.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Visitor, Serialize, Reflect, Deserialize)]
|
||||
pub struct TypeConstructorLine<'s> {
|
||||
/// The token beginning the line.
|
||||
pub newline: token::Newline<'s>,
|
||||
/// The type constructor definition, unless this is an empty line.
|
||||
pub expression: Option<TypeConstructorDef<'s>>,
|
||||
/// A line in a type definition's body block.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Visitor, Serialize, Reflect, Deserialize)]
|
||||
pub struct TypeDefLine<'s> {
|
||||
/// Token ending the previous line.
|
||||
pub newline: token::Newline<'s>,
|
||||
/// Type definition body statement, if any.
|
||||
pub statement: Option<TypeDefStatement<'s>>,
|
||||
}
|
||||
|
||||
impl<'s> span::Builder<'s> for TypeConstructorLine<'s> {
|
||||
impl<'s> span::Builder<'s> for TypeDefLine<'s> {
|
||||
fn add_to_span(&mut self, span: Span<'s>) -> Span<'s> {
|
||||
span.add(&mut self.newline).add(&mut self.expression)
|
||||
span.add(&mut self.newline).add(&mut self.statement)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> From<token::Newline<'s>> for TypeConstructorLine<'s> {
|
||||
impl<'s> From<token::Newline<'s>> for TypeDefLine<'s> {
|
||||
fn from(newline: token::Newline<'s>) -> Self {
|
||||
Self { newline, expression: None }
|
||||
Self { newline, statement: None }
|
||||
}
|
||||
}
|
||||
|
||||
/// A statement in a type-definition body.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Visitor, Serialize, Reflect, Deserialize)]
|
||||
pub enum TypeDefStatement<'s> {
|
||||
/// A binding in a type-definition body.
|
||||
Binding {
|
||||
/// The binding statement.
|
||||
statement: Tree<'s>,
|
||||
},
|
||||
/// A constructor definition within a type-definition body.
|
||||
#[reflect(inline)]
|
||||
Constructor {
|
||||
/// The constructor.
|
||||
constructor: TypeConstructorDef<'s>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'s> span::Builder<'s> for TypeDefStatement<'s> {
|
||||
fn add_to_span(&mut self, span: Span<'s>) -> Span<'s> {
|
||||
match self {
|
||||
TypeDefStatement::Binding { statement } => span.add(statement),
|
||||
TypeDefStatement::Constructor { constructor } => span.add(constructor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -446,6 +470,9 @@ impl<'s> span::Builder<'s> for TypeConstructorDef<'s> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// === Argument blocks ===
|
||||
|
||||
/// An argument specification on its own line.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Visitor, Serialize, Reflect, Deserialize)]
|
||||
pub struct ArgumentDefinitionLine<'s> {
|
||||
@ -867,8 +894,7 @@ pub fn apply_operator<'s>(
|
||||
},
|
||||
(lhs, rhs) => {
|
||||
let invalid = Tree::opr_app(lhs, opr, rhs);
|
||||
let err = Error::new("`:` operator must be applied to two operands.");
|
||||
Tree::invalid(err, invalid)
|
||||
invalid.with_error("`:` operator must be applied to two operands.")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user