Skip to content

Commit

Permalink
ALL: Add global variables
Browse files Browse the repository at this point in the history
  • Loading branch information
MineGame159 committed Jan 10, 2024
1 parent ece003d commit 8f0fad9
Show file tree
Hide file tree
Showing 19 changed files with 381 additions and 64 deletions.
14 changes: 12 additions & 2 deletions cmd/lsp/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ func getTypeCompletions(root ast.RootResolver, resolver ast.Resolver, c *complet
}
}

case *ast.Field:
if isAfterNode(pos, node.Name) {
getGlobalCompletions(resolver, c, false)
}

case *ast.Impl:
if isAfterCst(pos, node, scanner.Impl, true) {
getGlobalCompletions(resolver, c, false)
Expand All @@ -115,12 +120,12 @@ func getTypeCompletions(root ast.RootResolver, resolver ast.Resolver, c *complet
getGlobalCompletions(resolver, c, false)
}

case *ast.Field:
case *ast.Param:
if isAfterNode(pos, node.Name) {
getGlobalCompletions(resolver, c, false)
}

case *ast.Param:
case *ast.GlobalVar:
if isAfterNode(pos, node.Name) {
getGlobalCompletions(resolver, c, false)
}
Expand Down Expand Up @@ -300,6 +305,11 @@ func getResolverCompletions(c *completions, resolver ast.Resolver, functions boo
if functions {
c.addNode(protocol.CompletionItemKindFunction, node.Name, printType(node))
}

case *ast.GlobalVar:
if functions {
c.addNode(protocol.CompletionItemKindVariable, node.Name, printType(node.Type))
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions cmd/lsp/highlighter.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ func (h *highlighter) VisitFunc(decl *ast.Func) {
h.params = nil
}

func (h *highlighter) VisitGlobalVar(decl *ast.GlobalVar) {
h.add(decl.Name, variableKind)

decl.AcceptChildren(h)
}

// Statements

func (h *highlighter) VisitBlock(stmt *ast.Block) {
Expand Down
9 changes: 9 additions & 0 deletions cmd/lsp/symbols.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,15 @@ func getSymbols(symbols symbolConsumer, files []*workspace.File) {
range_: nodeCst(function).Range,
selectionRange: nodeCst(function.Name).Range,
}, 0)
} else if variable, ok := decl.(*ast.GlobalVar); ok && nodeCst(variable) != nil && nodeCst(variable.Name) != nil {
symbols.add(symbol{
file: file,
kind: protocol.SymbolKindVariable,
name: variable.Name.String(),
detail: printType(variable.Type),
range_: nodeCst(variable).Range,
selectionRange: nodeCst(variable.Name).Range,
}, 0)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/ast/cst2ast/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ func Convert(reporter utils.Reporter, path string, node cst.Node) *ast.File {
reportedMissingNamespace := false

for _, child := range node.Children {
if child.Kind == cst.NamespaceNode {
if child.Kind == cst.NamespaceDeclNode {
if namespace == nil {
namespace = c.convertNamespace(child)
namespace = c.convertNamespaceDecl(child)
} else {
c.error(child, "There can only be one top-level file namespace")
}
Expand Down
47 changes: 36 additions & 11 deletions core/ast/cst2ast/declarations.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,29 @@ import (

func (c *converter) convertDecl(node cst.Node) ast.Decl {
switch node.Kind {
case cst.NamespaceNode:
if namespace := c.convertNamespace(node); namespace != nil {
case cst.NamespaceDeclNode:
if namespace := c.convertNamespaceDecl(node); namespace != nil {
return namespace
}

return nil
case cst.UsingNode:
return c.convertUsing(node)
case cst.UsingDeclNode:
return c.convertUsingDecl(node)

case cst.StructNode:
case cst.StructDeclNode:
return c.convertStructDecl(node)
case cst.ImplNode:
case cst.ImplDeclNode:
return c.convertImplDecl(node)
case cst.EnumNode:
case cst.EnumDeclNode:
return c.convertEnumDecl(node)
case cst.FuncNode:
case cst.FuncDeclNode:
if f := c.convertFuncDecl(node); f != nil {
return f
}

return nil
case cst.VarDeclNode:
return c.convertVarDecl(node)

default:
panic("cst2ast.convertDecl() - Not implemented")
Expand All @@ -37,7 +39,7 @@ func (c *converter) convertDecl(node cst.Node) ast.Decl {

// Namespace

func (c *converter) convertNamespace(node cst.Node) *ast.Namespace {
func (c *converter) convertNamespaceDecl(node cst.Node) *ast.Namespace {
var name *ast.NamespaceName

for _, child := range node.Children {
Expand All @@ -51,7 +53,7 @@ func (c *converter) convertNamespace(node cst.Node) *ast.Namespace {
return ast.NewNamespace(node, name)
}

func (c *converter) convertUsing(node cst.Node) ast.Decl {
func (c *converter) convertUsingDecl(node cst.Node) ast.Decl {
var name *ast.NamespaceName

for _, child := range node.Children {
Expand Down Expand Up @@ -145,7 +147,7 @@ func (c *converter) convertImplDecl(node cst.Node) ast.Decl {
for _, child := range node.Children {
if child.Kind == cst.IdentifierNode {
struct_ = c.convertToken(child)
} else if child.Kind == cst.FuncNode {
} else if child.Kind == cst.FuncDeclNode {
method := c.convertFuncDecl(child)

if method != nil {
Expand Down Expand Up @@ -300,6 +302,29 @@ func (c *converter) convertFuncParam(node cst.Node) (*ast.Param, bool) {
return nil, varArgs
}

// Var

func (c *converter) convertVarDecl(node cst.Node) ast.Decl {
var name *ast.Token
var type_ ast.Type

for _, child := range node.Children {
if child.Kind == cst.IdentifierNode {
name = c.convertToken(child)
} else if child.Kind.IsType() {
type_ = c.convertType(child)
} else if child.Kind == cst.AttributesNode {
c.error(child.Children[0], "Global variables cannot have attributes")
}
}

if v := ast.NewGlobalVar(node, name, type_); v != nil {
return v
}

return nil
}

// Attributes

func (c *converter) convertAttributes(node cst.Node) []*ast.Attribute {
Expand Down
90 changes: 90 additions & 0 deletions core/ast/declarations.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type DeclVisitor interface {
VisitEnum(decl *Enum)
VisitImpl(decl *Impl)
VisitFunc(decl *Func)
VisitGlobalVar(decl *GlobalVar)
}

type Decl interface {
Expand Down Expand Up @@ -613,3 +614,92 @@ func (f *Func) String() string {
func (f *Func) AcceptDecl(visitor DeclVisitor) {
visitor.VisitFunc(f)
}

// GlobalVar

type GlobalVar struct {
cst cst.Node
parent Node

Name *Token
Type Type
}

func NewGlobalVar(node cst.Node, name *Token, type_ Type) *GlobalVar {
if name == nil && type_ == nil {
return nil
}

g := &GlobalVar{
cst: node,
Name: name,
Type: type_,
}

if name != nil {
name.SetParent(g)
}
if type_ != nil {
type_.SetParent(g)
}

return g
}

func (g *GlobalVar) Cst() *cst.Node {
if g.cst.Kind == cst.UnknownNode {
return nil
}

return &g.cst
}

func (g *GlobalVar) Token() scanner.Token {
return scanner.Token{}
}

func (g *GlobalVar) Parent() Node {
return g.parent
}

func (g *GlobalVar) SetParent(parent Node) {
if parent != nil && g.parent != nil {
panic("ast.GlobalVar.SetParent() - Parent is already set")
}

g.parent = parent
}

func (g *GlobalVar) AcceptChildren(visitor Visitor) {
if g.Name != nil {
visitor.VisitNode(g.Name)
}
if g.Type != nil {
visitor.VisitNode(g.Type)
}
}

func (g *GlobalVar) Clone() Node {
g2 := &GlobalVar{
cst: g.cst,
}

if g.Name != nil {
g2.Name = g.Name.Clone().(*Token)
g2.Name.SetParent(g2)
}
if g.Type != nil {
g2.Type = g.Type.Clone().(Type)
g2.Type.SetParent(g2)
}

return g2
}

func (g *GlobalVar) String() string {
return ""
}

func (g *GlobalVar) AcceptDecl(visitor DeclVisitor) {
visitor.VisitGlobalVar(g)
}
18 changes: 18 additions & 0 deletions core/ast/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,21 @@ func (f *Func) MangledName() string {

return sb.String()
}

// GlobalVar

func (g *GlobalVar) MangledName() string {
sb := strings.Builder{}
sb.WriteString("fb$")

file := GetParent[*File](g)
file.Namespace.Name.WriteTo(&sb)

sb.WriteString(":g:")

if g.Name != nil {
sb.WriteString(g.Name.String())
}

return sb.String()
}
2 changes: 2 additions & 0 deletions core/ast/other.go
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,8 @@ func IsNil(node Node) bool {
return node == nil
case *Func:
return node == nil
case *GlobalVar:
return node == nil
case *Expression:
return node == nil
case *Block:
Expand Down
11 changes: 11 additions & 0 deletions core/ast/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type Resolver interface {
GetType(name string) Type

GetFunction(name string) *Func
GetVariable(name string) *GlobalVar

GetMethod(type_ Type, name string, static bool) *Func
GetMethods(type_ Type, static bool) []*Func
Expand Down Expand Up @@ -63,6 +64,16 @@ func (c *CombinedResolver) GetFunction(name string) *Func {
return nil
}

func (c *CombinedResolver) GetVariable(name string) *GlobalVar {
for _, resolver := range c.resolvers {
if variable := resolver.GetVariable(name); variable != nil {
return variable
}
}

return nil
}

func (c *CombinedResolver) GetMethod(type_ Type, name string, static bool) *Func {
for _, resolver := range c.resolvers {
if method := resolver.GetMethod(type_, name, static); method != nil {
Expand Down
13 changes: 13 additions & 0 deletions core/checker/declarations.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,17 @@ func (c *checker) VisitFunc(decl *ast.Func) {
}
}

func (c *checker) VisitGlobalVar(decl *ast.GlobalVar) {
decl.AcceptChildren(c)

c.checkNameCollision(decl, decl.Name)

// Check void type
if ast.IsPrimitive(decl.Type, ast.Void) {
c.error(decl.Name, "Variable cannot be of type 'void'")
}
}

// Utils

func (c *checker) checkNameCollision(decl ast.Decl, name *ast.Token) {
Expand Down Expand Up @@ -275,6 +286,8 @@ func (c *checker) checkNameCollision(decl ast.Decl, name *ast.Token) {
name2 = node.Name
case *ast.Func:
name2 = node.Name
case *ast.GlobalVar:
name2 = node.Name
}

if name2 != nil && name.String() == name2.String() {
Expand Down
Loading

0 comments on commit 8f0fad9

Please sign in to comment.