tint: Add type constructors and converters support to intrinsic-gen
These are currently not used, but the first step towards moving type constructors and converters over to using the intrinisc table. This will simplify maintenance of type functions, and will greatly simplify the [AbstractInt -> i32|u32] [AbstractFloat -> f32|f16] logic. Bug: tint:1504 Change-Id: I15526670a6ff801e66551ab5adc37b1570ac49de Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/90242 Reviewed-by: Antonio Maiorano <amaiorano@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
2b3dcf45b7
commit
5a69597698
|
@ -29,6 +29,8 @@ type AST struct {
|
||||||
Types []TypeDecl
|
Types []TypeDecl
|
||||||
Matchers []MatcherDecl
|
Matchers []MatcherDecl
|
||||||
Builtins []IntrinsicDecl
|
Builtins []IntrinsicDecl
|
||||||
|
Constructors []IntrinsicDecl
|
||||||
|
Converters []IntrinsicDecl
|
||||||
Operators []IntrinsicDecl
|
Operators []IntrinsicDecl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +52,14 @@ func (a AST) String() string {
|
||||||
fmt.Fprintf(&sb, "%v", b)
|
fmt.Fprintf(&sb, "%v", b)
|
||||||
fmt.Fprintln(&sb)
|
fmt.Fprintln(&sb)
|
||||||
}
|
}
|
||||||
|
for _, o := range a.Constructors {
|
||||||
|
fmt.Fprintf(&sb, "%v", o)
|
||||||
|
fmt.Fprintln(&sb)
|
||||||
|
}
|
||||||
|
for _, o := range a.Converters {
|
||||||
|
fmt.Fprintf(&sb, "%v", o)
|
||||||
|
fmt.Fprintln(&sb)
|
||||||
|
}
|
||||||
for _, o := range a.Operators {
|
for _, o := range a.Operators {
|
||||||
fmt.Fprintf(&sb, "%v", o)
|
fmt.Fprintf(&sb, "%v", o)
|
||||||
fmt.Fprintln(&sb)
|
fmt.Fprintln(&sb)
|
||||||
|
@ -103,7 +113,7 @@ func (m MatcherDecl) Format(w fmt.State, verb rune) {
|
||||||
m.Options.Format(w, verb)
|
m.Options.Format(w, verb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntrinsicKind is either a Builtin or Operator
|
// IntrinsicKind is either a Builtin, Operator, Constructor or Converter
|
||||||
type IntrinsicKind string
|
type IntrinsicKind string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -113,6 +123,12 @@ const (
|
||||||
// Operator is a unary or binary operator.
|
// Operator is a unary or binary operator.
|
||||||
// Declared with 'op'.
|
// Declared with 'op'.
|
||||||
Operator IntrinsicKind = "operator"
|
Operator IntrinsicKind = "operator"
|
||||||
|
// Constructor is a type constructor function.
|
||||||
|
// Declared with 'ctor'.
|
||||||
|
Constructor IntrinsicKind = "constructor"
|
||||||
|
// Converter is a type conversion function.
|
||||||
|
// Declared with 'conv'.
|
||||||
|
Converter IntrinsicKind = "converter"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IntrinsicDecl describes a builtin or operator declaration
|
// IntrinsicDecl describes a builtin or operator declaration
|
||||||
|
@ -133,6 +149,10 @@ func (i IntrinsicDecl) Format(w fmt.State, verb rune) {
|
||||||
fmt.Fprintf(w, "fn ")
|
fmt.Fprintf(w, "fn ")
|
||||||
case Operator:
|
case Operator:
|
||||||
fmt.Fprintf(w, "op ")
|
fmt.Fprintf(w, "op ")
|
||||||
|
case Constructor:
|
||||||
|
fmt.Fprintf(w, "ctor ")
|
||||||
|
case Converter:
|
||||||
|
fmt.Fprintf(w, "conv ")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "%v", i.Name)
|
fmt.Fprintf(w, "%v", i.Name)
|
||||||
i.TemplateParams.Format(w, verb)
|
i.TemplateParams.Format(w, verb)
|
||||||
|
|
|
@ -45,6 +45,7 @@ type IntrinsicTable struct {
|
||||||
Builtins []Intrinsic // kBuiltins table content
|
Builtins []Intrinsic // kBuiltins table content
|
||||||
UnaryOperators []Intrinsic // kUnaryOperators table content
|
UnaryOperators []Intrinsic // kUnaryOperators table content
|
||||||
BinaryOperators []Intrinsic // kBinaryOperators table content
|
BinaryOperators []Intrinsic // kBinaryOperators table content
|
||||||
|
ConstructorsAndConverters []Intrinsic // kConstructorsAndConverters table content
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenType is used to create the C++ OpenTypeInfo structure
|
// OpenType is used to create the C++ OpenTypeInfo structure
|
||||||
|
@ -372,6 +373,7 @@ func buildIntrinsicTable(s *sem.Sem) (*IntrinsicTable, error) {
|
||||||
{s.Builtins, &b.Builtins},
|
{s.Builtins, &b.Builtins},
|
||||||
{s.UnaryOperators, &b.UnaryOperators},
|
{s.UnaryOperators, &b.UnaryOperators},
|
||||||
{s.BinaryOperators, &b.BinaryOperators},
|
{s.BinaryOperators, &b.BinaryOperators},
|
||||||
|
{s.ConstructorsAndConverters, &b.ConstructorsAndConverters},
|
||||||
} {
|
} {
|
||||||
out := make([]Intrinsic, len(intrinsics.in))
|
out := make([]Intrinsic, len(intrinsics.in))
|
||||||
for i, f := range intrinsics.in {
|
for i, f := range intrinsics.in {
|
||||||
|
|
|
@ -97,6 +97,8 @@ func (l *lexer) lex() error {
|
||||||
case l.match("op", tok.Operator):
|
case l.match("op", tok.Operator):
|
||||||
case l.match("enum", tok.Enum):
|
case l.match("enum", tok.Enum):
|
||||||
case l.match("type", tok.Type):
|
case l.match("type", tok.Type):
|
||||||
|
case l.match("ctor", tok.Constructor):
|
||||||
|
case l.match("conv", tok.Converter):
|
||||||
case l.match("match", tok.Match):
|
case l.match("match", tok.Match):
|
||||||
case unicode.IsLetter(l.peek(0)) || l.peek(0) == '_':
|
case unicode.IsLetter(l.peek(0)) || l.peek(0) == '_':
|
||||||
l.tok(l.count(alphaNumericOrUnderscore), tok.Identifier)
|
l.tok(l.count(alphaNumericOrUnderscore), tok.Identifier)
|
||||||
|
|
|
@ -58,6 +58,12 @@ func TestLexTokens(t *testing.T) {
|
||||||
{"type", tok.Token{Kind: tok.Type, Runes: []rune("type"), Source: tok.Source{
|
{"type", tok.Token{Kind: tok.Type, Runes: []rune("type"), Source: tok.Source{
|
||||||
S: loc(1, 1, 0), E: loc(1, 5, 4),
|
S: loc(1, 1, 0), E: loc(1, 5, 4),
|
||||||
}}},
|
}}},
|
||||||
|
{"ctor", tok.Token{Kind: tok.Constructor, Runes: []rune("ctor"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 5, 4),
|
||||||
|
}}},
|
||||||
|
{"conv", tok.Token{Kind: tok.Converter, Runes: []rune("conv"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 5, 4),
|
||||||
|
}}},
|
||||||
{"enum", tok.Token{Kind: tok.Enum, Runes: []rune("enum"), Source: tok.Source{
|
{"enum", tok.Token{Kind: tok.Enum, Runes: []rune("enum"), Source: tok.Source{
|
||||||
S: loc(1, 1, 0), E: loc(1, 5, 4),
|
S: loc(1, 1, 0), E: loc(1, 5, 4),
|
||||||
}}},
|
}}},
|
||||||
|
|
|
@ -71,6 +71,12 @@ func (p *parser) parse() (*ast.AST, error) {
|
||||||
case tok.Operator:
|
case tok.Operator:
|
||||||
out.Operators = append(out.Operators, p.operatorDecl(decorations))
|
out.Operators = append(out.Operators, p.operatorDecl(decorations))
|
||||||
decorations = nil
|
decorations = nil
|
||||||
|
case tok.Constructor:
|
||||||
|
out.Constructors = append(out.Constructors, p.constructorDecl(decorations))
|
||||||
|
decorations = nil
|
||||||
|
case tok.Converter:
|
||||||
|
out.Converters = append(out.Converters, p.converterDecl(decorations))
|
||||||
|
decorations = nil
|
||||||
default:
|
default:
|
||||||
p.err = fmt.Errorf("%v unexpected token '%v'", t.Source, t.Kind)
|
p.err = fmt.Errorf("%v unexpected token '%v'", t.Source, t.Kind)
|
||||||
}
|
}
|
||||||
|
@ -195,6 +201,47 @@ func (p *parser) operatorDecl(decos ast.Decorations) ast.IntrinsicDecl {
|
||||||
}
|
}
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *parser) constructorDecl(decos ast.Decorations) ast.IntrinsicDecl {
|
||||||
|
p.expect(tok.Constructor, "constructor declaration")
|
||||||
|
name := p.next()
|
||||||
|
f := ast.IntrinsicDecl{
|
||||||
|
Source: name.Source,
|
||||||
|
Kind: ast.Constructor,
|
||||||
|
Decorations: decos,
|
||||||
|
Name: string(name.Runes),
|
||||||
|
}
|
||||||
|
if p.peekIs(0, tok.Lt) {
|
||||||
|
f.TemplateParams = p.templateParams()
|
||||||
|
}
|
||||||
|
f.Parameters = p.parameters()
|
||||||
|
if p.match(tok.Arrow) != nil {
|
||||||
|
ret := p.templatedName()
|
||||||
|
f.ReturnType = &ret
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) converterDecl(decos ast.Decorations) ast.IntrinsicDecl {
|
||||||
|
p.expect(tok.Converter, "converter declaration")
|
||||||
|
name := p.next()
|
||||||
|
f := ast.IntrinsicDecl{
|
||||||
|
Source: name.Source,
|
||||||
|
Kind: ast.Converter,
|
||||||
|
Decorations: decos,
|
||||||
|
Name: string(name.Runes),
|
||||||
|
}
|
||||||
|
if p.peekIs(0, tok.Lt) {
|
||||||
|
f.TemplateParams = p.templateParams()
|
||||||
|
}
|
||||||
|
f.Parameters = p.parameters()
|
||||||
|
if p.match(tok.Arrow) != nil {
|
||||||
|
ret := p.templatedName()
|
||||||
|
f.ReturnType = &ret
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
func (p *parser) parameters() ast.Parameters {
|
func (p *parser) parameters() ast.Parameters {
|
||||||
l := ast.Parameters{}
|
l := ast.Parameters{}
|
||||||
p.expect(tok.Lparen, "function parameter list")
|
p.expect(tok.Lparen, "function parameter list")
|
||||||
|
|
|
@ -370,6 +370,254 @@ func TestParser(t *testing.T) {
|
||||||
},
|
},
|
||||||
Parameters: ast.Parameters{},
|
Parameters: ast.Parameters{},
|
||||||
}},
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"ctor F()",
|
||||||
|
ast.AST{
|
||||||
|
Constructors: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Constructor,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"[[deco]] ctor F()",
|
||||||
|
ast.AST{
|
||||||
|
Constructors: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Constructor,
|
||||||
|
Name: "F",
|
||||||
|
Decorations: ast.Decorations{
|
||||||
|
{Name: "deco", Values: []string{}},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"ctor F(a)",
|
||||||
|
ast.AST{
|
||||||
|
Constructors: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Constructor,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Type: ast.TemplatedName{Name: "a"}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"ctor F(a: T)",
|
||||||
|
ast.AST{
|
||||||
|
Constructors: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Constructor,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Name: "a", Type: ast.TemplatedName{Name: "T"}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"ctor F(a, b)",
|
||||||
|
ast.AST{
|
||||||
|
Constructors: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Constructor,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Type: ast.TemplatedName{Name: "a"}},
|
||||||
|
{Type: ast.TemplatedName{Name: "b"}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"ctor F<A : B<C> >()",
|
||||||
|
ast.AST{
|
||||||
|
Constructors: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Constructor,
|
||||||
|
Name: "F",
|
||||||
|
TemplateParams: ast.TemplateParams{
|
||||||
|
{
|
||||||
|
Name: "A", Type: ast.TemplatedName{
|
||||||
|
Name: "B",
|
||||||
|
TemplateArgs: ast.TemplatedNames{
|
||||||
|
{Name: "C"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"ctor F<T>(a: X, b: Y<T>)",
|
||||||
|
ast.AST{
|
||||||
|
Constructors: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Constructor,
|
||||||
|
Name: "F",
|
||||||
|
TemplateParams: ast.TemplateParams{
|
||||||
|
{Name: "T"},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Name: "a", Type: ast.TemplatedName{Name: "X"}},
|
||||||
|
{Name: "b", Type: ast.TemplatedName{
|
||||||
|
Name: "Y",
|
||||||
|
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"ctor F() -> X",
|
||||||
|
ast.AST{
|
||||||
|
Constructors: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Constructor,
|
||||||
|
Name: "F",
|
||||||
|
ReturnType: &ast.TemplatedName{Name: "X"},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"ctor F() -> X<T>",
|
||||||
|
ast.AST{
|
||||||
|
Constructors: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Constructor,
|
||||||
|
Name: "F",
|
||||||
|
ReturnType: &ast.TemplatedName{
|
||||||
|
Name: "X",
|
||||||
|
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"conv F()",
|
||||||
|
ast.AST{
|
||||||
|
Converters: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Converter,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"[[deco]] conv F()",
|
||||||
|
ast.AST{
|
||||||
|
Converters: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Converter,
|
||||||
|
Name: "F",
|
||||||
|
Decorations: ast.Decorations{
|
||||||
|
{Name: "deco", Values: []string{}},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"conv F(a)",
|
||||||
|
ast.AST{
|
||||||
|
Converters: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Converter,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Type: ast.TemplatedName{Name: "a"}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"conv F(a: T)",
|
||||||
|
ast.AST{
|
||||||
|
Converters: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Converter,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Name: "a", Type: ast.TemplatedName{Name: "T"}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"conv F(a, b)",
|
||||||
|
ast.AST{
|
||||||
|
Converters: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Converter,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Type: ast.TemplatedName{Name: "a"}},
|
||||||
|
{Type: ast.TemplatedName{Name: "b"}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"conv F<A : B<C> >()",
|
||||||
|
ast.AST{
|
||||||
|
Converters: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Converter,
|
||||||
|
Name: "F",
|
||||||
|
TemplateParams: ast.TemplateParams{
|
||||||
|
{
|
||||||
|
Name: "A", Type: ast.TemplatedName{
|
||||||
|
Name: "B",
|
||||||
|
TemplateArgs: ast.TemplatedNames{
|
||||||
|
{Name: "C"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"conv F<T>(a: X, b: Y<T>)",
|
||||||
|
ast.AST{
|
||||||
|
Converters: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Converter,
|
||||||
|
Name: "F",
|
||||||
|
TemplateParams: ast.TemplateParams{
|
||||||
|
{Name: "T"},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Name: "a", Type: ast.TemplatedName{Name: "X"}},
|
||||||
|
{Name: "b", Type: ast.TemplatedName{
|
||||||
|
Name: "Y",
|
||||||
|
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"conv F() -> X",
|
||||||
|
ast.AST{
|
||||||
|
Converters: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Converter,
|
||||||
|
Name: "F",
|
||||||
|
ReturnType: &ast.TemplatedName{Name: "X"},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"conv F() -> X<T>",
|
||||||
|
ast.AST{
|
||||||
|
Converters: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Converter,
|
||||||
|
Name: "F",
|
||||||
|
ReturnType: &ast.TemplatedName{
|
||||||
|
Name: "X",
|
||||||
|
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
}},
|
}},
|
||||||
} {
|
} {
|
||||||
got, err := parser.Parse(test.src, "file.txt")
|
got, err := parser.Parse(test.src, "file.txt")
|
||||||
|
|
|
@ -31,6 +31,7 @@ type resolver struct {
|
||||||
builtins map[string]*sem.Intrinsic
|
builtins map[string]*sem.Intrinsic
|
||||||
unaryOperators map[string]*sem.Intrinsic
|
unaryOperators map[string]*sem.Intrinsic
|
||||||
binaryOperators map[string]*sem.Intrinsic
|
binaryOperators map[string]*sem.Intrinsic
|
||||||
|
constructorsAndConverters map[string]*sem.Intrinsic
|
||||||
enumEntryMatchers map[*sem.EnumEntry]*sem.EnumMatcher
|
enumEntryMatchers map[*sem.EnumEntry]*sem.EnumMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ func Resolve(a *ast.AST) (*sem.Sem, error) {
|
||||||
builtins: map[string]*sem.Intrinsic{},
|
builtins: map[string]*sem.Intrinsic{},
|
||||||
unaryOperators: map[string]*sem.Intrinsic{},
|
unaryOperators: map[string]*sem.Intrinsic{},
|
||||||
binaryOperators: map[string]*sem.Intrinsic{},
|
binaryOperators: map[string]*sem.Intrinsic{},
|
||||||
|
constructorsAndConverters: map[string]*sem.Intrinsic{},
|
||||||
enumEntryMatchers: map[*sem.EnumEntry]*sem.EnumMatcher{},
|
enumEntryMatchers: map[*sem.EnumEntry]*sem.EnumMatcher{},
|
||||||
}
|
}
|
||||||
// Declare and resolve all the enumerators
|
// Declare and resolve all the enumerators
|
||||||
|
@ -85,6 +87,21 @@ func Resolve(a *ast.AST) (*sem.Sem, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Declare and resolve type constructors and converters
|
||||||
|
for _, c := range a.Constructors {
|
||||||
|
if err := r.intrinsic(c, r.constructorsAndConverters, &r.s.ConstructorsAndConverters); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, c := range a.Converters {
|
||||||
|
if len(c.Parameters) != 1 {
|
||||||
|
return nil, fmt.Errorf("%v conversions must have a single parameter", c.Source)
|
||||||
|
}
|
||||||
|
if err := r.intrinsic(c, r.constructorsAndConverters, &r.s.ConstructorsAndConverters); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the unique parameter names
|
// Calculate the unique parameter names
|
||||||
r.s.UniqueParameterNames = r.calculateUniqueParameterNames()
|
r.s.UniqueParameterNames = r.calculateUniqueParameterNames()
|
||||||
|
|
||||||
|
@ -440,6 +457,8 @@ func (r *resolver) templateParam(a ast.TemplateParam) (sem.TemplateParam, error)
|
||||||
return &sem.TemplateEnumParam{Name: a.Name, Enum: r.Enum, Matcher: r}, nil
|
return &sem.TemplateEnumParam{Name: a.Name, Enum: r.Enum, Matcher: r}, nil
|
||||||
case *sem.TypeMatcher:
|
case *sem.TypeMatcher:
|
||||||
return &sem.TemplateTypeParam{Name: a.Name, Type: r}, nil
|
return &sem.TemplateTypeParam{Name: a.Name, Type: r}, nil
|
||||||
|
case *sem.Type:
|
||||||
|
return &sem.TemplateTypeParam{Name: a.Name, Type: r}, nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%v invalid template parameter type '%v'", a.Source, a.Type.Name)
|
return nil, fmt.Errorf("%v invalid template parameter type '%v'", a.Source, a.Type.Name)
|
||||||
}
|
}
|
||||||
|
@ -525,6 +544,7 @@ func (r *resolver) calculateUniqueParameterNames() []string {
|
||||||
r.s.Builtins,
|
r.s.Builtins,
|
||||||
r.s.UnaryOperators,
|
r.s.UnaryOperators,
|
||||||
r.s.BinaryOperators,
|
r.s.BinaryOperators,
|
||||||
|
r.s.ConstructorsAndConverters,
|
||||||
} {
|
} {
|
||||||
for _, i := range intrinsics {
|
for _, i := range intrinsics {
|
||||||
for _, o := range i.Overloads {
|
for _, o := range i.Overloads {
|
||||||
|
|
|
@ -141,6 +141,40 @@ type f32
|
||||||
type T<x>
|
type T<x>
|
||||||
fn f(T< T<f32> >)`,
|
fn f(T< T<f32> >)`,
|
||||||
success,
|
success,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type f32
|
||||||
|
op -(f32)`,
|
||||||
|
success,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type f32
|
||||||
|
type T<x>
|
||||||
|
op +(T<f32>, T<f32>)`,
|
||||||
|
success,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type f32
|
||||||
|
ctor f32(f32)`,
|
||||||
|
success,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type f32
|
||||||
|
type T<x>
|
||||||
|
ctor f32(T<f32>)`,
|
||||||
|
success,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type f32
|
||||||
|
type i32
|
||||||
|
conv f32(i32)`,
|
||||||
|
success,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type f32
|
||||||
|
type T<x>
|
||||||
|
conv f32(T<f32>)`,
|
||||||
|
success,
|
||||||
}, {
|
}, {
|
||||||
`enum E {A A}`,
|
`enum E {A A}`,
|
||||||
`
|
`
|
||||||
|
@ -363,6 +397,125 @@ op << <M: m>(P<M>)`,
|
||||||
`file.txt:4:16 cannot use template enum 'E' as template number`,
|
`file.txt:4:16 cannot use template enum 'E' as template number`,
|
||||||
}, {
|
}, {
|
||||||
`
|
`
|
||||||
|
type i
|
||||||
|
enum e { a }
|
||||||
|
ctor F(i) -> e`,
|
||||||
|
`file.txt:3:14 cannot use 'e' as return type. Must be a type or template type`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type T<x>
|
||||||
|
ctor F(T<u>)`,
|
||||||
|
`file.txt:2:10 cannot resolve 'u'`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type x
|
||||||
|
ctor F<T>(T<x>)`,
|
||||||
|
`file.txt:2:11 'T' template parameters do not accept template arguments`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type A<N: num>
|
||||||
|
type B
|
||||||
|
ctor F(A<B>)`,
|
||||||
|
`file.txt:3:10 cannot use type 'B' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type A<N>
|
||||||
|
enum E { b }
|
||||||
|
ctor F(A<b>)`,
|
||||||
|
`file.txt:3:10 cannot use enum entry 'E.b' as template type`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type T
|
||||||
|
type P<N: num>
|
||||||
|
match m: T
|
||||||
|
ctor F(P<m>)`,
|
||||||
|
`file.txt:4:10 cannot use type matcher 'm' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type P<N: num>
|
||||||
|
enum E { b }
|
||||||
|
ctor F(P<E>)`,
|
||||||
|
`file.txt:3:10 cannot use enum 'E' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type P<N: num>
|
||||||
|
enum E { a b }
|
||||||
|
match m: a | b
|
||||||
|
ctor F(P<m>)`,
|
||||||
|
`file.txt:4:10 cannot use enum matcher 'm' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type P<N: num>
|
||||||
|
enum E { a b }
|
||||||
|
match m: a | b
|
||||||
|
ctor F<M: m>(P<M>)`,
|
||||||
|
`file.txt:4:16 cannot use template enum 'E' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
conv F()`,
|
||||||
|
`file.txt:1:6 conversions must have a single parameter`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type i
|
||||||
|
conv F(i, i, i)`,
|
||||||
|
`file.txt:2:6 conversions must have a single parameter`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type i
|
||||||
|
enum e { a }
|
||||||
|
conv F(i) -> e`,
|
||||||
|
`file.txt:3:14 cannot use 'e' as return type. Must be a type or template type`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type T<x>
|
||||||
|
conv F(T<u>)`,
|
||||||
|
`file.txt:2:10 cannot resolve 'u'`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type x
|
||||||
|
conv F<T>(T<x>)`,
|
||||||
|
`file.txt:2:11 'T' template parameters do not accept template arguments`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type A<N: num>
|
||||||
|
type B
|
||||||
|
conv F(A<B>)`,
|
||||||
|
`file.txt:3:10 cannot use type 'B' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type A<N>
|
||||||
|
enum E { b }
|
||||||
|
conv F(A<b>)`,
|
||||||
|
`file.txt:3:10 cannot use enum entry 'E.b' as template type`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type T
|
||||||
|
type P<N: num>
|
||||||
|
match m: T
|
||||||
|
conv F(P<m>)`,
|
||||||
|
`file.txt:4:10 cannot use type matcher 'm' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type P<N: num>
|
||||||
|
enum E { b }
|
||||||
|
conv F(P<E>)`,
|
||||||
|
`file.txt:3:10 cannot use enum 'E' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type P<N: num>
|
||||||
|
enum E { a b }
|
||||||
|
match m: a | b
|
||||||
|
conv F(P<m>)`,
|
||||||
|
`file.txt:4:10 cannot use enum matcher 'm' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type P<N: num>
|
||||||
|
enum E { a b }
|
||||||
|
match m: a | b
|
||||||
|
conv F<M: m>(P<M>)`,
|
||||||
|
`file.txt:4:16 cannot use template enum 'E' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
enum E { a }
|
enum E { a }
|
||||||
type T<X: a>`,
|
type T<X: a>`,
|
||||||
`file.txt:2:8 invalid template parameter type 'a'`,
|
`file.txt:2:8 invalid template parameter type 'a'`,
|
||||||
|
|
|
@ -29,6 +29,7 @@ type Sem struct {
|
||||||
Builtins []*Intrinsic
|
Builtins []*Intrinsic
|
||||||
UnaryOperators []*Intrinsic
|
UnaryOperators []*Intrinsic
|
||||||
BinaryOperators []*Intrinsic
|
BinaryOperators []*Intrinsic
|
||||||
|
ConstructorsAndConverters []*Intrinsic
|
||||||
// Maximum number of open-types used across all builtins
|
// Maximum number of open-types used across all builtins
|
||||||
MaxOpenTypes int
|
MaxOpenTypes int
|
||||||
// Maximum number of open-numbers used across all builtins
|
// Maximum number of open-numbers used across all builtins
|
||||||
|
|
|
@ -30,6 +30,8 @@ const (
|
||||||
Match Kind = "match"
|
Match Kind = "match"
|
||||||
Function Kind = "fn"
|
Function Kind = "fn"
|
||||||
Operator Kind = "op"
|
Operator Kind = "op"
|
||||||
|
Constructor Kind = "ctor"
|
||||||
|
Converter Kind = "conv"
|
||||||
Type Kind = "type"
|
Type Kind = "type"
|
||||||
Enum Kind = "enum"
|
Enum Kind = "enum"
|
||||||
And Kind = "&"
|
And Kind = "&"
|
||||||
|
|
Loading…
Reference in New Issue