Skip to content

Commit 40aae13

Browse files
author
Max Brunsfeld
authored
Merge pull request tree-sitter#1 from mads-hartmann/type-parameter-variance
Type parameter variance
2 parents b152e1b + 9f67a58 commit 40aae13

File tree

8 files changed

+55801
-53076
lines changed

8 files changed

+55801
-53076
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,20 @@ References
99

1010
* [The Scala Language Specification](http://www.scala-lang.org/docu/files/ScalaReference.pdf)
1111
* [Scala Syntax Summary](https://www.scala-lang.org/files/archive/spec/2.11/13-syntax-summary.html)
12+
13+
Development
14+
-----------
15+
16+
First, install the project's dependencies:
17+
18+
```sh
19+
npm install
20+
```
21+
22+
Add a test case to `./corpus`, make the required changes to `grammar.js`,
23+
regenerate and recompile the parser, and run the tests:
24+
25+
```sh
26+
npm run build
27+
npm test
28+
```

corpus/definitions.txt

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,44 @@
1+
================================
2+
Package
3+
================================
4+
5+
package a.b
6+
package c {
7+
object A
8+
}
9+
10+
---
11+
12+
(compilation_unit
13+
(package_clause (package_identifier (identifier) (identifier)))
14+
(package_clause (package_identifier (identifier))
15+
(template_body
16+
(object_definition (identifier)))))
17+
18+
================================
19+
Package object
20+
================================
21+
22+
package object d extends A {
23+
val hello: String = "there"
24+
}
25+
26+
---
27+
28+
(compilation_unit
29+
(package_object
30+
(identifier)
31+
(extends_clause (type_identifier))
32+
(template_body
33+
(val_definition (identifier) (type_identifier) (string)))))
34+
135
================================
236
Imports
337
================================
438

539
import PartialFunction.condOpt
40+
import a.b, c.e
641
import reflect.io.{Directory, File, Path}
7-
import tools.nsc.classpath._
8-
import lang.System.{lineSeparator => EOL}
942

1043
---
1144

@@ -14,10 +47,33 @@ import lang.System.{lineSeparator => EOL}
1447
(stable_identifier (identifier) (identifier)))
1548
(import_declaration
1649
(stable_identifier (identifier) (identifier))
17-
(import_selectors (identifier) (identifier) (identifier)))
50+
(stable_identifier (identifier) (identifier)))
51+
(import_declaration
52+
(stable_identifier (identifier) (identifier))
53+
(import_selectors (identifier) (identifier) (identifier))))
54+
55+
================================
56+
Imports: Wildcard
57+
================================
58+
59+
import tools.nsc.classpath._
60+
61+
---
62+
63+
(compilation_unit
1864
(import_declaration
1965
(stable_identifier (stable_identifier (identifier) (identifier)) (identifier))
20-
(wildcard))
66+
(wildcard)))
67+
68+
================================
69+
Imports: Rename
70+
================================
71+
72+
import lang.System.{lineSeparator => EOL}
73+
74+
---
75+
76+
(compilation_unit
2177
(import_declaration
2278
(stable_identifier (identifier) (identifier))
2379
(import_selectors (renamed_identifier (identifier) (identifier)))))
@@ -33,12 +89,16 @@ object O1 {
3389
case object O2 {
3490
}
3591

92+
object O3 extends A {
93+
}
94+
3695
---
3796

3897
(compilation_unit
3998
(comment)
4099
(object_definition (identifier) (template_body))
41-
(object_definition (identifier) (template_body)))
100+
(object_definition (identifier) (template_body))
101+
(object_definition (identifier) (extends_clause (type_identifier)) (template_body)))
42102

43103
=======================================
44104
Class definitions

corpus/types.txt

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,83 @@ type A = B Foo C
8787
(type_definition
8888
(type_identifier)
8989
(infix_type (type_identifier) (identifier) (type_identifier))))
90+
91+
92+
==================================
93+
Variant Types
94+
==================================
95+
96+
class Function1[-T1, +R]
97+
98+
---
99+
100+
(compilation_unit
101+
(class_definition
102+
(identifier)
103+
(type_parameters
104+
(contravariant_type_parameter (identifier))
105+
(covariant_type_parameter (identifier)))))
106+
107+
108+
==================================
109+
Upper bound
110+
==================================
111+
112+
class A[B <: C]
113+
114+
---
115+
116+
(compilation_unit
117+
(class_definition
118+
(identifier)
119+
(type_parameters
120+
(identifier)
121+
(upper_bound (type_identifier)))))
122+
123+
==================================
124+
Lower bound
125+
==================================
126+
127+
class A[B >: C]
128+
129+
---
130+
131+
(compilation_unit
132+
(class_definition
133+
(identifier)
134+
(type_parameters
135+
(identifier)
136+
(lower_bound (type_identifier)))))
137+
138+
==================================
139+
View bound
140+
==================================
141+
142+
143+
class A[B <% C <% D]
144+
145+
---
146+
147+
(compilation_unit
148+
(class_definition
149+
(identifier)
150+
(type_parameters
151+
(identifier)
152+
(view_bound (type_identifier))
153+
(view_bound (type_identifier)))))
154+
155+
==================================
156+
Context bound
157+
==================================
158+
159+
class A[B : C : D]
160+
161+
---
162+
163+
(compilation_unit
164+
(class_definition
165+
(identifier)
166+
(type_parameters
167+
(identifier)
168+
(context_bound (type_identifier))
169+
(context_bound (type_identifier)))))

examples/Packages.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package a.b
2+
package c {
3+
object A
4+
}
5+
package c {
6+
package object d {
7+
val hello: String = "there"
8+
}
9+
}

examples/Variance.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
class Function1[-T1, +R]

grammar.js

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ module.exports = grammar({
3939

4040
_definition: $ => choice(
4141
$.package_clause,
42+
$.package_object,
4243
$.class_definition,
4344
$.import_declaration,
4445
$.object_definition,
@@ -54,11 +55,30 @@ module.exports = grammar({
5455

5556
package_clause: $ => seq(
5657
'package',
57-
choice($.identifier, $.stable_identifier)
58+
$.package_identifier,
59+
// This is slightly more permissive than the EBNF in that it allows any
60+
// kind of delcaration inside of the package blocks. As we're more
61+
// concerned with the structure rather than the validity of the program
62+
// we'll allow it.
63+
optional($.template_body)
64+
),
65+
66+
package_identifier: $ => sep1(
67+
'.', $.identifier
68+
),
69+
70+
package_object: $ => seq(
71+
'package',
72+
'object',
73+
$._object_definition
5874
),
5975

6076
import_declaration: $ => seq(
6177
'import',
78+
sep1(',', $._import_expression)
79+
),
80+
81+
_import_expression: $ => seq(
6282
choice($.stable_identifier, $.identifier),
6383
optional(seq(
6484
'.',
@@ -87,8 +107,13 @@ module.exports = grammar({
87107
object_definition: $ => seq(
88108
optional('case'),
89109
'object',
110+
$._object_definition
111+
),
112+
113+
_object_definition: $ => seq(
90114
$.identifier,
91-
$.template_body
115+
optional($.extends_clause),
116+
optional($.template_body),
92117
),
93118

94119
class_definition: $ => seq(
@@ -110,17 +135,51 @@ module.exports = grammar({
110135
$.template_body
111136
),
112137

138+
// The EBNF makes a distinction between function type parameters and other
139+
// type parameters as you can't specify variance on function type
140+
// parameters. This isn't important to the structure of the AST so we don't
141+
// make that distinction.
113142
type_parameters: $ => seq(
114143
'[',
115-
commaSep1($._type_parameter),
144+
commaSep1($._variant_type_parameter),
116145
']'
117146
),
118147

119-
_type_parameter: $ => choice(
120-
'_',
121-
$.identifier
148+
_variant_type_parameter: $ => seq(
149+
choice(
150+
$.covariant_type_parameter,
151+
$.contravariant_type_parameter,
152+
$._type_parameter // invariant type parameter
153+
)
154+
),
155+
156+
covariant_type_parameter: $ => seq(
157+
'+',
158+
$._type_parameter
122159
),
123160

161+
contravariant_type_parameter: $ => seq(
162+
'-',
163+
$._type_parameter,
164+
),
165+
166+
_type_parameter: $ => seq(
167+
choice($.wildcard, $.identifier),
168+
optional($.type_parameters),
169+
optional($.upper_bound),
170+
optional($.lower_bound),
171+
optional(repeat($.view_bound)),
172+
optional(repeat($.context_bound)),
173+
),
174+
175+
upper_bound: $ => seq('<:', $._type),
176+
177+
lower_bound: $ => seq('>:', $._type),
178+
179+
view_bound: $ => seq('<%', $._type),
180+
181+
context_bound: $ => seq(':', $._type),
182+
124183
template_body: $ => seq(
125184
'{',
126185
repeat($._definition),

0 commit comments

Comments
 (0)