Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Introduce Intermediate Representation (IR) for Linter #68

Open
notJoon opened this issue Sep 14, 2024 · 0 comments
Open

Proposal: Introduce Intermediate Representation (IR) for Linter #68

notJoon opened this issue Sep 14, 2024 · 0 comments
Labels
C-propossal Category: sumitting RFC or proposal

Comments

@notJoon
Copy link
Contributor

notJoon commented Sep 14, 2024

Background

Currently, tlin directly uses the go/ast and go/parser pacakge to analyze and process the gno code. While this approach has served us very well, it presents challenges in terms of scalability, maintability, and future language divergence.

Proposal

I propose introducing an Intermediate Representation (IR) layer between AST and our linter rulws. This IR will abstract away the specifics of AST, providing a more flexible and maintainable foundation for our linter.

Pros and Cons

Pros

  1. Abstraction: Simplifies rule implementation by hiding AST complexities.
  2. Maintainability: Easier to update and modify rules without deep AST background knowledge.
  3. Language Divergence: Allows for easier adaptation as gno evolves differently from Go.

Cons

  1. Initial Complexity: Require upfront design and implementation effort.
  2. Learning Curve: Need to learn the new IR structure.
  3. Potential Performance Overhead: Additional layer may introduce some performance cost.

Proof of Concept Implementation

Here's basic PoC for the IR structure and usage:

package linter

import "go/token"

// Node represents any node in our IR
type Node interface {
    Pos() token.Pos
    End() token.Pos
}

// Expression represents any expression in our IR
type Expression interface {
    Node
    exprNode()
}

// Statement represents any statement in our IR
type Statement interface {
    Node
    stmtNode()
}

// Concrete IR nodes
type (
    Ident struct {
        NamePos token.Pos
        Name    string
    }

    FuncDecl struct {
        Name *Ident
        Body *BlockStmt
    }

    BlockStmt struct {
        Statements []Statement
    }
)

// Implement necessary interface methods
func (i *Ident) Pos() token.Pos     { return i.NamePos }
func (i *Ident) End() token.Pos     { return token.Pos(int(i.NamePos) + len(i.Name)) }
func (i *Ident) exprNode()          {}

func (f *FuncDecl) Pos() token.Pos  { return f.Name.Pos() }
func (f *FuncDecl) End() token.Pos  { return f.Body.End() }
func (f *FuncDecl) stmtNode()       {}

// AST to IR conversion (simplified)
func AST2IR(file *ast.File) *IR {
    // Implementation
}

// Rule interface
type Rule interface {
    Check(node Node) []Issue
}

// Sample rule implementation
type UnusedVariableRule struct{}

func (r *UnusedVariableRule) Check(node Node) []Issue {
    // Implementation using IR
}

// Linter execution
func RunLinter(ir *IR, rules []Rule) []Issue {
    var issues []Issue
    for _, rule := range rules {
        issues = append(issues, applyRule(ir, rule)...)
    }
    return issues
}

Handling Language Divergence

As out language evolves and potentially diverges from Go, the IR approach offers significant advantages:

  1. Abstraction Layer: The IR serves as a buffer between the language-specific AST and out linter rulws. When language changes occur, we can update the IR generation process without modifying all the rules.
  2. Custom Nodes: We can introduce custom IR nodes for new language features without waiting for or relying on updates to the go's package.
  3. Gradual Migration: We can incrementally move away from go/ast (and more related packages) by implementing our own parser that generates our IR directly, allowing for a smooth transition as the language diverge.
  4. Feature Toogling: The IR can include flags or variants to represent language specific feeatures, allowing rules to adapt their behavior based on the target language version.
@notJoon notJoon added the C-propossal Category: sumitting RFC or proposal label Sep 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-propossal Category: sumitting RFC or proposal
Projects
None yet
Development

No branches or pull requests

1 participant