Move LSP semantics into typed analysis
This commit is contained in:
parent
f4cd4f4458
commit
bac1183593
26 changed files with 1232 additions and 637 deletions
|
|
@ -17,7 +17,14 @@ func Parse(input string) (*Program, error) {
|
|||
return nil, err
|
||||
}
|
||||
p := &parser{tokens: tokens}
|
||||
return p.parseProgram()
|
||||
program, err := p.parseProgram()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := hydrateTypeRefs(program); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return program, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseProgram() (*Program, error) {
|
||||
|
|
@ -292,6 +299,10 @@ func (p *parser) parseClass() (ClassDecl, error) {
|
|||
if err != nil {
|
||||
return ClassDecl{}, err
|
||||
}
|
||||
typeParams, err := p.parseTypeParameters()
|
||||
if err != nil {
|
||||
return ClassDecl{}, err
|
||||
}
|
||||
var fields []FieldDecl
|
||||
if p.match(tokenLParen) {
|
||||
fields, err = p.parseClassFields()
|
||||
|
|
@ -308,7 +319,7 @@ func (p *parser) parseClass() (ClassDecl, error) {
|
|||
return ClassDecl{}, err
|
||||
}
|
||||
if !p.match(tokenLBrace) {
|
||||
return ClassDecl{Name: name.lexeme, Data: data, Fields: fields, Parents: parents, Methods: nil}, nil
|
||||
return ClassDecl{Name: name.lexeme, TypeParams: typeParams, Data: data, Fields: fields, Parents: parents, Methods: nil}, nil
|
||||
}
|
||||
|
||||
var methods []FunctionDecl
|
||||
|
|
@ -329,7 +340,7 @@ func (p *parser) parseClass() (ClassDecl, error) {
|
|||
return ClassDecl{}, err
|
||||
}
|
||||
|
||||
return ClassDecl{Name: name.lexeme, Data: data, Fields: fields, Parents: parents, Methods: methods}, nil
|
||||
return ClassDecl{Name: name.lexeme, TypeParams: typeParams, Data: data, Fields: fields, Parents: parents, Methods: methods}, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseClassParents() ([]string, error) {
|
||||
|
|
@ -467,6 +478,7 @@ func (p *parser) parseFunction() (FunctionDecl, error) {
|
|||
|
||||
return FunctionDecl{
|
||||
Name: signature.Name,
|
||||
TypeParams: signature.TypeParams,
|
||||
Params: signature.Params,
|
||||
ReturnType: signature.ReturnType,
|
||||
Body: body,
|
||||
|
|
@ -483,6 +495,10 @@ func (p *parser) parseFunctionSignature() (FunctionSignature, error) {
|
|||
if err != nil {
|
||||
return FunctionSignature{}, err
|
||||
}
|
||||
typeParams, err := p.parseTypeParameters()
|
||||
if err != nil {
|
||||
return FunctionSignature{}, err
|
||||
}
|
||||
if _, err := p.expect(tokenLParen, "expected '('"); err != nil {
|
||||
return FunctionSignature{}, err
|
||||
}
|
||||
|
|
@ -505,12 +521,39 @@ func (p *parser) parseFunctionSignature() (FunctionSignature, error) {
|
|||
|
||||
return FunctionSignature{
|
||||
Name: name.lexeme,
|
||||
TypeParams: typeParams,
|
||||
Params: params,
|
||||
ReturnType: returnType,
|
||||
Suspend: suspend,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseTypeParameters() ([]string, error) {
|
||||
if !p.match(tokenLt) {
|
||||
return nil, nil
|
||||
}
|
||||
var params []string
|
||||
seen := map[string]bool{}
|
||||
for {
|
||||
name, err := p.expect(tokenIdent, "expected type parameter")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if seen[name.lexeme] {
|
||||
return nil, fmt.Errorf("duplicate type parameter %s", name.lexeme)
|
||||
}
|
||||
seen[name.lexeme] = true
|
||||
params = append(params, name.lexeme)
|
||||
if !p.match(tokenComma) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if _, err := p.expect(tokenGt, "expected '>' after type parameters"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseParams() ([]Param, error) {
|
||||
var params []Param
|
||||
if p.check(tokenRParen) {
|
||||
|
|
@ -528,7 +571,11 @@ func (p *parser) parseParams() ([]Param, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params = append(params, Param{Name: name.lexeme, Type: typ})
|
||||
ref, err := ParseTypeRef(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params = append(params, Param{Name: name.lexeme, Type: typ, TypeRef: ref})
|
||||
if !p.match(tokenComma) {
|
||||
return params, nil
|
||||
}
|
||||
|
|
@ -832,7 +879,7 @@ func (p *parser) parseVarDecl(mutable bool) (Stmt, error) {
|
|||
return nil, err
|
||||
}
|
||||
if len(names) == 1 {
|
||||
return VarDecl{Mutable: mutable, Name: name, Type: typ, Value: value}, nil
|
||||
return VarDecl{Mutable: mutable, Name: name, Pos: names[0].pos, Type: typ, Value: value}, nil
|
||||
}
|
||||
decl := MultiVarDecl{Mutable: mutable, Names: make([]string, 0, len(names)), Value: value}
|
||||
for _, name := range names {
|
||||
|
|
@ -908,7 +955,7 @@ func (p *parser) parsePrefix() (Expr, error) {
|
|||
tok := p.advance()
|
||||
switch tok.kind {
|
||||
case tokenIdent:
|
||||
return p.parsePostfix(IdentExpr{Name: tok.lexeme})
|
||||
return p.parsePostfix(IdentExpr{Name: tok.lexeme, Pos: tok.pos})
|
||||
case tokenInt:
|
||||
return IntExpr{Value: tok.lexeme}, nil
|
||||
case tokenFloat:
|
||||
|
|
@ -999,6 +1046,10 @@ func (p *parser) parseLambdaParams() ([]Param, bool, error) {
|
|||
return nil, false, err
|
||||
}
|
||||
param.Type = typ
|
||||
param.TypeRef, err = ParseTypeRef(typ)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
params = append(params, param)
|
||||
if !p.match(tokenComma) {
|
||||
|
|
@ -1028,13 +1079,13 @@ func (p *parser) parsePostfix(expr Expr) (Expr, error) {
|
|||
if !selectorName(name.lexeme) {
|
||||
return nil, fmt.Errorf("expected selector name at %d, found %q", name.pos, name.lexeme)
|
||||
}
|
||||
expr = SelectorExpr{Receiver: expr, Name: name.lexeme}
|
||||
expr = SelectorExpr{Receiver: expr, Name: name.lexeme, NamePos: name.pos}
|
||||
case p.match(tokenSafeDot):
|
||||
name := p.advance()
|
||||
if !selectorName(name.lexeme) {
|
||||
return nil, fmt.Errorf("expected selector name at %d, found %q", name.pos, name.lexeme)
|
||||
}
|
||||
expr = SafeSelectorExpr{Receiver: expr, Name: name.lexeme}
|
||||
expr = SafeSelectorExpr{Receiver: expr, Name: name.lexeme, NamePos: name.pos}
|
||||
case p.match(tokenDoubleBang):
|
||||
expr = NonNullExpr{Value: expr}
|
||||
case p.match(tokenQuestion):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue